@@ -3,14 +3,14 @@ package bitswap
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "sync"
6
7
"time"
7
8
8
9
"github.com/ipfs/boxo/blockstore"
9
10
"github.com/ipfs/boxo/exchange"
10
11
"go.opentelemetry.io/otel"
11
12
"go.opentelemetry.io/otel/attribute"
12
13
"go.opentelemetry.io/otel/codes"
13
- "go.opentelemetry.io/otel/trace"
14
14
15
15
"github.com/celestiaorg/celestia-app/v3/pkg/wrapper"
16
16
libshare "github.com/celestiaorg/go-square/v2/share"
@@ -30,8 +30,8 @@ type Getter struct {
30
30
bstore blockstore.Blockstore
31
31
availWndw time.Duration
32
32
33
- availableSession exchange. Fetcher
34
- archivalSession exchange. Fetcher
33
+ availablePool * pool
34
+ archivalPool * pool
35
35
36
36
cancel context.CancelFunc
37
37
}
@@ -42,7 +42,13 @@ func NewGetter(
42
42
bstore blockstore.Blockstore ,
43
43
availWndw time.Duration ,
44
44
) * Getter {
45
- return & Getter {exchange : exchange , bstore : bstore , availWndw : availWndw }
45
+ return & Getter {
46
+ exchange : exchange ,
47
+ bstore : bstore ,
48
+ availWndw : availWndw ,
49
+ availablePool : newPool (exchange ),
50
+ archivalPool : newPool (exchange ),
51
+ }
46
52
}
47
53
48
54
// Start kicks off internal fetching sessions.
@@ -57,12 +63,13 @@ func NewGetter(
57
63
// with regular full node peers.
58
64
func (g * Getter ) Start () {
59
65
ctx , cancel := context .WithCancel (context .Background ())
60
- g .availableSession = g .exchange .NewSession (ctx )
61
- g .archivalSession = g .exchange .NewSession (ctx )
62
66
g .cancel = cancel
67
+
68
+ g .availablePool .ctx = ctx
69
+ g .availablePool .ctx = ctx
63
70
}
64
71
65
- // Stop shuts down Getter's internal fetching session .
72
+ // Stop shuts down Getter's internal fetching getSession .
66
73
func (g * Getter ) Stop () {
67
74
g .cancel ()
68
75
}
@@ -97,7 +104,12 @@ func (g *Getter) GetShares(
97
104
blks [i ] = sid
98
105
}
99
106
100
- ses := g .session (ctx , hdr )
107
+ isArchival := g .isArchival (hdr )
108
+ span .SetAttributes (attribute .Bool ("is_archival" , isArchival ))
109
+
110
+ ses , release := g .getSession (isArchival )
111
+ defer release ()
112
+
101
113
err := Fetch (ctx , g .exchange , hdr .DAH , blks , WithStore (g .bstore ), WithFetcher (ses ))
102
114
if err != nil {
103
115
span .RecordError (err )
@@ -156,7 +168,12 @@ func (g *Getter) GetEDS(
156
168
blks [i ] = blk
157
169
}
158
170
159
- ses := g .session (ctx , hdr )
171
+ isArchival := g .isArchival (hdr )
172
+ span .SetAttributes (attribute .Bool ("is_archival" , isArchival ))
173
+
174
+ ses , release := g .getSession (isArchival )
175
+ defer release ()
176
+
160
177
err := Fetch (ctx , g .exchange , hdr .DAH , blks , WithFetcher (ses ))
161
178
if err != nil {
162
179
span .RecordError (err )
@@ -210,7 +227,12 @@ func (g *Getter) GetNamespaceData(
210
227
blks [i ] = rndblk
211
228
}
212
229
213
- ses := g .session (ctx , hdr )
230
+ isArchival := g .isArchival (hdr )
231
+ span .SetAttributes (attribute .Bool ("is_archival" , isArchival ))
232
+
233
+ ses , release := g .getSession (isArchival )
234
+ defer release ()
235
+
214
236
if err = Fetch (ctx , g .exchange , hdr .DAH , blks , WithFetcher (ses )); err != nil {
215
237
span .RecordError (err )
216
238
span .SetStatus (codes .Error , "Fetch" )
@@ -230,17 +252,19 @@ func (g *Getter) GetNamespaceData(
230
252
return nsShrs , nil
231
253
}
232
254
233
- // session decides which fetching session to use for the given header.
234
- func (g * Getter ) session (ctx context.Context , hdr * header.ExtendedHeader ) exchange.Fetcher {
235
- session := g .archivalSession
255
+ // isArchival reports whether the header is for archival data
256
+ func (g * Getter ) isArchival (hdr * header.ExtendedHeader ) bool {
257
+ return ! availability .IsWithinWindow (hdr .Time (), g .availWndw )
258
+ }
236
259
237
- isWithinAvailability := availability .IsWithinWindow (hdr .Time (), g .availWndw )
238
- if isWithinAvailability {
239
- session = g .availableSession
260
+ // getSession takes a session out of the respective session pool
261
+ func (g * Getter ) getSession (isArchival bool ) (ses exchange.Fetcher , release func ()) {
262
+ if isArchival {
263
+ ses = g .archivalPool .get ()
264
+ return ses , func () { g .archivalPool .put (ses ) }
240
265
}
241
-
242
- trace .SpanFromContext (ctx ).SetAttributes (attribute .Bool ("within_availability" , isWithinAvailability ))
243
- return session
266
+ ses = g .availablePool .get ()
267
+ return ses , func () { g .availablePool .put (ses ) }
244
268
}
245
269
246
270
// edsFromRows imports given Rows and computes EDS out of them, assuming enough Rows were provided.
@@ -274,3 +298,40 @@ func edsFromRows(roots *share.AxisRoots, rows []shwap.Row) (*rsmt2d.ExtendedData
274
298
275
299
return square , nil
276
300
}
301
+
302
+ // pool is a pool of Bitswap sessions.
303
+ type pool struct {
304
+ lock sync.Mutex
305
+ sessions []exchange.Fetcher
306
+ ctx context.Context
307
+ exchange exchange.SessionExchange
308
+ }
309
+
310
+ func newPool (ex exchange.SessionExchange ) * pool {
311
+ return & pool {
312
+ exchange : ex ,
313
+ sessions : make ([]exchange.Fetcher , 0 ),
314
+ }
315
+ }
316
+
317
+ // get returns a session from the pool or creates a new one if the pool is empty.
318
+ func (p * pool ) get () exchange.Fetcher {
319
+ p .lock .Lock ()
320
+ defer p .lock .Unlock ()
321
+
322
+ if len (p .sessions ) == 0 {
323
+ return p .exchange .NewSession (p .ctx )
324
+ }
325
+
326
+ ses := p .sessions [len (p .sessions )- 1 ]
327
+ p .sessions = p .sessions [:len (p .sessions )- 1 ]
328
+ return ses
329
+ }
330
+
331
+ // put returns a session to the pool.
332
+ func (p * pool ) put (ses exchange.Fetcher ) {
333
+ p .lock .Lock ()
334
+ defer p .lock .Unlock ()
335
+
336
+ p .sessions = append (p .sessions , ses )
337
+ }
0 commit comments