Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions benchmarks/barrier_bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,7 @@ main(int argc, char **argv)
splinterdb *db;
checked(splinterdb_open(&cfg, &db), "open");
splinterdb_iterator *it;
checked(splinterdb_iterator_init(db, &it, greater_than_or_equal, NULL_SLICE),
"iterator init");
checked(splinterdb_iterator_init(db, &it), "iterator init");
for (uint64_t id = 0; id < batch * count; id++) {
assert(splinterdb_iterator_valid(it));
slice k, v;
Expand Down
39 changes: 14 additions & 25 deletions benchmarks/btree_prefix_bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,22 +508,16 @@ init_iterator(benchmark *b,
page_type type,
key start)
{
check(btree_iterator_init((cache *)&b->cc,
&b->btree_cfg,
it,
root,
BTREE_BRANCH_FORMAT_VERSION,
type,
greater_than_or_equal,
NEGATIVE_INFINITY_KEY,
less_than,
POSITIVE_INFINITY_KEY,
greater_than_or_equal,
start,
FALSE,
0,
0),
"iterator init");
check(
btree_iterator_init((cache *)&b->cc,
&b->btree_cfg,
it,
root,
BTREE_BRANCH_FORMAT_VERSION,
type,
&(const btree_iterator_init_options){
.start_position = key_start_at_or_after(start)}),
"iterator init");
}

static void
Expand Down Expand Up @@ -597,15 +591,10 @@ pack_once(benchmark *b, bool measured)
array_iterator it = {
.super = {.ops = &array_ops}, .tuples = b->tuples, .count = b->opt.keys};
btree_pack_req *req = allocate(1, sizeof(*req));
check(btree_pack_req_init(req,
(cache *)&b->cc,
&b->btree_cfg,
&it.super,
b->opt.keys,
0,
FALSE,
b->hid),
"pack req init");
check(
btree_pack_req_init(
req, (cache *)&b->cc, &b->btree_cfg, &it.super, b->opt.keys, b->hid),
"pack req init");
counters before = {0};
if (measured) {
before = begin_interval(b);
Expand Down
20 changes: 12 additions & 8 deletions benchmarks/hash_range_benchmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,22 @@ run_queries(splinterdb *db,
write_be(key + 8, 0);
splinterdb_iterator *it = NULL;
#ifdef PREDICATE_RANGE_FILTER_API
check(splinterdb_iterator_init_with_filter(
check(splinterdb_iterator_init(
db,
&it,
greater_than_or_equal,
slice_create(sizeof(key), key),
tenant_matches,
filter,
strcmp(mode, "pruned") == 0 ? slice_create(sizeof(hash_key), hash_key)
: NULL_SLICE));
.start_position =
splinterdb_start_at_or_after(slice_create(sizeof(key), key)),
.predicate = tenant_matches,
.predicate_context = filter,
.routing_filter_key = strcmp(mode, "pruned") == 0
? slice_create(sizeof(hash_key), hash_key)
: NULL_SLICE));
#else
check(splinterdb_iterator_init(
db, &it, greater_than_or_equal, slice_create(sizeof(key), key)));
db,
&it,
.start_position =
splinterdb_start_at_or_after(slice_create(sizeof(key), key))));
#endif
int count = 0;
while (splinterdb_iterator_valid(it)) {
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/insert_benchmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ run_worker(void *arg)
gettid());
if (w->query) {
splinterdb_lookup_result_init(
b->db, &result, SPLINTERDB_LOOKUP_VALUE, sizeof(value), value);
b->db, &result, .buffer = slice_create(sizeof(value), value));
}
while (!atomic_load_explicit(&b->start, memory_order_acquire)) {
struct timespec delay = {.tv_nsec = 1000000};
Expand Down
16 changes: 11 additions & 5 deletions benchmarks/kvbench.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,8 +758,11 @@ warm_worker(void *arg)
make_key(2 * lo, key);
wait_start();
splinterdb_iterator *it;
int rc = splinterdb_iterator_init(
kvs, &it, greater_than_or_equal, slice_create(KEY_SIZE, key));
int rc =
splinterdb_iterator_init(kvs,
&it,
.start_position = splinterdb_start_at_or_after(
slice_create(KEY_SIZE, key)));
if (rc) {
w->errors++;
fprintf(stderr, "ERROR: warm iterator_init rc=%d\n", rc);
Expand Down Expand Up @@ -815,7 +818,7 @@ point_worker(void *arg)
char buf[256];
splinterdb_lookup_result res;
splinterdb_lookup_result_init(
kvs, &res, SPLINTERDB_LOOKUP_VALUE, sizeof(buf), buf);
kvs, &res, .buffer = slice_create(sizeof(buf), buf));
uint64_t T = (uint64_t)nworkers;
uint64_t lo = opt.n * (uint64_t)w->idx / T,
hi = opt.n * (uint64_t)(w->idx + 1) / T;
Expand Down Expand Up @@ -906,7 +909,10 @@ range_worker(void *arg)
uint64_t t0 = now_ns(), t1 = 0, tl = 0;
splinterdb_iterator *it;
int rc = splinterdb_iterator_init(
kvs, &it, greater_than_or_equal, slice_create(KEY_SIZE, key));
kvs,
&it,
.start_position =
splinterdb_start_at_or_after(slice_create(KEY_SIZE, key)));
if (rc) {
w->errors++;
if (w->errors <= 3) {
Expand Down Expand Up @@ -1037,7 +1043,7 @@ verify_overwrite_sample(const phase_t *ph, int threads)
char key[KEY_SIZE], buffer[VALUE_SIZE];
splinterdb_lookup_result result;
splinterdb_lookup_result_init(
kvs, &result, SPLINTERDB_LOOKUP_VALUE, sizeof(buffer), buffer);
kvs, &result, .buffer = slice_create(sizeof(buffer), buffer));

for (int i = 0; i < threads; i++) {
worker_t *original = &workers[i];
Expand Down
15 changes: 11 additions & 4 deletions benchmarks/optimize_notification_bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,19 @@ optimize(splinterdb *db, bool empty_range)
{
slice bound = empty_range ? slice_create(1, "k") : NULL_SLICE;
#ifdef HAVE_SENTINEL_NOTIFICATION
checked(splinterdb_optimize(db, bound, bound, true, NULL), "optimize");
checked(
splinterdb_optimize(
db, .min_key = bound, .max_key = bound, .full_leaf_compactions = true),
"optimize");
#else
splinterdb_notification note;
splinterdb_notification_init_blocking(&note);
checked(splinterdb_optimize(db, bound, bound, true, &note), "optimize");
checked(splinterdb_optimize(db,
.min_key = bound,
.max_key = bound,
.full_leaf_compactions = true,
.notification = &note),
"optimize");
splinterdb_notification_deinit(&note);
#endif
}
Expand Down Expand Up @@ -129,8 +137,7 @@ main(int argc, char **argv)
checked(splinterdb_close(&db, false), "close");
checked(splinterdb_open(&cfg, &db), "reopen");
splinterdb_iterator *it;
checked(splinterdb_iterator_init(db, &it, greater_than_or_equal, NULL_SLICE),
"iterator init");
checked(splinterdb_iterator_init(db, &it), "iterator init");
for (uint64_t id = 0; id < keys; id++) {
assert(splinterdb_iterator_valid(it));
slice k, v;
Expand Down
2 changes: 1 addition & 1 deletion docs/filtered-ranges-pr.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Allow range iterators to apply an exact key predicate, with optional routing-filter branch pruning. The new `splinterdb_iterator_init_with_filter()` and `splinterdb_iterator_init_with_bounds_and_filter()` take separate predicate, context and representative-key arguments. A predicate alone scans all relevant branches; a representative routing key requires a predicate and asserts hash compatibility under every possible seed. Pruning without a predicate returns `EINVAL`.
Allow range iterators to apply an exact key predicate, with optional routing-filter branch pruning. `splinterdb_iterator_init()` takes optional `.predicate`, `.predicate_context` and `.routing_filter_key` parameters. A predicate alone scans all relevant branches; a representative routing key requires a predicate and asserts hash compatibility under every possible seed. Pruning without a predicate returns `EINVAL`.

Rejected keys are skipped before application merge/finalize callbacks, preserving complete update histories for accepted keys even when routing filters admit collisions. The iterator owns its routing-key copy across trunk spans, direction changes and thread handoff; predicate context remains caller-owned. Ordinary iterator APIs remain unchanged and do not allocate filter state. No callback is added to `data_config`.

Expand Down
11 changes: 6 additions & 5 deletions docs/hash-filtered-ranges.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ integration from `36183807` on top of main's persisted configuration. The main
update leaves the previously tested implementation unchanged; see the
[main-update proof](../benchmarks/results-20261013/filtered-main-1d6ea2a3/README.txt).

`splinterdb_iterator_init_with_filter()` and
`splinterdb_iterator_init_with_bounds_and_filter()` append three separate
arguments to the corresponding ordinary initializer: a
`splinterdb_key_predicate`, its `void *` context, and a `slice`
`routing_filter_key`. There is no new `data_config` callback.
`splinterdb_iterator_init()` accepts optional designated-initializer
parameters (see `splinterdb_iterator_init_options`). The filter parameters are
`.predicate` (a `splinterdb_key_predicate`), `.predicate_context` (a `void *`),
and `.routing_filter_key` (a `slice`); they combine freely with the `.lower_limit`,
`.upper_limit` and `.start_position` parameters.
There is no new `data_config` callback.

| Predicate | Routing-filter key | Behavior |
| --- | --- | --- |
Expand Down
4 changes: 3 additions & 1 deletion examples/splinterdb_custom_ipv4_addr_sortcmp_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,9 @@ do_iterate_from(splinterdb *spl_handle, const char *from_key)
slice start_key =
(from_key ? slice_create(strlen(from_key), from_key) : NULL_SLICE);
int rc = splinterdb_iterator_init(
spl_handle, &it, greater_than_or_equal, start_key);
spl_handle,
&it,
.start_position = splinterdb_start_at_or_after(start_key));

int i = 0;

Expand Down
6 changes: 2 additions & 4 deletions examples/splinterdb_intro_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ main()

// Retrieve a key-value pair.
splinterdb_lookup_result result;
splinterdb_lookup_result_init(
spl_handle, &result, SPLINTERDB_LOOKUP_VALUE, 0, NULL);
splinterdb_lookup_result_init(spl_handle, &result);

fruit = "Orange";
key = slice_create((size_t)strlen(fruit), fruit);
Expand Down Expand Up @@ -115,8 +114,7 @@ main()
" returning keys in lexicographic sort order:\n");

splinterdb_iterator *it = NULL;
rc = splinterdb_iterator_init(
spl_handle, &it, greater_than_or_equal, NULL_SLICE);
rc = splinterdb_iterator_init(spl_handle, &it);

int i = 0;
for (; splinterdb_iterator_valid(it); splinterdb_iterator_next(it)) {
Expand Down
4 changes: 3 additions & 1 deletion examples/splinterdb_iterators_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ do_iterate_from(splinterdb *spl_handle, const char *from_key)
slice start_key =
(from_key ? slice_create(strlen(from_key), from_key) : NULL_SLICE);
int rc = splinterdb_iterator_init(
spl_handle, &it, greater_than_or_equal, start_key);
spl_handle,
&it,
.start_position = splinterdb_start_at_or_after(start_key));

int i = 0;

Expand Down
10 changes: 5 additions & 5 deletions examples/splinterdb_optimize_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ main(int argc, char **argv)
opts.min_key == NULL ? "-infinity" : opts.min_key,
opts.max_key == NULL ? "+infinity" : opts.max_key);

rc = splinterdb_optimize(spl,
min_key,
max_key,
opts.full_leaf_compactions,
SPLINTERDB_NOTIFICATION_BLOCKING);
rc =
splinterdb_optimize(spl,
.min_key = min_key,
.max_key = max_key,
.full_leaf_compactions = opts.full_leaf_compactions);

if (rc == 0) {
printf("Optimize completed successfully.\n");
Expand Down
2 changes: 1 addition & 1 deletion examples/splinterdb_wide_values_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ main()

splinterdb_lookup_result result;
splinterdb_lookup_result_init(
spl_handle, &result, SPLINTERDB_LOOKUP_VALUE, sizeof(outbuf), outbuf);
spl_handle, &result, .buffer = slice_create(sizeof(outbuf), outbuf));

printf("Retrieve values of different lengths using output buffer of"
" fixed size=%lu bytes:\n",
Expand Down
Loading
Loading