mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
swarm/storage/localstore: replace atomics with mutexes for gcSize and tests
This commit is contained in:
parent
25a068a048
commit
ca1e24f73e
5 changed files with 60 additions and 27 deletions
|
|
@ -17,7 +17,6 @@
|
||||||
package localstore
|
package localstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
@ -88,7 +87,7 @@ func (db *DB) collectGarbage() (collectedCount int64, done bool, err error) {
|
||||||
}
|
}
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
gcSize := atomic.LoadInt64(&db.gcSize)
|
gcSize := db.getGCSize()
|
||||||
if gcSize-collectedCount <= target {
|
if gcSize-collectedCount <= target {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +130,12 @@ func (db *DB) incGCSize(count int64) {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
new := atomic.AddInt64(&db.gcSize, count)
|
|
||||||
|
db.gcSizeMu.Lock()
|
||||||
|
new := db.gcSize + count
|
||||||
|
db.gcSize = new
|
||||||
|
db.gcSizeMu.Unlock()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case db.writeGCSizeTrigger <- struct{}{}:
|
case db.writeGCSizeTrigger <- struct{}{}:
|
||||||
default:
|
default:
|
||||||
|
|
@ -141,6 +145,15 @@ func (db *DB) incGCSize(count int64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getGCSize returns gcSize value by locking it
|
||||||
|
// with gcSizeMu mutex.
|
||||||
|
func (db *DB) getGCSize() (count int64) {
|
||||||
|
db.gcSizeMu.RLock()
|
||||||
|
count = db.gcSize
|
||||||
|
db.gcSizeMu.RUnlock()
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
// triggerGarbageCollection signals collectGarbageWorker
|
// triggerGarbageCollection signals collectGarbageWorker
|
||||||
// to call collectGarbage.
|
// to call collectGarbage.
|
||||||
func (db *DB) triggerGarbageCollection() {
|
func (db *DB) triggerGarbageCollection() {
|
||||||
|
|
@ -159,7 +172,7 @@ func (db *DB) writeGCSizeWorker() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-db.writeGCSizeTrigger:
|
case <-db.writeGCSizeTrigger:
|
||||||
err := db.writeGCSize(atomic.LoadInt64(&db.gcSize))
|
err := db.writeGCSize(db.getGCSize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("localstore write gc size", "err", err)
|
log.Error("localstore write gc size", "err", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"sync/atomic"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -89,25 +88,18 @@ func testDB_collectGarbageWorker(t *testing.T, db *DB) {
|
||||||
|
|
||||||
gcTarget := db.gcTarget()
|
gcTarget := db.gcTarget()
|
||||||
|
|
||||||
var totalCollectedCount int64
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case c := <-testHookCollectGarbageChan:
|
case <-testHookCollectGarbageChan:
|
||||||
totalCollectedCount += c
|
|
||||||
case <-time.After(10 * time.Second):
|
case <-time.After(10 * time.Second):
|
||||||
t.Error("collect garbage timeout")
|
t.Error("collect garbage timeout")
|
||||||
}
|
}
|
||||||
gcSize := atomic.LoadInt64(&db.gcSize)
|
gcSize := db.getGCSize()
|
||||||
if gcSize == gcTarget {
|
if gcSize == gcTarget {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wantTotalCollectedCount := int64(chunkCount) - gcTarget
|
|
||||||
if totalCollectedCount != wantTotalCollectedCount {
|
|
||||||
t.Errorf("total collected chunks %v, want %v", totalCollectedCount, wantTotalCollectedCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("pull index count", newItemsCountTest(db.pullIndex, int(gcTarget)))
|
t.Run("pull index count", newItemsCountTest(db.pullIndex, int(gcTarget)))
|
||||||
|
|
||||||
t.Run("gc index count", newItemsCountTest(db.gcIndex, int(gcTarget)))
|
t.Run("gc index count", newItemsCountTest(db.gcIndex, int(gcTarget)))
|
||||||
|
|
@ -200,7 +192,7 @@ func TestDB_collectGarbageWorker_withRequests(t *testing.T) {
|
||||||
case <-time.After(10 * time.Second):
|
case <-time.After(10 * time.Second):
|
||||||
t.Error("collect garbage timeout")
|
t.Error("collect garbage timeout")
|
||||||
}
|
}
|
||||||
gcSize := atomic.LoadInt64(&db.gcSize)
|
gcSize := db.getGCSize()
|
||||||
if gcSize == gcTarget {
|
if gcSize == gcTarget {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
@ -82,7 +81,10 @@ type DB struct {
|
||||||
gcUncountedHashesIndex shed.Index
|
gcUncountedHashesIndex shed.Index
|
||||||
|
|
||||||
// number of elements in garbage collection index
|
// number of elements in garbage collection index
|
||||||
|
// it must be always read by getGCSize and
|
||||||
|
// set with incGCSize which are locking gcSizeMu
|
||||||
gcSize int64
|
gcSize int64
|
||||||
|
gcSizeMu sync.RWMutex
|
||||||
// garbage collection is triggered when gcSize exceeds
|
// garbage collection is triggered when gcSize exceeds
|
||||||
// the capacity value
|
// the capacity value
|
||||||
capacity int64
|
capacity int64
|
||||||
|
|
@ -361,7 +363,7 @@ 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()
|
||||||
if err := db.writeGCSize(atomic.LoadInt64(&db.gcSize)); 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)
|
||||||
}
|
}
|
||||||
return db.shed.Close()
|
return db.shed.Close()
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -408,7 +407,7 @@ func newIndexGCSizeTest(db *DB) func(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
got := atomic.LoadInt64(&db.gcSize)
|
got := db.getGCSize()
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("got gc size %v, want %v", got, want)
|
t.Errorf("got gc size %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync/atomic"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -143,8 +143,12 @@ func TestDB_SubscribePull_since(t *testing.T) {
|
||||||
var wantedChunksCount int
|
var wantedChunksCount int
|
||||||
|
|
||||||
lastTimestamp := time.Now().UTC().UnixNano()
|
lastTimestamp := time.Now().UTC().UnixNano()
|
||||||
|
var lastTimestampMu sync.RWMutex
|
||||||
defer setNow(func() (t int64) {
|
defer setNow(func() (t int64) {
|
||||||
return atomic.AddInt64(&lastTimestamp, 1)
|
lastTimestampMu.Lock()
|
||||||
|
defer lastTimestampMu.Unlock()
|
||||||
|
lastTimestamp++
|
||||||
|
return lastTimestamp
|
||||||
})()
|
})()
|
||||||
|
|
||||||
uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
|
uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
|
||||||
|
|
@ -167,9 +171,13 @@ func TestDB_SubscribePull_since(t *testing.T) {
|
||||||
wantedChunksCount++
|
wantedChunksCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastTimestampMu.RLock()
|
||||||
|
storeTimestamp := lastTimestamp
|
||||||
|
lastTimestampMu.RUnlock()
|
||||||
|
|
||||||
last[bin] = ChunkDescriptor{
|
last[bin] = ChunkDescriptor{
|
||||||
Address: chunk.Address(),
|
Address: chunk.Address(),
|
||||||
StoreTimestamp: atomic.LoadInt64(&lastTimestamp),
|
StoreTimestamp: storeTimestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return last
|
return last
|
||||||
|
|
@ -222,8 +230,12 @@ func TestDB_SubscribePull_until(t *testing.T) {
|
||||||
var wantedChunksCount int
|
var wantedChunksCount int
|
||||||
|
|
||||||
lastTimestamp := time.Now().UTC().UnixNano()
|
lastTimestamp := time.Now().UTC().UnixNano()
|
||||||
|
var lastTimestampMu sync.RWMutex
|
||||||
defer setNow(func() (t int64) {
|
defer setNow(func() (t int64) {
|
||||||
return atomic.AddInt64(&lastTimestamp, 1)
|
lastTimestampMu.Lock()
|
||||||
|
defer lastTimestampMu.Unlock()
|
||||||
|
lastTimestamp++
|
||||||
|
return lastTimestamp
|
||||||
})()
|
})()
|
||||||
|
|
||||||
uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
|
uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
|
||||||
|
|
@ -246,9 +258,13 @@ func TestDB_SubscribePull_until(t *testing.T) {
|
||||||
wantedChunksCount++
|
wantedChunksCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastTimestampMu.RLock()
|
||||||
|
storeTimestamp := lastTimestamp
|
||||||
|
lastTimestampMu.RUnlock()
|
||||||
|
|
||||||
last[bin] = ChunkDescriptor{
|
last[bin] = ChunkDescriptor{
|
||||||
Address: chunk.Address(),
|
Address: chunk.Address(),
|
||||||
StoreTimestamp: atomic.LoadInt64(&lastTimestamp),
|
StoreTimestamp: storeTimestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return last
|
return last
|
||||||
|
|
@ -302,8 +318,12 @@ func TestDB_SubscribePull_sinceAndUntil(t *testing.T) {
|
||||||
var wantedChunksCount int
|
var wantedChunksCount int
|
||||||
|
|
||||||
lastTimestamp := time.Now().UTC().UnixNano()
|
lastTimestamp := time.Now().UTC().UnixNano()
|
||||||
|
var lastTimestampMu sync.RWMutex
|
||||||
defer setNow(func() (t int64) {
|
defer setNow(func() (t int64) {
|
||||||
return atomic.AddInt64(&lastTimestamp, 1)
|
lastTimestampMu.Lock()
|
||||||
|
defer lastTimestampMu.Unlock()
|
||||||
|
lastTimestamp++
|
||||||
|
return lastTimestamp
|
||||||
})()
|
})()
|
||||||
|
|
||||||
uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
|
uploadRandomChunks := func(count int, wanted bool) (last map[uint8]ChunkDescriptor) {
|
||||||
|
|
@ -326,9 +346,13 @@ func TestDB_SubscribePull_sinceAndUntil(t *testing.T) {
|
||||||
wantedChunksCount++
|
wantedChunksCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastTimestampMu.RLock()
|
||||||
|
storeTimestamp := lastTimestamp
|
||||||
|
lastTimestampMu.RUnlock()
|
||||||
|
|
||||||
last[bin] = ChunkDescriptor{
|
last[bin] = ChunkDescriptor{
|
||||||
Address: chunk.Address(),
|
Address: chunk.Address(),
|
||||||
StoreTimestamp: atomic.LoadInt64(&lastTimestamp),
|
StoreTimestamp: storeTimestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return last
|
return last
|
||||||
|
|
@ -410,6 +434,9 @@ func readPullSubscriptionBin(ctx context.Context, bin uint8, ch <-chan ChunkDesc
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
want := addrs[bin][i]
|
want := addrs[bin][i]
|
||||||
var err error
|
var err error
|
||||||
if !bytes.Equal(got.Address, want) {
|
if !bytes.Equal(got.Address, want) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue