kvdb+etcd: enable channeldb testing with both bdb/etcd
This commit is contained in:
parent
3b7525659c
commit
248a00f211
@ -98,13 +98,22 @@ func makeTestDB() (*DB, func(), error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Next, create channeldb for the first time.
|
// Next, create channeldb for the first time.
|
||||||
cdb, err := Open(tempDirName, OptionClock(testClock))
|
backend, backendCleanup, err := kvdb.GetTestBackend(tempDirName, "cdb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
backendCleanup()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cdb, err := CreateWithBackend(backend, OptionClock(testClock))
|
||||||
|
if err != nil {
|
||||||
|
backendCleanup()
|
||||||
|
os.RemoveAll(tempDirName)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanUp := func() {
|
cleanUp := func() {
|
||||||
cdb.Close()
|
cdb.Close()
|
||||||
|
backendCleanup()
|
||||||
os.RemoveAll(tempDirName)
|
os.RemoveAll(tempDirName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
@ -154,15 +153,32 @@ type DB struct {
|
|||||||
dryRun bool
|
dryRun bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open opens an existing channeldb. Any necessary schemas migrations due to
|
// Open opens or creates channeldb. Any necessary schemas migrations due
|
||||||
// updates will take place as necessary.
|
// to updates will take place as necessary.
|
||||||
|
// TODO(bhandras): deprecate this function.
|
||||||
func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
|
func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
|
||||||
path := filepath.Join(dbPath, dbName)
|
opts := DefaultOptions()
|
||||||
|
for _, modifier := range modifiers {
|
||||||
|
modifier(&opts)
|
||||||
|
}
|
||||||
|
|
||||||
if !fileExists(path) {
|
backend, err := kvdb.GetBoltBackend(dbPath, dbName, opts.NoFreelistSync)
|
||||||
if err := createChannelDB(dbPath); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db, err := CreateWithBackend(backend, modifiers...)
|
||||||
|
if err == nil {
|
||||||
|
db.dbPath = dbPath
|
||||||
|
}
|
||||||
|
return db, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateWithBackend creates channeldb instance using the passed kvdb.Backend.
|
||||||
|
// Any necessary schemas migrations due to updates will take place as necessary.
|
||||||
|
func CreateWithBackend(backend kvdb.Backend, modifiers ...OptionModifier) (*DB, error) {
|
||||||
|
if err := initChannelDB(backend); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := DefaultOptions()
|
opts := DefaultOptions()
|
||||||
@ -170,16 +186,8 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
|
|||||||
modifier(&opts)
|
modifier(&opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specify bbolt freelist options to reduce heap pressure in case the
|
|
||||||
// freelist grows to be very large.
|
|
||||||
bdb, err := kvdb.Open(kvdb.BoltBackendName, path, opts.NoFreelistSync)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
chanDB := &DB{
|
chanDB := &DB{
|
||||||
Backend: bdb,
|
Backend: backend,
|
||||||
dbPath: dbPath,
|
|
||||||
clock: opts.clock,
|
clock: opts.clock,
|
||||||
dryRun: opts.dryRun,
|
dryRun: opts.dryRun,
|
||||||
}
|
}
|
||||||
@ -189,7 +197,7 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
|
|||||||
|
|
||||||
// Synchronize the version of database and apply migrations if needed.
|
// Synchronize the version of database and apply migrations if needed.
|
||||||
if err := chanDB.syncVersions(dbVersions); err != nil {
|
if err := chanDB.syncVersions(dbVersions); err != nil {
|
||||||
bdb.Close()
|
backend.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,20 +259,15 @@ func (d *DB) Wipe() error {
|
|||||||
// the case that the target path has not yet been created or doesn't yet exist,
|
// the case that the target path has not yet been created or doesn't yet exist,
|
||||||
// then the path is created. Additionally, all required top-level buckets used
|
// then the path is created. Additionally, all required top-level buckets used
|
||||||
// within the database are created.
|
// within the database are created.
|
||||||
func createChannelDB(dbPath string) error {
|
func initChannelDB(db kvdb.Backend) error {
|
||||||
if !fileExists(dbPath) {
|
err := kvdb.Update(db, func(tx kvdb.RwTx) error {
|
||||||
if err := os.MkdirAll(dbPath, 0700); err != nil {
|
meta := &Meta{}
|
||||||
return err
|
// Check if DB is already initialized.
|
||||||
}
|
err := fetchMeta(meta, tx)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(dbPath, dbName)
|
|
||||||
bdb, err := kvdb.Create(kvdb.BoltBackendName, path, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = kvdb.Update(bdb, func(tx kvdb.RwTx) error {
|
|
||||||
if _, err := tx.CreateTopLevelBucket(openChannelBucket); err != nil {
|
if _, err := tx.CreateTopLevelBucket(openChannelBucket); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -331,16 +334,14 @@ func createChannelDB(dbPath string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
meta := &Meta{
|
meta.DbVersionNumber = getLatestDBVersion(dbVersions)
|
||||||
DbVersionNumber: getLatestDBVersion(dbVersions),
|
|
||||||
}
|
|
||||||
return putMeta(meta, tx)
|
return putMeta(meta, tx)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create new channeldb")
|
return fmt.Errorf("unable to create new channeldb: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return bdb.Close()
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// fileExists returns true if the file exists, and false otherwise.
|
// fileExists returns true if the file exists, and false otherwise.
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/shachain"
|
"github.com/lightningnetwork/lnd/shachain"
|
||||||
@ -33,7 +34,13 @@ func TestOpenWithCreate(t *testing.T) {
|
|||||||
|
|
||||||
// Next, open thereby creating channeldb for the first time.
|
// Next, open thereby creating channeldb for the first time.
|
||||||
dbPath := filepath.Join(tempDirName, "cdb")
|
dbPath := filepath.Join(tempDirName, "cdb")
|
||||||
cdb, err := Open(dbPath)
|
backend, cleanup, err := kvdb.GetTestBackend(dbPath, "cdb")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to get test db backend: %v", err)
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
cdb, err := CreateWithBackend(backend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create channeldb: %v", err)
|
t.Fatalf("unable to create channeldb: %v", err)
|
||||||
}
|
}
|
||||||
@ -73,7 +80,13 @@ func TestWipe(t *testing.T) {
|
|||||||
|
|
||||||
// Next, open thereby creating channeldb for the first time.
|
// Next, open thereby creating channeldb for the first time.
|
||||||
dbPath := filepath.Join(tempDirName, "cdb")
|
dbPath := filepath.Join(tempDirName, "cdb")
|
||||||
cdb, err := Open(dbPath)
|
backend, cleanup, err := kvdb.GetTestBackend(dbPath, "cdb")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to get test db backend: %v", err)
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
cdb, err := CreateWithBackend(backend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create channeldb: %v", err)
|
t.Fatalf("unable to create channeldb: %v", err)
|
||||||
}
|
}
|
||||||
|
79
channeldb/kvdb/backend.go
Normal file
79
channeldb/kvdb/backend.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package kvdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb/kvdb/etcd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// fileExists returns true if the file exists, and false otherwise.
|
||||||
|
func fileExists(path string) bool {
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBoltBackend opens (or creates if doesn't exits) a bbolt
|
||||||
|
// backed database and returns a kvdb.Backend wrapping it.
|
||||||
|
func GetBoltBackend(path, name string, noFreeListSync bool) (Backend, error) {
|
||||||
|
dbFilePath := filepath.Join(path, name)
|
||||||
|
var (
|
||||||
|
db Backend
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if !fileExists(dbFilePath) {
|
||||||
|
if !fileExists(path) {
|
||||||
|
if err := os.MkdirAll(path, 0700); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err = Create(BoltBackendName, dbFilePath, noFreeListSync)
|
||||||
|
} else {
|
||||||
|
db, err = Open(BoltBackendName, dbFilePath, noFreeListSync)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTestBackend opens (or creates if doesn't exist) a bbolt or etcd
|
||||||
|
// backed database (for testing), and returns a kvdb.Backend and a cleanup
|
||||||
|
// func. Whether to create/open bbolt or embedded etcd database is based
|
||||||
|
// on the TestBackend constant which is conditionally compiled with build tag.
|
||||||
|
// The passed path is used to hold all db files, while the name is only used
|
||||||
|
// for bbolt.
|
||||||
|
func GetTestBackend(path, name string) (Backend, func(), error) {
|
||||||
|
empty := func() {}
|
||||||
|
|
||||||
|
if TestBackend == BoltBackendName {
|
||||||
|
db, err := GetBoltBackend(path, name, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return db, empty, nil
|
||||||
|
} else if TestBackend == EtcdBackendName {
|
||||||
|
config, cleanup, err := etcd.NewEmbeddedEtcdInstance(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
backend, err := Open(EtcdBackendName, *config)
|
||||||
|
if err != nil {
|
||||||
|
cleanup()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return backend, cleanup, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil, fmt.Errorf("unknown backend")
|
||||||
|
}
|
5
channeldb/kvdb/kvdb_test_bdb.go
Normal file
5
channeldb/kvdb/kvdb_test_bdb.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// +build !kvdb_etcd
|
||||||
|
|
||||||
|
package kvdb
|
||||||
|
|
||||||
|
const TestBackend = "bdb"
|
5
channeldb/kvdb/kvdb_test_etcd.go
Normal file
5
channeldb/kvdb/kvdb_test_etcd.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// +build kvdb_etcd
|
||||||
|
|
||||||
|
package kvdb
|
||||||
|
|
||||||
|
const TestBackend = "etcd"
|
@ -3,6 +3,7 @@ package channeldb
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
@ -421,12 +422,21 @@ func TestMigrationReversion(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
tempDirName, err := ioutil.TempDir("", "channeldb")
|
tempDirName, err := ioutil.TempDir("", "channeldb")
|
||||||
|
defer func() {
|
||||||
|
os.RemoveAll(tempDirName)
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create temp dir: %v", err)
|
t.Fatalf("unable to create temp dir: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cdb, err := Open(tempDirName)
|
backend, cleanup, err := kvdb.GetTestBackend(tempDirName, "cdb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
t.Fatalf("unable to get test db backend: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cdb, err := CreateWithBackend(backend)
|
||||||
|
if err != nil {
|
||||||
|
cleanup()
|
||||||
t.Fatalf("unable to open channeldb: %v", err)
|
t.Fatalf("unable to open channeldb: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,12 +452,19 @@ func TestMigrationReversion(t *testing.T) {
|
|||||||
|
|
||||||
// Close the database. Even if we succeeded, our next step is to reopen.
|
// Close the database. Even if we succeeded, our next step is to reopen.
|
||||||
cdb.Close()
|
cdb.Close()
|
||||||
|
cleanup()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to increase db version: %v", err)
|
t.Fatalf("unable to increase db version: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = Open(tempDirName)
|
backend, cleanup, err = kvdb.GetTestBackend(tempDirName, "cdb")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to get test db backend: %v", err)
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
_, err = CreateWithBackend(backend)
|
||||||
if err != ErrDBReversion {
|
if err != ErrDBReversion {
|
||||||
t.Fatalf("unexpected error when opening channeldb, "+
|
t.Fatalf("unexpected error when opening channeldb, "+
|
||||||
"want: %v, got: %v", ErrDBReversion, err)
|
"want: %v, got: %v", ErrDBReversion, err)
|
||||||
|
Loading…
Reference in New Issue
Block a user