Skip to content

Commit

Permalink
Merge pull request #3290 from ipfs/feat/el-cid-2
Browse files Browse the repository at this point in the history
The conquest of El Cid, Pt. 2
  • Loading branch information
whyrusleeping committed Oct 10, 2016
2 parents 391b78a + 282bdc4 commit 7962903
Show file tree
Hide file tree
Showing 52 changed files with 544 additions and 535 deletions.
33 changes: 14 additions & 19 deletions blocks/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"errors"
"fmt"

key "gx/ipfs/QmYEoKZXHoAToWfhGF3vryhMn3WWhE1o2MasQ8uzY5iDi9/go-key"

mh "gx/ipfs/QmYDds3421prZgqKbLpEK7T9Aa2eVdQ7o3YarX1LVLdP2J/go-multihash"
cid "gx/ipfs/QmakyCk6Vnn16WEKjbkxieZmM2YLTzkFWizbmGowoYPjro/go-cid"
u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
Expand All @@ -18,58 +16,55 @@ var ErrWrongHash = errors.New("data did not match given hash!")
type Block interface {
Multihash() mh.Multihash
RawData() []byte
Key() key.Key
Cid() *cid.Cid
String() string
Loggable() map[string]interface{}
}

// Block is a singular block of data in ipfs
type BasicBlock struct {
multihash mh.Multihash
data []byte
cid *cid.Cid
data []byte
}

// NewBlock creates a Block object from opaque data. It will hash the data.
func NewBlock(data []byte) *BasicBlock {
return &BasicBlock{data: data, multihash: u.Hash(data)}
// TODO: fix assumptions
return &BasicBlock{data: data, cid: cid.NewCidV0(u.Hash(data))}
}

// NewBlockWithHash creates a new block when the hash of the data
// is already known, this is used to save time in situations where
// we are able to be confident that the data is correct
func NewBlockWithHash(data []byte, h mh.Multihash) (*BasicBlock, error) {
func NewBlockWithCid(data []byte, c *cid.Cid) (*BasicBlock, error) {
if u.Debug {
chk := u.Hash(data)
if string(chk) != string(h) {
// TODO: fix assumptions
chkc := cid.NewCidV0(u.Hash(data))
if !chkc.Equals(c) {
return nil, ErrWrongHash
}
}
return &BasicBlock{data: data, multihash: h}, nil
return &BasicBlock{data: data, cid: c}, nil
}

func (b *BasicBlock) Multihash() mh.Multihash {
return b.multihash
return b.cid.Hash()
}

func (b *BasicBlock) RawData() []byte {
return b.data
}

func (b *BasicBlock) Cid() *cid.Cid {
return cid.NewCidV0(b.multihash)
}

// Key returns the block's Multihash as a Key value.
func (b *BasicBlock) Key() key.Key {
return key.Key(b.multihash)
return b.cid
}

func (b *BasicBlock) String() string {
return fmt.Sprintf("[Block %s]", b.Key())
return fmt.Sprintf("[Block %s]", b.Cid())
}

func (b *BasicBlock) Loggable() map[string]interface{} {
return map[string]interface{}{
"block": b.Key().String(),
"block": b.Cid().String(),
}
}
15 changes: 9 additions & 6 deletions blocks/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

mh "gx/ipfs/QmYDds3421prZgqKbLpEK7T9Aa2eVdQ7o3YarX1LVLdP2J/go-multihash"
cid "gx/ipfs/QmakyCk6Vnn16WEKjbkxieZmM2YLTzkFWizbmGowoYPjro/go-cid"
u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
)

Expand Down Expand Up @@ -44,12 +45,12 @@ func TestHash(t *testing.T) {
}
}

