swarm: Fix localstore test deadlock with race detector (#19153)
* swarm/storage/localstore: close localstore in two tests * swarm/storage/localstore: fix a possible deadlock in tests * swarm/storage/localstore: re-enable pull subs tests for travis race * swarm/storage/localstore: stop sending to errChan on context done in tests * swarm/storage/localstore: better want check in readPullSubscriptionBin * swarm/storage/localstore: protect chunk put with addr lock in tests * swamr/storage/localstore: wait for gc and writeGCSize workers on Close * swarm/storage/localstore: more correct testDB_collectGarbageWorker * swarm/storage/localstore: set DB Close timeout to 5s
This commit is contained in:
		
							parent
							
								
									d9adcd3a27
								
							
						
					
					
						commit
						02c28046a0
					
				@ -117,6 +117,8 @@ var (
 | 
				
			|||||||
// run. GC run iterates on gcIndex and removes older items
 | 
					// run. GC run iterates on gcIndex and removes older items
 | 
				
			||||||
// form retrieval and other indexes.
 | 
					// form retrieval and other indexes.
 | 
				
			||||||
func (db *DB) collectGarbageWorker() {
 | 
					func (db *DB) collectGarbageWorker() {
 | 
				
			||||||
 | 
						defer close(db.collectGarbageWorkerDone)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case <-db.collectGarbageTrigger:
 | 
							case <-db.collectGarbageTrigger:
 | 
				
			||||||
@ -132,7 +134,7 @@ func (db *DB) collectGarbageWorker() {
 | 
				
			|||||||
				db.triggerGarbageCollection()
 | 
									db.triggerGarbageCollection()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if testHookCollectGarbage != nil {
 | 
								if collectedCount > 0 && testHookCollectGarbage != nil {
 | 
				
			||||||
				testHookCollectGarbage(collectedCount)
 | 
									testHookCollectGarbage(collectedCount)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case <-db.close:
 | 
							case <-db.close:
 | 
				
			||||||
@ -243,6 +245,8 @@ func (db *DB) triggerGarbageCollection() {
 | 
				
			|||||||
// writeGCSizeDelay duration to avoid very frequent
 | 
					// writeGCSizeDelay duration to avoid very frequent
 | 
				
			||||||
// database operations.
 | 
					// database operations.
 | 
				
			||||||
func (db *DB) writeGCSizeWorker() {
 | 
					func (db *DB) writeGCSizeWorker() {
 | 
				
			||||||
 | 
						defer close(db.writeGCSizeWorkerDone)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case <-db.writeGCSizeTrigger:
 | 
							case <-db.writeGCSizeTrigger:
 | 
				
			||||||
 | 
				
			|||||||
@ -118,15 +118,6 @@ func testDB_collectGarbageWorker(t *testing.T) {
 | 
				
			|||||||
			t.Fatal(err)
 | 
								t.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// cleanup: drain the last testHookCollectGarbageChan
 | 
					 | 
				
			||||||
	// element before calling deferred functions not to block
 | 
					 | 
				
			||||||
	// collectGarbageWorker loop, preventing the race in
 | 
					 | 
				
			||||||
	// setting testHookCollectGarbage function
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-testHookCollectGarbageChan:
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TestDB_collectGarbageWorker_withRequests is a helper test function
 | 
					// TestDB_collectGarbageWorker_withRequests is a helper test function
 | 
				
			||||||
@ -290,6 +281,7 @@ func TestDB_gcSize(t *testing.T) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						defer db.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.Run("gc index size", newIndexGCSizeTest(db))
 | 
						t.Run("gc index size", newIndexGCSizeTest(db))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -107,6 +107,12 @@ type DB struct {
 | 
				
			|||||||
	// this channel is closed when close function is called
 | 
						// this channel is closed when close function is called
 | 
				
			||||||
	// to terminate other goroutines
 | 
						// to terminate other goroutines
 | 
				
			||||||
	close chan struct{}
 | 
						close chan struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// protect Close method from exiting before
 | 
				
			||||||
 | 
						// garbage collection and gc size write workers
 | 
				
			||||||
 | 
						// are done
 | 
				
			||||||
 | 
						collectGarbageWorkerDone chan struct{}
 | 
				
			||||||
 | 
						writeGCSizeWorkerDone    chan struct{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options struct holds optional parameters for configuring DB.
 | 
					// Options struct holds optional parameters for configuring DB.
 | 
				
			||||||
@ -141,6 +147,8 @@ func New(path string, baseKey []byte, o *Options) (db *DB, err error) {
 | 
				
			|||||||
		collectGarbageTrigger:    make(chan struct{}, 1),
 | 
							collectGarbageTrigger:    make(chan struct{}, 1),
 | 
				
			||||||
		writeGCSizeTrigger:       make(chan struct{}, 1),
 | 
							writeGCSizeTrigger:       make(chan struct{}, 1),
 | 
				
			||||||
		close:                    make(chan struct{}),
 | 
							close:                    make(chan struct{}),
 | 
				
			||||||
 | 
							collectGarbageWorkerDone: make(chan struct{}),
 | 
				
			||||||
 | 
							writeGCSizeWorkerDone:    make(chan struct{}),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if db.capacity <= 0 {
 | 
						if db.capacity <= 0 {
 | 
				
			||||||
		db.capacity = defaultCapacity
 | 
							db.capacity = defaultCapacity
 | 
				
			||||||
@ -361,6 +369,21 @@ func New(path string, baseKey []byte, o *Options) (db *DB, err error) {
 | 
				
			|||||||
func (db *DB) Close() (err error) {
 | 
					func (db *DB) Close() (err error) {
 | 
				
			||||||
	close(db.close)
 | 
						close(db.close)
 | 
				
			||||||
	db.updateGCWG.Wait()
 | 
						db.updateGCWG.Wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// wait for gc worker and gc size write workers to
 | 
				
			||||||
 | 
						// return before closing the shed
 | 
				
			||||||
 | 
						timeout := time.After(5 * time.Second)
 | 
				
			||||||
 | 
						select {
 | 
				
			||||||
 | 
						case <-db.collectGarbageWorkerDone:
 | 
				
			||||||
 | 
						case <-timeout:
 | 
				
			||||||
 | 
							log.Error("localstore: collect garbage worker did not return after db close")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						select {
 | 
				
			||||||
 | 
						case <-db.writeGCSizeWorkerDone:
 | 
				
			||||||
 | 
						case <-timeout:
 | 
				
			||||||
 | 
							log.Error("localstore: write gc size worker did not return after db close")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := db.writeGCSize(db.getGCSize()); err != nil {
 | 
						if err := db.writeGCSize(db.getGCSize()); err != nil {
 | 
				
			||||||
		log.Error("localstore: write gc size", "err", err)
 | 
							log.Error("localstore: write gc size", "err", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -163,6 +163,7 @@ func BenchmarkNew(b *testing.B) {
 | 
				
			|||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				b.Fatal(err)
 | 
									b.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								defer db.Close()
 | 
				
			||||||
			uploader := db.NewPutter(ModePutUpload)
 | 
								uploader := db.NewPutter(ModePutUpload)
 | 
				
			||||||
			syncer := db.NewSetter(ModeSetSync)
 | 
								syncer := db.NewSetter(ModeSetSync)
 | 
				
			||||||
			for i := 0; i < count; i++ {
 | 
								for i := 0; i < count; i++ {
 | 
				
			||||||
 | 
				
			|||||||
@ -20,13 +20,11 @@ import (
 | 
				
			|||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/swarm/storage"
 | 
						"github.com/ethereum/go-ethereum/swarm/storage"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/swarm/testutil"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TestDB_SubscribePull uploads some chunks before and after
 | 
					// TestDB_SubscribePull uploads some chunks before and after
 | 
				
			||||||
@ -34,12 +32,6 @@ import (
 | 
				
			|||||||
// all addresses are received in the right order
 | 
					// all addresses are received in the right order
 | 
				
			||||||
// for expected proximity order bins.
 | 
					// for expected proximity order bins.
 | 
				
			||||||
func TestDB_SubscribePull(t *testing.T) {
 | 
					func TestDB_SubscribePull(t *testing.T) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if testutil.RaceEnabled && os.Getenv("TRAVIS") == "true" {
 | 
					 | 
				
			||||||
		t.Skip("does not complete with -race on Travis")
 | 
					 | 
				
			||||||
		// Note: related ticket TODO
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	db, cleanupFunc := newTestDB(t, nil)
 | 
						db, cleanupFunc := newTestDB(t, nil)
 | 
				
			||||||
	defer cleanupFunc()
 | 
						defer cleanupFunc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -87,12 +79,6 @@ func TestDB_SubscribePull(t *testing.T) {
 | 
				
			|||||||
// validates if all addresses are received in the right order
 | 
					// validates if all addresses are received in the right order
 | 
				
			||||||
// for expected proximity order bins.
 | 
					// for expected proximity order bins.
 | 
				
			||||||
func TestDB_SubscribePull_multiple(t *testing.T) {
 | 
					func TestDB_SubscribePull_multiple(t *testing.T) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if testutil.RaceEnabled && os.Getenv("TRAVIS") == "true" {
 | 
					 | 
				
			||||||
		t.Skip("does not complete with -race on Travis")
 | 
					 | 
				
			||||||
		// Note: related ticket TODO
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	db, cleanupFunc := newTestDB(t, nil)
 | 
						db, cleanupFunc := newTestDB(t, nil)
 | 
				
			||||||
	defer cleanupFunc()
 | 
						defer cleanupFunc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -146,12 +132,6 @@ func TestDB_SubscribePull_multiple(t *testing.T) {
 | 
				
			|||||||
// and validates if all expected addresses are received in the
 | 
					// and validates if all expected addresses are received in the
 | 
				
			||||||
// right order for expected proximity order bins.
 | 
					// right order for expected proximity order bins.
 | 
				
			||||||
func TestDB_SubscribePull_since(t *testing.T) {
 | 
					func TestDB_SubscribePull_since(t *testing.T) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if testutil.RaceEnabled && os.Getenv("TRAVIS") == "true" {
 | 
					 | 
				
			||||||
		t.Skip("does not complete with -race on Travis")
 | 
					 | 
				
			||||||
		// Note: related ticket TODO
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	db, cleanupFunc := newTestDB(t, nil)
 | 
						db, cleanupFunc := newTestDB(t, nil)
 | 
				
			||||||
	defer cleanupFunc()
 | 
						defer cleanupFunc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -171,6 +151,9 @@ func TestDB_SubscribePull_since(t *testing.T) {
 | 
				
			|||||||
	})()
 | 
						})()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
 | 
						uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
 | 
				
			||||||
 | 
							addrsMu.Lock()
 | 
				
			||||||
 | 
							defer addrsMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		last = make(map[uint8]ChunkDescriptor)
 | 
							last = make(map[uint8]ChunkDescriptor)
 | 
				
			||||||
		for i := 0; i < count; i++ {
 | 
							for i := 0; i < count; i++ {
 | 
				
			||||||
			chunk := generateRandomChunk()
 | 
								chunk := generateRandomChunk()
 | 
				
			||||||
@ -182,7 +165,6 @@ func TestDB_SubscribePull_since(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			bin := db.po(chunk.Address())
 | 
								bin := db.po(chunk.Address())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			addrsMu.Lock()
 | 
					 | 
				
			||||||
			if _, ok := addrs[bin]; !ok {
 | 
								if _, ok := addrs[bin]; !ok {
 | 
				
			||||||
				addrs[bin] = make([]storage.Address, 0)
 | 
									addrs[bin] = make([]storage.Address, 0)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -190,7 +172,6 @@ func TestDB_SubscribePull_since(t *testing.T) {
 | 
				
			|||||||
				addrs[bin] = append(addrs[bin], chunk.Address())
 | 
									addrs[bin] = append(addrs[bin], chunk.Address())
 | 
				
			||||||
				wantedChunksCount++
 | 
									wantedChunksCount++
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			addrsMu.Unlock()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			lastTimestampMu.RLock()
 | 
								lastTimestampMu.RLock()
 | 
				
			||||||
			storeTimestamp := lastTimestamp
 | 
								storeTimestamp := lastTimestamp
 | 
				
			||||||
@ -242,12 +223,6 @@ func TestDB_SubscribePull_since(t *testing.T) {
 | 
				
			|||||||
// and validates if all expected addresses are received in the
 | 
					// and validates if all expected addresses are received in the
 | 
				
			||||||
// right order for expected proximity order bins.
 | 
					// right order for expected proximity order bins.
 | 
				
			||||||
func TestDB_SubscribePull_until(t *testing.T) {
 | 
					func TestDB_SubscribePull_until(t *testing.T) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if testutil.RaceEnabled && os.Getenv("TRAVIS") == "true" {
 | 
					 | 
				
			||||||
		t.Skip("does not complete with -race on Travis")
 | 
					 | 
				
			||||||
		// Note: related ticket TODO
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	db, cleanupFunc := newTestDB(t, nil)
 | 
						db, cleanupFunc := newTestDB(t, nil)
 | 
				
			||||||
	defer cleanupFunc()
 | 
						defer cleanupFunc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -267,6 +242,9 @@ func TestDB_SubscribePull_until(t *testing.T) {
 | 
				
			|||||||
	})()
 | 
						})()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
 | 
						uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
 | 
				
			||||||
 | 
							addrsMu.Lock()
 | 
				
			||||||
 | 
							defer addrsMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		last = make(map[uint8]ChunkDescriptor)
 | 
							last = make(map[uint8]ChunkDescriptor)
 | 
				
			||||||
		for i := 0; i < count; i++ {
 | 
							for i := 0; i < count; i++ {
 | 
				
			||||||
			chunk := generateRandomChunk()
 | 
								chunk := generateRandomChunk()
 | 
				
			||||||
@ -278,7 +256,6 @@ func TestDB_SubscribePull_until(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			bin := db.po(chunk.Address())
 | 
								bin := db.po(chunk.Address())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			addrsMu.Lock()
 | 
					 | 
				
			||||||
			if _, ok := addrs[bin]; !ok {
 | 
								if _, ok := addrs[bin]; !ok {
 | 
				
			||||||
				addrs[bin] = make([]storage.Address, 0)
 | 
									addrs[bin] = make([]storage.Address, 0)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -286,7 +263,6 @@ func TestDB_SubscribePull_until(t *testing.T) {
 | 
				
			|||||||
				addrs[bin] = append(addrs[bin], chunk.Address())
 | 
									addrs[bin] = append(addrs[bin], chunk.Address())
 | 
				
			||||||
				wantedChunksCount++
 | 
									wantedChunksCount++
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			addrsMu.Unlock()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			lastTimestampMu.RLock()
 | 
								lastTimestampMu.RLock()
 | 
				
			||||||
			storeTimestamp := lastTimestamp
 | 
								storeTimestamp := lastTimestamp
 | 
				
			||||||
@ -337,12 +313,6 @@ func TestDB_SubscribePull_until(t *testing.T) {
 | 
				
			|||||||
// and until arguments, and validates if all expected addresses
 | 
					// and until arguments, and validates if all expected addresses
 | 
				
			||||||
// are received in the right order for expected proximity order bins.
 | 
					// are received in the right order for expected proximity order bins.
 | 
				
			||||||
func TestDB_SubscribePull_sinceAndUntil(t *testing.T) {
 | 
					func TestDB_SubscribePull_sinceAndUntil(t *testing.T) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if testutil.RaceEnabled && os.Getenv("TRAVIS") == "true" {
 | 
					 | 
				
			||||||
		t.Skip("does not complete with -race on Travis")
 | 
					 | 
				
			||||||
		// Note: related ticket TODO
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	db, cleanupFunc := newTestDB(t, nil)
 | 
						db, cleanupFunc := newTestDB(t, nil)
 | 
				
			||||||
	defer cleanupFunc()
 | 
						defer cleanupFunc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -362,6 +332,9 @@ func TestDB_SubscribePull_sinceAndUntil(t *testing.T) {
 | 
				
			|||||||
	})()
 | 
						})()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
 | 
						uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
 | 
				
			||||||
 | 
							addrsMu.Lock()
 | 
				
			||||||
 | 
							defer addrsMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		last = make(map[uint8]ChunkDescriptor)
 | 
							last = make(map[uint8]ChunkDescriptor)
 | 
				
			||||||
		for i := 0; i < count; i++ {
 | 
							for i := 0; i < count; i++ {
 | 
				
			||||||
			chunk := generateRandomChunk()
 | 
								chunk := generateRandomChunk()
 | 
				
			||||||
@ -373,7 +346,6 @@ func TestDB_SubscribePull_sinceAndUntil(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			bin := db.po(chunk.Address())
 | 
								bin := db.po(chunk.Address())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			addrsMu.Lock()
 | 
					 | 
				
			||||||
			if _, ok := addrs[bin]; !ok {
 | 
								if _, ok := addrs[bin]; !ok {
 | 
				
			||||||
				addrs[bin] = make([]storage.Address, 0)
 | 
									addrs[bin] = make([]storage.Address, 0)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -381,7 +353,6 @@ func TestDB_SubscribePull_sinceAndUntil(t *testing.T) {
 | 
				
			|||||||
				addrs[bin] = append(addrs[bin], chunk.Address())
 | 
									addrs[bin] = append(addrs[bin], chunk.Address())
 | 
				
			||||||
				wantedChunksCount++
 | 
									wantedChunksCount++
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			addrsMu.Unlock()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			lastTimestampMu.RLock()
 | 
								lastTimestampMu.RLock()
 | 
				
			||||||
			storeTimestamp := lastTimestamp
 | 
								storeTimestamp := lastTimestamp
 | 
				
			||||||
@ -442,6 +413,9 @@ func TestDB_SubscribePull_sinceAndUntil(t *testing.T) {
 | 
				
			|||||||
// uploadRandomChunksBin uploads random chunks to database and adds them to
 | 
					// uploadRandomChunksBin uploads random chunks to database and adds them to
 | 
				
			||||||
// the map of addresses ber bin.
 | 
					// the map of addresses ber bin.
 | 
				
			||||||
func uploadRandomChunksBin(t *testing.T, db *DB, uploader *Putter, addrs map[uint8][]storage.Address, addrsMu *sync.Mutex, wantedChunksCount *int, count int) {
 | 
					func uploadRandomChunksBin(t *testing.T, db *DB, uploader *Putter, addrs map[uint8][]storage.Address, addrsMu *sync.Mutex, wantedChunksCount *int, count int) {
 | 
				
			||||||
 | 
						addrsMu.Lock()
 | 
				
			||||||
 | 
						defer addrsMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < count; i++ {
 | 
						for i := 0; i < count; i++ {
 | 
				
			||||||
		chunk := generateRandomChunk()
 | 
							chunk := generateRandomChunk()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -450,13 +424,11 @@ func uploadRandomChunksBin(t *testing.T, db *DB, uploader *Putter, addrs map[uin
 | 
				
			|||||||
			t.Fatal(err)
 | 
								t.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		addrsMu.Lock()
 | 
					 | 
				
			||||||
		bin := db.po(chunk.Address())
 | 
							bin := db.po(chunk.Address())
 | 
				
			||||||
		if _, ok := addrs[bin]; !ok {
 | 
							if _, ok := addrs[bin]; !ok {
 | 
				
			||||||
			addrs[bin] = make([]storage.Address, 0)
 | 
								addrs[bin] = make([]storage.Address, 0)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		addrs[bin] = append(addrs[bin], chunk.Address())
 | 
							addrs[bin] = append(addrs[bin], chunk.Address())
 | 
				
			||||||
		addrsMu.Unlock()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		*wantedChunksCount++
 | 
							*wantedChunksCount++
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -473,19 +445,24 @@ func readPullSubscriptionBin(ctx context.Context, bin uint8, ch <-chan ChunkDesc
 | 
				
			|||||||
			if !ok {
 | 
								if !ok {
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								var err error
 | 
				
			||||||
			addrsMu.Lock()
 | 
								addrsMu.Lock()
 | 
				
			||||||
			if i+1 > len(addrs[bin]) {
 | 
								if i+1 > len(addrs[bin]) {
 | 
				
			||||||
				errChan <- fmt.Errorf("got more chunk addresses %v, then expected %v, for bin %v", i+1, len(addrs[bin]), bin)
 | 
									err = fmt.Errorf("got more chunk addresses %v, then expected %v, for bin %v", i+1, len(addrs[bin]), bin)
 | 
				
			||||||
			}
 | 
								} else {
 | 
				
			||||||
				want := addrs[bin][i]
 | 
									want := addrs[bin][i]
 | 
				
			||||||
			addrsMu.Unlock()
 | 
					 | 
				
			||||||
			var err error
 | 
					 | 
				
			||||||
				if !bytes.Equal(got.Address, want) {
 | 
									if !bytes.Equal(got.Address, want) {
 | 
				
			||||||
					err = fmt.Errorf("got chunk address %v in bin %v %s, want %s", i, bin, got.Address.Hex(), want)
 | 
										err = fmt.Errorf("got chunk address %v in bin %v %s, want %s", i, bin, got.Address.Hex(), want)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								addrsMu.Unlock()
 | 
				
			||||||
			i++
 | 
								i++
 | 
				
			||||||
			// send one and only one error per received address
 | 
								// send one and only one error per received address
 | 
				
			||||||
			errChan <- err
 | 
								select {
 | 
				
			||||||
 | 
								case errChan <- err:
 | 
				
			||||||
 | 
								case <-ctx.Done():
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		case <-ctx.Done():
 | 
							case <-ctx.Done():
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -40,6 +40,9 @@ func TestDB_SubscribePush(t *testing.T) {
 | 
				
			|||||||
	var chunksMu sync.Mutex
 | 
						var chunksMu sync.Mutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uploadRandomChunks := func(count int) {
 | 
						uploadRandomChunks := func(count int) {
 | 
				
			||||||
 | 
							chunksMu.Lock()
 | 
				
			||||||
 | 
							defer chunksMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for i := 0; i < count; i++ {
 | 
							for i := 0; i < count; i++ {
 | 
				
			||||||
			chunk := generateRandomChunk()
 | 
								chunk := generateRandomChunk()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,9 +51,7 @@ func TestDB_SubscribePush(t *testing.T) {
 | 
				
			|||||||
				t.Fatal(err)
 | 
									t.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			chunksMu.Lock()
 | 
					 | 
				
			||||||
			chunks = append(chunks, chunk)
 | 
								chunks = append(chunks, chunk)
 | 
				
			||||||
			chunksMu.Unlock()
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -90,7 +91,11 @@ func TestDB_SubscribePush(t *testing.T) {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				i++
 | 
									i++
 | 
				
			||||||
				// send one and only one error per received address
 | 
									// send one and only one error per received address
 | 
				
			||||||
				errChan <- err
 | 
									select {
 | 
				
			||||||
 | 
									case errChan <- err:
 | 
				
			||||||
 | 
									case <-ctx.Done():
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			case <-ctx.Done():
 | 
								case <-ctx.Done():
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -123,6 +128,9 @@ func TestDB_SubscribePush_multiple(t *testing.T) {
 | 
				
			|||||||
	var addrsMu sync.Mutex
 | 
						var addrsMu sync.Mutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uploadRandomChunks := func(count int) {
 | 
						uploadRandomChunks := func(count int) {
 | 
				
			||||||
 | 
							addrsMu.Lock()
 | 
				
			||||||
 | 
							defer addrsMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for i := 0; i < count; i++ {
 | 
							for i := 0; i < count; i++ {
 | 
				
			||||||
			chunk := generateRandomChunk()
 | 
								chunk := generateRandomChunk()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -131,9 +139,7 @@ func TestDB_SubscribePush_multiple(t *testing.T) {
 | 
				
			|||||||
				t.Fatal(err)
 | 
									t.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			addrsMu.Lock()
 | 
					 | 
				
			||||||
			addrs = append(addrs, chunk.Address())
 | 
								addrs = append(addrs, chunk.Address())
 | 
				
			||||||
			addrsMu.Unlock()
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -175,7 +181,11 @@ func TestDB_SubscribePush_multiple(t *testing.T) {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
					i++
 | 
										i++
 | 
				
			||||||
					// send one and only one error per received address
 | 
										// send one and only one error per received address
 | 
				
			||||||
					errChan <- err
 | 
										select {
 | 
				
			||||||
 | 
										case errChan <- err:
 | 
				
			||||||
 | 
										case <-ctx.Done():
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				case <-ctx.Done():
 | 
									case <-ctx.Done():
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user