From 222b277eef9d9a01cf2829a98cd761d5e0527b9e Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 23 Dec 2023 14:29:33 +0100 Subject: [PATCH] feat(lsm): store iterators --- CHANGELOG.md | 1 + lsm/include/lsm/store.h | 36 +++++++++++++++++ lsm/src/_include/lsm/store_internal.h | 5 +++ lsm/src/store/lsm_store_iter.c | 58 +++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 lsm/src/store/lsm_store_iter.c diff --git a/CHANGELOG.md b/CHANGELOG.md index 16513b9..ea1d396 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * LSM * Binary tree iterators * Trie iterators + * Store iterators ## Removed diff --git a/lsm/include/lsm/store.h b/lsm/include/lsm/store.h index c680c43..1b632b9 100644 --- a/lsm/include/lsm/store.h +++ b/lsm/include/lsm/store.h @@ -228,4 +228,40 @@ lsm_error lsm_entry_data_read(uint64_t *out, char *buf, */ uint64_t lsm_entry_data_len(lsm_entry_handle *handle); +/** + * Represents an in-flight iterator over an LSM store. + */ +typedef struct lsm_store_iterator lsm_store_iterator; + +/** + * Initialize an iterator to iterate over all entries with keys starting + * with the given prefix. + * + * @param out pointer to store iterator pointer in + * @param trie trie to iterate + * @param prefix prefix of the keys; a zero-length string means iterating over + * the entire trie; NULL is interpreted as a zero-length string + */ +lsm_error lsm_store_iter(lsm_store_iterator **out, lsm_store *store, + const lsm_str *prefix); + +/** + * Advance the iterator, returning a read handle to the next entry. The caller + * is responsible for closing this handle. + */ +lsm_error lsm_store_iter_next_read(lsm_entry_handle **out, + lsm_store_iterator *iter); + +/** + * Advance the iterator, returning a write handle to the next entry. The caller + * is responsible for closing this handle. + */ +/* lsm_error lsm_store_iter_next_write(lsm_entry_handle **out, + * lsm_store_iterator *iter); */ + +/** + * Free the given iterator. + */ +void lsm_store_iter_free(lsm_store_iterator *iter); + #endif diff --git a/lsm/src/_include/lsm/store_internal.h b/lsm/src/_include/lsm/store_internal.h index e446a0d..e853308 100644 --- a/lsm/src/_include/lsm/store_internal.h +++ b/lsm/src/_include/lsm/store_internal.h @@ -34,6 +34,11 @@ typedef struct lsm_entry { uint64_t idx_file_offset; } lsm_entry; +struct lsm_store_iterator { + lsm_trie_iterator *iter; + lsm_store *store; +}; + /** * Allocate and initialize a new lsm_entry object. * diff --git a/lsm/src/store/lsm_store_iter.c b/lsm/src/store/lsm_store_iter.c new file mode 100644 index 0000000..3879d5e --- /dev/null +++ b/lsm/src/store/lsm_store_iter.c @@ -0,0 +1,58 @@ +#include "lsm/store.h" +#include "lsm/store_internal.h" + +lsm_error lsm_store_iter(lsm_store_iterator **out, lsm_store *store, + const lsm_str *prefix) { + lsm_trie_iterator *trie_iter; + LSM_RES(lsm_trie_iter(&trie_iter, store->trie, prefix)); + + lsm_store_iterator *iter = calloc(1, sizeof(lsm_store_iterator)); + + if (iter == NULL) { + lsm_trie_iter_free(trie_iter); + + return lsm_error_failed_alloc; + } + + iter->iter = trie_iter; + iter->store = store; + + *out = iter; + + return lsm_error_ok; +} + +lsm_error lsm_store_iter_next_read(lsm_entry_handle **out, + lsm_store_iterator *iter) { + lsm_entry_wrapper *wrapper = NULL; + + // Traverse through the trie until a node is found with a filled data field + do { + // Exits function if iterator is done + LSM_RES(lsm_trie_iter_next((void **)&wrapper, iter->iter)); + + // TODO error handling? + pthread_rwlock_rdlock(&wrapper->lock); + + if (wrapper->entry == NULL) { + pthread_rwlock_unlock(&wrapper->lock); + + wrapper = NULL; + } + } while (wrapper == NULL); + + lsm_entry_handle *handle; + LSM_RES2(lsm_entry_handle_init(&handle), + pthread_rwlock_unlock(&wrapper->lock)); + + handle->wrapper = wrapper; + handle->store = iter->store; + *out = handle; + + return lsm_error_ok; +} + +void lsm_store_iter_free(lsm_store_iterator *iter) { + lsm_trie_iter_free(iter->iter); + free(iter); +}