Skip to content

Commit

Permalink
introduce non-pooled StorageKey method.
Browse files Browse the repository at this point in the history
  • Loading branch information
raulk committed Nov 2, 2020
1 parent 7facdf6 commit d1ebf3c
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 2 deletions.
2 changes: 1 addition & 1 deletion cmd/lotus-shed/pruning.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ var stateTreePruneCmd = &cli.Command{
defer b.Cancel()

markForRemoval := func(c cid.Cid) error {
return b.Delete(badgbs.PrefixedKey(c))
return b.Delete(badgbs.StorageKey(nil, c))
}

keys, err := bs.AllKeysChan(context.Background())
Expand Down
27 changes: 26 additions & 1 deletion lib/blockstore/badger/badger.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ func (b *Blockstore) HashOnRead(_ bool) {
func (b *Blockstore) PooledStorageKey(cid cid.Cid) (key []byte, pooled bool) {
h := cid.Hash()
size := base32.RawStdEncoding.EncodedLen(len(h))
if !b.prefixing {
if !b.prefixing { // optimize for branch prediction.
k := pool.Get(size)
base32.RawStdEncoding.Encode(k, h)
return k, true // slicing upto length unnecessary; the pool has already done this.
Expand All @@ -373,3 +373,28 @@ func (b *Blockstore) PooledStorageKey(cid cid.Cid) (key []byte, pooled bool) {
base32.RawStdEncoding.Encode(k[b.prefixLen:], h)
return k, true // slicing upto length unnecessary; the pool has already done this.
}

// Storage acts like PooledStorageKey, but attempts to write the storage key
// into the provided slice. If the slice capacity is insufficient, it allocates
// a new byte slice with enough capacity to accommodate the result. This method
// returns the resulting slice.
func (b *Blockstore) StorageKey(dst []byte, cid cid.Cid) []byte {
h := cid.Hash()
reqsize := base32.RawStdEncoding.EncodedLen(len(h)) + b.prefixLen
if reqsize > cap(dst) {
// passed slice is smaller than required size; create new.
dst = make([]byte, reqsize)
} else if reqsize > len(dst) {
// passed slice has enough capacity, but its length is
// restricted, expand.
dst = dst[:cap(dst)]
}

if b.prefixing { // optimize for branch prediction.
copy(dst, b.prefix)
base32.RawStdEncoding.Encode(dst[b.prefixLen:], h)
} else {
base32.RawStdEncoding.Encode(dst, h)
}
return dst[:reqsize]
}
34 changes: 34 additions & 0 deletions lib/blockstore/badger/badger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"os"
"testing"

blocks "github.com/ipfs/go-block-format"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/stretchr/testify/require"
)

func TestBadgerBlockstore(t *testing.T) {
Expand All @@ -26,6 +28,38 @@ func TestBadgerBlockstore(t *testing.T) {
}).RunTests(t, "prefixed")
}

func TestStorageKey(t *testing.T) {
bs, _ := newBlockstore(DefaultOptions)(t)
bbs := bs.(*Blockstore)
defer bbs.Close() //nolint:errcheck

cid1 := blocks.NewBlock([]byte("some data")).Cid()
cid2 := blocks.NewBlock([]byte("more data")).Cid()
cid3 := blocks.NewBlock([]byte("a little more data")).Cid()
require.NotEqual(t, cid1, cid2) // sanity check
require.NotEqual(t, cid2, cid3) // sanity check

// nil slice; let StorageKey allocate for us.
k1 := bbs.StorageKey(nil, cid1)
require.Len(t, k1, 55)
require.True(t, cap(k1) == len(k1))

// k1's backing array is reused.
k2 := bbs.StorageKey(k1, cid2)
require.Len(t, k2, 55)
require.True(t, cap(k2) == len(k1))

// bring k2 to len=0, and verify that its backing array gets reused
// (i.e. k1 and k2 are overwritten)
k3 := bbs.StorageKey(k2[:0], cid3)
require.Len(t, k3, 55)
require.True(t, cap(k3) == len(k3))

// backing array of k1 and k2 has been modified, i.e. memory is shared.
require.Equal(t, k3, k1)
require.Equal(t, k3, k2)
}

func newBlockstore(optsSupplier func(path string) Options) func(tb testing.TB) (bs blockstore.Blockstore, path string) {
return func(tb testing.TB) (bs blockstore.Blockstore, path string) {
tb.Helper()
Expand Down

0 comments on commit d1ebf3c

Please sign in to comment.