Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use namespaces in legacy rocksdb driver. #2071

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
87 changes: 76 additions & 11 deletions nimbus/db/core_db/backend/legacy_rocksdb.nim
Expand Up @@ -11,43 +11,108 @@
{.push raises: [].}

import
std/[tables, sequtils],
eth/trie/db,
eth/db/kvstore,
rocksdb,
../base,
./legacy_db,
../../storage_types,
../../kvstore_rocksdb

type
LegaPersDbRef = ref object of LegacyDbRef
rdb: RocksStoreRef # for backend access with legacy mode

ChainDB = ref object of RootObj
kv: KvStoreRef
rdb: RocksStoreRef
nsMap: Table[DBKeyKind, RocksNamespaceRef]

proc toNamespace(k: DBKeyKind): string =
$ord(k)

template isDefault(k: DBKeyKind): bool =
k == DBKeyKind.default

proc getDbKeyKinds(): seq[DBKeyKind] =
var namespaces = newSeq[DBKeyKind]()
for k in DBKeyKind.items():
namespaces.add(k)
namespaces

const
dbKindLow = byte ord(DBKeyKind.low()) + 1 # add one to skip default
dbKindHigh = byte ord(DBKeyKind.high())

proc toDbKeyKind(key: openArray[byte]): DBKeyKind {.inline.} =
let prefixByte = key[0]
if prefixByte >= dbKindLow and prefixByte <= dbKindHigh:
DBKeyKind(prefixByte)
else:
default

# TODO KvStore is a virtual interface and TrieDB is a virtual interface - one
# will be enough eventually - unless the TrieDB interface gains operations
# that are not typical to KvStores
proc get(db: ChainDB, key: openArray[byte]): seq[byte] =
let kind = key.toDbKeyKind()

var res: seq[byte]
proc onData(data: openArray[byte]) = res = @data
if db.kv.get(key, onData).expect("working database"):

if kind.isDefault():
discard db.rdb.get(key, onData).expect("working database")
return res

let ns = db.nsMap.getOrDefault(kind)
if ns.contains(key).expect("working database"):
discard ns.get(key, onData).expect("working database")
else:
discard db.rdb.get(key, onData).expect("working database")

res

proc put(db: ChainDB, key, value: openArray[byte]) =
db.kv.put(key, value).expect("working database")
let kind = key.toDbKeyKind()
if kind.isDefault():
db.rdb.put(key, value).expect("working database")
else:
db.nsMap.getOrDefault(kind).put(key, value).expect("working database")

proc contains(db: ChainDB, key: openArray[byte]): bool =
db.kv.contains(key).expect("working database")
let kind = key.toDbKeyKind()

let r1 = db.rdb.contains(key).expect("working database")
if kind.isDefault():
return r1

let r2 = db.nsMap.getOrDefault(kind).contains(key).expect("working database")
r1 or r2

proc del(db: ChainDB, key: openArray[byte]): bool =
db.kv.del(key).expect("working database")
let kind = key.toDbKeyKind()

let r1 = db.rdb.del(key).expect("working database")
if kind.isDefault():
return r1

let r2 = db.nsMap.getOrDefault(kind).del(key).expect("working database")
r1 or r2

proc newChainDB(path: string): KvResult[ChainDB] =
let rdb = RocksStoreRef.init(path, "nimbus").valueOr:
let dbKeyKinds = getDbKeyKinds()

let rdb = RocksStoreRef.init(
path,
"nimbus",
namespaces = dbKeyKinds.mapIt(it.toNamespace())).valueOr:
return err(error)
ok(ChainDB(kv: kvStore rdb, rdb: rdb))

var nsMap = initTable[DBKeyKind, RocksNamespaceRef]()
for k in dbKeyKinds:
let namespace = rdb.openNamespace(k.toNamespace()).valueOr:
let msg = "DB initialisation : " & error
raise (ref ResultDefect)(msg: msg)
nsMap[k] = namespace

ok(ChainDB(rdb: rdb, nsMap: nsMap))

# ------------------------------------------------------------------------------
# Public constructor and low level data retrieval, storage & transation frame
Expand All @@ -62,7 +127,7 @@ proc newLegacyPersistentCoreDbRef*(path: string): CoreDbRef =
proc done() =
backend.rdb.close()

LegaPersDbRef(rdb: backend.rdb).init(LegacyDbPersistent, backend.trieDB, done)
LegaPersDbRef(rdb: backend.rdb).init(LegacyDbPersistent, trieDB(backend), done)

# ------------------------------------------------------------------------------
# Public helper for direct backend access
Expand Down
4 changes: 3 additions & 1 deletion nimbus/db/storage_types.nim
Expand Up @@ -13,6 +13,9 @@ import

type
DBKeyKind* = enum
# Starts at -1 because the existing code and tests require this.
# Don't change the order of the below enums or the tests will break.
default = -1
genericHash
blockNumberToHash
blockHashToScore
Expand Down Expand Up @@ -140,4 +143,3 @@ template toOpenArray*(k: DbKey): openArray[byte] =

proc `==`*(a, b: DbKey): bool {.inline.} =
a.toOpenArray == b.toOpenArray