feat(lsm): store iterators
parent
f4d711365d
commit
222b277eef
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue