Skip to content
Browse files

bplus: bp_removev, bp_removevs

bplus: update_cb and return_cb should return 0 on fail
  • Loading branch information...
1 parent d3afa02 commit 04885c3fe68c93865c5df57ea5349398899bc06a @indutny committed Jan 28, 2012
Showing with 75 additions and 13 deletions.
  1. +17 −0 include/bplus.h
  2. +1 −0 include/private/errors.h
  3. +5 −1 include/private/pages.h
  4. +20 −4 src/bplus.c
  5. +23 −5 src/pages.c
  6. +8 −2 test/test-api.cc
  7. +1 −1 test/test-bulk.cc
View
17 include/bplus.h
@@ -23,6 +23,8 @@ typedef int (*bp_compare_cb)(const bp_key_t* a, const bp_key_t* b);
typedef int (*bp_update_cb)(void* arg,
const bp_value_t* previous,
const bp_value_t* value);
+typedef int (*bp_remove_cb)(void* arg,
+ const bp_value_t* value);
typedef void (*bp_range_cb)(void* arg,
const bp_key_t* key,
const bp_value_t* value);
@@ -61,6 +63,7 @@ int bp_sets(bp_db_t* tree,
/*
* Update or create value by key (with solving conflicts)
+ * **MVCC**
*/
int bp_update(bp_db_t* tree,
const bp_key_t* key,
@@ -87,6 +90,7 @@ int bp_bulk_sets(bp_db_t* tree,
/*
* Update multiple values by keys
+ * **MVCC**
*/
int bp_bulk_update(bp_db_t* tree,
const uint64_t count,
@@ -108,6 +112,19 @@ int bp_remove(bp_db_t* tree, const bp_key_t* key);
int bp_removes(bp_db_t* tree, const char* key);
/*
+ * Remove value by key only if it's equal to specified one
+ * **MVCC**
+ */
+int bp_removev(bp_db_t* tree,
+ const bp_key_t* key,
+ bp_remove_cb remove_cb,
+ void *arg);
+int bp_removevs(bp_db_t* tree,
+ const char* key,
+ bp_remove_cb remove_cb,
+ void *arg);
+
+/*
* Get all values in range
* Note: value will be automatically freed after invokation of callback
*/
View
1 include/private/errors.h
@@ -22,5 +22,6 @@
#define BP_ESPLITPAGE 0x402
#define BP_EEMPTYPAGE 0x403
#define BP_EUPDATECONFLICT 0x404
+#define BP_EREMOVECONFLICT 0x405
#endif /* _PRIVATE_ERRORS_H_ */
View
6 include/private/pages.h
@@ -79,7 +79,11 @@ int bp__page_bulk_insert(bp_db_t* t,
bp_value_t** values,
bp_update_cb update_cb,
void* arg);
-int bp__page_remove(bp_db_t* t, bp__page_t* page, const bp_key_t* key);
+int bp__page_remove(bp_db_t* t,
+ bp__page_t* page,
+ const bp_key_t* key,
+ bp_remove_cb remove_cb,
+ void* arg);
int bp__page_copy(bp_db_t* source, bp_db_t* target, bp__page_t* page);
int bp__page_remove_idx(bp_db_t* t, bp__page_t* page, const uint64_t index);
View
24 src/bplus.c
@@ -156,12 +156,15 @@ int bp_bulk_set(bp_db_t* tree,
}
-int bp_remove(bp_db_t* tree, const bp_key_t* key) {
+int bp_removev(bp_db_t* tree,
+ const bp_key_t* key,
+ bp_remove_cb remove_cb,
+ void *arg) {
int ret;
bp__rwlock_wrlock(&tree->rwlock);
- ret = bp__page_remove(tree, tree->head.page, key);
+ ret = bp__page_remove(tree, tree->head.page, key, remove_cb, arg);
if (ret == BP_OK) {
ret = bp__tree_write_head((bp__writer_t*) tree, NULL);
}
@@ -172,6 +175,11 @@ int bp_remove(bp_db_t* tree, const bp_key_t* key) {
}
+int bp_remove(bp_db_t* tree, const bp_key_t* key) {
+ return bp_removev(tree, key, NULL, NULL);
+}
+
+
int bp_compact(bp_db_t* tree) {
int ret;
char* compacted_name;
@@ -339,12 +347,20 @@ int bp_bulk_sets(bp_db_t* tree,
}
-int bp_removes(bp_db_t* tree, const char* key) {
+int bp_removevs(bp_db_t* tree,
+ const char* key,
+ bp_remove_cb remove_cb,
+ void *arg) {
bp_key_t bkey;
BP__STOVAL(key, bkey);
- return bp_remove(tree, &bkey);
+ return bp_removev(tree, &bkey, remove_cb, arg);
+}
+
+
+int bp_removes(bp_db_t* tree, const char* key) {
+ return bp_removevs(tree, key, NULL, NULL);
}
View
28 src/pages.c
@@ -222,9 +222,10 @@ int bp__page_save_value(bp_db_t* t,
ret = bp__page_load_value(t, page, index, &prev_value);
if (ret != BP_OK) return ret;
- if (update_cb(arg, &prev_value, value) != BP_OK) {
- return BP_EUPDATECONFLICT;
- }
+ ret = update_cb(arg, &prev_value, value);
+ free(prev_value.value);
+
+ if (!ret) return BP_EUPDATECONFLICT;
}
previous.offset = page->keys[index].offset;
previous.length = page->keys[index].config;
@@ -540,20 +541,37 @@ int bp__page_bulk_insert(bp_db_t* t,
}
-int bp__page_remove(bp_db_t* t, bp__page_t* page, const bp_key_t* key) {
+int bp__page_remove(bp_db_t* t,
+ bp__page_t* page,
+ const bp_key_t* key,
+ bp_remove_cb remove_cb,
+ void* arg) {
int ret;
bp__page_search_res_t res;
ret = bp__page_search(t, page, key, kLoad, &res);
if (ret != BP_OK) return ret;
if (res.child == NULL) {
if (res.cmp != 0) return BP_ENOTFOUND;
+
+ /* remove only if remove_cb returns BP_OK */
+ if (remove_cb != NULL) {
+ bp_value_t prev_val;
+
+ ret = bp__page_load_value(t, page, res.index, &prev_val);
+ if (ret != BP_OK) return ret;
+
+ ret = remove_cb(arg, &prev_val);
+ free(prev_val.value);
+
+ if (!ret) return BP_EREMOVECONFLICT;
+ }
bp__page_remove_idx(t, page, res.index);
if (page->length == 0 && !page->is_head) return BP_EEMPTYPAGE;
} else {
/* Insert kv in child page */
- ret = bp__page_remove(t, res.child, key);
+ ret = bp__page_remove(t, res.child, key, remove_cb, arg);
if (ret != BP_OK && ret != BP_EEMPTYPAGE) {
return ret;
View
10 test/test-api.cc
@@ -4,7 +4,12 @@ int update_cb(void* arg, const bp_value_t* previous, const bp_value_t* curr) {
char* expected = (char*) arg;
assert(strcmp(previous->value, expected) == 0);
- return BP_OK;
+ return 1;
+}
+
+int remove_cb(void* arg, const bp_value_t* value) {
+ char* expected = (char*) arg;
+ return strcmp(value->value, expected) == 0;
}
TEST_START("API test", "api")
@@ -104,7 +109,8 @@ TEST_START("API test", "api")
for (i = 0; i < n; i++) {
sprintf(key, "some key %d", i);
- assert(bp_removes(&db, key) == BP_OK);
+ sprintf(expected, "some another value %d", i);
+ assert(bp_removevs(&db, key, remove_cb, (void*) expected) == BP_OK);
}
assert(bp_compact(&db) == BP_OK);
View
2 test/test-bulk.cc
@@ -2,7 +2,7 @@
int update_cb(void* arg, const bp_value_t* previous, const bp_value_t* curr) {
int i = (unsigned char) previous->value[5];
- return i % 2 == 0 ? BP_OK : 1;
+ return i % 2 == 0 ? 1 : 0;
}
TEST_START("bulk set test", "bulk-set")

0 comments on commit 04885c3

Please sign in to comment.
Something went wrong with that request. Please try again.