Unverified Commit 30263ad3 authored by Anton Evangelatov's avatar Anton Evangelatov Committed by GitHub

swarm/storage: set false, only when we get a chunk back (#19599)

parent f2612ac9
...@@ -93,10 +93,6 @@ func (s *SwarmSyncerServer) SessionIndex() (uint64, error) { ...@@ -93,10 +93,6 @@ func (s *SwarmSyncerServer) SessionIndex() (uint64, error) {
// are added in batchTimeout period, the batch will be returned. This function // are added in batchTimeout period, the batch will be returned. This function
// will block until new chunks are received from localstore pull subscription. // will block until new chunks are received from localstore pull subscription.
func (s *SwarmSyncerServer) SetNextBatch(from, to uint64) ([]byte, uint64, uint64, *HandoverProof, error) { func (s *SwarmSyncerServer) SetNextBatch(from, to uint64) ([]byte, uint64, uint64, *HandoverProof, error) {
//TODO: maybe add unit test for intervals usage in netstore/localstore together with SwarmSyncerServer?
if from > 0 {
from--
}
batchStart := time.Now() batchStart := time.Now()
descriptors, stop := s.netStore.SubscribePull(context.Background(), s.po, from, to) descriptors, stop := s.netStore.SubscribePull(context.Background(), s.po, from, to)
defer stop() defer stop()
......
...@@ -31,9 +31,9 @@ import ( ...@@ -31,9 +31,9 @@ import (
// SubscribePull returns a channel that provides chunk addresses and stored times from pull syncing index. // SubscribePull returns a channel that provides chunk addresses and stored times from pull syncing index.
// Pull syncing index can be only subscribed to a particular proximity order bin. If since // Pull syncing index can be only subscribed to a particular proximity order bin. If since
// is not 0, the iteration will start from the first item stored after that id. If until is not 0, // is not 0, the iteration will start from the since item (the item with binID == since). If until is not 0,
// only chunks stored up to this id will be sent to the channel, and the returned channel will be // only chunks stored up to this id will be sent to the channel, and the returned channel will be
// closed. The since-until interval is open on since side, and closed on until side: (since,until] <=> [since+1,until]. Returned stop // closed. The since-until interval is closed on since side, and closed on until side: [since,until]. Returned stop
// function will terminate current and further iterations without errors, and also close the returned channel. // function will terminate current and further iterations without errors, and also close the returned channel.
// Make sure that you check the second returned parameter from the channel to stop iteration when its value // Make sure that you check the second returned parameter from the channel to stop iteration when its value
// is false. // is false.
...@@ -135,7 +135,9 @@ func (db *DB) SubscribePull(ctx context.Context, bin uint8, since, until uint64) ...@@ -135,7 +135,9 @@ func (db *DB) SubscribePull(ctx context.Context, bin uint8, since, until uint64)
log.Error("localstore pull subscription iteration", "bin", bin, "since", since, "until", until, "err", err) log.Error("localstore pull subscription iteration", "bin", bin, "since", since, "until", until, "err", err)
return return
} }
first = false if count > 0 {
first = false
}
case <-stopChan: case <-stopChan:
// terminate the subscription // terminate the subscription
// on stop // on stop
......
...@@ -28,6 +28,55 @@ import ( ...@@ -28,6 +28,55 @@ import (
"github.com/ethereum/go-ethereum/swarm/shed" "github.com/ethereum/go-ethereum/swarm/shed"
) )
// TestDB_SubscribePull_first is a regression test for the first=false (from-1) bug
// The bug was that `first=false` was not behind an if-condition `if count > 0`. This resulted in chunks being missed, when
// the subscription is established before the chunk is actually uploaded. For example if a subscription is established with since=49,
// which means that the `SubscribePull` method should return chunk with BinID=49 via the channel, and the chunk for BinID=49 is uploaded,
// after the subscription, then it would have been skipped, where the correct behaviour is to not skip it and return it via the channel.
func TestDB_SubscribePull_first(t *testing.T) {
db, cleanupFunc := newTestDB(t, nil)
defer cleanupFunc()
addrs := make(map[uint8][]chunk.Address)
var addrsMu sync.Mutex
var wantedChunksCount int
// prepopulate database with some chunks
// before the subscription
uploadRandomChunksBin(t, db, addrs, &addrsMu, &wantedChunksCount, 100)
// any bin should do the trick
bin := uint8(1)
chunksInGivenBin := uint64(len(addrs[bin]))
errc := make(chan error)
since := chunksInGivenBin + 1
go func() {
ch, stop := db.SubscribePull(context.TODO(), bin, since, 0)
defer stop()
chnk := <-ch
if chnk.BinID != since {
errc <- fmt.Errorf("expected chunk.BinID to be %v , but got %v", since, chnk.BinID)
} else {
errc <- nil
}
}()
time.Sleep(100 * time.Millisecond)
uploadRandomChunksBin(t, db, addrs, &addrsMu, &wantedChunksCount, 100)
err := <-errc
if err != nil {
t.Fatal(err)
}
}
// TestDB_SubscribePull uploads some chunks before and after // TestDB_SubscribePull uploads some chunks before and after
// pull syncing subscription is created and validates if // pull syncing subscription is created and validates if
// all addresses are received in the right order // all addresses are received in the right order
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment