|
62 | 62 | // ErrActiveKeepAliveHandles is returned when attempting to close a database with unfreed memory. |
63 | 63 | ErrActiveKeepAliveHandles = errors.New("cannot close database with active keep-alive handles") |
64 | 64 |
|
65 | | - errDBClosed = errors.New("firewood database already closed") |
| 65 | + errDBClosed = errors.New("firewood database already closed") |
| 66 | + errZeroCommitCount = errors.New("deferred persistence commit count must not be 0") |
66 | 67 | ) |
67 | 68 |
|
68 | 69 | // Database is an FFI wrapper for the Rust Firewood database. |
@@ -113,14 +114,18 @@ type config struct { |
113 | 114 | rootStore bool |
114 | 115 | // expensiveMetricsEnabled controls whether expensive metrics recording is enabled. |
115 | 116 | expensiveMetricsEnabled bool |
| 117 | + // deferredPersistenceCommitCount determines the maximum number of unpersisted |
| 118 | + // revisions that can exist at a given time. |
| 119 | + deferredPersistenceCommitCount uint64 |
116 | 120 | } |
117 | 121 |
|
118 | 122 | func defaultConfig() *config { |
119 | 123 | return &config{ |
120 | | - nodeCacheEntries: 1_000_000, |
121 | | - freeListCacheEntries: 1_000_000, |
122 | | - revisions: 100, |
123 | | - readCacheStrategy: OnlyCacheWrites, |
| 124 | + nodeCacheEntries: 1_000_000, |
| 125 | + freeListCacheEntries: 1_000_000, |
| 126 | + revisions: 100, |
| 127 | + readCacheStrategy: OnlyCacheWrites, |
| 128 | + deferredPersistenceCommitCount: 1, |
124 | 129 | } |
125 | 130 | } |
126 | 131 |
|
@@ -193,6 +198,15 @@ func WithExpensiveMetrics() Option { |
193 | 198 | } |
194 | 199 | } |
195 | 200 |
|
| 201 | +// WithDeferredPersistenceCommitCount sets the maximum number of unpersisted revisions |
| 202 | +// that can exist at a time. Note: `commitCount` must be greater than 0. |
| 203 | +// Default: 1 |
| 204 | +func WithDeferredPersistenceCommitCount(commitCount uint64) Option { |
| 205 | + return func(c *config) { |
| 206 | + c.deferredPersistenceCommitCount = commitCount |
| 207 | + } |
| 208 | +} |
| 209 | + |
196 | 210 | // A CacheStrategy represents the caching strategy used by a [Database]. |
197 | 211 | type CacheStrategy uint8 |
198 | 212 |
|
@@ -245,20 +259,24 @@ func New(dbDir string, nodeHashAlgorithm NodeHashAlgorithm, opts ...Option) (*Da |
245 | 259 | if conf.freeListCacheEntries < 1 { |
246 | 260 | return nil, fmt.Errorf("free list cache entries must be >= 1, got %d", conf.freeListCacheEntries) |
247 | 261 | } |
| 262 | + if conf.deferredPersistenceCommitCount == 0 { |
| 263 | + return nil, errZeroCommitCount |
| 264 | + } |
248 | 265 |
|
249 | 266 | var pinner runtime.Pinner |
250 | 267 | defer pinner.Unpin() |
251 | 268 |
|
252 | 269 | args := C.struct_DatabaseHandleArgs{ |
253 | | - dir: newBorrowedBytes([]byte(dbDir), &pinner), |
254 | | - cache_size: C.size_t(conf.nodeCacheEntries), |
255 | | - free_list_cache_size: C.size_t(conf.freeListCacheEntries), |
256 | | - revisions: C.size_t(conf.revisions), |
257 | | - strategy: C.uint8_t(conf.readCacheStrategy), |
258 | | - truncate: C.bool(conf.truncate), |
259 | | - root_store: C.bool(conf.rootStore), |
260 | | - expensive_metrics: C.bool(conf.expensiveMetricsEnabled), |
261 | | - node_hash_algorithm: C.enum_NodeHashAlgorithm(nodeHashAlgorithm), |
| 270 | + dir: newBorrowedBytes([]byte(dbDir), &pinner), |
| 271 | + cache_size: C.size_t(conf.nodeCacheEntries), |
| 272 | + free_list_cache_size: C.size_t(conf.freeListCacheEntries), |
| 273 | + revisions: C.size_t(conf.revisions), |
| 274 | + strategy: C.uint8_t(conf.readCacheStrategy), |
| 275 | + truncate: C.bool(conf.truncate), |
| 276 | + root_store: C.bool(conf.rootStore), |
| 277 | + expensive_metrics: C.bool(conf.expensiveMetricsEnabled), |
| 278 | + node_hash_algorithm: C.enum_NodeHashAlgorithm(nodeHashAlgorithm), |
| 279 | + deferred_persistence_commit_count: C.uint64_t(conf.deferredPersistenceCommitCount), |
262 | 280 | } |
263 | 281 |
|
264 | 282 | return getDatabaseFromHandleResult(C.fwd_open_db(args)) |
|
0 commit comments