Class LevelDBStorage
- All Implemented Interfaces:
BlockchainStorage,AutoCloseable
BlockchainStorage implementation backed by LevelDB.
LevelDB is a sorted key-value store with write-ahead logging (WAL) that
guarantees atomicity and crash-recovery (NFR-REL-01). Each block is stored under
a big-endian 4-byte integer key equal to its index, serialized to JSON via
BlockSerializer.
Key layout
Key : big-endian 4-byte block index (e.g., block 7 → 0x00_00_00_07) Value: UTF-8 JSON of the Block object
Using numeric big-endian keys ensures LevelDB's lexicographic ordering matches
the natural block order, making loadAll() a single sequential scan without
any sorting overhead.
Thread safety
Concurrent reads use the read lock; all writes acquire the exclusive write lock.
The underlying LevelDB instance is thread-safe for concurrent reads once opened,
but we add our own ReentrantReadWriteLock to serialize writes and guard
against concurrent close operations.
Lifecycle
Instantiate once via the constructor, inject into BlockchainConfig,
and call close() when the node shuts down to release the LevelDB file
lock. Failing to call close() will leave a LOCK file and prevent
other processes from opening the same database directory.
Usage
try (LevelDBStorage storage = new LevelDBStorage("/data/chain")) {
BlockchainNode node = BlockchainConfig.builder()
.storage(storage)
.build();
node.start();
// ...
}
- Since:
- 1.0.0
- See Also:
-
Constructor Summary
ConstructorsConstructorDescriptionLevelDBStorage(String dataDirectory) Opens (or creates) a LevelDB database at the given directory path. -
Method Summary
Modifier and TypeMethodDescriptionintReturns the number of stored blocks by counting block-keyed entries.voidclose()Closes the LevelDB database and releases the file lock.voidRemoves all block entries from the LevelDB store.booleanReturnstrueif a block with the given hash exists.loadAll()Returns all stored blocks in ascending index order.loadBlock(int index) Retrieves a block by its index.loadBlockByHash(String hash) Searches for a block by its SHA-256 hash.voidPersists a block atomically using a LevelDBWriteBatch.toString()Returns a human-readable description of this storage instance.
-
Constructor Details
-
LevelDBStorage
Opens (or creates) a LevelDB database at the given directory path.If the directory does not exist it will be created automatically by LevelDB. If the database is already locked by another process an exception is thrown immediately rather than blocking.
- Parameters:
dataDirectory- path to the directory where LevelDB files will be stored- Throws:
NullPointerException- ifdataDirectoryis nullIllegalArgumentException- ifdataDirectoryis blankBlockValidationException- if the database cannot be opened
-
-
Method Details
-
saveBlock
Persists a block atomically using a LevelDBWriteBatch.Using a write batch guarantees that the block is either fully written or not written at all, satisfying the atomicity requirement of
BlockchainStorage.saveBlock(com.privatechain.core.model.Block).- Specified by:
saveBlockin interfaceBlockchainStorage- Parameters:
block- the block to persist (non-null)- Throws:
NullPointerException- ifblockis nullBlockValidationException- if the write fails
-
loadBlock
Retrieves a block by its index.- Specified by:
loadBlockin interfaceBlockchainStorage- Parameters:
index- block index (≥ 0)- Returns:
- the deserialized
Block - Throws:
NoSuchElementException- if no block exists atindexBlockValidationException- if deserialization or hash verification fails
-
loadBlockByHash
Searches for a block by its SHA-256 hash.Because LevelDB is indexed by block index (not hash), this is a sequential scan. For production chains with millions of blocks, consider maintaining a secondary index; for the current milestone this linear scan is sufficient.
- Specified by:
loadBlockByHashin interfaceBlockchainStorage- Parameters:
hash- hex-encoded block hash (non-null)- Returns:
- an
Optionalcontaining the matching block, or empty if absent - Throws:
NullPointerException- ifhashis null
-
loadAll
Returns all stored blocks in ascending index order.Leverages LevelDB's lexicographic ordering of big-endian keys to perform a single sequential forward scan without sorting.
- Specified by:
loadAllin interfaceBlockchainStorage- Returns:
- non-null, ordered list (maybe empty)
-
exists
Returnstrueif a block with the given hash exists.- Specified by:
existsin interfaceBlockchainStorage- Parameters:
hash- hex-encoded block hash (non-null)- Returns:
trueif present- Throws:
NullPointerException- ifhashis null
-
chainHeight
public int chainHeight()Returns the number of stored blocks by counting block-keyed entries.- Specified by:
chainHeightin interfaceBlockchainStorage- Returns:
- block count (≥ 0)
-
deleteAll
public void deleteAll()Removes all block entries from the LevelDB store.Warning: This is irreversible. Intended for testing and chain-reset scenarios only.
- Specified by:
deleteAllin interfaceBlockchainStorage
-
close
public void close()Closes the LevelDB database and releases the file lock.Must be called when the owning
BlockchainNodestops to prevent a staleLOCKfile from blocking subsequent opens. Idempotent — repeated calls after the first are silently ignored.- Specified by:
closein interfaceAutoCloseable- Throws:
BlockValidationException- if closing the database fails
-
toString
Returns a human-readable description of this storage instance.
-