p2p/discover: parametrize nodedb version, add persistency tests

This commit is contained in:
Péter Szilágyi 2015-04-27 15:28:17 +03:00
parent 75fd738dea
commit a136e2bb22
3 changed files with 62 additions and 11 deletions

View File

@ -39,11 +39,11 @@ var (
// newNodeDB creates a new node database for storing and retrieving infos about // newNodeDB creates a new node database for storing and retrieving infos about
// known peers in the network. If no path is given, an in-memory, temporary // known peers in the network. If no path is given, an in-memory, temporary
// database is constructed. // database is constructed.
func newNodeDB(path string) (*nodeDB, error) { func newNodeDB(path string, version int) (*nodeDB, error) {
if path == "" { if path == "" {
return newMemoryNodeDB() return newMemoryNodeDB()
} }
return newPersistentNodeDB(path) return newPersistentNodeDB(path, version)
} }
// newMemoryNodeDB creates a new in-memory node database without a persistent // newMemoryNodeDB creates a new in-memory node database without a persistent
@ -58,7 +58,7 @@ func newMemoryNodeDB() (*nodeDB, error) {
// newPersistentNodeDB creates/opens a leveldb backed persistent node database, // newPersistentNodeDB creates/opens a leveldb backed persistent node database,
// also flushing its contents in case of a version mismatch. // also flushing its contents in case of a version mismatch.
func newPersistentNodeDB(path string) (*nodeDB, error) { func newPersistentNodeDB(path string, version int) (*nodeDB, error) {
// Try to open the cache, recovering any corruption // Try to open the cache, recovering any corruption
db, err := leveldb.OpenFile(path, nil) db, err := leveldb.OpenFile(path, nil)
if _, iscorrupted := err.(leveldb.ErrCorrupted); iscorrupted { if _, iscorrupted := err.(leveldb.ErrCorrupted); iscorrupted {
@ -70,7 +70,7 @@ func newPersistentNodeDB(path string) (*nodeDB, error) {
// The nodes contained in the cache correspond to a certain protocol version. // The nodes contained in the cache correspond to a certain protocol version.
// Flush all nodes if the version doesn't match. // Flush all nodes if the version doesn't match.
currentVer := make([]byte, binary.MaxVarintLen64) currentVer := make([]byte, binary.MaxVarintLen64)
currentVer = currentVer[:binary.PutVarint(currentVer, Version)] currentVer = currentVer[:binary.PutVarint(currentVer, int64(version))]
blob, err := db.Get(nodeDBVersionKey, nil) blob, err := db.Get(nodeDBVersionKey, nil)
switch err { switch err {
@ -88,7 +88,7 @@ func newPersistentNodeDB(path string) (*nodeDB, error) {
if err = os.RemoveAll(path); err != nil { if err = os.RemoveAll(path); err != nil {
return nil, err return nil, err
} }
return newPersistentNodeDB(path) return newPersistentNodeDB(path, version)
} }
} }
return &nodeDB{lvl: db}, nil return &nodeDB{lvl: db}, nil

View File

@ -2,7 +2,10 @@ package discover
import ( import (
"bytes" "bytes"
"io/ioutil"
"net" "net"
"os"
"path/filepath"
"testing" "testing"
"time" "time"
) )
@ -59,7 +62,8 @@ var nodeDBInt64Tests = []struct {
} }
func TestNodeDBInt64(t *testing.T) { func TestNodeDBInt64(t *testing.T) {
db, _ := newNodeDB("") db, _ := newNodeDB("", Version)
defer db.close()
tests := nodeDBInt64Tests tests := nodeDBInt64Tests
for i := 0; i < len(tests); i++ { for i := 0; i < len(tests); i++ {
@ -87,7 +91,9 @@ func TestNodeDBFetchStore(t *testing.T) {
TCPPort: 30303, TCPPort: 30303,
} }
inst := time.Now() inst := time.Now()
db, _ := newNodeDB("")
db, _ := newNodeDB("", Version)
defer db.close()
// Check fetch/store operations on a node ping object // Check fetch/store operations on a node ping object
if stored := db.lastPing(node.ID); stored.Unix() != 0 { if stored := db.lastPing(node.ID); stored.Unix() != 0 {
@ -151,7 +157,8 @@ var nodeDBSeedQueryNodes = []struct {
} }
func TestNodeDBSeedQuery(t *testing.T) { func TestNodeDBSeedQuery(t *testing.T) {
db, _ := newNodeDB("") db, _ := newNodeDB("", Version)
defer db.close()
// Insert a batch of nodes for querying // Insert a batch of nodes for querying
for i, seed := range nodeDBSeedQueryNodes { for i, seed := range nodeDBSeedQueryNodes {
@ -190,7 +197,8 @@ func TestNodeDBSeedQuery(t *testing.T) {
} }
func TestNodeDBSeedQueryContinuation(t *testing.T) { func TestNodeDBSeedQueryContinuation(t *testing.T) {
db, _ := newNodeDB("") db, _ := newNodeDB("", Version)
defer db.close()
// Insert a batch of nodes for querying // Insert a batch of nodes for querying
for i, seed := range nodeDBSeedQueryNodes { for i, seed := range nodeDBSeedQueryNodes {
@ -213,3 +221,46 @@ func TestNodeDBSeedQueryContinuation(t *testing.T) {
} }
} }
} }
func TestNodeDBPersistency(t *testing.T) {
root, err := ioutil.TempDir("", "nodedb-")
if err != nil {
t.Fatalf("failed to create temporary data folder: %v", err)
}
defer os.RemoveAll(root)
var (
testKey = []byte("somekey")
testInt = int64(314)
)
// Create a persistent database and store some values
db, err := newNodeDB(filepath.Join("root", "database"), Version)
if err != nil {
t.Fatalf("failed to create persistent database: %v", err)
}
if err := db.storeInt64(testKey, testInt); err != nil {
t.Fatalf("failed to store value: %v.", err)
}
db.close()
// Reopen the database and check the value
db, err = newNodeDB(filepath.Join("root", "database"), Version)
if err != nil {
t.Fatalf("failed to open persistent database: %v", err)
}
if val := db.fetchInt64(testKey); val != testInt {
t.Fatalf("value mismatch: have %v, want %v", val, testInt)
}
db.close()
// Change the database version and check flush
db, err = newNodeDB(filepath.Join("root", "database"), Version+1)
if err != nil {
t.Fatalf("failed to open persistent database: %v", err)
}
if val := db.fetchInt64(testKey); val != 0 {
t.Fatalf("value mismatch: have %v, want %v", val, 0)
}
db.close()
}

View File

@ -63,10 +63,10 @@ type bucket struct {
func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string) *Table { func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string) *Table {
// If no node database was given, use an in-memory one // If no node database was given, use an in-memory one
db, err := newNodeDB(nodeDBPath) db, err := newNodeDB(nodeDBPath, Version)
if err != nil { if err != nil {
glog.V(logger.Warn).Infoln("Failed to open node database:", err) glog.V(logger.Warn).Infoln("Failed to open node database:", err)
db, _ = newNodeDB("") db, _ = newNodeDB("", Version)
} }
tab := &Table{ tab := &Table{
net: t, net: t,