func TestKey(t *testing.T) {
func TestCid(t *testing.T) {
data := []byte("yet another data")
block := NewBlock(data)
key := block.Key()
c := block.Cid()

if !bytes.Equal(block.Multihash(), key.ToMultihash()) {
if !bytes.Equal(block.Multihash(), c.Hash()) {
t.Error("key contains wrong data")
}
}
Expand All @@ -66,8 +67,10 @@ func TestManualHash(t *testing.T) {
t.Fatal(err)
}

c := cid.NewCidV0(hash)

u.Debug = false
block, err := NewBlockWithHash(data, hash)
block, err := NewBlockWithCid(data, c)
if err != nil {
t.Fatal(err)
}
Expand All @@ -77,7 +80,7 @@ func TestManualHash(t *testing.T) {
}

data[5] = byte((uint32(data[5]) + 5) % 256) // Transfrom hash to be different
block, err = NewBlockWithHash(data, hash)
block, err = NewBlockWithCid(data, c)
if err != nil {
t.Fatal(err)
}
Expand All @@ -88,7 +91,7 @@ func TestManualHash(t *testing.T) {

u.Debug = true

block, err = NewBlockWithHash(data, hash)
block, err = NewBlockWithCid(data, c)
if err != ErrWrongHash {
t.Fatal(err)
}
Expand Down
44 changes: 27 additions & 17 deletions blocks/blockstore/arc_cache.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package blockstore

import (
key "gx/ipfs/QmYEoKZXHoAToWfhGF3vryhMn3WWhE1o2MasQ8uzY5iDi9/go-key"
"context"

"github.com/ipfs/go-ipfs/blocks"

context "context"
"gx/ipfs/QmRg1gKTHzc3CZXSKzem8aR4E3TubFhbgXwfVuWnSK5CC5/go-metrics-interface"
lru "gx/ipfs/QmVYxfoJQiZijTgPNHCHgHELvQpbsJNTg6Crmc3dQkj3yy/golang-lru"
cid "gx/ipfs/QmakyCk6Vnn16WEKjbkxieZmM2YLTzkFWizbmGowoYPjro/go-cid"
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
)

Expand All @@ -31,7 +31,7 @@ func newARCCachedBS(ctx context.Context, bs Blockstore, lruSize int) (*arccache,
return c, nil
}

func (b *arccache) DeleteBlock(k key.Key) error {
func (b *arccache) DeleteBlock(k *cid.Cid) error {
if has, ok := b.hasCached(k); ok && !has {
return ErrNotFound
}
Expand All @@ -40,7 +40,7 @@ func (b *arccache) DeleteBlock(k key.Key) error {
err := b.blockstore.DeleteBlock(k)
switch err {
case nil, ds.ErrNotFound, ErrNotFound:
b.arc.Add(k, false)
b.addCache(k, false)
return err
default:
return err
Expand All @@ -49,56 +49,62 @@ func (b *arccache) DeleteBlock(k key.Key) error {

// if ok == false has is inconclusive
// if ok == true then has respons to question: is it contained
func (b *arccache) hasCached(k key.Key) (has bool, ok bool) {
func (b *arccache) hasCached(k *cid.Cid) (has bool, ok bool) {
b.total.Inc()
if k == "" {
if k == nil {
log.Error("nil cid in arccache")
// Return cache invalid so the call to blockstore happens
// in case of invalid key and correct error is created.
return false, false
}

h, ok := b.arc.Get(k)
h, ok := b.arc.Get(k.KeyString())
if ok {
b.hits.Inc()
return h.(bool), true
}
return false, false
}

func (b *arccache) Has(k key.Key) (bool, error) {
func (b *arccache) Has(k *cid.Cid) (bool, error) {
if has, ok := b.hasCached(k); ok {
return has, nil
}

res, err := b.blockstore.Has(k)
if err == nil {
b.arc.Add(k, res)
b.addCache(k, res)
}
return res, err
}

func (b *arccache) Get(k key.Key) (blocks.Block, error) {
func (b *arccache) Get(k *cid.Cid) (blocks.Block, error) {
if k == nil {
log.Error("nil cid in arc cache")
return nil, ErrNotFound
}

if has, ok := b.hasCached(k); ok && !has {
return nil, ErrNotFound
}

bl, err := b.blockstore.Get(k)
if bl == nil && err == ErrNotFound {
b.arc.Add(k, false)
b.addCache(k, false)
} else if bl != nil {
b.arc.Add(k, true)
b.addCache(k, true)
}
return bl, err
}

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

err := b.blockstore.Put(bl)
if err == nil {
b.arc.Add(bl.Key(), true)
b.addCache(bl.Cid(), true)
}
return err
}
Expand All @@ -108,7 +114,7 @@ func (b *arccache) PutMany(bs []blocks.Block) error {
for _, block := range bs {
// call put on block if result is inconclusive or we are sure that
// the block isn't in storage
if has, ok := b.hasCached(block.Key()); !ok || (ok && !has) {
if has, ok := b.hasCached(block.Cid()); !ok || (ok && !has) {
good = append(good, block)
}
}
Expand All @@ -117,12 +123,16 @@ func (b *arccache) PutMany(bs []blocks.Block) error {
return err
}
for _, block := range good {
b.arc.Add(block.Key(), true)
b.addCache(block.Cid(), true)
}
return nil
}

func (b *arccache) AllKeysChan(ctx context.Context) (<-chan key.Key, error) {
func (b *arccache) addCache(c *cid.Cid, has bool) {
b.arc.Add(c.KeyString(), has)
}

func (b *arccache) AllKeysChan(ctx context.Context) (<-chan *cid.Cid, error) {
return b.blockstore.AllKeysChan(ctx)
}

Expand Down
Loading

0 comments on commit 7962903

Please sign in to comment.