nimbus-eth1/nimbus/db/era1_db/db_desc.nim

96 lines
3.0 KiB
Nim

# Nimbus
# Copyright (c) 2021-2024 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
{.push raises: [].}
import
std/[os, tables],
stew/[interval_set, keyed_queue, sorted_set],
results,
../../fluffy/eth_data/era1
const
NumOpenEra1DbBlocks* = 10
type
Era1DbError* = enum
NothingWrong = 0
Era1DbBlocks* = object
## Capability of an `era1` file, to be indexed by starting block num
fileName*: string # File name on disk
nBlocks*: uint # Number of blocks available
Era1DbRef* = ref object
dir*: string # Database folder
blocks*: KeyedQueue[uint64,Era1File] # Era1 block on disk
byBlkNum*: SortedSet[uint64,Era1DbBlocks] # File access info
ranges*: IntervalSetRef[uint64,uint64] # Covered ranges
# ------------------------------------------------------------------------------
# Private helpers
# ------------------------------------------------------------------------------
proc load(db: Era1DbRef, eFile: string) =
let
path = db.dir / eFile
dsc = Era1File.open(path).valueOr:
return
key = dsc.blockIdx.startNumber
if db.blocks.lruFetch(key).isOk or dsc.blockIdx.offsets.len == 0:
dsc.close()
else:
# Add to LRU table
while NumOpenEra1DbBlocks <= db.blocks.len:
db.blocks.shift.value.data.close() # unqueue first/least item
discard db.blocks.lruAppend(key, dsc, NumOpenEra1DbBlocks)
# Add to index list
let w = db.byBlkNum.findOrInsert(key).valueOr:
raiseAssert "Load error, index corrupted: " & $error
if w.data.nBlocks != 0:
discard db.ranges.reduce(key, key+w.data.nBlocks.uint64-1)
w.data.fileName = eFile
w.data.nBlocks = dsc.blockIdx.offsets.len.uint
discard db.ranges.merge(key, key+dsc.blockIdx.offsets.len.uint64-1)
# ------------------------------------------------------------------------------
# Public constructor
# ------------------------------------------------------------------------------
proc init*(
T: type Era1DbRef;
dir: string;
): T =
## Load `era1` index
result = T(
dir: dir,
byBlkNum: SortedSet[uint64,Era1DbBlocks].init(),
ranges: IntervalSetRef[uint64,uint64].init())
try:
for w in dir.walkDir(relative=true):
if w.kind in {pcFile, pcLinkToFile}:
result.load w.path
except CatchableError:
discard
proc dispose*(db: Era1DbRef) =
for w in db.blocks.nextValues:
w.close()
db.blocks.clear()
db.ranges.clear()
db.byBlkNum.clear()
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------