7
7
8
8
"github.com/ipfs/go-cid"
9
9
"github.com/ipfs/go-datastore"
10
+ "github.com/ipfs/go-datastore/namespace"
10
11
"github.com/ipld/go-ipld-prime"
11
12
peer "github.com/libp2p/go-libp2p-core/peer"
12
13
cbg "github.com/whyrusleeping/cbor-gen"
@@ -20,6 +21,7 @@ import (
20
21
"github.com/filecoin-project/go-data-transfer/channels/internal"
21
22
"github.com/filecoin-project/go-data-transfer/channels/internal/migrations"
22
23
"github.com/filecoin-project/go-data-transfer/cidlists"
24
+ "github.com/filecoin-project/go-data-transfer/cidsets"
23
25
"github.com/filecoin-project/go-data-transfer/encoding"
24
26
)
25
27
@@ -53,6 +55,7 @@ type Channels struct {
53
55
stateMachines fsm.Group
54
56
migrateStateMachines func (context.Context ) error
55
57
cidLists cidlists.CIDLists
58
+ seenCIDs * cidsets.CIDSetManager
56
59
}
57
60
58
61
// ChannelEnvironment -- just a proxy for DTNetwork for now
@@ -71,8 +74,11 @@ func New(ds datastore.Batching,
71
74
voucherResultDecoder DecoderByTypeFunc ,
72
75
env ChannelEnvironment ,
73
76
selfPeer peer.ID ) (* Channels , error ) {
77
+
78
+ seenCIDsDS := namespace .Wrap (ds , datastore .NewKey ("seencids" ))
74
79
c := & Channels {
75
80
cidLists : cidLists ,
81
+ seenCIDs : cidsets .NewCIDSetManager (seenCIDsDS ),
76
82
notifier : notifier ,
77
83
voucherDecoder : voucherDecoder ,
78
84
voucherResultDecoder : voucherResultDecoder ,
@@ -117,6 +123,19 @@ func (c *Channels) dispatch(eventName fsm.EventName, channel fsm.StateType) {
117
123
}
118
124
119
125
c .notifier (evt , fromInternalChannelState (realChannel , c .voucherDecoder , c .voucherResultDecoder , c .cidLists .ReadList ))
126
+
127
+ // When the channel has been cleaned up, remove the caches of seen cids
128
+ if evt .Code == datatransfer .CleanupComplete {
129
+ chid := datatransfer.ChannelID {
130
+ Initiator : realChannel .Initiator ,
131
+ Responder : realChannel .Responder ,
132
+ ID : realChannel .TransferID ,
133
+ }
134
+ err := c .removeSeenCIDCaches (chid )
135
+ if err != nil {
136
+ log .Errorf ("failed to clean up channel %s: %s" , err )
137
+ }
138
+ }
120
139
}
121
140
122
141
// CreateNew creates a new channel id and channel state and saves to channels.
@@ -206,20 +225,21 @@ func (c *Channels) CompleteCleanupOnRestart(chid datatransfer.ChannelID) error {
206
225
return c .send (chid , datatransfer .CompleteCleanupOnRestart )
207
226
}
208
227
209
- func (c * Channels ) DataSent (chid datatransfer.ChannelID , cid cid.Cid , delta uint64 ) error {
210
- return c .send (chid , datatransfer .DataSent , delta )
228
+ func (c * Channels ) DataSent (chid datatransfer.ChannelID , k cid.Cid , delta uint64 ) error {
229
+ return c .fireProgressEvent (chid , datatransfer .DataSent , datatransfer . DataSentProgress , k , delta )
211
230
}
212
231
213
- func (c * Channels ) DataQueued (chid datatransfer.ChannelID , cid cid.Cid , delta uint64 ) error {
214
- return c .send (chid , datatransfer .DataQueued , delta )
232
+ func (c * Channels ) DataQueued (chid datatransfer.ChannelID , k cid.Cid , delta uint64 ) error {
233
+ return c .fireProgressEvent (chid , datatransfer .DataQueued , datatransfer . DataQueuedProgress , k , delta )
215
234
}
216
235
217
- func (c * Channels ) DataReceived (chid datatransfer.ChannelID , cid cid.Cid , delta uint64 ) error {
218
- err := c .cidLists .AppendList (chid , cid )
236
+ func (c * Channels ) DataReceived (chid datatransfer.ChannelID , k cid.Cid , delta uint64 ) error {
237
+ err := c .cidLists .AppendList (chid , k )
219
238
if err != nil {
220
239
return err
221
240
}
222
- return c .send (chid , datatransfer .DataReceived , delta )
241
+
242
+ return c .fireProgressEvent (chid , datatransfer .DataReceived , datatransfer .DataReceivedProgress , k , delta )
223
243
}
224
244
225
245
// PauseInitiator pauses the initator of this channel
@@ -304,7 +324,60 @@ func (c *Channels) HasChannel(chid datatransfer.ChannelID) (bool, error) {
304
324
return c .stateMachines .Has (chid )
305
325
}
306
326
327
+ // removeSeenCIDCaches cleans up the caches of "seen" blocks, ie
328
+ // blocks that have already been queued / sent / received
329
+ func (c * Channels ) removeSeenCIDCaches (chid datatransfer.ChannelID ) error {
330
+ progressStates := []datatransfer.EventCode {
331
+ datatransfer .DataQueuedProgress ,
332
+ datatransfer .DataSentProgress ,
333
+ datatransfer .DataReceivedProgress ,
334
+ }
335
+ for _ , evt := range progressStates {
336
+ sid := cidsets .SetID (chid .String () + "/" + datatransfer .Events [evt ])
337
+ err := c .seenCIDs .DeleteSet (sid )
338
+ if err != nil {
339
+ return err
340
+ }
341
+ }
342
+ return nil
343
+ }
344
+
345
+ // onProgress fires an event indicating progress has been made in
346
+ // queuing / sending / receiving blocks.
347
+ // These events are fired only for new blocks (not for example if
348
+ // a block is resent)
349
+ func (c * Channels ) fireProgressEvent (chid datatransfer.ChannelID , evt datatransfer.EventCode , progressEvt datatransfer.EventCode , k cid.Cid , delta uint64 ) error {
350
+ if err := c .checkChannelExists (chid , evt ); err != nil {
351
+ return err
352
+ }
353
+
354
+ // Check if the block has already been seen
355
+ sid := cidsets .SetID (chid .String () + "/" + datatransfer .Events [evt ])
356
+ seen , err := c .seenCIDs .InsertSetCID (sid , k )
357
+ if err != nil {
358
+ return err
359
+ }
360
+
361
+ // If the block has not been seen before, fire the progress event
362
+ if ! seen {
363
+ if err := c .stateMachines .Send (chid , progressEvt , delta ); err != nil {
364
+ return err
365
+ }
366
+ }
367
+
368
+ // Fire the regular event
369
+ return c .stateMachines .Send (chid , evt )
370
+ }
371
+
307
372
func (c * Channels ) send (chid datatransfer.ChannelID , code datatransfer.EventCode , args ... interface {}) error {
373
+ err := c .checkChannelExists (chid , code )
374
+ if err != nil {
375
+ return err
376
+ }
377
+ return c .stateMachines .Send (chid , code , args ... )
378
+ }
379
+
380
+ func (c * Channels ) checkChannelExists (chid datatransfer.ChannelID , code datatransfer.EventCode ) error {
308
381
has , err := c .stateMachines .Has (chid )
309
382
if err != nil {
310
383
return err
@@ -313,5 +386,5 @@ func (c *Channels) send(chid datatransfer.ChannelID, code datatransfer.EventCode
313
386
return xerrors .Errorf ("cannot send FSM event %s to data-transfer channel %s: %w" ,
314
387
datatransfer .Events [code ], chid , NewErrNotFound (chid ))
315
388
}
316
- return c . stateMachines . Send ( chid , code , args ... )
389
+ return nil
317
390
}
0 commit comments