channeldb: add NoMigration mode

In case the channeldb package is used as a library in external tools, it
can be useful to allow read-only access to a DB. This allows such a
tool to access a DB even if not all migrations were executed, which can
be useful for recovery purposes.
To make it possible to even start the DB with a read-only backend, we
need to disable the automatic migration step.
This commit is contained in:
Oliver Gugger
2021-12-13 10:53:58 +01:00
parent a8f75e0221
commit b147d589c1
5 changed files with 33 additions and 13 deletions

View File

@@ -263,15 +263,17 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
// CreateWithBackend creates channeldb instance using the passed kvdb.Backend. // CreateWithBackend creates channeldb instance using the passed kvdb.Backend.
// Any necessary schemas migrations due to updates will take place as necessary. // Any necessary schemas migrations due to updates will take place as necessary.
func CreateWithBackend(backend kvdb.Backend, modifiers ...OptionModifier) (*DB, error) { func CreateWithBackend(backend kvdb.Backend, modifiers ...OptionModifier) (*DB, error) {
if err := initChannelDB(backend); err != nil {
return nil, err
}
opts := DefaultOptions() opts := DefaultOptions()
for _, modifier := range modifiers { for _, modifier := range modifiers {
modifier(&opts) modifier(&opts)
} }
if !opts.NoMigration {
if err := initChannelDB(backend); err != nil {
return nil, err
}
}
chanDB := &DB{ chanDB := &DB{
Backend: backend, Backend: backend,
channelStateDB: &ChannelStateDB{ channelStateDB: &ChannelStateDB{
@@ -291,17 +293,19 @@ func CreateWithBackend(backend kvdb.Backend, modifiers ...OptionModifier) (*DB,
chanDB.graph, err = NewChannelGraph( chanDB.graph, err = NewChannelGraph(
backend, opts.RejectCacheSize, opts.ChannelCacheSize, backend, opts.RejectCacheSize, opts.ChannelCacheSize,
opts.BatchCommitInterval, opts.PreAllocCacheNumNodes, opts.BatchCommitInterval, opts.PreAllocCacheNumNodes,
opts.UseGraphCache, opts.UseGraphCache, opts.NoMigration,
) )
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Synchronize the version of database and apply migrations if needed. // Synchronize the version of database and apply migrations if needed.
if !opts.NoMigration {
if err := chanDB.syncVersions(dbVersions); err != nil { if err := chanDB.syncVersions(dbVersions); err != nil {
backend.Close() backend.Close()
return nil, err return nil, err
} }
}
return chanDB, nil return chanDB, nil
} }

View File

@@ -189,11 +189,13 @@ type ChannelGraph struct {
// returned instance has its own unique reject cache and channel cache. // returned instance has its own unique reject cache and channel cache.
func NewChannelGraph(db kvdb.Backend, rejectCacheSize, chanCacheSize int, func NewChannelGraph(db kvdb.Backend, rejectCacheSize, chanCacheSize int,
batchCommitInterval time.Duration, preAllocCacheNumNodes int, batchCommitInterval time.Duration, preAllocCacheNumNodes int,
useGraphCache bool) (*ChannelGraph, error) { useGraphCache, noMigrations bool) (*ChannelGraph, error) {
if !noMigrations {
if err := initChannelGraph(db); err != nil { if err := initChannelGraph(db); err != nil {
return nil, err return nil, err
} }
}
g := &ChannelGraph{ g := &ChannelGraph{
db: db, db: db,

View File

@@ -77,7 +77,7 @@ func MakeTestGraph(modifiers ...OptionModifier) (*ChannelGraph, func(), error) {
graph, err := NewChannelGraph( graph, err := NewChannelGraph(
backend, opts.RejectCacheSize, opts.ChannelCacheSize, backend, opts.RejectCacheSize, opts.ChannelCacheSize,
opts.BatchCommitInterval, opts.PreAllocCacheNumNodes, opts.BatchCommitInterval, opts.PreAllocCacheNumNodes,
true, true, false,
) )
if err != nil { if err != nil {
backendCleanup() backendCleanup()

View File

@@ -50,6 +50,11 @@ type Options struct {
// path finding. // path finding.
UseGraphCache bool UseGraphCache bool
// NoMigration specifies that underlying backend was opened in read-only
// mode and migrations shouldn't be performed. This can be useful for
// applications that use the channeldb package as a library.
NoMigration bool
// clock is the time source used by the database. // clock is the time source used by the database.
clock clock.Clock clock clock.Clock
@@ -71,6 +76,7 @@ func DefaultOptions() Options {
ChannelCacheSize: DefaultChannelCacheSize, ChannelCacheSize: DefaultChannelCacheSize,
PreAllocCacheNumNodes: DefaultPreAllocCacheNumNodes, PreAllocCacheNumNodes: DefaultPreAllocCacheNumNodes,
UseGraphCache: true, UseGraphCache: true,
NoMigration: false,
clock: clock.NewDefaultClock(), clock: clock.NewDefaultClock(),
} }
} }
@@ -136,6 +142,14 @@ func OptionSetBatchCommitInterval(interval time.Duration) OptionModifier {
} }
} }
// OptionNoMigration allows the database to be opened in read only mode by
// disabling migrations.
func OptionNoMigration(b bool) OptionModifier {
return func(o *Options) {
o.NoMigration = b
}
}
// OptionClock sets a non-default clock dependency. // OptionClock sets a non-default clock dependency.
func OptionClock(clock clock.Clock) OptionModifier { func OptionClock(clock clock.Clock) OptionModifier {
return func(o *Options) { return func(o *Options) {

View File

@@ -175,7 +175,7 @@ func makeTestGraph(useCache bool) (*channeldb.ChannelGraph, kvdb.Backend,
graph, err := channeldb.NewChannelGraph( graph, err := channeldb.NewChannelGraph(
backend, opts.RejectCacheSize, opts.ChannelCacheSize, backend, opts.RejectCacheSize, opts.ChannelCacheSize,
opts.BatchCommitInterval, opts.PreAllocCacheNumNodes, opts.BatchCommitInterval, opts.PreAllocCacheNumNodes,
useCache, useCache, false,
) )
if err != nil { if err != nil {
cleanUp() cleanUp()