Skip to content
This repository was archived by the owner on Aug 2, 2021. It is now read-only.

Commit 5169578

Browse files
committed
storage/localstore: cleanup and squash of GC changes
1 parent 4a2d7b0 commit 5169578

File tree

5 files changed

+89
-71
lines changed

5 files changed

+89
-71
lines changed

storage/localstore/gc.go

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/ethereum/go-ethereum/log"
2323
"github.com/ethereum/go-ethereum/metrics"
24+
"github.com/ethersphere/swarm/chunk"
2425
"github.com/ethersphere/swarm/shed"
2526
"github.com/syndtr/goleveldb/leveldb"
2627
)
@@ -40,6 +41,36 @@ var (
4041
gcBatchSize uint64 = 200
4142
)
4243

44+
type GCPolicy interface {
45+
GetEvictionMetric(addr chunk.Address) Fraction
46+
GetAdmissionMetric(addr chunk.Address) Fraction
47+
}
48+
49+
// based on https://hackmd.io/t-OQFK3mTsGfrpLCqDrdlw#Synced-chunks
50+
type DefaultGCPolicy struct {
51+
db *DB
52+
}
53+
54+
// based on https://hackmd.io/t-OQFK3mTsGfrpLCqDrdlw#Synced-chunks
55+
func (p *DefaultGCPolicy) GetEvictionMetric(addr chunk.Address) Fraction {
56+
item := addressToItem(addr)
57+
po := int(p.db.po(item.Address))
58+
responsibilityRadius := p.db.getResponsibilityRadius()
59+
60+
if po < responsibilityRadius {
61+
// More Distant Chunks
62+
n := uint64(responsibilityRadius - po)
63+
return Fraction{Numerator: n, Denominator: n + 1}
64+
}
65+
// Most Proximate Chunks
66+
return Fraction{Numerator: 1, Denominator: 3}
67+
}
68+
69+
// GetAdmissionMetric is currently not in use
70+
func (p *DefaultGCPolicy) GetAdmissionMetric(addr chunk.Address) Fraction {
71+
return Fraction{1, 1}
72+
}
73+
4374
// collectGarbageWorker is a long running function that waits for
4475
// collectGarbageTrigger channel to signal a garbage collection
4576
// run. GC run iterates on gcIndex and removes older items
@@ -96,7 +127,7 @@ func (db *DB) collectGarbage() (collectedCount uint64, done bool, err error) {
96127

97128
// run through the recently pinned chunks and
98129
// remove them from the gcIndex before iterating through gcIndex
99-
err = db.removeChunksInExcludeIndexFromGC()
130+
err = db.syncExcludeAndGCIndex()
100131
if err != nil {
101132
log.Error("localstore exclude pinned chunks", "err", err)
102133
return 0, true, err
@@ -148,8 +179,8 @@ func (db *DB) collectGarbage() (collectedCount uint64, done bool, err error) {
148179
return collectedCount, done, err
149180
}
150181

151-
// removeChunksInExcludeIndexFromGC removed any recently chunks in the exclude Index, from the gcIndex.
152-
func (db *DB) removeChunksInExcludeIndexFromGC() (err error) {
182+
// syncExcludeAndGCIndex removes any chunks in the exclude Index, from the gcIndex.
183+
func (db *DB) syncExcludeAndGCIndex() (err error) {
153184
metricName := "localstore/gc/exclude"
154185
metrics.GetOrRegisterCounter(metricName, nil).Inc(1)
155186
defer totalTimeMetric(metricName, time.Now())
@@ -275,20 +306,8 @@ func (db *DB) updateGCQuantiles() (err error) {
275306
}
276307
var newQuantiles quantiles
277308
for _, q := range gcQuantiles {
278-
item, position, found := gcQuantiles.Get(q.Fraction)
279-
if !found {
280-
continue
281-
}
282309
newPosition := quantilePosition(gcSize, q.Numerator, q.Denominator)
283-
diff := uint64Diff(position, newPosition)
284-
if diff == 0 {
285-
continue
286-
}
287-
newItem, err := db.gcIndex.Offset(&item, diff)
288-
if err != nil {
289-
return err
290-
}
291-
newQuantiles.Set(q.Fraction, newItem, newPosition)
310+
newQuantiles = newQuantiles.Set(q.Fraction, q.Item, newPosition)
292311
}
293312
return db.gcQuantiles.Put(newQuantiles)
294313
}

storage/localstore/gc_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,5 +578,4 @@ func TestUpdateGCQuantiles(t *testing.T) {
578578
defer db.Close()
579579

580580
db.collectGarbage()
581-
db.collectGarbage()
582581
}

storage/localstore/localstore.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ type DB struct {
8989
// pin files Index
9090
pinIndex shed.Index
9191

92+
gcPolicy GCPolicy
93+
9294
// field that stores number of intems in gc index
9395
gcSize shed.Uint64Field
9496

@@ -183,6 +185,7 @@ func New(path string, baseKey []byte, o *Options) (db *DB, err error) {
183185
collectGarbageWorkerDone: make(chan struct{}),
184186
putToGCCheck: o.PutToGCCheck,
185187
}
188+
db.gcPolicy = &DefaultGCPolicy{db}
186189
if db.capacity <= 0 {
187190
db.capacity = defaultCapacity
188191
}

storage/localstore/mode_set.go

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"errors"
2222
"fmt"
23+
"github.com/ethersphere/swarm/shed"
2324
"time"
2425

2526
"github.com/ethereum/go-ethereum/metrics"
@@ -201,7 +202,7 @@ func (db *DB) setSync(batch *leveldb.Batch, addr chunk.Address, mode chunk.ModeS
201202
// provided by the access function, and it is not
202203
// a property of a chunk provided to Accessor.Put.
203204

204-
i, err := db.retrievalDataIndex.Get(item)
205+
accessIndexItem, err := db.retrievalDataIndex.Get(item)
205206
if err != nil {
206207
if err == leveldb.ErrNotFound {
207208
// chunk is not found,
@@ -213,8 +214,8 @@ func (db *DB) setSync(batch *leveldb.Batch, addr chunk.Address, mode chunk.ModeS
213214
}
214215
return 0, err
215216
}
216-
item.StoreTimestamp = i.StoreTimestamp
217-
item.BinID = i.BinID
217+
item.StoreTimestamp = accessIndexItem.StoreTimestamp
218+
item.BinID = accessIndexItem.BinID
218219

219220
switch mode {
220221
case chunk.ModeSetSyncPull:
@@ -286,10 +287,10 @@ func (db *DB) setSync(batch *leveldb.Batch, addr chunk.Address, mode chunk.ModeS
286287
db.pushIndex.DeleteInBatch(batch, item)
287288
}
288289

289-
i, err = db.retrievalAccessIndex.Get(item)
290+
accessIndexItem, err = db.retrievalAccessIndex.Get(item)
290291
switch err {
291292
case nil:
292-
item.AccessTimestamp = i.AccessTimestamp
293+
item.AccessTimestamp = accessIndexItem.AccessTimestamp
293294
db.gcIndex.DeleteInBatch(batch, item)
294295
gcSizeChange--
295296
case leveldb.ErrNotFound:
@@ -306,50 +307,57 @@ func (db *DB) setSync(batch *leveldb.Batch, addr chunk.Address, mode chunk.ModeS
306307
return 0, err
307308
}
308309
if !pinned {
309-
// set access timestamp based on quantile calculated from
310-
// chunk proximity and db.responsibilityRadius
311-
f := chunkQuantileFraction(int(db.po(item.Address)), db.getResponsibilityRadius())
312-
gcSize, err := db.gcSize.Get()
310+
err := db.addToGC(batch, item, accessIndexItem)
313311
if err != nil {
314312
return 0, err
315313
}
316-
position := quantilePosition(gcSize, f.Numerator, f.Denominator)
317-
var gcQuantiles quantiles
318-
err = db.gcQuantiles.Get(&gcQuantiles)
319-
if err != nil && err != leveldb.ErrNotFound {
320-
return 0, err
314+
gcSizeChange++
315+
}
316+
317+
return gcSizeChange, nil
318+
}
319+
320+
func (db *DB) addToGC(batch *leveldb.Batch, item shed.Item, i shed.Item) error {
321+
// set access timestamp based on quantile calculated from
322+
// chunk proximity and db.responsibilityRadius
323+
f := db.gcPolicy.GetEvictionMetric(item.Address)
324+
gcSize, err := db.gcSize.Get()
325+
if err != nil {
326+
return err
327+
}
328+
position := quantilePosition(gcSize, f.Numerator, f.Denominator)
329+
var gcQuantiles quantiles
330+
err = db.gcQuantiles.Get(&gcQuantiles)
331+
if err != nil && err != leveldb.ErrNotFound {
332+
return err
333+
}
334+
var found bool
335+
for _, q := range gcQuantiles {
336+
if q.Fraction == f {
337+
item.AccessTimestamp = q.Item.AccessTimestamp + 1
338+
found = true
339+
break
321340
}
322-
var found bool
323-
for _, q := range gcQuantiles {
324-
if q.Fraction == f {
325-
item.AccessTimestamp = q.Item.AccessTimestamp + 1
326-
found = true
327-
break
328-
}
341+
}
342+
if len(gcQuantiles) > 0 && !found {
343+
var shift int64
344+
if closest := gcQuantiles.Closest(f); closest == nil {
345+
shift = int64(position)
346+
} else {
347+
shift = int64(closest.Position) - int64(position)
329348
}
330-
if len(gcQuantiles) > 0 && !found {
331-
var shift int64
332-
if closest := gcQuantiles.Closest(f); closest == nil {
333-
shift = int64(position)
334-
} else {
335-
shift = int64(closest.Position) - int64(position)
336-
}
337-
i, err = db.gcIndex.Offset(nil, shift)
338-
if err != nil {
339-
return 0, err
340-
}
349+
i, err = db.gcIndex.Offset(nil, shift)
350+
if err == nil {
341351
item.AccessTimestamp = i.AccessTimestamp + 1
342352
}
343-
gcQuantiles = gcQuantiles.Set(f, item, position)
344-
db.gcQuantiles.PutInBatch(batch, gcQuantiles)
345-
346-
db.retrievalAccessIndex.PutInBatch(batch, item)
347-
db.pushIndex.DeleteInBatch(batch, item)
348-
db.gcIndex.PutInBatch(batch, item)
349-
gcSizeChange++
350353
}
354+
gcQuantiles = gcQuantiles.Set(f, item, position)
355+
db.gcQuantiles.PutInBatch(batch, gcQuantiles)
351356

352-
return gcSizeChange, nil
357+
db.retrievalAccessIndex.PutInBatch(batch, item)
358+
db.pushIndex.DeleteInBatch(batch, item)
359+
db.gcIndex.PutInBatch(batch, item)
360+
return nil
353361
}
354362

355363
// setRemove removes the chunk by updating indexes:

storage/localstore/quantile.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,26 +66,15 @@ func (q quantiles) Set(f Fraction, item shed.Item, position uint64) quantiles {
6666
return q
6767
}
6868
}
69-
q = append(q, quantile{
69+
newQ := append(q, quantile{
7070
Fraction: f,
7171
Item: item,
7272
})
73-
sort.Sort(q)
74-
return q
73+
sort.Sort(newQ)
74+
return newQ
7575
}
7676

7777
func quantilePosition(total, numerator, denominator uint64) uint64 {
7878
return total / denominator * numerator
7979
}
8080

81-
// based on https://hackmd.io/t-OQFK3mTsGfrpLCqDrdlw#Synced-chunks
82-
// TODO: review and document exact quantiles for chunks
83-
func chunkQuantileFraction(po, responsibilityRadius int) Fraction {
84-
if po < responsibilityRadius {
85-
// More Distant Chunks
86-
n := uint64(responsibilityRadius - po)
87-
return Fraction{Numerator: n, Denominator: n + 1}
88-
}
89-
// Most Proximate Chunks
90-
return Fraction{Numerator: 1, Denominator: 3}
91-
}

0 commit comments

Comments
 (0)