Overlay error handling (#880)

This commit is contained in:
Egon Elbre 2018-12-17 20:47:26 +02:00 committed by GitHub
parent 5c26aa3e4a
commit 6b5945139f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 56 deletions

View File

@ -21,10 +21,13 @@ const (
OverlayBucket = "overlay"
)
// ErrNodeNotFound error standardization
// ErrEmptyNode is returned when the nodeID is empty
var ErrEmptyNode = errs.New("empty node ID")
// ErrNodeNotFound is returned if a node does not exist in database
var ErrNodeNotFound = errs.New("Node not found")
// ErrBucketNotFound returns if a bucket is unable to be found in the routing table
// ErrBucketNotFound is returned if a bucket is unable to be found in the routing table
var ErrBucketNotFound = errs.New("Bucket not found")
// OverlayError creates class of errors for stack traces
@ -44,14 +47,21 @@ func NewOverlayCache(db storage.KeyValueStore, dht dht.DHT, sdb statdb.DB) *Cach
// Get looks up the provided nodeID from the overlay cache
func (o *Cache) Get(ctx context.Context, nodeID storj.NodeID) (*pb.Node, error) {
if nodeID.IsZero() {
return nil, ErrEmptyNode
}
b, err := o.DB.Get(nodeID.Bytes())
if err != nil {
if storage.ErrKeyNotFound.Has(err) {
return nil, ErrNodeNotFound
}
return nil, err
}
if b.IsZero() {
// TODO: log? return an error?
return nil, nil
if b == nil {
return nil, ErrNodeNotFound
}
na := &pb.Node{}
if err := proto.Unmarshal(b, na); err != nil {
return nil, err
@ -92,7 +102,7 @@ func (o *Cache) GetAll(ctx context.Context, nodeIDs storj.NodeIDList) ([]*pb.Nod
func (o *Cache) Put(ctx context.Context, nodeID storj.NodeID, value pb.Node) error {
// If we get a Node without an ID (i.e. bootstrap node)
// we don't want to add to the routing tbale
if nodeID == (storj.NodeID{}) {
if nodeID.IsZero() {
return nil
}

View File

@ -5,14 +5,15 @@ package overlay_test
import (
"context"
"math/rand"
"testing"
"github.com/stretchr/testify/assert"
"storj.io/storj/internal/testcontext"
"storj.io/storj/internal/testplanet"
"storj.io/storj/internal/teststorj"
"storj.io/storj/pkg/overlay"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/statdb"
"storj.io/storj/pkg/storj"
"storj.io/storj/satellite/satellitedb"
@ -23,34 +24,47 @@ import (
"storj.io/storj/storage/teststore"
)
var (
valid1ID = teststorj.NodeIDFromString("valid1")
valid2ID = teststorj.NodeIDFromString("valid2")
invalid1ID = teststorj.NodeIDFromString("invalid1")
invalid2ID = teststorj.NodeIDFromString("invalid2")
)
func testCache(ctx context.Context, t *testing.T, store storage.KeyValueStore, sdb statdb.DB) {
valid1ID := storj.NodeID{}
valid2ID := storj.NodeID{}
missingID := storj.NodeID{}
_, _ = rand.Read(valid1ID[:])
_, _ = rand.Read(valid2ID[:])
_, _ = rand.Read(missingID[:])
cache := overlay.Cache{DB: store, StatDB: sdb}
{ // Put
err := cache.Put(ctx, valid1ID, *teststorj.MockNode("valid1"))
err := cache.Put(ctx, valid1ID, pb.Node{Id: valid1ID})
if err != nil {
t.Fatal(err)
}
err = cache.Put(ctx, valid2ID, *teststorj.MockNode("valid2"))
err = cache.Put(ctx, valid2ID, pb.Node{Id: valid2ID})
if err != nil {
t.Fatal(err)
}
}
{ // Get
valid2, err := cache.Get(ctx, valid2ID)
assert.NoError(t, err)
assert.Equal(t, valid2.Id, valid2ID)
invalid2, err := cache.Get(ctx, invalid2ID)
_, err := cache.Get(ctx, storj.NodeID{})
assert.Error(t, err)
assert.True(t, err == overlay.ErrEmptyNode)
valid1, err := cache.Get(ctx, valid1ID)
if assert.NoError(t, err) {
assert.Equal(t, valid1.Id, valid1ID)
}
valid2, err := cache.Get(ctx, valid2ID)
if assert.NoError(t, err) {
assert.Equal(t, valid2.Id, valid2ID)
}
invalid2, err := cache.Get(ctx, missingID)
assert.Error(t, err)
assert.True(t, err == overlay.ErrNodeNotFound)
assert.Nil(t, invalid2)
if storeClient, ok := store.(*teststore.Client); ok {
@ -67,7 +81,7 @@ func testCache(ctx context.Context, t *testing.T, store storage.KeyValueStore, s
assert.Equal(t, nodes[1].Id, valid1ID)
assert.Equal(t, nodes[2].Id, valid2ID)
nodes, err = cache.GetAll(ctx, storj.NodeIDList{valid1ID, invalid1ID})
nodes, err = cache.GetAll(ctx, storj.NodeIDList{valid1ID, missingID})
assert.NoError(t, err)
assert.Equal(t, nodes[0].Id, valid1ID)
assert.Nil(t, nodes[1])

View File

@ -9,10 +9,9 @@ import (
"github.com/stretchr/testify/assert"
"storj.io/storj/internal/identity"
testidentity "storj.io/storj/internal/identity"
"storj.io/storj/internal/testcontext"
"storj.io/storj/internal/testplanet"
"storj.io/storj/internal/teststorj"
"storj.io/storj/pkg/overlay"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/storj"
@ -46,6 +45,20 @@ func TestNewOverlayClient(t *testing.T) {
}
func TestChoose(t *testing.T) {
n1 := &pb.Node{Id: storj.NodeID{1}, Type: pb.NodeType_STORAGE}
n2 := &pb.Node{Id: storj.NodeID{2}, Type: pb.NodeType_STORAGE}
n3 := &pb.Node{Id: storj.NodeID{3}, Type: pb.NodeType_STORAGE}
n4 := &pb.Node{Id: storj.NodeID{4}, Type: pb.NodeType_STORAGE}
n5 := &pb.Node{Id: storj.NodeID{5}, Type: pb.NodeType_STORAGE}
n6 := &pb.Node{Id: storj.NodeID{6}, Type: pb.NodeType_STORAGE}
n7 := &pb.Node{Id: storj.NodeID{7}, Type: pb.NodeType_STORAGE}
n8 := &pb.Node{Id: storj.NodeID{8}, Type: pb.NodeType_STORAGE}
id1 := storj.NodeID{1}
id2 := storj.NodeID{2}
id3 := storj.NodeID{3}
id4 := storj.NodeID{4}
ctx := testcontext.New(t)
defer ctx.Cleanup()
@ -72,28 +85,8 @@ func TestChoose(t *testing.T) {
uptimeCount: 0,
auditSuccess: 0,
auditCount: 0,
allNodes: func() []*pb.Node {
n1 := teststorj.MockNode("n1")
n2 := teststorj.MockNode("n2")
n3 := teststorj.MockNode("n3")
n4 := teststorj.MockNode("n4")
n5 := teststorj.MockNode("n5")
n6 := teststorj.MockNode("n6")
n7 := teststorj.MockNode("n7")
n8 := teststorj.MockNode("n8")
nodes := []*pb.Node{n1, n2, n3, n4, n5, n6, n7, n8}
for _, n := range nodes {
n.Type = pb.NodeType_STORAGE
}
return nodes
}(),
excluded: func() storj.NodeIDList {
id1 := teststorj.NodeIDFromString("n1")
id2 := teststorj.NodeIDFromString("n2")
id3 := teststorj.NodeIDFromString("n3")
id4 := teststorj.NodeIDFromString("n4")
return storj.NodeIDList{id1, id2, id3, id4}
}(),
allNodes: []*pb.Node{n1, n2, n3, n4, n5, n6, n7, n8},
excluded: storj.NodeIDList{id1, id2, id3, id4},
},
}
@ -146,7 +139,7 @@ func TestLookup(t *testing.T) {
expectErr: false,
},
{
nodeID: teststorj.NodeIDFromString("n1"),
nodeID: storj.NodeID{1},
expectErr: true,
},
}
@ -203,20 +196,22 @@ func TestBulkLookupV2(t *testing.T) {
oc := getOverlayClient(t, planet)
cache := planet.Satellites[0].Overlay
n1 := teststorj.MockNode("n1")
n2 := teststorj.MockNode("n2")
n3 := teststorj.MockNode("n3")
nid1 := storj.NodeID{1}
nid2 := storj.NodeID{2}
nid3 := storj.NodeID{3}
nid4 := storj.NodeID{4}
nid5 := storj.NodeID{5}
n1 := &pb.Node{Id: storj.NodeID{1}}
n2 := &pb.Node{Id: storj.NodeID{2}}
n3 := &pb.Node{Id: storj.NodeID{3}}
nodes := []*pb.Node{n1, n2, n3}
for _, n := range nodes {
assert.NoError(t, cache.Put(ctx, n.Id, *n))
}
nid1 := teststorj.NodeIDFromString("n1")
nid2 := teststorj.NodeIDFromString("n2")
nid3 := teststorj.NodeIDFromString("n3")
nid4 := teststorj.NodeIDFromString("n4")
nid5 := teststorj.NodeIDFromString("n5")
{ // empty id
_, err := oc.BulkLookup(ctx, storj.NodeIDList{})
assert.Error(t, err)

View File

@ -71,6 +71,11 @@ func (id NodeID) String() string {
return base58.CheckEncode(id[:], IDVersion)
}
// IsZero returns whether NodeID is unassigned
func (id NodeID) IsZero() bool {
return id == NodeID{}
}
// Bytes returns raw bytes of the id
func (id NodeID) Bytes() []byte { return id[:] }