Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
2c21f8b
initial attempt
rtjohnso Jul 17, 2026
4c6c682
clarify durability semantics
rtjohnso Jul 17, 2026
6954ceb
get rid of mark_dirty
rtjohnso Jul 17, 2026
7aebf2c
fix cach writeback impl
rtjohnso Jul 17, 2026
c8d0fd8
simplify cache writeback
rtjohnso Jul 18, 2026
f5ed615
type decl cleanup
rtjohnso Jul 18, 2026
68dbb43
clockcache.h cleanup
rtjohnso Jul 18, 2026
a1fc2ea
cleanups
rtjohnso Jul 18, 2026
b4a0552
clockcache.c assert on async io contract violation
rtjohnso Jul 18, 2026
b45f857
clockcache.c cleanup control flow
rtjohnso Jul 18, 2026
7231532
formatting
rtjohnso Jul 18, 2026
96b0b60
Cleaning up trunk
rtjohnso Jul 19, 2026
7b8b844
clean up mini allocator recovery
rtjohnso Jul 19, 2026
45137d8
superblock reorg
rtjohnso Jul 23, 2026
eb052f5
rc_allocator cleanup
rtjohnso Jul 24, 2026
07fc939
s/open_refcounts/load_refcounts/g
rtjohnso Jul 24, 2026
500e4a5
cleanup rc_allocator.c
rtjohnso Jul 25, 2026
dbbf4b3
cleanup api for loading vs recovering refcounts
rtjohnso Jul 25, 2026
c54c04e
cleanup allocator
rtjohnso Jul 25, 2026
2645881
cleanup superblock
rtjohnso Jul 25, 2026
44e1019
cleaning up log
rtjohnso Jul 26, 2026
82944af
two-log foundation
rtjohnso Jul 26, 2026
bd45a14
non-concurrent checkpoint
rtjohnso Jul 26, 2026
902cf19
comment cleanup
rtjohnso Jul 26, 2026
5d0346b
incorporation-driven checkpointing
rtjohnso Jul 27, 2026
4361da6
formatting
rtjohnso Jul 27, 2026
8957f66
convert superblock to semantic transitions
rtjohnso Jul 28, 2026
e84b014
comment
rtjohnso Jul 28, 2026
69acd49
formatting
rtjohnso Jul 28, 2026
f1821e5
formatting
rtjohnso Jul 28, 2026
5b846a6
Cleanup log
rtjohnso Jul 28, 2026
0adc509
Cleanup log
rtjohnso Jul 28, 2026
4ba8009
log cleanup
rtjohnso Jul 28, 2026
dcfce5b
log cleanup
rtjohnso Jul 28, 2026
ac06b14
memtable cleanup
rtjohnso Jul 28, 2026
e51b09d
comment formatting cleanup
rtjohnso Jul 28, 2026
24eae2d
core cleanup
rtjohnso Jul 28, 2026
eb05adb
formatting
rtjohnso Jul 28, 2026
8430b98
simplify generation semantics in superblock
rtjohnso Jul 28, 2026
0904e1c
core cleanup
rtjohnso Jul 28, 2026
7f954e7
core cleanup
rtjohnso Jul 28, 2026
cee1ac7
core cleanup
rtjohnso Jul 28, 2026
9c9765e
make memtable_force_rotation act like a normal rotation
rtjohnso Jul 28, 2026
416a1ab
simplify core_checkpoint and fix a bug
rtjohnso Jul 29, 2026
38cb7e0
make core_checkpoint reclaim log space
rtjohnso Jul 29, 2026
9defdf6
formatting
rtjohnso Jul 29, 2026
40abda4
re-fix superblock api and callers
rtjohnso Jul 29, 2026
4154de3
formatting
rtjohnso Jul 29, 2026
a05fd10
renaming
rtjohnso Jul 29, 2026
bd888f8
simplify commit_current_root
rtjohnso Jul 29, 2026
3324216
make core_checkpoint_begin return bool
rtjohnso Jul 29, 2026
60735e8
avoid excess waiting in core_checkpoint
rtjohnso Jul 29, 2026
6c6c922
Comment
rtjohnso Jul 29, 2026
d2b0357
Comment
rtjohnso Jul 29, 2026
edff0c9
checkpoint policy cleanup
rtjohnso Jul 29, 2026
7839ee0
checkpoint policy cleanup
rtjohnso Jul 29, 2026
9718bb5
formatting
rtjohnso Jul 29, 2026
bc8981d
add stats and config
rtjohnso Jul 30, 2026
93c85d4
remove multi-table tests
rtjohnso Jul 30, 2026
5c27a42
formatting
rtjohnso Jul 30, 2026
557e29d
remove multi-table testing code
rtjohnso Jul 30, 2026
d5d555d
formatting
rtjohnso Jul 30, 2026
4b12f3f
increase shmem size in splinter_test
rtjohnso Jul 30, 2026
f83bc0e
fix gc bug
rtjohnso Jul 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,11 @@ $(BINDIR)/$(UNITDIR)/task_system_test: $(COMMON_TESTOBJ)
$(OBJDIR)/$(FUNCTIONAL_TESTSDIR)/test_async.o \
$(LIBDIR)/libsplinterdb.so

