Skip to content

Commit ba22102

Browse files
committed
provider: buffer pin providers.
Fixes #10596. The reproviding process can take long. Currently, each CID to be provided is obtained by making a query to the pinner and reading one by one as the CIDs get provided. While this query is ongoing, the pinner holds a Read mutex on the pinset. If a pin-add-request arrives, a goroutine will start waiting for a Write mutex on the pinset. From that point, no new Read mutexes can be taken until the writer can proceed and finishes. However, no one can proceed because the read mutex is still held while the reproviding is ongoing. The fix is mostly in Boxo, where we add a "buffered" provider which reads the cids onto memory so that they can be provided at its own pace without making everyone wait. The consequence is we will need more RAM memory. Rule of thumb is 1GiB extra per 20M cids to be reprovided.
1 parent 6f2196f commit ba22102

File tree

2 files changed

+15
-3
lines changed

2 files changed

+15
-3
lines changed

core/node/provider.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,23 @@ func newProvidingStrategy(onlyPinned, onlyRoots bool) interface{} {
167167
IPLDFetcher fetcher.Factory `name:"ipldFetcher"`
168168
}
169169
return func(in input) provider.KeyChanFunc {
170+
// Pinner-related CIDs will be buffered in memory to avoid
171+
// deadlocking the pinner when the providing process is slow.
172+
170173
if onlyRoots {
171-
return provider.NewPinnedProvider(true, in.Pinner, in.IPLDFetcher)
174+
return provider.NewBufferedProvider(
175+
provider.NewPinnedProvider(true, in.Pinner, in.IPLDFetcher),
176+
)
172177
}
173178

174179
if onlyPinned {
175-
return provider.NewPinnedProvider(false, in.Pinner, in.IPLDFetcher)
180+
return provider.NewBufferedProvider(
181+
provider.NewPinnedProvider(false, in.Pinner, in.IPLDFetcher),
182+
)
176183
}
177184

178185
return provider.NewPrioritizedProvider(
179-
provider.NewPinnedProvider(true, in.Pinner, in.IPLDFetcher),
186+
provider.NewBufferedProvider(provider.NewPinnedProvider(true, in.Pinner, in.IPLDFetcher)),
180187
provider.NewBlockstoreProvider(in.Blockstore),
181188
)
182189
}

docs/changelogs/v0.34.md

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
- [Badger datastore update](#badger-datastore-update)
1515
- [Datastore Implementation Updates](#datastore-implementation-updates)
1616
- [One Multi-error Package](#one-multi-error-package)
17+
- [Fix hanging pinset operations during reprovides](#fix-hanging-pinset-operations-during-reprovides)
1718
- [📦️ Important dependency updates](#-important-dependency-updates)
1819
- [👨‍👩‍👧‍👦 Contributors](#-contributors)
1920

@@ -74,6 +75,10 @@ The go-ds-xxx datastore implementations have been updated to support the updated
7475

7576
Kubo previously depended on multiple multi-error packages, `github.com/hashicorp/go-multierror` and `go.uber.org/multierr`. These have nearly identical functionality so there was no need to use both. Therefore, `go.uber.org/multierr` was selected as the package to depend on. Any future code needing multi-error functionality should use `go.uber.org/multierr` to avoid introducing unneeded dependencies.
7677

78+
#### Fix hanging pinset operations during reprovides
79+
80+
The reprovide process can be quite slow. In default settings, the reprovide process will start reading CIDs that belong to the pinset. During this operation, starvation can occurr for other operations that need pinset access (see https://github.com/ipfs/kubo/issue/10596). We have now switch to buffering pinset-related cids that are going to be reprovided in memory, so that we can free pinset mutexes as soon as possible so that pinset-writes and subsequent read operations can proceed. The downside is larger pinsets will need some extra memory, with an estimation of ~1GiB of RAM memory-use per 20 million items to be reprovided.
81+
7782
#### 📦️ Important dependency updates
7883

7984
- update `go-libp2p` to [v0.41.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.41.0) (incl. [v0.40.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.40.0))

0 commit comments

Comments
 (0)