-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3908 from oasisprotocol/kostko/feature/rt-storage…
…-rename go/oasis-node: Add storage namespace rename subcommand
- Loading branch information
Showing
4 changed files
with
175 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
go/oasis-node: Add storage namespace rename subcommand |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package badger | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/dgraph-io/badger/v2" | ||
|
||
"github.com/oasisprotocol/oasis-core/go/common" | ||
"github.com/oasisprotocol/oasis-core/go/common/cbor" | ||
"github.com/oasisprotocol/oasis-core/go/common/logging" | ||
"github.com/oasisprotocol/oasis-core/go/storage/mkvs/db/api" | ||
) | ||
|
||
// RenameNamespace changes the namespace specified in the database. | ||
func RenameNamespace(cfg *api.Config, newNamespace common.Namespace) error { | ||
db := &badgerNodeDB{ | ||
logger: logging.GetLogger("mkvs/db/badger/rename"), | ||
namespace: cfg.Namespace, | ||
discardWriteLogs: cfg.DiscardWriteLogs, | ||
} | ||
opts := commonConfigToBadgerOptions(cfg, db) | ||
|
||
var err error | ||
if db.db, err = badger.OpenManaged(opts); err != nil { | ||
return fmt.Errorf("failed to open database: %w", err) | ||
} | ||
defer db.Close() | ||
|
||
tx := db.db.NewTransactionAt(tsMetadata, true) | ||
defer tx.Discard() | ||
|
||
item, err := tx.Get(metadataKeyFmt.Encode()) | ||
switch err { | ||
case nil: | ||
case badger.ErrKeyNotFound: | ||
// Nothing to rename. | ||
return nil | ||
default: | ||
return err | ||
} | ||
|
||
var meta metadata | ||
err = item.Value(func(data []byte) error { | ||
return cbor.UnmarshalTrusted(data, &meta.value) | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed to load database metadata: %w", err) | ||
} | ||
|
||
// Sanity checks. | ||
if meta.value.Version != dbVersion { | ||
return fmt.Errorf("incompatible database version (expected: %d got: %d)", | ||
dbVersion, | ||
meta.value.Version, | ||
) | ||
} | ||
if !meta.value.Namespace.Equal(&cfg.Namespace) { | ||
return fmt.Errorf("incompatible namespace (expected: %s got: %s)", | ||
cfg.Namespace, | ||
meta.value.Namespace, | ||
) | ||
} | ||
|
||
// Rename the namespace in database metadata. | ||
meta.value.Namespace = newNamespace | ||
if err = meta.save(tx); err != nil { | ||
return fmt.Errorf("failed to save database metadata: %w", err) | ||
} | ||
if err = tx.CommitAt(tsMetadata, nil); err != nil { | ||
return fmt.Errorf("failed to commit database metadata: %w", err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package badger | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/oasisprotocol/oasis-core/go/common" | ||
"github.com/oasisprotocol/oasis-core/go/storage/mkvs/db/api" | ||
) | ||
|
||
func TestRenameNamespace(t *testing.T) { | ||
require := require.New(t) | ||
|
||
srcNs := common.NewTestNamespaceFromSeed([]byte("badger node db test ns 1"), 0) | ||
dstNs := common.NewTestNamespaceFromSeed([]byte("badger node db test ns 2"), 0) | ||
|
||
// Create a new random temporary directory under /tmp. | ||
dir, err := ioutil.TempDir("", "mkvs.test.badger") | ||
require.NoError(err, "TempDir") | ||
defer os.RemoveAll(dir) | ||
|
||
dbCfg = &api.Config{ | ||
DB: dir, | ||
Namespace: srcNs, | ||
MaxCacheSize: 16 * 1024 * 1024, | ||
NoFsync: true, | ||
} | ||
|
||
ndb, err := New(dbCfg) | ||
require.NoError(err, "New(srcNs)") | ||
ndb.Close() | ||
|
||
err = RenameNamespace(dbCfg, dstNs) | ||
require.NoError(err, "RenameNamespace") | ||
|
||
_, err = New(dbCfg) | ||
require.Error(err, "New(srcNs) should fail on renamed database") | ||
|
||
dbCfg.Namespace = dstNs | ||
|
||
ndb, err = New(dbCfg) | ||
require.NoError(err, "New(dstNs)") | ||
ndb.Close() | ||
} |