migration_01_to_11: remove version checking for migration tests
This commit is contained in:
parent
60503d6c44
commit
4486a06b1a
@ -21,11 +21,6 @@ const (
|
|||||||
// up-to-date version of the database.
|
// up-to-date version of the database.
|
||||||
type migration func(tx *bbolt.Tx) error
|
type migration func(tx *bbolt.Tx) error
|
||||||
|
|
||||||
type version struct {
|
|
||||||
number uint32
|
|
||||||
migration migration
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Big endian is the preferred byte order, due to cursor scans over
|
// Big endian is the preferred byte order, due to cursor scans over
|
||||||
// integer keys iterating in order.
|
// integer keys iterating in order.
|
||||||
@ -220,89 +215,7 @@ func (d *DB) FetchClosedChannels(pendingOnly bool) ([]*ChannelCloseSummary, erro
|
|||||||
return chanSummaries, nil
|
return chanSummaries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// syncVersions function is used for safe db version synchronization. It
|
|
||||||
// applies migration functions to the current database and recovers the
|
|
||||||
// previous state of db if at least one error/panic appeared during migration.
|
|
||||||
func (d *DB) syncVersions(versions []version) error {
|
|
||||||
meta, err := d.FetchMeta(nil)
|
|
||||||
if err != nil {
|
|
||||||
if err == ErrMetaNotFound {
|
|
||||||
meta = &Meta{}
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
latestVersion := getLatestDBVersion(versions)
|
|
||||||
log.Infof("Checking for schema update: latest_version=%v, "+
|
|
||||||
"db_version=%v", latestVersion, meta.DbVersionNumber)
|
|
||||||
|
|
||||||
switch {
|
|
||||||
|
|
||||||
// If the database reports a higher version that we are aware of, the
|
|
||||||
// user is probably trying to revert to a prior version of lnd. We fail
|
|
||||||
// here to prevent reversions and unintended corruption.
|
|
||||||
case meta.DbVersionNumber > latestVersion:
|
|
||||||
log.Errorf("Refusing to revert from db_version=%d to "+
|
|
||||||
"lower version=%d", meta.DbVersionNumber,
|
|
||||||
latestVersion)
|
|
||||||
return ErrDBReversion
|
|
||||||
|
|
||||||
// If the current database version matches the latest version number,
|
|
||||||
// then we don't need to perform any migrations.
|
|
||||||
case meta.DbVersionNumber == latestVersion:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Performing database schema migration")
|
|
||||||
|
|
||||||
// Otherwise, we fetch the migrations which need to applied, and
|
|
||||||
// execute them serially within a single database transaction to ensure
|
|
||||||
// the migration is atomic.
|
|
||||||
migrations, migrationVersions := getMigrationsToApply(
|
|
||||||
versions, meta.DbVersionNumber,
|
|
||||||
)
|
|
||||||
return d.Update(func(tx *bbolt.Tx) error {
|
|
||||||
for i, migration := range migrations {
|
|
||||||
if migration == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Applying migration #%v", migrationVersions[i])
|
|
||||||
|
|
||||||
if err := migration(tx); err != nil {
|
|
||||||
log.Infof("Unable to apply migration #%v",
|
|
||||||
migrationVersions[i])
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meta.DbVersionNumber = latestVersion
|
|
||||||
return putMeta(meta, tx)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChannelGraph returns a new instance of the directed channel graph.
|
// ChannelGraph returns a new instance of the directed channel graph.
|
||||||
func (d *DB) ChannelGraph() *ChannelGraph {
|
func (d *DB) ChannelGraph() *ChannelGraph {
|
||||||
return d.graph
|
return d.graph
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLatestDBVersion(versions []version) uint32 {
|
|
||||||
return versions[len(versions)-1].number
|
|
||||||
}
|
|
||||||
|
|
||||||
// getMigrationsToApply retrieves the migration function that should be
|
|
||||||
// applied to the database.
|
|
||||||
func getMigrationsToApply(versions []version, version uint32) ([]migration, []uint32) {
|
|
||||||
migrations := make([]migration, 0, len(versions))
|
|
||||||
migrationVersions := make([]uint32, 0, len(versions))
|
|
||||||
|
|
||||||
for _, v := range versions {
|
|
||||||
if v.number > version {
|
|
||||||
migrations = append(migrations, v.migration)
|
|
||||||
migrationVersions = append(migrationVersions, v.number)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return migrations, migrationVersions
|
|
||||||
}
|
|
||||||
|
@ -5,11 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
||||||
// ErrDBReversion is returned when detecting an attempt to revert to a
|
|
||||||
// prior database version.
|
|
||||||
ErrDBReversion = fmt.Errorf("channel db cannot revert to prior version")
|
|
||||||
|
|
||||||
// ErrNoInvoicesCreated is returned when we don't have invoices in
|
// ErrNoInvoicesCreated is returned when we don't have invoices in
|
||||||
// our database to return.
|
// our database to return.
|
||||||
ErrNoInvoicesCreated = fmt.Errorf("there are no existing invoices")
|
ErrNoInvoicesCreated = fmt.Errorf("there are no existing invoices")
|
||||||
@ -18,10 +13,6 @@ var (
|
|||||||
// created.
|
// created.
|
||||||
ErrNoPaymentsCreated = fmt.Errorf("there are no existing payments")
|
ErrNoPaymentsCreated = fmt.Errorf("there are no existing payments")
|
||||||
|
|
||||||
// ErrMetaNotFound is returned when meta bucket hasn't been
|
|
||||||
// created.
|
|
||||||
ErrMetaNotFound = fmt.Errorf("unable to locate meta information")
|
|
||||||
|
|
||||||
// ErrGraphNotFound is returned when at least one of the components of
|
// ErrGraphNotFound is returned when at least one of the components of
|
||||||
// graph doesn't exist.
|
// graph doesn't exist.
|
||||||
ErrGraphNotFound = fmt.Errorf("graph bucket not initialized")
|
ErrGraphNotFound = fmt.Errorf("graph bucket not initialized")
|
||||||
|
@ -18,47 +18,6 @@ type Meta struct {
|
|||||||
DbVersionNumber uint32
|
DbVersionNumber uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchMeta fetches the meta data from boltdb and returns filled meta
|
|
||||||
// structure.
|
|
||||||
func (d *DB) FetchMeta(tx *bbolt.Tx) (*Meta, error) {
|
|
||||||
meta := &Meta{}
|
|
||||||
|
|
||||||
err := d.View(func(tx *bbolt.Tx) error {
|
|
||||||
return fetchMeta(meta, tx)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetchMeta is an internal helper function used in order to allow callers to
|
|
||||||
// re-use a database transaction. See the publicly exported FetchMeta method
|
|
||||||
// for more information.
|
|
||||||
func fetchMeta(meta *Meta, tx *bbolt.Tx) error {
|
|
||||||
metaBucket := tx.Bucket(metaBucket)
|
|
||||||
if metaBucket == nil {
|
|
||||||
return ErrMetaNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
data := metaBucket.Get(dbVersionKey)
|
|
||||||
if data == nil {
|
|
||||||
meta.DbVersionNumber = 0
|
|
||||||
} else {
|
|
||||||
meta.DbVersionNumber = byteOrder.Uint32(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PutMeta writes the passed instance of the database met-data struct to disk.
|
|
||||||
func (d *DB) PutMeta(meta *Meta) error {
|
|
||||||
return d.Update(func(tx *bbolt.Tx) error {
|
|
||||||
return putMeta(meta, tx)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// putMeta is an internal helper function used in order to allow callers to
|
// putMeta is an internal helper function used in order to allow callers to
|
||||||
// re-use a database transaction. See the publicly exported PutMeta method for
|
// re-use a database transaction. See the publicly exported PutMeta method for
|
||||||
// more information.
|
// more information.
|
||||||
|
@ -3,6 +3,7 @@ package migration_01_to_11
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/coreos/bbolt"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,24 +32,6 @@ func applyMigration(t *testing.T, beforeMigration, afterMigration func(d *DB),
|
|||||||
// with test data.
|
// with test data.
|
||||||
beforeMigration(cdb)
|
beforeMigration(cdb)
|
||||||
|
|
||||||
// Create test meta info with zero database version and put it on disk.
|
|
||||||
// Than creating the version list pretending that new version was added.
|
|
||||||
meta := &Meta{DbVersionNumber: 0}
|
|
||||||
if err := cdb.PutMeta(meta); err != nil {
|
|
||||||
t.Fatalf("unable to store meta data: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
versions := []version{
|
|
||||||
{
|
|
||||||
number: 0,
|
|
||||||
migration: nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
number: 1,
|
|
||||||
migration: migrationFunc,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
err = errors.New(r)
|
err = errors.New(r)
|
||||||
@ -65,8 +48,10 @@ func applyMigration(t *testing.T, beforeMigration, afterMigration func(d *DB),
|
|||||||
afterMigration(cdb)
|
afterMigration(cdb)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Sync with the latest version - applying migration function.
|
// Apply migration.
|
||||||
err = cdb.syncVersions(versions)
|
err = cdb.Update(func(tx *bbolt.Tx) error {
|
||||||
|
return migrationFunc(tx)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -88,15 +88,6 @@ func TestMigrateInvoices(t *testing.T) {
|
|||||||
|
|
||||||
// Verify that all invoices were migrated.
|
// Verify that all invoices were migrated.
|
||||||
afterMigrationFunc := func(d *DB) {
|
afterMigrationFunc := func(d *DB) {
|
||||||
meta, err := d.FetchMeta(nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if meta.DbVersionNumber != 1 {
|
|
||||||
t.Fatal("migration 'invoices' wasn't applied")
|
|
||||||
}
|
|
||||||
|
|
||||||
dbInvoices, err := d.FetchAllInvoices(false)
|
dbInvoices, err := d.FetchAllInvoices(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch invoices: %v", err)
|
t.Fatalf("unable to fetch invoices: %v", err)
|
||||||
|
@ -135,15 +135,6 @@ func TestPaymentStatusesMigration(t *testing.T) {
|
|||||||
// Verify that the created payment status is "Completed" for our one
|
// Verify that the created payment status is "Completed" for our one
|
||||||
// fake payment.
|
// fake payment.
|
||||||
afterMigrationFunc := func(d *DB) {
|
afterMigrationFunc := func(d *DB) {
|
||||||
meta, err := d.FetchMeta(nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if meta.DbVersionNumber != 1 {
|
|
||||||
t.Fatal("migration 'paymentStatusesMigration' wasn't applied")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that our completed payments were migrated.
|
// Check that our completed payments were migrated.
|
||||||
paymentStatus, err := d.fetchPaymentStatus(paymentHash)
|
paymentStatus, err := d.fetchPaymentStatus(paymentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -404,15 +395,6 @@ func TestMigrateOptionalChannelCloseSummaryFields(t *testing.T) {
|
|||||||
|
|
||||||
// After the migration it should be found in the new format.
|
// After the migration it should be found in the new format.
|
||||||
afterMigrationFunc := func(d *DB) {
|
afterMigrationFunc := func(d *DB) {
|
||||||
meta, err := d.FetchMeta(nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if meta.DbVersionNumber != 1 {
|
|
||||||
t.Fatal("migration wasn't applied")
|
|
||||||
}
|
|
||||||
|
|
||||||
// We generate the new serialized version, to check
|
// We generate the new serialized version, to check
|
||||||
// against what is found in the DB.
|
// against what is found in the DB.
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
@ -521,16 +503,8 @@ func TestMigrateGossipMessageStoreKeys(t *testing.T) {
|
|||||||
// 2. We can find the message under its new key.
|
// 2. We can find the message under its new key.
|
||||||
// 3. The message matches the original.
|
// 3. The message matches the original.
|
||||||
afterMigration := func(db *DB) {
|
afterMigration := func(db *DB) {
|
||||||
meta, err := db.FetchMeta(nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to fetch db version: %v", err)
|
|
||||||
}
|
|
||||||
if meta.DbVersionNumber != 1 {
|
|
||||||
t.Fatalf("migration should have succeeded but didn't")
|
|
||||||
}
|
|
||||||
|
|
||||||
var rawMsg []byte
|
var rawMsg []byte
|
||||||
err = db.View(func(tx *bbolt.Tx) error {
|
err := db.View(func(tx *bbolt.Tx) error {
|
||||||
messageStore := tx.Bucket(messageStoreBucket)
|
messageStore := tx.Bucket(messageStoreBucket)
|
||||||
if messageStore == nil {
|
if messageStore == nil {
|
||||||
return errors.New("message store bucket not " +
|
return errors.New("message store bucket not " +
|
||||||
@ -617,15 +591,6 @@ func TestOutgoingPaymentsMigration(t *testing.T) {
|
|||||||
|
|
||||||
// Verify that all payments were migrated.
|
// Verify that all payments were migrated.
|
||||||
afterMigrationFunc := func(d *DB) {
|
afterMigrationFunc := func(d *DB) {
|
||||||
meta, err := d.FetchMeta(nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if meta.DbVersionNumber != 1 {
|
|
||||||
t.Fatal("migration 'paymentStatusesMigration' wasn't applied")
|
|
||||||
}
|
|
||||||
|
|
||||||
sentPayments, err := d.fetchPaymentsMigration9()
|
sentPayments, err := d.fetchPaymentsMigration9()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch sent payments: %v", err)
|
t.Fatalf("unable to fetch sent payments: %v", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user