Skip to content
This repository has been archived by the owner on Jun 19, 2023. It is now read-only.

feat: add context to interfaces & plumb through datastore contexts #89

Merged
merged 1 commit into from
Oct 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions arc_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ func newARCCachedBS(ctx context.Context, bs Blockstore, lruSize int) (*arccache,
return c, nil
}

func (b *arccache) DeleteBlock(k cid.Cid) error {
func (b *arccache) DeleteBlock(ctx context.Context, k cid.Cid) error {
if has, _, ok := b.hasCached(k); ok && !has {
return nil
}

b.arc.Remove(k) // Invalidate cache before deleting.
err := b.blockstore.DeleteBlock(k)
err := b.blockstore.DeleteBlock(ctx, k)
if err == nil {
b.cacheHave(k, false)
}
Expand Down Expand Up @@ -72,19 +72,19 @@ func (b *arccache) hasCached(k cid.Cid) (has bool, size int, ok bool) {
return false, -1, false
}

func (b *arccache) Has(k cid.Cid) (bool, error) {
func (b *arccache) Has(ctx context.Context, k cid.Cid) (bool, error) {
if has, _, ok := b.hasCached(k); ok {
return has, nil
}
has, err := b.blockstore.Has(k)
has, err := b.blockstore.Has(ctx, k)
if err != nil {
return false, err
}
b.cacheHave(k, has)
return has, nil
}

func (b *arccache) GetSize(k cid.Cid) (int, error) {
func (b *arccache) GetSize(ctx context.Context, k cid.Cid) (int, error) {
if has, blockSize, ok := b.hasCached(k); ok {
if !has {
// don't have it, return
Expand All @@ -96,7 +96,7 @@ func (b *arccache) GetSize(k cid.Cid) (int, error) {
}
// we have it but don't know the size, ask the datastore.
}
blockSize, err := b.blockstore.GetSize(k)
blockSize, err := b.blockstore.GetSize(ctx, k)
if err == ErrNotFound {
b.cacheHave(k, false)
} else if err == nil {
Expand All @@ -105,7 +105,7 @@ func (b *arccache) GetSize(k cid.Cid) (int, error) {
return blockSize, err
}

func (b *arccache) Get(k cid.Cid) (blocks.Block, error) {
func (b *arccache) Get(ctx context.Context, k cid.Cid) (blocks.Block, error) {
if !k.Defined() {
log.Error("undefined cid in arc cache")
return nil, ErrNotFound
Expand All @@ -115,7 +115,7 @@ func (b *arccache) Get(k cid.Cid) (blocks.Block, error) {
return nil, ErrNotFound
}

bl, err := b.blockstore.Get(k)
bl, err := b.blockstore.Get(ctx, k)
if bl == nil && err == ErrNotFound {
b.cacheHave(k, false)
} else if bl != nil {
Expand All @@ -124,19 +124,19 @@ func (b *arccache) Get(k cid.Cid) (blocks.Block, error) {
return bl, err
}

func (b *arccache) Put(bl blocks.Block) error {
func (b *arccache) Put(ctx context.Context, bl blocks.Block) error {
if has, _, ok := b.hasCached(bl.Cid()); ok && has {
return nil
}

err := b.blockstore.Put(bl)
err := b.blockstore.Put(ctx, bl)
if err == nil {
b.cacheSize(bl.Cid(), len(bl.RawData()))
}
return err
}

func (b *arccache) PutMany(bs []blocks.Block) error {
func (b *arccache) PutMany(ctx context.Context, bs []blocks.Block) error {
var good []blocks.Block
for _, block := range bs {
// call put on block if result is inconclusive or we are sure that
Expand All @@ -145,7 +145,7 @@ func (b *arccache) PutMany(bs []blocks.Block) error {
good = append(good, block)
}
}
err := b.blockstore.PutMany(good)
err := b.blockstore.PutMany(ctx, good)
if err != nil {
return err
}
Expand All @@ -171,14 +171,14 @@ func (b *arccache) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
return b.blockstore.AllKeysChan(ctx)
}

func (b *arccache) GCLock() Unlocker {
return b.blockstore.(GCBlockstore).GCLock()
func (b *arccache) GCLock(ctx context.Context) Unlocker {
return b.blockstore.(GCBlockstore).GCLock(ctx)
}

func (b *arccache) PinLock() Unlocker {
return b.blockstore.(GCBlockstore).PinLock()
func (b *arccache) PinLock(ctx context.Context) Unlocker {
return b.blockstore.(GCBlockstore).PinLock(ctx)
}

func (b *arccache) GCRequested() bool {
return b.blockstore.(GCBlockstore).GCRequested()
func (b *arccache) GCRequested(ctx context.Context) bool {
return b.blockstore.(GCBlockstore).GCRequested(ctx)
}
91 changes: 47 additions & 44 deletions arc_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import (
syncds "github.com/ipfs/go-datastore/sync"
)

var exampleBlock = blocks.NewBlock([]byte("foo"))
var (
exampleBlock = blocks.NewBlock([]byte("foo"))
bg = context.Background()
)

func testArcCached(ctx context.Context, bs Blockstore) (*arccache, error) {
if ctx == nil {
Expand Down Expand Up @@ -48,7 +51,7 @@ func untrap(cd *callbackDatastore) {
func TestRemoveCacheEntryOnDelete(t *testing.T) {
arc, _, cd := createStores(t)

arc.Put(exampleBlock)
arc.Put(bg, exampleBlock)

cd.Lock()
writeHitTheDatastore := false
Expand All @@ -58,8 +61,8 @@ func TestRemoveCacheEntryOnDelete(t *testing.T) {
writeHitTheDatastore = true
})

arc.DeleteBlock(exampleBlock.Cid())
arc.Put(exampleBlock)
arc.DeleteBlock(bg, exampleBlock.Cid())
arc.Put(bg, exampleBlock)
if !writeHitTheDatastore {
t.Fail()
}
Expand All @@ -68,78 +71,78 @@ func TestRemoveCacheEntryOnDelete(t *testing.T) {
func TestElideDuplicateWrite(t *testing.T) {
arc, _, cd := createStores(t)

arc.Put(exampleBlock)
arc.Put(bg, exampleBlock)
trap("write hit datastore", cd, t)
arc.Put(exampleBlock)
arc.Put(bg, exampleBlock)
}

func TestHasRequestTriggersCache(t *testing.T) {
arc, _, cd := createStores(t)

arc.Has(exampleBlock.Cid())
arc.Has(bg, exampleBlock.Cid())
trap("has hit datastore", cd, t)
if has, err := arc.Has(exampleBlock.Cid()); has || err != nil {
if has, err := arc.Has(bg, exampleBlock.Cid()); has || err != nil {
t.Fatal("has was true but there is no such block")
}

untrap(cd)
err := arc.Put(exampleBlock)
err := arc.Put(bg, exampleBlock)
if err != nil {
t.Fatal(err)
}

trap("has hit datastore", cd, t)

if has, err := arc.Has(exampleBlock.Cid()); !has || err != nil {
if has, err := arc.Has(bg, exampleBlock.Cid()); !has || err != nil {
t.Fatal("has returned invalid result")
}
}

func TestGetFillsCache(t *testing.T) {
arc, _, cd := createStores(t)

if bl, err := arc.Get(exampleBlock.Cid()); bl != nil || err == nil {
if bl, err := arc.Get(bg, exampleBlock.Cid()); bl != nil || err == nil {
t.Fatal("block was found or there was no error")
}

trap("has hit datastore", cd, t)

if has, err := arc.Has(exampleBlock.Cid()); has || err != nil {
if has, err := arc.Has(bg, exampleBlock.Cid()); has || err != nil {
t.Fatal("has was true but there is no such block")
}
if _, err := arc.GetSize(exampleBlock.Cid()); err != ErrNotFound {
if _, err := arc.GetSize(bg, exampleBlock.Cid()); err != ErrNotFound {
t.Fatal("getsize was true but there is no such block")
}

untrap(cd)

if err := arc.Put(exampleBlock); err != nil {
if err := arc.Put(bg, exampleBlock); err != nil {
t.Fatal(err)
}

trap("has hit datastore", cd, t)

if has, err := arc.Has(exampleBlock.Cid()); !has || err != nil {
if has, err := arc.Has(bg, exampleBlock.Cid()); !has || err != nil {
t.Fatal("has returned invalid result")
}
if blockSize, err := arc.GetSize(exampleBlock.Cid()); blockSize == -1 || err != nil {
if blockSize, err := arc.GetSize(bg, exampleBlock.Cid()); blockSize == -1 || err != nil {
t.Fatal("getsize returned invalid result", blockSize, err)
}
}

func TestGetAndDeleteFalseShortCircuit(t *testing.T) {
arc, _, cd := createStores(t)

arc.Has(exampleBlock.Cid())
arc.GetSize(exampleBlock.Cid())
arc.Has(bg, exampleBlock.Cid())
arc.GetSize(bg, exampleBlock.Cid())

trap("get hit datastore", cd, t)

if bl, err := arc.Get(exampleBlock.Cid()); bl != nil || err != ErrNotFound {
if bl, err := arc.Get(bg, exampleBlock.Cid()); bl != nil || err != ErrNotFound {
t.Fatal("get returned invalid result")
}

if arc.DeleteBlock(exampleBlock.Cid()) != nil {
if arc.DeleteBlock(bg, exampleBlock.Cid()) != nil {
t.Fatal("expected deletes to be idempotent")
}
}
Expand All @@ -153,7 +156,7 @@ func TestArcCreationFailure(t *testing.T) {
func TestInvalidKey(t *testing.T) {
arc, _, _ := createStores(t)

bl, err := arc.Get(cid.Cid{})
bl, err := arc.Get(bg, cid.Cid{})

if bl != nil {
t.Fatal("blocks should be nil")
Expand All @@ -166,38 +169,38 @@ func TestInvalidKey(t *testing.T) {
func TestHasAfterSucessfulGetIsCached(t *testing.T) {
arc, bs, cd := createStores(t)

bs.Put(exampleBlock)
bs.Put(bg, exampleBlock)

arc.Get(exampleBlock.Cid())
arc.Get(bg, exampleBlock.Cid())

trap("has hit datastore", cd, t)
arc.Has(exampleBlock.Cid())
arc.Has(bg, exampleBlock.Cid())
}

func TestGetSizeAfterSucessfulGetIsCached(t *testing.T) {
arc, bs, cd := createStores(t)

bs.Put(exampleBlock)
bs.Put(bg, exampleBlock)

arc.Get(exampleBlock.Cid())
arc.Get(bg, exampleBlock.Cid())

trap("has hit datastore", cd, t)
arc.GetSize(exampleBlock.Cid())
arc.GetSize(bg, exampleBlock.Cid())
}

func TestGetSizeAfterSucessfulHas(t *testing.T) {
arc, bs, _ := createStores(t)

bs.Put(exampleBlock)
has, err := arc.Has(exampleBlock.Cid())
bs.Put(bg, exampleBlock)
has, err := arc.Has(bg, exampleBlock.Cid())
if err != nil {
t.Fatal(err)
}
if !has {
t.Fatal("expected to have block")
}

if size, err := arc.GetSize(exampleBlock.Cid()); err != nil {
if size, err := arc.GetSize(bg, exampleBlock.Cid()); err != nil {
t.Fatal(err)
} else if size != len(exampleBlock.RawData()) {
t.Fatalf("expected size %d, got %d", len(exampleBlock.RawData()), size)
Expand All @@ -209,30 +212,30 @@ func TestGetSizeMissingZeroSizeBlock(t *testing.T) {
emptyBlock := blocks.NewBlock([]byte{})
missingBlock := blocks.NewBlock([]byte("missingBlock"))

bs.Put(emptyBlock)
bs.Put(bg, emptyBlock)

arc.Get(emptyBlock.Cid())
arc.Get(bg, emptyBlock.Cid())

trap("has hit datastore", cd, t)
if blockSize, err := arc.GetSize(emptyBlock.Cid()); blockSize != 0 || err != nil {
if blockSize, err := arc.GetSize(bg, emptyBlock.Cid()); blockSize != 0 || err != nil {
t.Fatal("getsize returned invalid result")
}
untrap(cd)

arc.Get(missingBlock.Cid())
arc.Get(bg, missingBlock.Cid())

trap("has hit datastore", cd, t)
if _, err := arc.GetSize(missingBlock.Cid()); err != ErrNotFound {
if _, err := arc.GetSize(bg, missingBlock.Cid()); err != ErrNotFound {
t.Fatal("getsize returned invalid result")
}
}

func TestDifferentKeyObjectsWork(t *testing.T) {
arc, bs, cd := createStores(t)

bs.Put(exampleBlock)
bs.Put(bg, exampleBlock)

arc.Get(exampleBlock.Cid())
arc.Get(bg, exampleBlock.Cid())

trap("has hit datastore", cd, t)
cidstr := exampleBlock.Cid().String()
Expand All @@ -242,20 +245,20 @@ func TestDifferentKeyObjectsWork(t *testing.T) {
t.Fatal(err)
}

arc.Has(ncid)
arc.Has(bg, ncid)
}

func TestPutManyCaches(t *testing.T) {
arc, _, cd := createStores(t)
arc.PutMany([]blocks.Block{exampleBlock})
arc.PutMany(bg, []blocks.Block{exampleBlock})

trap("has hit datastore", cd, t)
arc.Has(exampleBlock.Cid())
arc.GetSize(exampleBlock.Cid())
arc.Has(bg, exampleBlock.Cid())
arc.GetSize(bg, exampleBlock.Cid())
untrap(cd)
arc.DeleteBlock(exampleBlock.Cid())
arc.DeleteBlock(bg, exampleBlock.Cid())

arc.Put(exampleBlock)
arc.Put(bg, exampleBlock)
trap("PunMany has hit datastore", cd, t)
arc.PutMany([]blocks.Block{exampleBlock})
arc.PutMany(bg, []blocks.Block{exampleBlock})
}
Loading