diff --git a/lsm/include/lsm/store.h b/lsm/include/lsm/store.h index d7e2e83..1557dd1 100644 --- a/lsm/include/lsm/store.h +++ b/lsm/include/lsm/store.h @@ -44,6 +44,16 @@ bool lsm_entry_attr_present(lsm_entry_handle *handle, lsm_attr_type type); lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry_handle *handle, lsm_attr_type type); +/** + * Convenience wrapper around `lsm_entry_attr_get` that can be used if we know + * beforehand the attribute value is a 64-bit number. + * + * @param out where to store attribute data + * @param entry entry to search for + * @param type type of attribute to return + */ +lsm_error lsm_entry_attr_get_num(uint64_t *out, lsm_entry_handle *handle, lsm_attr_type type); + /** * Add a new attribute to the entry. * @@ -54,6 +64,16 @@ lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry_handle *handle, lsm_error lsm_entry_attr_insert(lsm_entry_handle *handle, lsm_attr_type type, lsm_str *data); +/** + * Convenience wrapper around `lsm_entry_attr_insert` that can be used if the + * data to be stored is a 64-bit number. + * + * @param entry entry to modify + * @param type type of attribute to add + * @param data data of attribute + */ +lsm_error lsm_entry_attr_insert_num(lsm_entry_handle *handle, lsm_attr_type type, uint64_t data); + /** * Remove an atribute from the given entry, if present. * @@ -151,6 +171,16 @@ lsm_error lsm_store_insert(lsm_entry_handle **out, lsm_store *store, lsm_error lsm_entry_data_append(lsm_store *store, lsm_entry_handle *handle, lsm_str *data); +/** + * Same as `lsm_entry_data_append`, except that it takes a direct char array. + * + * @param store store the entry is stored in + * @param entry entry to append data to + * @param data data to append + * @param len length of data array + */ +lsm_error lsm_entry_data_append_raw(lsm_store *store, lsm_entry_handle *handle, char *data, uint64_t len); + /** * Read a number of bytes from the entry's data field. The position from which * data is read is dependent on previous read calls. @@ -163,4 +193,12 @@ lsm_error lsm_entry_data_append(lsm_store *store, lsm_entry_handle *handle, lsm_error lsm_entry_data_read(uint64_t *out, char *buf, lsm_entry_handle *handle, uint64_t len); +/** + * Return the length of the entry's data. + * + * @param handle entry handle to return length for + * @return length of the data + */ +uint64_t lsm_entry_data_len(lsm_entry_handle *handle); + #endif diff --git a/lsm/src/store/lsm_store.c b/lsm/src/store/lsm_store.c index 26e6af7..d056621 100644 --- a/lsm/src/store/lsm_store.c +++ b/lsm/src/store/lsm_store.c @@ -153,18 +153,32 @@ lsm_error lsm_store_insert(lsm_entry_handle **out, lsm_store *store, lsm_str *key) { // TODO what happens when two inserts to the same key happen at the same time? lsm_entry_wrapper *wrapper; - LSM_RES(lsm_entry_wrapper_init(&wrapper)); - pthread_rwlock_wrlock(&wrapper->lock); - lsm_error res = lsm_trie_insert(store->trie, key, wrapper); + // If a key was previously removed from the trie, the wrapper will already be + // present in the trie + if (lsm_trie_search((void **)&wrapper, store->trie, key) == lsm_error_not_found) { + LSM_RES(lsm_entry_wrapper_init(&wrapper)); + pthread_rwlock_wrlock(&wrapper->lock); - // Check if entry isn't already present in advance - if (res != lsm_error_ok) { - lsm_entry_wrapper_free(wrapper); + lsm_error res = lsm_trie_insert(store->trie, key, wrapper); - return res; + // Check if entry isn't already present in advance + if (res != lsm_error_ok) { + lsm_entry_wrapper_free(wrapper); + + return res; + } + } else { + pthread_rwlock_wrlock(&wrapper->lock); + + if (wrapper->entry != NULL) { + pthread_rwlock_unlock(&wrapper->lock); + + return lsm_error_already_present; + } } + lsm_entry *entry; LSM_RES(lsm_entry_init(&entry)); diff --git a/lsm/src/store/lsm_store_entry.c b/lsm/src/store/lsm_store_entry.c index ffbc138..d7bbc40 100644 --- a/lsm/src/store/lsm_store_entry.c +++ b/lsm/src/store/lsm_store_entry.c @@ -5,6 +5,7 @@ #include "lsm.h" #include "lsm/store_internal.h" +#include "lsm/str.h" lsm_error lsm_entry_init(lsm_entry **ptr) { lsm_entry *entry = calloc(1, sizeof(lsm_entry)); @@ -77,6 +78,22 @@ lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry_handle *handle, return lsm_error_ok; } +lsm_error lsm_entry_attr_get_num(uint64_t *out, lsm_entry_handle *handle, lsm_attr_type type) { + lsm_str *s; + + LSM_RES(lsm_entry_attr_get(&s, handle, type)); + + uint64_t num; + + for (uint8_t i = 0; i < sizeof(uint64_t) / sizeof(char); i++) { + ((char *)&num)[i] = lsm_str_char(s, i); + } + + *out = num; + + return lsm_error_ok; +} + lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry_handle *handle, lsm_attr_type type) { if (!lsm_entry_attr_present(handle, type)) { @@ -149,3 +166,14 @@ lsm_error lsm_entry_attr_insert(lsm_entry_handle *handle, lsm_attr_type type, return lsm_error_ok; } + +lsm_error lsm_entry_attr_insert_num(lsm_entry_handle *handle, lsm_attr_type type, uint64_t data) { + lsm_str *s; + LSM_RES(lsm_str_init_copy_n(&s, (char *)&data, sizeof(uint64_t) / sizeof(char))); + + return lsm_entry_attr_insert(handle, type, s); +} + +uint64_t lsm_entry_data_len(lsm_entry_handle *handle) { + return handle->wrapper->entry->data.len; +} diff --git a/lsm/src/str/lsm_str.c b/lsm/src/str/lsm_str.c index afab724..0cfd571 100644 --- a/lsm/src/str/lsm_str.c +++ b/lsm/src/str/lsm_str.c @@ -77,16 +77,16 @@ lsm_error lsm_str_overwrite_copy(lsm_str *str, char *s) { } lsm_error lsm_str_overwrite_copy_n(lsm_str *str, char *s, uint64_t len) { - if (str->len <= 8) { - memcpy(str->data.val, s, str->len); + if (len <= 8) { + memcpy(str->data.val, s, len); } else { - char *buf = malloc(str->len * sizeof(char)); + char *buf = malloc(len * sizeof(char)); if (buf == NULL) { return lsm_error_failed_alloc; } - memcpy(buf, s, str->len); + memcpy(buf, s, len); str->data.ptr = buf; }