#ifndef LSM_STORE #define LSM_STORE #include #include #include "lsm.h" #include "lsm/str.h" #define LSM_STORE_DATA_LEVELS 3 /** * A handle referencing an entry inside a store. Read/write operations from/to * the entry go through this handle. */ typedef struct lsm_entry_handle lsm_entry_handle; /** * Checks whether the entry has an attribute with the specified type. * * @param entry entry to check * @param type type of attribute to check for */ bool lsm_entry_attr_present(lsm_entry_handle *handle, uint8_t type); /** * Retrieve the contents of an attribute from an entry, if present * * @param out where to store pointer to attribute data * @param entry entry to search for * @param type type of attribute to return */ lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry_handle *handle, uint8_t 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_uint64_t(uint64_t *out, lsm_entry_handle *handle, uint8_t type); /** * Convenience wrapper around `lsm_entry_attr_get` that can be used if we know * beforehand the attribute value is an 8-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_uint8_t(uint8_t *out, lsm_entry_handle *handle, uint8_t type); /** * Add a new attribute to the entry. * * @param entry entry to modify * @param type type of attribute to add * @param data data of attribute; ownership of pointer is taken over */ lsm_error lsm_entry_attr_insert(lsm_entry_handle *handle, uint8_t 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_uint64_t(lsm_entry_handle *handle, uint8_t type, uint64_t data); /** * Convenience wrapper around `lsm_entry_attr_insert` that can be used if the * data to be stored is an 8-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_uint8_t(lsm_entry_handle *handle, uint8_t type, uint8_t data); /** * Remove an atribute from the given entry, if present. * * @param out pointer to store removed data pointer in. If NULL, data pointer * will be leaked. * @param entry entry to remove attribute from * @param type type of attribute to remove */ lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry_handle *handle, uint8_t type); /** * Retrieve a pointer to the entry's key. */ void lsm_entry_key(const lsm_str **out, lsm_entry_handle *handle); /** * A store consisting of LSM entries. * * A store manages both an in-memory data structure for quick lookup, and a * database file for persistent storage of the contained entries. */ typedef struct lsm_store lsm_store; /** * Allocate and initialize a new lsm_store object. * * @param ptr where to store newly allocated pointer */ lsm_error lsm_store_init(lsm_store **ptr); /** * Return how many elements are stored in the trie. * * @param store store to use * @return how many elements are in the store */ uint64_t lsm_store_size(const lsm_store *store); /** * Open the given database file and load it into a new store object. * * @param ptr pointer to store newly allocated store * @param data_path path to the data directory */ lsm_error lsm_store_load(lsm_store **ptr, lsm_str *data_path); /** * Dealocate an existing lsm_store object. * * @param store object to deallocate */ void lsm_store_free(lsm_store *store); /** * Open a read handle to the given entry. This entry must be properly closed * using `lsm_store_handle_close`. * * @param out pointer to store handle pointer * @param store store to retrieve entry from * @param key key to search */ lsm_error lsm_store_open_read(lsm_entry_handle **out, lsm_store *store, const lsm_str *key); /** * Open a write handle to the given entry. This handle should only be used for * writing; read operations on this handle are unsupported. This entry must be * properly closed using `lsm_store_handle_close`. * * @param out pointer to store handle pointer * @param store store to retrieve entry from * @param key key to search */ lsm_error lsm_store_open_write(lsm_entry_handle **out, lsm_store *store, const lsm_str *key); /** * Close an open entry handle. * * @param store store the handle's entry is stored in * @param handle handle to close */ void lsm_entry_close(lsm_entry_handle *handle); /** * Insert a new entry into the store, returning a write handle to the newly * created entry. * * @param out pointer to store new entry pointer in * @param store store to modify * @param key key to add; ownership of key pointer is taken over */ lsm_error lsm_store_insert(lsm_entry_handle **out, lsm_store *store, lsm_str *key); /** * Mark the entry as removed. * * @param handle handle to entry to remove */ void lsm_entry_remove(lsm_entry_handle *handle); /** * Append new data to the given entry, which is expected to be in the store. * * This function will append either to disk or to memory, depending on the * length of the entry's data. * * @param store store the entry is stored in * @param entry entry to append data to * @param data data to append */ lsm_error lsm_entry_data_append(lsm_entry_handle *handle, const 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_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. * * @param out where to write how many bytes were read * @param buf buffer to store read data in * @param handle entry handle to read from * @param len how many bytes to read at most */ 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); /** * 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