$(BINDIR)/$(UNITDIR)/superblock_test: $(COMMON_TESTOBJ) \
$(COMMON_UNIT_TESTOBJ) \
$(OBJDIR)/$(FUNCTIONAL_TESTSDIR)/test_async.o \
$(LIBDIR)/libsplinterdb.so

$(BINDIR)/$(UNITDIR)/platform_apis_test: $(UTIL_SYS) \
$(COMMON_UNIT_TESTOBJ) \
$(OBJDIR)/$(TESTS_DIR)/config.o \
Expand Down Expand Up @@ -551,6 +556,7 @@ unit/writable_buffer_test: $(BINDIR)/$(UNITDIR)/writable_buffer_test
unit/config_parse_test: $(BINDIR)/$(UNITDIR)/config_parse_test
unit/limitations_test: $(BINDIR)/$(UNITDIR)/limitations_test
unit/task_system_test: $(BINDIR)/$(UNITDIR)/task_system_test
unit/superblock_test: $(BINDIR)/$(UNITDIR)/superblock_test
unit/splinter_shmem_test: $(BINDIR)/$(UNITDIR)/splinter_shmem_test
unit/splinter_ipc_test: $(BINDIR)/$(UNITDIR)/splinter_ipc_test
unit_test: $(BINDIR)/unit_test
Expand Down
16 changes: 16 additions & 0 deletions include/splinterdb/splinterdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ typedef struct splinterdb_config {
// log
_Bool use_log;

// Automatic checkpoints: once the write-ahead log has grown by this many
// bytes, SplinterDB takes a checkpoint, which folds the logged updates into
// the durable tree and reclaims that log's space. This bounds both how much
// log a crash has to replay and how much space the log occupies.
//
// The trigger is sized in log bytes rather than in updates because the two
// are independent: a workload that repeatedly overwrites the same keys grows
// the log with every write while barely growing the tree.
//
// Zero selects a default of one cache's worth of log, on the reasoning that
// replaying much more log than the cache can hold has little to gain. To
// effectively disable automatic checkpoints -- for an application that calls
// for them itself, and accepts that the log grows until it does -- set this
// very large (UINT64_MAX).
uint64 checkpoint_log_size_bytes;

// splinter
uint64 memtable_capacity;
uint64 fanout;
Expand Down
85 changes: 60 additions & 25 deletions src/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,47 +136,71 @@ typedef platform_status (*alloc_fn)(allocator *al,
typedef refcount (*dec_ref_fn)(allocator *al, uint64 addr, page_type type);
typedef refcount (*generic_ref_fn)(allocator *al, uint64 addr);

typedef platform_status (*get_super_addr_fn)(allocator *al,
allocator_root_id spl_id,
uint64 *addr);
typedef platform_status (*alloc_super_addr_fn)(allocator *al,
allocator_root_id spl_id,
uint64 *addr);
typedef void (*remove_super_addr_fn)(allocator *al, allocator_root_id spl_id);
/*
* Record one logical reference to addr while rebuilding a recovery map (see
* allocator_load_refcounts() with rebuild == TRUE). The first reference to a
* given extent establishes its nonzero allocation floor; later references
* increment it normally. addr must be the base address of a non-reserved
* extent.
*/
typedef platform_status (*recovery_record_reference_fn)(allocator *al,
uint64 addr,
page_type type);

/*
*
*/
typedef platform_status (*generic_status_allocator_fn)(allocator *al);

/*
* Write the refcount map to its durable location and make it durable. Returns
* the base address of the persisted map in *state_addr; the caller records that
* as the superblock's allocation_state_addr only after this returns, so the
* "map is trustworthy" flag never becomes durable before the map itself. Not
* valid while a recovery rebuild is in progress.
*/
typedef platform_status (*persist_refcounts_fn)(allocator *al,
uint64 *state_addr);

typedef uint64 (*get_size_fn)(allocator *al);
typedef uint64 (*base_addr_fn)(const allocator *al, uint64 addr);

typedef void (*print_fn)(allocator *al);
typedef void (*assert_fn)(allocator *al);
typedef void (*generic_void_allocator_fn)(allocator *al);

/*
* Define an abstract allocator interface, holding different allocation-related
* function pointers.
*/
typedef struct allocator_ops {
allocator_get_config_fn get_config;
alloc_fn alloc;

alloc_fn alloc;
generic_ref_fn inc_ref;
dec_ref_fn dec_ref;
generic_ref_fn get_ref;

alloc_super_addr_fn alloc_super_addr;
get_super_addr_fn get_super_addr;
remove_super_addr_fn remove_super_addr;
// After a mount, you must do either a recovery or a load

generic_status_allocator_fn recovery_begin;
recovery_record_reference_fn recovery_record_reference;
generic_void_allocator_fn recovery_finish;

generic_status_allocator_fn load_refcounts;

persist_refcounts_fn persist;

get_size_fn in_use;

get_size_fn get_capacity;
base_addr_fn extent_base_addr;

assert_fn assert_noleaks;
generic_void_allocator_fn assert_noleaks;

print_fn print_stats;
print_fn print_allocated;
generic_void_allocator_fn print_stats;
generic_void_allocator_fn print_allocated;
} allocator_ops;

// To sub-class cache, make a cache your first field;
// To sub-class allocator, make an allocator your first field;
struct allocator {
const allocator_ops *ops;
};
Expand Down Expand Up @@ -212,23 +236,34 @@ allocator_get_refcount(allocator *al, uint64 addr)
}

static inline platform_status
allocator_get_super_addr(allocator *al, allocator_root_id spl_id, uint64 *addr)
allocator_recovery_begin(allocator *al)
{
return al->ops->get_super_addr(al, spl_id, addr);
return al->ops->recovery_begin(al);
}

static inline platform_status
allocator_alloc_super_addr(allocator *al,
allocator_root_id spl_id,
uint64 *addr)
allocator_recovery_record_reference(allocator *al, uint64 addr, page_type type)
{
return al->ops->alloc_super_addr(al, spl_id, addr);
return al->ops->recovery_record_reference(al, addr, type);
}

static inline void
allocator_remove_super_addr(allocator *al, allocator_root_id spl_id)
allocator_recovery_finish(allocator *al)
{
al->ops->recovery_finish(al);
}


static inline platform_status
allocator_load_refcounts(allocator *al)
{
return al->ops->load_refcounts(al);
}

static inline platform_status
allocator_persist(allocator *al, uint64 *state_addr)
{
return al->ops->remove_super_addr(al, spl_id);
return al->ops->persist(al, state_addr);
}

static inline uint64
Expand Down
3 changes: 1 addition & 2 deletions src/blob.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ blob_page_iterator_get_curr(blob_page_iterator *iter,
iter->cc, iter->fragment.addr, TRUE, PAGE_TYPE_BLOB);
}
cache_lock(iter->cc, iter->page);
cache_mark_dirty(iter->cc, iter->page);
}
}
}
Expand Down Expand Up @@ -327,7 +326,7 @@ blob_sync(cache *cc, slice sblob)
if (!SUCCESS(rc)) {
break;
}
cache_page_sync(cc, itor.page, FALSE, PAGE_TYPE_BLOB);
cache_page_writeback(cc, itor.page, FALSE, PAGE_TYPE_BLOB);
blob_page_iterator_advance_page(&itor);
}

Expand Down
3 changes: 0 additions & 3 deletions src/btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,6 @@ btree_node_lock(cache *cc, // IN
btree_node *node) // IN
{
cache_lock(cc, node->page);
cache_mark_dirty(cc, node->page);
}

static inline void
Expand Down Expand Up @@ -1294,8 +1293,6 @@ btree_create(cache *cc,

btree_init_hdr(cfg, root.hdr);

cache_mark_dirty(cc, root.page);

// If this btree is for a memtable then pin all pages belonging to it
if (pinned) {
cache_pin(cc, root.page);
Expand Down
Loading
Loading