8
8
"errors"
9
9
"fmt"
10
10
"io"
11
+ "sync"
11
12
12
13
blocks "github.com/ipfs/go-block-format"
13
14
cid "github.com/ipfs/go-cid"
@@ -116,8 +117,9 @@ func NewSession(ctx context.Context, bs BlockService) *Session {
116
117
if sessEx , ok := exch .(exchange.SessionExchange ); ok {
117
118
ses := sessEx .NewSession (ctx )
118
119
return & Session {
119
- ses : ses ,
120
- bs : bs .Blockstore (),
120
+ ses : ses ,
121
+ sessEx : sessEx ,
122
+ bs : bs .Blockstore (),
121
123
}
122
124
}
123
125
return & Session {
@@ -199,15 +201,19 @@ func (s *blockService) AddBlocks(bs []blocks.Block) error {
199
201
func (s * blockService ) GetBlock (ctx context.Context , c cid.Cid ) (blocks.Block , error ) {
200
202
log .Debugf ("BlockService GetBlock: '%s'" , c )
201
203
202
- var f exchange.Fetcher
204
+ var f func () exchange.Fetcher
203
205
if s .exchange != nil {
204
- f = s .exchange
206
+ f = s .getExchange
205
207
}
206
208
207
209
return getBlock (ctx , c , s .blockstore , f ) // hash security
208
210
}
209
211
210
- func getBlock (ctx context.Context , c cid.Cid , bs blockstore.Blockstore , f exchange.Fetcher ) (blocks.Block , error ) {
212
+ func (s * blockService ) getExchange () exchange.Fetcher {
213
+ return s .exchange
214
+ }
215
+
216
+ func getBlock (ctx context.Context , c cid.Cid , bs blockstore.Blockstore , fget func () exchange.Fetcher ) (blocks.Block , error ) {
211
217
err := verifcid .ValidateCid (c ) // hash security
212
218
if err != nil {
213
219
return nil , err
@@ -218,7 +224,9 @@ func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, f exchan
218
224
return block , nil
219
225
}
220
226
221
- if err == blockstore .ErrNotFound && f != nil {
227
+ if err == blockstore .ErrNotFound && fget != nil {
228
+ f := fget () // Don't load the exchange until we have to
229
+
222
230
// TODO be careful checking ErrNotFound. If the underlying
223
231
// implementation changes, this will break.
224
232
log .Debug ("Blockservice: Searching bitswap" )
@@ -245,10 +253,10 @@ func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, f exchan
245
253
// the returned channel.
246
254
// NB: No guarantees are made about order.
247
255
func (s * blockService ) GetBlocks (ctx context.Context , ks []cid.Cid ) <- chan blocks.Block {
248
- return getBlocks (ctx , ks , s .blockstore , s .exchange ) // hash security
256
+ return getBlocks (ctx , ks , s .blockstore , s .getExchange ) // hash security
249
257
}
250
258
251
- func getBlocks (ctx context.Context , ks []cid.Cid , bs blockstore.Blockstore , f exchange.Fetcher ) <- chan blocks.Block {
259
+ func getBlocks (ctx context.Context , ks []cid.Cid , bs blockstore.Blockstore , fget func () exchange.Fetcher ) <- chan blocks.Block {
252
260
out := make (chan blocks.Block )
253
261
254
262
go func () {
@@ -284,6 +292,7 @@ func getBlocks(ctx context.Context, ks []cid.Cid, bs blockstore.Blockstore, f ex
284
292
return
285
293
}
286
294
295
+ f := fget () // don't load exchange unless we have to
287
296
rblocks , err := f .GetBlocks (ctx , misses )
288
297
if err != nil {
289
298
log .Debugf ("Error with GetBlocks: %s" , err )
@@ -318,18 +327,31 @@ func (s *blockService) Close() error {
318
327
319
328
// Session is a helper type to provide higher level access to bitswap sessions
320
329
type Session struct {
321
- bs blockstore.Blockstore
322
- ses exchange.Fetcher
330
+ bs blockstore.Blockstore
331
+ ses exchange.Fetcher
332
+ sessEx exchange.SessionExchange
333
+ sessCtx context.Context
334
+ lk sync.Mutex
335
+ }
336
+
337
+ func (s * Session ) getSession () exchange.Fetcher {
338
+ s .lk .Lock ()
339
+ defer s .lk .Unlock ()
340
+ if s .ses == nil {
341
+ s .ses = s .sessEx .NewSession (s .sessCtx )
342
+ }
343
+
344
+ return s .ses
323
345
}
324
346
325
347
// GetBlock gets a block in the context of a request session
326
348
func (s * Session ) GetBlock (ctx context.Context , c cid.Cid ) (blocks.Block , error ) {
327
- return getBlock (ctx , c , s .bs , s .ses ) // hash security
349
+ return getBlock (ctx , c , s .bs , s .getSession ) // hash security
328
350
}
329
351
330
352
// GetBlocks gets blocks in the context of a request session
331
353
func (s * Session ) GetBlocks (ctx context.Context , ks []cid.Cid ) <- chan blocks.Block {
332
- return getBlocks (ctx , ks , s .bs , s .ses ) // hash security
354
+ return getBlocks (ctx , ks , s .bs , s .getSession ) // hash security
333
355
}
334
356
335
357
var _ BlockGetter = (* Session )(nil )
0 commit comments