114 lines
2.7 KiB
Go
114 lines
2.7 KiB
Go
package blockstore
|
|
|
|
import (
|
|
"context"
|
|
|
|
blocks "github.com/ipfs/go-block-format"
|
|
"github.com/ipfs/go-cid"
|
|
)
|
|
|
|
// BlockstoreCache is a cache for blocks, compatible with lru.Cache; Must be safe for concurrent access
|
|
type BlockstoreCache interface {
|
|
Remove(mhString MhString) bool
|
|
Contains(mhString MhString) bool
|
|
Get(mhString MhString) (blocks.Block, bool)
|
|
Add(mhString MhString, block blocks.Block) (evicted bool)
|
|
}
|
|
|
|
type ReadCachedBlockstore struct {
|
|
top Blockstore
|
|
cache BlockstoreCache
|
|
}
|
|
|
|
type MhString string
|
|
|
|
func NewReadCachedBlockstore(top Blockstore, cache BlockstoreCache) *ReadCachedBlockstore {
|
|
return &ReadCachedBlockstore{
|
|
top: top,
|
|
cache: cache,
|
|
}
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) DeleteBlock(ctx context.Context, cid cid.Cid) error {
|
|
c.cache.Remove(MhString(cid.Hash()))
|
|
return c.top.DeleteBlock(ctx, cid)
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) Has(ctx context.Context, cid cid.Cid) (bool, error) {
|
|
if c.cache.Contains(MhString(cid.Hash())) {
|
|
return true, nil
|
|
}
|
|
|
|
return c.top.Has(ctx, cid)
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) {
|
|
if out, ok := c.cache.Get(MhString(cid.Hash())); ok {
|
|
return out, nil
|
|
}
|
|
|
|
out, err := c.top.Get(ctx, cid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c.cache.Add(MhString(cid.Hash()), out)
|
|
return out, nil
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
|
|
if b, ok := c.cache.Get(MhString(cid.Hash())); ok {
|
|
return len(b.RawData()), nil
|
|
}
|
|
|
|
return c.top.GetSize(ctx, cid)
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) Put(ctx context.Context, block blocks.Block) error {
|
|
c.cache.Add(MhString(block.Cid().Hash()), block)
|
|
return c.top.Put(ctx, block)
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) PutMany(ctx context.Context, blocks []blocks.Block) error {
|
|
for _, b := range blocks {
|
|
c.cache.Add(MhString(b.Cid().Hash()), b)
|
|
}
|
|
|
|
return c.top.PutMany(ctx, blocks)
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
|
return c.top.AllKeysChan(ctx)
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) HashOnRead(enabled bool) {
|
|
c.top.HashOnRead(enabled)
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) View(ctx context.Context, cid cid.Cid, callback func([]byte) error) error {
|
|
return c.top.View(ctx, cid, func(bb []byte) error {
|
|
blk, err := blocks.NewBlockWithCid(bb, cid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c.cache.Add(MhString(cid.Hash()), blk)
|
|
|
|
return callback(bb)
|
|
})
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) DeleteMany(ctx context.Context, cids []cid.Cid) error {
|
|
for _, ci := range cids {
|
|
c.cache.Remove(MhString(ci.Hash()))
|
|
}
|
|
|
|
return c.top.DeleteMany(ctx, cids)
|
|
}
|
|
|
|
func (c *ReadCachedBlockstore) Flush(ctx context.Context) error {
|
|
return c.top.Flush(ctx)
|
|
}
|
|
|
|
var _ Blockstore = (*ReadCachedBlockstore)(nil)
|