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