lnd/channeldb/meta.go
Andrey Samokhvalov c53ea091dd channeldb: added channeldb versioning
In this commit the upgrade mechanism for database was added which makes he current schema rigid and upgradeable. Additional bucket 'metaBucket' was added which stores
    key that house meta-data related to the current/version state of the database. 'createChannelDB' was modified to create this new bucket+key during initializing. Also
    backup logic was added which makes a complete copy of the current database during migration process and restore the previous version of database if migration failed.
2016-11-22 15:25:21 -06:00

91 lines
2.0 KiB
Go

package channeldb
import (
"github.com/boltdb/bolt"
)
var (
// metaBucket stores all the meta information concerning the state of
// the database.
metaBucket = []byte("metadata")
// dbVersionKey is a boltdb key and it's used for storing/retrieveing
// current database version.
dbVersionKey = []byte("dbp")
)
// Meta structure holds the database meta information.
type Meta struct {
dbVersionNumber uint32
}
// FetchMeta fetches the meta data from boltdb and returns filled meta
// structure. If transaction object is specified then it will be used rather
// than initiation creation of new one.
func (d *DB) FetchMeta(tx *bolt.Tx) (*Meta, error) {
meta := &Meta{}
fetchMeta := func(tx *bolt.Tx) error {
if metaBucket := tx.Bucket(metaBucket); metaBucket != nil {
fetchDbVersion(metaBucket, meta)
return nil
} else {
return ErrMetaNotFound
}
}
var err error
if tx == nil {
err = d.store.View(fetchMeta)
} else {
err = fetchMeta(tx)
}
if err != nil {
return nil, err
}
return meta, nil
}
// PutMeta gets as input meta structure and put it into boltdb. If transaction
// object is specified then it will be used rather than initiation creation of
// new one.
func (d *DB) PutMeta(meta *Meta, tx *bolt.Tx) error {
putMeta := func(tx *bolt.Tx) error {
metaBucket := tx.Bucket(metaBucket)
if metaBucket == nil {
return ErrMetaNotFound
}
if err := putDbVersion(metaBucket, meta); err != nil {
return err
}
return nil
}
if tx == nil {
return d.store.Update(putMeta)
} else {
return putMeta(tx)
}
}
func putDbVersion(metaBucket *bolt.Bucket, meta *Meta) error {
scratch := make([]byte, 4)
byteOrder.PutUint32(scratch, meta.dbVersionNumber)
if err := metaBucket.Put(dbVersionKey, scratch); err != nil {
return err
}
return nil
}
func fetchDbVersion(metaBucket *bolt.Bucket, meta *Meta) {
if data := metaBucket.Get(dbVersionKey); data != nil {
meta.dbVersionNumber = byteOrder.Uint32(data)
} else {
meta.dbVersionNumber = getLatestDBVersion(DBVersions)
}
}