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
2 changes: 1 addition & 1 deletion examples/splinterdb_custom_ipv4_addr_sortcmp_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ do_inserts(splinterdb *spl_handle, kv_pair *kv_pairs, int num_kv_pairs)
slice_create(strlen(kv_pairs[ictr].kv_key), kv_pairs[ictr].kv_key);
slice value = slice_create(WWW_PING_SIZE(&kv_pairs[ictr].kv_val),
(const char *)&kv_pairs[ictr].kv_val);
int rc = splinterdb_insert(spl_handle, key, value);
int rc = splinterdb_insert(spl_handle, key, value, NULL);
if (rc) {
printf(
"Insert of key '%s' failed; rc=%d\n", kv_pairs[ictr].kv_key, rc);
Expand Down
6 changes: 3 additions & 3 deletions examples/splinterdb_intro_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,21 @@ main()
slice key = slice_create((size_t)strlen(fruit), fruit);
slice value = slice_create((size_t)strlen(descr), descr);

rc = splinterdb_insert(spl_handle, key, value);
rc = splinterdb_insert(spl_handle, key, value, NULL);
printf("Inserted key '%s'\n", fruit);

fruit = "Orange";
descr = "Is a good source of vitamin-C.";
key = slice_create((size_t)strlen(fruit), fruit);
value = slice_create((size_t)strlen(descr), descr);
rc = splinterdb_insert(spl_handle, key, value);
rc = splinterdb_insert(spl_handle, key, value, NULL);
printf("Inserted key '%s'\n", fruit);

fruit = "Mango";
descr = "Mango is the king of fruits.";
key = slice_create((size_t)strlen(fruit), fruit);
value = slice_create((size_t)strlen(descr), descr);
rc = splinterdb_insert(spl_handle, key, value);
rc = splinterdb_insert(spl_handle, key, value, NULL);
printf("Inserted key '%s'\n", fruit);

// Retrieve a key-value pair.
Expand Down
2 changes: 1 addition & 1 deletion examples/splinterdb_iterators_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ do_inserts(splinterdb *spl_handle, kv_pair *kv_pairs, int num_kv_pairs)
slice_create(strlen(kv_pairs[ictr].kv_key), kv_pairs[ictr].kv_key);
slice value =
slice_create(strlen(kv_pairs[ictr].kv_val), kv_pairs[ictr].kv_val);
int rc = splinterdb_insert(spl_handle, key, value);
int rc = splinterdb_insert(spl_handle, key, value, NULL);
if (rc) {
printf(
"Insert for key='%s' failed, rc=%d\n", kv_pairs[ictr].kv_key, rc);
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 @@ -62,7 +62,7 @@ main()

slice key = slice_create(strlen(key_buf), key_buf);
slice value = slice_create(val_len, val_buf);
rc = splinterdb_insert(spl_handle, key, value);
rc = splinterdb_insert(spl_handle, key, value, NULL);
if (rc) {
break;
}
Expand Down
50 changes: 37 additions & 13 deletions include/splinterdb/splinterdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ typedef struct splinterdb_config {
uint64 queue_scale_percent;
} splinterdb_config;

///////////////////////////////////////
// Lifecycle
///////////////////////////////////////

// Opaque handle to an opened instance of SplinterDB
typedef struct splinterdb splinterdb;

Expand Down Expand Up @@ -174,20 +178,10 @@ splinterdb_open(const splinterdb_config *cfg, splinterdb **kvs);
void
splinterdb_close(splinterdb **kvs);

// Insert a key and value. Overwrites any previous value associated with the
// key.
int
splinterdb_insert(splinterdb *kvsb, slice key, slice value);

// Delete a given key and any associated value / messages
int
splinterdb_delete(splinterdb *kvsb, slice key);

// Update the value associated with key.
int
splinterdb_update(splinterdb *kvsb, slice key, slice delta);

////////////////////////////////////
// Lookups
////////////////////////////////////

typedef uint64 splinterdb_lookup_flags;

Expand All @@ -201,7 +195,7 @@ typedef uint64 splinterdb_lookup_flags;
//
// Once initialized, a splinterdb_lookup_result may be used for multiple
// lookups. It is not safe to use from multiple threads.
typedef struct {
typedef struct splinterdb_lookup_result {
char opaque[SPLINTERDB_LOOKUP_BUFSIZE];
} __attribute__((__aligned__(8))) splinterdb_lookup_result;

Expand Down Expand Up @@ -267,6 +261,36 @@ splinterdb_lookup(splinterdb *kvs, // IN
);


/////////////////////////////////
// Updates
/////////////////////////////////


// Insert a key and value. Overwrites any previous value associated with the
// key.
//
// If old_result is non-NULL, it must have been initialized using
// splinterdb_lookup_result_init() and will receive the value previously
// associated with key.
int
splinterdb_insert(splinterdb *kvsb,
slice key,
slice value,
splinterdb_lookup_result *old_result);

// Delete a given key and any associated value / messages
int
splinterdb_delete(splinterdb *kvsb,
slice key,
splinterdb_lookup_result *old_result);

// Update the value associated with key.
int
splinterdb_update(splinterdb *kvsb,
slice key,
slice delta,
splinterdb_lookup_result *old_result);

/*
Iterator API (range query)

Expand Down
100 changes: 77 additions & 23 deletions src/btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,21 @@ spec_message(const leaf_incorporate_spec *spec)
}
}

static inline platform_status
btree_record_old_result(const btree_config *cfg,
const btree_hdr *hdr,
const leaf_incorporate_spec *spec,
lookup_result *old_result)
{
if (old_result == NULL || spec->old_entry_state != ENTRY_STILL_EXISTS) {
return STATUS_OK;
}

leaf_entry *entry = btree_get_leaf_entry(cfg, hdr, spec->idx);
return lookup_result_update(
old_result, leaf_entry_key(entry), leaf_entry_message(entry));
}

platform_status
btree_create_leaf_incorporate_spec(const btree_config *cfg,
platform_heap_id heap_id,
Expand Down Expand Up @@ -1276,7 +1291,7 @@ btree_dec_ref(cache *cc,
*
* This function violates our locking rules. See comment at top of file.
*/
static inline int
static inline platform_status
btree_split_child_leaf(cache *cc,
const btree_config *cfg,
mini_allocator *mini,
Expand All @@ -1285,6 +1300,7 @@ btree_split_child_leaf(cache *cc,
uint64 index_of_child_in_parent,
btree_node *child,
leaf_incorporate_spec *spec,
lookup_result *old_result,
uint64 *generation) // OUT
{
btree_node right_child;
Expand Down Expand Up @@ -1329,7 +1345,7 @@ btree_split_child_leaf(cache *cc,
btree_node_full_unlock(cc, cfg, parent);
btree_node_unclaim(cc, cfg, child);
btree_node_unget(cc, cfg, child);
return -1;
return STATUS_BUSY;
}
platform_sleep_ns(child_next_wait);
child_next_wait =
Expand All @@ -1343,6 +1359,18 @@ btree_split_child_leaf(cache *cc,
btree_node_lock(cc, cfg, child);
/* p: write, c: write, rc: write, cn: write if exists */

platform_status rc =
btree_record_old_result(cfg, child->hdr, spec, old_result);
if (!SUCCESS(rc)) {
if (child_next.addr != 0) {
btree_node_full_unlock(cc, cfg, &child_next);
}
btree_node_full_unlock(cc, cfg, &right_child);
btree_node_full_unlock(cc, cfg, parent);
btree_node_full_unlock(cc, cfg, child);
return rc;
}

{
/* limit the scope of pivot_key, since subsequent mutations of the nodes
* may invalidate the memory it points to.
Expand Down Expand Up @@ -1381,7 +1409,7 @@ btree_split_child_leaf(cache *cc,
btree_node_full_unlock(cc, cfg, child);
/* p: unlocked, c: unlocked, rc: unlocked, cn: unlocked */

return 0;
return STATUS_OK;
}

/*
Expand All @@ -1393,7 +1421,7 @@ btree_split_child_leaf(cache *cc,
* - all nodes fully unlocked
* - insertion is complete
*/
static inline int
static inline platform_status
btree_defragment_or_split_child_leaf(cache *cc,
const btree_config *cfg,
mini_allocator *mini,
Expand All @@ -1402,6 +1430,7 @@ btree_defragment_or_split_child_leaf(cache *cc,
uint64 index_of_child_in_parent,
btree_node *child,
leaf_incorporate_spec *spec,
lookup_result *old_result,
uint64 *generation) // OUT
{
uint64 nentries = btree_num_entries(child->hdr);
Expand All @@ -1425,6 +1454,12 @@ btree_defragment_or_split_child_leaf(cache *cc,
btree_node_unclaim(cc, cfg, parent);
btree_node_unget(cc, cfg, parent);
btree_node_lock(cc, cfg, child);
platform_status rc =
btree_record_old_result(cfg, child->hdr, spec, old_result);
if (!SUCCESS(rc)) {
btree_node_full_unlock(cc, cfg, child);
return rc;
}
btree_defragment_leaf(cfg, scratch, child->hdr, spec);
bool32 incorporated = btree_try_perform_leaf_incorporate_spec(
cfg, child->hdr, spec, generation);
Expand All @@ -1439,10 +1474,11 @@ btree_defragment_or_split_child_leaf(cache *cc,
index_of_child_in_parent,
child,
spec,
old_result,
generation);
}

return 0;
return STATUS_OK;
}

/*
Expand Down Expand Up @@ -1698,8 +1734,8 @@ btree_insert(cache *cc, // IN
mini_allocator *mini, // IN
key tuple_key, // IN
message msg, // IN
uint64 *generation, // OUT
bool32 *was_unique) // OUT
lookup_result *old_result, // IN/OUT
uint64 *generation) // OUT
{
platform_status rc;
leaf_incorporate_spec spec;
Expand All @@ -1721,6 +1757,10 @@ btree_insert(cache *cc, // IN

log_trace_key(tuple_key, "btree_insert");

if (old_result != NULL) {
lookup_result_reset(old_result);
}

start_over:
btree_node_get(cc, cfg, &root_node, PAGE_TYPE_MEMTABLE);
uint64 leaf_wait = 1;
Expand All @@ -1738,10 +1778,16 @@ btree_insert(cache *cc, // IN
goto start_over;
}
btree_node_lock(cc, cfg, &root_node);
if (btree_try_perform_leaf_incorporate_spec(
cfg, root_node.hdr, &spec, generation))
{
*was_unique = spec.old_entry_state == ENTRY_DID_NOT_EXIST;
if (btree_can_perform_leaf_incorporate_spec(cfg, root_node.hdr, &spec)) {
rc = btree_record_old_result(cfg, root_node.hdr, &spec, old_result);
if (!SUCCESS(rc)) {
btree_node_full_unlock(cc, cfg, &root_node);
destroy_leaf_incorporate_spec(&spec);
return rc;
}
bool32 incorporated = btree_try_perform_leaf_incorporate_spec(
cfg, root_node.hdr, &spec, generation);
platform_assert(incorporated);
btree_node_full_unlock(cc, cfg, &root_node);
destroy_leaf_incorporate_spec(&spec);
return STATUS_OK;
Expand Down Expand Up @@ -1946,12 +1992,17 @@ btree_insert(cache *cc, // IN
goto start_over;
}
btree_node_lock(cc, cfg, &child_node);
rc = btree_record_old_result(cfg, child_node.hdr, &spec, old_result);
if (!SUCCESS(rc)) {
btree_node_full_unlock(cc, cfg, &child_node);
destroy_leaf_incorporate_spec(&spec);
return rc;
}
bool32 incorporated = btree_try_perform_leaf_incorporate_spec(
cfg, child_node.hdr, &spec, generation);
platform_assert(incorporated);
btree_node_full_unlock(cc, cfg, &child_node);
destroy_leaf_incorporate_spec(&spec);
*was_unique = spec.old_entry_state == ENTRY_DID_NOT_EXIST;
return STATUS_OK;
}

Expand Down Expand Up @@ -1984,20 +2035,23 @@ btree_insert(cache *cc, // IN
return rc;
}
}
int result = btree_defragment_or_split_child_leaf(cc,
cfg,
mini,
scratch,
&parent_node,
child_idx,
&child_node,
&spec,
generation);
rc = btree_defragment_or_split_child_leaf(cc,
cfg,
mini,
scratch,
&parent_node,
child_idx,
&child_node,
&spec,
old_result,
generation);
destroy_leaf_incorporate_spec(&spec);
if (result < 0) {
if (STATUS_IS_EQ(rc, STATUS_BUSY)) {
goto start_over;
}
*was_unique = spec.old_entry_state == ENTRY_DID_NOT_EXIST;
if (!SUCCESS(rc)) {
return rc;
}
return STATUS_OK;
}

Expand Down
4 changes: 2 additions & 2 deletions src/btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ btree_insert(cache *cc, // IN
mini_allocator *mini, // IN
key tuple_key, // IN
message data, // IN
uint64 *generation, // OUT
bool32 *was_unique); // OUT
lookup_result *old_result, // IN/OUT
uint64 *generation); // OUT

uint64
btree_create(cache *cc,
Expand Down
Loading
Loading