diff --git a/Database/Package.swift b/Database/Package.swift index 92d8e400..e820ad24 100644 --- a/Database/Package.swift +++ b/Database/Package.swift @@ -17,17 +17,24 @@ let package = Package( ], dependencies: [ .package(path: "../Blockchain"), + .package(path: "../Codec"), .package(path: "../Utils"), .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), ], targets: [ - // Targets are the basic building blocks of a package, defining a module or a test suite. - // Targets can depend on other targets in this package and products from dependencies. .target( name: "Database", dependencies: [ - "rocksdb", + "RocksDBSwift", "Blockchain", + "Codec", + "Utils", + ] + ), + .target( + name: "RocksDBSwift", + dependencies: [ + "rocksdb", "Utils", ], linkerSettings: [ @@ -49,6 +56,13 @@ let package = Package( .product(name: "Testing", package: "swift-testing"), ] ), + .testTarget( + name: "RocksDBSwiftTests", + dependencies: [ + "RocksDBSwift", + .product(name: "Testing", package: "swift-testing"), + ] + ), ], swiftLanguageModes: [.version("6")] ) diff --git a/Database/Sources/Database/RocksDBBackend.swift b/Database/Sources/Database/RocksDBBackend.swift index 78f02e12..b75d1881 100644 --- a/Database/Sources/Database/RocksDBBackend.swift +++ b/Database/Sources/Database/RocksDBBackend.swift @@ -1,7 +1,27 @@ import Blockchain import Foundation +import RocksDBSwift import Utils +enum StoreId: UInt8, ColumnFamilyKey { + // metadata and configurations + case meta + // blocks + // blockHash => blockBody + case blocks + // timeslot => blockHash + // blockNumber => blockHash + case blockIndexes + // state trie + // hash => trie node + // value hash => state value + case state + // ref count + // node hash => ref count + // value hash => ref count + case stateRefs +} + public final class RocksDBBackend: StateBackendProtocol { public init() {} diff --git a/Database/Sources/Database/Options.swift b/Database/Sources/RocksDBSwift/Options.swift similarity index 64% rename from Database/Sources/Database/Options.swift rename to Database/Sources/RocksDBSwift/Options.swift index 011e9f9d..ade4bdff 100644 --- a/Database/Sources/Database/Options.swift +++ b/Database/Sources/RocksDBSwift/Options.swift @@ -1,52 +1,52 @@ import rocksdb import Utils -public struct Options: ~Copyable, Sendable { +struct Options: ~Copyable, Sendable { let ptr: SafePointer var value: OpaquePointer { ptr.value } - public init() { + init() { ptr = .init(ptr: rocksdb_options_create(), free: rocksdb_options_destroy) } - public func increaseParallelism(cpus: Int) { + func increaseParallelism(cpus: Int) { rocksdb_options_increase_parallelism(ptr.value, Int32(cpus)) } - public func optimizeLevelStyleCompaction(memtableMemoryBudget: UInt64) { + func optimizeLevelStyleCompaction(memtableMemoryBudget: UInt64) { rocksdb_options_optimize_level_style_compaction(ptr.value, memtableMemoryBudget) } - public func setCreateIfMissing(_ createIfMissing: Bool) { + func setCreateIfMissing(_ createIfMissing: Bool) { rocksdb_options_set_create_if_missing(ptr.value, createIfMissing ? 1 : 0) } - public func setLevelCompactionDynamicLevelBytes(_ levelCompactionDynamicLevelBytes: Bool) { + func setLevelCompactionDynamicLevelBytes(_ levelCompactionDynamicLevelBytes: Bool) { rocksdb_options_set_level_compaction_dynamic_level_bytes(ptr.value, levelCompactionDynamicLevelBytes ? 1 : 0) } - public func setCreateIfMissingColumnFamilies(_ createIfMissingColumnFamilies: Bool) { + func setCreateIfMissingColumnFamilies(_ createIfMissingColumnFamilies: Bool) { rocksdb_options_set_create_missing_column_families(ptr.value, createIfMissingColumnFamilies ? 1 : 0) } } -public struct WriteOptions: ~Copyable, Sendable { +struct WriteOptions: ~Copyable, Sendable { let ptr: SafePointer var value: OpaquePointer { ptr.value } - public init() { + init() { ptr = .init(ptr: rocksdb_writeoptions_create(), free: rocksdb_writeoptions_destroy) } } -public struct ReadOptions: ~Copyable, Sendable { +struct ReadOptions: ~Copyable, Sendable { let ptr: SafePointer var value: OpaquePointer { ptr.value } - public init() { + init() { ptr = .init(ptr: rocksdb_readoptions_create(), free: rocksdb_readoptions_destroy) } } diff --git a/Database/Sources/Database/RocksDB.swift b/Database/Sources/RocksDBSwift/RocksDB.swift similarity index 100% rename from Database/Sources/Database/RocksDB.swift rename to Database/Sources/RocksDBSwift/RocksDB.swift diff --git a/Database/Sources/RocksDBSwift/Store.swift b/Database/Sources/RocksDBSwift/Store.swift new file mode 100644 index 00000000..dd52f062 --- /dev/null +++ b/Database/Sources/RocksDBSwift/Store.swift @@ -0,0 +1,29 @@ +import Foundation + +public protocol StoreCoder: Sendable { + associatedtype Key: Encodable + associatedtype Value: Decodable + + func encode(key: Key) throws -> Data + func decode(data: Data) throws -> Value +} + +public final class Store: Sendable { + private let db: RocksDB + private let column: CFKey + private let coder: Coder + + public init(db: RocksDB, column: CFKey, coder: Coder) { + self.db = db + self.column = column + self.coder = coder + } + + public func get(key: Coder.Key) throws -> Coder.Value? { + let encodedKey = try coder.encode(key: key) + + let data = try db.get(column: column, key: encodedKey) + + return try data.map { try coder.decode(data: $0) } + } +} diff --git a/Database/Tests/DatabaseTests/DatabaseTests.swift b/Database/Tests/DatabaseTests/DatabaseTests.swift new file mode 100644 index 00000000..e69de29b diff --git a/Database/Tests/DatabaseTests/RocksDBTests.swift b/Database/Tests/RocksDBSwiftTests/RocksDBTests.swift similarity index 99% rename from Database/Tests/DatabaseTests/RocksDBTests.swift rename to Database/Tests/RocksDBSwiftTests/RocksDBTests.swift index 9586ccc4..e2de12b3 100644 --- a/Database/Tests/DatabaseTests/RocksDBTests.swift +++ b/Database/Tests/RocksDBSwiftTests/RocksDBTests.swift @@ -3,7 +3,7 @@ import Foundation import Testing -@testable import Database +@testable import RocksDBSwift extension String { var data: Data { Data(utf8) }