mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-29 07:00:55 +02:00
channeldb: add optional meta and migration30
This commit enables the db to run optional migrations that are specified by config flags. To achieve this, an optional meta is introduced to manage the optional migrations. We distinguish the two types of migrations here so it's easier to manage them for the concern a future migration can cause trouble for us to determine the db version if we don't.
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -12,6 +16,10 @@ var (
|
||||
// dbVersionKey is a boltdb key and it's used for storing/retrieving
|
||||
// current database version.
|
||||
dbVersionKey = []byte("dbp")
|
||||
|
||||
// dbVersionKey is a boltdb key and it's used for storing/retrieving
|
||||
// a list of optional migrations that have been applied.
|
||||
optionalVersionKey = []byte("ovk")
|
||||
)
|
||||
|
||||
// Meta structure holds the database meta information.
|
||||
@@ -80,3 +88,92 @@ func putDbVersion(metaBucket kvdb.RwBucket, meta *Meta) error {
|
||||
byteOrder.PutUint32(scratch, meta.DbVersionNumber)
|
||||
return metaBucket.Put(dbVersionKey, scratch)
|
||||
}
|
||||
|
||||
// OptionalMeta structure holds the database optional migration information.
|
||||
type OptionalMeta struct {
|
||||
// Versions is a set that contains the versions that have been applied.
|
||||
// When saved to disk, only the indexes are stored.
|
||||
Versions map[uint64]string
|
||||
}
|
||||
|
||||
func (om *OptionalMeta) String() string {
|
||||
s := ""
|
||||
for index, name := range om.Versions {
|
||||
s += fmt.Sprintf("%d: %s", index, name)
|
||||
}
|
||||
if s == "" {
|
||||
s = "empty"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// fetchOptionalMeta reads the optional meta from the database.
|
||||
func (d *DB) fetchOptionalMeta() (*OptionalMeta, error) {
|
||||
om := &OptionalMeta{
|
||||
Versions: make(map[uint64]string),
|
||||
}
|
||||
|
||||
err := kvdb.View(d, func(tx kvdb.RTx) error {
|
||||
metaBucket := tx.ReadBucket(metaBucket)
|
||||
if metaBucket == nil {
|
||||
return ErrMetaNotFound
|
||||
}
|
||||
|
||||
vBytes := metaBucket.Get(optionalVersionKey)
|
||||
// Exit early if nothing found.
|
||||
if vBytes == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read the versions' length.
|
||||
r := bytes.NewReader(vBytes)
|
||||
vLen, err := tlv.ReadVarInt(r, &[8]byte{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the version index.
|
||||
for i := uint64(0); i < vLen; i++ {
|
||||
version, err := tlv.ReadVarInt(r, &[8]byte{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
om.Versions[version] = optionalVersions[i].name
|
||||
}
|
||||
|
||||
return nil
|
||||
}, func() {})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return om, nil
|
||||
}
|
||||
|
||||
// fetchOptionalMeta writes an optional meta to the database.
|
||||
func (d *DB) putOptionalMeta(om *OptionalMeta) error {
|
||||
return kvdb.Update(d, func(tx kvdb.RwTx) error {
|
||||
metaBucket, err := tx.CreateTopLevelBucket(metaBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
|
||||
// Write the total length.
|
||||
err = tlv.WriteVarInt(&b, uint64(len(om.Versions)), &[8]byte{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the version indexes.
|
||||
for v := range om.Versions {
|
||||
err := tlv.WriteVarInt(&b, v, &[8]byte{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return metaBucket.Put(optionalVersionKey, b.Bytes())
|
||||
}, func() {})
|
||||
}
|
||||
|
Reference in New Issue
Block a user