diff --git a/swarm/storage/ldbstore.go b/swarm/storage/ldbstore.go index 25ea50213a..ab90a6708c 100644 --- a/swarm/storage/ldbstore.go +++ b/swarm/storage/ldbstore.go @@ -101,7 +101,7 @@ type garbage struct { count int // number of chunks deleted in running round target int // number of chunks to delete in running round batch *dbBatch // the delete batch - running bool + runC chan struct{} } type LDBStore struct { @@ -187,6 +187,8 @@ func NewLDBStore(params *LDBStoreParams) (s *LDBStore, err error) { maxRound: defaultMaxGCRound, ratio: defaultGCRatio, } + s.gc.runC = make(chan struct{}, 1) + s.gc.runC <- struct{}{} return s, nil } @@ -310,18 +312,13 @@ func decodeData(addr Address, data []byte) (*chunk, error) { func (s *LDBStore) collectGarbage() error { - // the running param prevents duplicate gc from starting when one is already running - s.lock.Lock() - if s.gc.running { - s.lock.Unlock() + // prevent duplicate gc from starting when one is already running + // runC contains a struct{} as long as we are NOT running + if len(s.gc.runC) == 0 { return nil } - s.gc.running = true - defer func() { - s.lock.Lock() - s.gc.running = false - s.lock.Unlock() - }() + <-s.gc.runC + s.lock.Lock() entryCnt := s.entryCnt s.lock.Unlock() @@ -370,6 +367,8 @@ func (s *LDBStore) collectGarbage() error { it.Release() log.Trace("garbage collect batch done", "batch", singleIterationCount, "total", s.gc.count) } + + s.gc.runC <- struct{}{} log.Debug("garbage collect done", "c", s.gc.count) metrics.GetOrRegisterCounter("ldbstore.collectgarbage.delete", nil).Inc(int64(totalDeleted)) diff --git a/swarm/storage/ldbstore_test.go b/swarm/storage/ldbstore_test.go index 454a246f65..e1a4d0bae1 100644 --- a/swarm/storage/ldbstore_test.go +++ b/swarm/storage/ldbstore_test.go @@ -19,7 +19,6 @@ package storage import ( "bytes" "context" - "errors" "fmt" "io/ioutil" "os" @@ -586,20 +585,25 @@ func TestLDBStoreCollectGarbageAccessUnlikeIndex(t *testing.T) { log.Info("ldbstore", "total", n, "missing", missing, "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt) } -func waitGc(ctx context.Context, ldb *LDBStore) error { - ticker := time.Tick(time.Millisecond * 100) - for { - select { - - case <-ctx.Done(): - return errors.New("timeout") - case <-ticker: - ldb.lock.Lock() - running := ldb.gc.running - ldb.lock.Unlock() - if !running { - return nil - } - } - } +func waitGc(ctx context.Context, ldb *LDBStore) { + <-ldb.gc.runC + ldb.gc.runC <- struct{}{} } + +//func waitGc(ctx context.Context, ldb *LDBStore) error { +// ticker := time.Tick(time.Millisecond * 100) +// for { +// select { +// +// case <-ctx.Done(): +// return errors.New("timeout") +// case <-ticker: +// ldb.lock.Lock() +// running := ldb.gc.running +// ldb.lock.Unlock() +// if !running { +// return nil +// } +// } +// } +//}