watchtower/wtdb/tower_db: add TowerDB and db versioning
This commit is contained in:
2 files changed
+817
No files matched your search
@@ -0,0 +1,84 @@
|
||||
package wtdb
|
||||
|
||||
import "github.com/coreos/bbolt"
|
||||
|
||||
// migration is a function which takes a prior outdated version of the database
|
||||
// instances and mutates the key/bucket structure to arrive at a more
|
||||
// up-to-date version of the database.
|
||||
type migration func(tx *bbolt.Tx) error
|
||||
|
||||
// version pairs a version number with the migration that would need to be
|
||||
// applied from the prior version to upgrade.
|
||||
type version struct {
|
||||
number uint32
|
||||
migration migration
|
||||
}
|
||||
|
||||
// dbVersions stores all versions and migrations of the database. This list will
|
||||
// be used when opening the database to determine if any migrations must be
|
||||
// applied.
|
||||
var dbVersions = []version{
|
||||
{
|
||||
// Initial version requires no migration.
|
||||
number: 0,
|
||||
migration: nil,
|
||||
},
|
||||
}
|
||||
|
||||
// getLatestDBVersion returns the last known database version.
|
||||
func getLatestDBVersion(versions []version) uint32 {
|
||||
return versions[len(versions)-1].number
|
||||
}
|
||||
|
||||
// getMigrations returns a slice of all updates with a greater number that
|
||||
// curVersion that need to be applied to sync up with the latest version.
|
||||
func getMigrations(versions []version, curVersion uint32) []version {
|
||||
var updates []version
|
||||
for _, v := range versions {
|
||||
if v.number > curVersion {
|
||||
updates = append(updates, v)
|
||||
}
|
||||
}
|
||||
|
||||
return updates
|
||||
}
|
||||
|
||||
// getDBVersion retrieves the current database version from the metadata bucket
|
||||
// using the dbVersionKey.
|
||||
func getDBVersion(tx *bbolt.Tx) (uint32, error) {
|
||||
metadata := tx.Bucket(metadataBkt)
|
||||
if metadata == nil {
|
||||
return 0, ErrUninitializedDB
|
||||
}
|
||||
|
||||
versionBytes := metadata.Get(dbVersionKey)
|
||||
if len(versionBytes) != 4 {
|
||||
return 0, ErrNoDBVersion
|
||||
}
|
||||
|
||||
return byteOrder.Uint32(versionBytes), nil
|
||||
}
|
||||
|
||||
// initDBVersion initializes the top-level metadata bucket and writes the passed
|
||||
// version number as the current version.
|
||||
func initDBVersion(tx *bbolt.Tx, version uint32) error {
|
||||
_, err := tx.CreateBucketIfNotExists(metadataBkt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return putDBVersion(tx, version)
|
||||
}
|
||||
|
||||
// putDBVersion stores the passed database version in the metadata bucket under
|
||||
// the dbVersionKey.
|
||||
func putDBVersion(tx *bbolt.Tx, version uint32) error {
|
||||
metadata := tx.Bucket(metadataBkt)
|
||||
if metadata == nil {
|
||||
return ErrUninitializedDB
|
||||
}
|
||||
|
||||
versionBytes := make([]byte, 4)
|
||||
byteOrder.PutUint32(versionBytes, version)
|
||||
return metadata.Put(dbVersionKey, versionBytes)
|
||||
}
|
||||
Reference in new issue
Block a user