@@ -46,6 +46,7 @@ type KeyStore struct {
46
46
prefixLen int
47
47
48
48
gcFunc KeyChanFunc // optional function to get keys for garbage collection
49
+ gcFuncLk sync.Mutex
49
50
gcInterval time.Duration
50
51
gcBatchSize int
51
52
}
@@ -103,17 +104,6 @@ func WithDatastorePrefix(base string) KeyStoreOption {
103
104
}
104
105
}
105
106
106
- // WithGCFunc sets the function periodically used to garbage collect keys that
107
- // shouldn't be provided anymore. During the garbage collection process, the
108
- // store is entirely purged, and is repopulated from the keys supplied by the
109
- // KeyChanFunc.
110
- func WithGCFunc (gcFunc KeyChanFunc ) KeyStoreOption {
111
- return func (cfg * keyStoreCfg ) error {
112
- cfg .gcFunc = gcFunc
113
- return nil
114
- }
115
- }
116
-
117
107
// WithGCInterval defines the interval at which the KeyStore is garbage
118
108
// collected. During the garbage collection process, the store is entirely
119
109
// purged, and is repopulated from the keys supplied by the gcFunc.
@@ -141,6 +131,33 @@ func WithGCBatchSize(size int) KeyStoreOption {
141
131
}
142
132
}
143
133
134
+ // WithGCFunc sets the function periodically used to garbage collect keys that
135
+ // shouldn't be provided anymore. During the garbage collection process, the
136
+ // store is entirely purged, and is repopulated from the keys supplied by the
137
+ // KeyChanFunc.
138
+ func WithGCFunc (gcFunc KeyChanFunc ) KeyStoreOption {
139
+ return func (cfg * keyStoreCfg ) error {
140
+ cfg .gcFunc = gcFunc
141
+ return nil
142
+ }
143
+ }
144
+
145
+ func (s * KeyStore ) SetGCFunc (gcFunc KeyChanFunc ) {
146
+ if gcFunc == nil {
147
+ return
148
+ }
149
+ s .gcFuncLk .Lock ()
150
+ defer s .gcFuncLk .Unlock ()
151
+
152
+ startGC := s .gcFunc == nil && s .gcInterval > 0
153
+ s .gcFunc = gcFunc
154
+
155
+ if startGC {
156
+ s .wg .Add (1 )
157
+ go s .runGC ()
158
+ }
159
+ }
160
+
144
161
// NewKeyStore creates a new KeyStore backed by the provided datastore.
145
162
func NewKeyStore (d ds.Batching , opts ... KeyStoreOption ) (* KeyStore , error ) {
146
163
var cfg keyStoreCfg
@@ -161,6 +178,7 @@ func NewKeyStore(d ds.Batching, opts ...KeyStoreOption) (*KeyStore, error) {
161
178
gcBatchSize : cfg .gcBatchSize ,
162
179
}
163
180
if cfg .gcFunc != nil && cfg .gcInterval > 0 {
181
+ keyStore .wg .Add (1 )
164
182
go keyStore .runGC ()
165
183
}
166
184
return & keyStore , nil
@@ -188,15 +206,16 @@ func (s *KeyStore) closed() bool {
188
206
// resets the state of the KeyStore to match the state returned by the GC
189
207
// function.
190
208
func (s * KeyStore ) runGC () {
191
- s .wg .Add (1 )
192
209
defer s .wg .Done ()
193
210
ticker := time .NewTicker (s .gcInterval )
194
211
for {
195
212
select {
196
213
case <- s .done :
197
214
return
198
215
case <- ticker .C :
216
+ s .gcFuncLk .Lock ()
199
217
keysChan , err := s .gcFunc (context .Background ())
218
+ s .gcFuncLk .Unlock ()
200
219
if err != nil {
201
220
logger .Errorf ("garbage collection failed: %v" , err )
202
221
continue
@@ -218,17 +237,14 @@ func (s *KeyStore) ResetCids(ctx context.Context, keysChan <-chan cid.Cid) error
218
237
if err != nil {
219
238
return fmt .Errorf ("KeyStore empty failed during reset: %w" , err )
220
239
}
221
- keys := make ([]mh.Multihash , s .gcBatchSize )
222
- i := 0
240
+ keys := make ([]mh.Multihash , 0 , s .gcBatchSize )
223
241
for c := range keysChan {
224
- keys [i ] = c .Hash ()
225
- i ++
226
- if i == s .gcBatchSize {
242
+ keys = append (keys , c .Hash ())
243
+ if len (keys ) == s .gcBatchSize {
227
244
_ , err = s .Put (ctx , keys ... )
228
245
if err != nil {
229
246
return fmt .Errorf ("KeyStore put failed during reset: %w" , err )
230
247
}
231
- i = 0
232
248
keys = keys [:0 ]
233
249
}
234
250
}
@@ -245,7 +261,7 @@ func (s *KeyStore) dsKey(prefix bitstr.Key) ds.Key {
245
261
246
262
// putLocked stores the provided keys while assuming s.lk is already held.
247
263
func (s * KeyStore ) putLocked (ctx context.Context , keys ... mh.Multihash ) ([]mh.Multihash , error ) {
248
- groups := make (map [bitstr.Key ][]mh.Multihash )
264
+ groups := make (map [bitstr.Key ][]mh.Multihash , len ( keys ) )
249
265
for _ , h := range keys {
250
266
k := keyspace .MhToBit256 (h )
251
267
bs := bitstr .Key (key .BitString (k )[:s .prefixLen ])
0 commit comments