-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First efficient ranged-export implementation by @frisst
This first commit contains the first and second implementation stabs (after primary review by @hsanjuan), using a stack for task buffering. Known issues: ctrl-c (context cancellation) results in the export code getting deadlocked. Duplicate blocks in exports. Duplicate block reads from store. Original commit messages: works works against mainnet and calibnet feat: add internal export api method - will hopfully make things faster by not streaming the export over the json rpc api polish: better file nameing fix: potential race in marking cids as seen chore: improve logging feat: front export with cache fix: give hector a good channel buffer on this shit docsgen
- Loading branch information
Showing
13 changed files
with
980 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package store | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"sync/atomic" | ||
|
||
lru "github.com/hashicorp/golang-lru" | ||
blocks "github.com/ipfs/go-block-format" | ||
"github.com/ipfs/go-cid" | ||
|
||
"github.com/filecoin-project/lotus/blockstore" | ||
) | ||
|
||
type CachingBlockstore struct { | ||
cache *lru.ARCCache | ||
blocks blockstore.Blockstore | ||
reads int64 // updated atomically | ||
hits int64 // updated atomically | ||
bytes int64 // updated atomically | ||
} | ||
|
||
func NewCachingBlockstore(blocks blockstore.Blockstore, cacheSize int) (*CachingBlockstore, error) { | ||
cache, err := lru.NewARC(cacheSize) | ||
if err != nil { | ||
return nil, fmt.Errorf("new arc: %w", err) | ||
} | ||
|
||
return &CachingBlockstore{ | ||
cache: cache, | ||
blocks: blocks, | ||
}, nil | ||
} | ||
|
||
func (cs *CachingBlockstore) DeleteBlock(ctx context.Context, c cid.Cid) error { | ||
return cs.blocks.DeleteBlock(ctx, c) | ||
} | ||
|
||
func (cs *CachingBlockstore) GetSize(ctx context.Context, c cid.Cid) (int, error) { | ||
return cs.blocks.GetSize(ctx, c) | ||
} | ||
|
||
func (cs *CachingBlockstore) Put(ctx context.Context, blk blocks.Block) error { | ||
return cs.blocks.Put(ctx, blk) | ||
} | ||
|
||
func (cs *CachingBlockstore) PutMany(ctx context.Context, blks []blocks.Block) error { | ||
return cs.blocks.PutMany(ctx, blks) | ||
} | ||
|
||
func (cs *CachingBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { | ||
return cs.blocks.AllKeysChan(ctx) | ||
} | ||
|
||
func (cs *CachingBlockstore) HashOnRead(enabled bool) { | ||
cs.blocks.HashOnRead(enabled) | ||
} | ||
|
||
func (cs *CachingBlockstore) DeleteMany(ctx context.Context, cids []cid.Cid) error { | ||
return cs.blocks.DeleteMany(ctx, cids) | ||
} | ||
|
||
func (cs *CachingBlockstore) Get(ctx context.Context, c cid.Cid) (blocks.Block, error) { | ||
reads := atomic.AddInt64(&cs.reads, 1) | ||
if reads%100000 == 0 { | ||
hits := atomic.LoadInt64(&cs.hits) | ||
by := atomic.LoadInt64(&cs.bytes) | ||
log.Infow("CachingBlockstore stats", "reads", reads, "cache_len", cs.cache.Len(), "hit_rate", float64(hits)/float64(reads), "bytes_read", by) | ||
} | ||
|
||
v, hit := cs.cache.Get(c) | ||
if hit { | ||
atomic.AddInt64(&cs.hits, 1) | ||
return v.(blocks.Block), nil | ||
} | ||
|
||
blk, err := cs.blocks.Get(ctx, c) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
atomic.AddInt64(&cs.bytes, int64(len(blk.RawData()))) | ||
cs.cache.Add(c, blk) | ||
return blk, err | ||
} | ||
|
||
func (cs *CachingBlockstore) View(ctx context.Context, c cid.Cid, callback func([]byte) error) error { | ||
reads := atomic.AddInt64(&cs.reads, 1) | ||
if reads%1000000 == 0 { | ||
hits := atomic.LoadInt64(&cs.hits) | ||
by := atomic.LoadInt64(&cs.bytes) | ||
log.Infow("CachingBlockstore stats", "reads", reads, "cache_len", cs.cache.Len(), "hit_rate", float64(hits)/float64(reads), "bytes_read", by) | ||
} | ||
v, hit := cs.cache.Get(c) | ||
if hit { | ||
atomic.AddInt64(&cs.hits, 1) | ||
return callback(v.(blocks.Block).RawData()) | ||
} | ||
|
||
blk, err := cs.blocks.Get(ctx, c) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
atomic.AddInt64(&cs.bytes, int64(len(blk.RawData()))) | ||
cs.cache.Add(c, blk) | ||
return callback(blk.RawData()) | ||
} | ||
|
||
func (cs *CachingBlockstore) Has(ctx context.Context, c cid.Cid) (bool, error) { | ||
atomic.AddInt64(&cs.reads, 1) | ||
// Safe to query cache since blockstore never deletes | ||
if cs.cache.Contains(c) { | ||
return true, nil | ||
} | ||
|
||
return cs.blocks.Has(ctx, c) | ||
} |
Oops, something went wrong.