p2p/discover: parametrize nodedb version, add persistency tests
This commit is contained in:
parent
75fd738dea
commit
a136e2bb22
@ -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
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user