feat(lsm): some more string functions; start of data streaming api
							parent
							
								
									fca8495de4
								
							
						
					
					
						commit
						b552e0a81b
					
				
							
								
								
									
										7
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										7
									
								
								Makefile
								
								
								
								
							| 
						 | 
					@ -39,8 +39,12 @@ objs: $(OBJS)
 | 
				
			||||||
libtrie:
 | 
					libtrie:
 | 
				
			||||||
	$(MAKE) -C trie
 | 
						$(MAKE) -C trie
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: liblsm
 | 
				
			||||||
 | 
					liblsm:
 | 
				
			||||||
 | 
						$(MAKE) -C lsm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: bin
 | 
					.PHONY: bin
 | 
				
			||||||
$(BIN): libtrie $(OBJS)
 | 
					$(BIN): libtrie liblsm $(OBJS)
 | 
				
			||||||
	$(CC) -o $@ $(OBJS) $(_LDFLAGS)
 | 
						$(CC) -o $@ $(OBJS) $(_LDFLAGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c
 | 
					$(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c
 | 
				
			||||||
| 
						 | 
					@ -104,6 +108,7 @@ fmt:
 | 
				
			||||||
clean:
 | 
					clean:
 | 
				
			||||||
	rm -rf $(BUILD_DIR)
 | 
						rm -rf $(BUILD_DIR)
 | 
				
			||||||
	$(MAKE) -C trie clean
 | 
						$(MAKE) -C trie clean
 | 
				
			||||||
 | 
						$(MAKE) -C lsm clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: bear
 | 
					.PHONY: bear
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,9 +7,9 @@ SRC_DIR        = src
 | 
				
			||||||
TEST_DIR       = test
 | 
					TEST_DIR       = test
 | 
				
			||||||
THIRDPARTY_DIR = thirdparty
 | 
					THIRDPARTY_DIR = thirdparty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INC_DIRS  = include $(THIRDPARTY_DIR)/include trie/include
 | 
					INC_DIRS  = include $(THIRDPARTY_DIR)/include trie/include lsm/include
 | 
				
			||||||
LIBS      = trie m
 | 
					LIBS      = trie m lsm
 | 
				
			||||||
LIB_DIRS  = ./trie/build
 | 
					LIB_DIRS  = ./trie/build  ./lsm/build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -MMD: generate a .d file for every source file. This file can be imported by
 | 
					# -MMD: generate a .d file for every source file. This file can be imported by
 | 
				
			||||||
#  make and makes make aware that a header file has been changed, ensuring an
 | 
					#  make and makes make aware that a header file has been changed, ensuring an
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LSM_MAX_SKIP_SIZE 8
 | 
					#define LSM_RES(x) \
 | 
				
			||||||
 | 
					  { \
 | 
				
			||||||
 | 
					    lsm_error res = x; \
 | 
				
			||||||
 | 
					    if (res != lsm_error_ok) \
 | 
				
			||||||
 | 
					      return res; \
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum lsm_error {
 | 
					typedef enum lsm_error {
 | 
				
			||||||
  lsm_error_ok = 0,
 | 
					  lsm_error_ok = 0,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,8 @@
 | 
				
			||||||
#include "lsm.h"
 | 
					#include "lsm.h"
 | 
				
			||||||
#include "lsm/str.h"
 | 
					#include "lsm/str.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LSM_STORE_DISK_THRESHOLD 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The type of an entry attribute.
 | 
					 * The type of an entry attribute.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -73,7 +75,7 @@ lsm_error lsm_entry_attr_insert(lsm_entry *entry, lsm_attr_type type,
 | 
				
			||||||
 * Remove an atribute from the given entry, if present.
 | 
					 * Remove an atribute from the given entry, if present.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param out pointer to store removed data pointer in. If NULL, data pointer
 | 
					 * @param out pointer to store removed data pointer in. If NULL, data pointer
 | 
				
			||||||
 * can get leaked.
 | 
					 * will be leaked.
 | 
				
			||||||
 * @param entry entry to remove attribute from
 | 
					 * @param entry entry to remove attribute from
 | 
				
			||||||
 * @param type type of attribute to remove
 | 
					 * @param type type of attribute to remove
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -95,6 +97,15 @@ typedef struct lsm_store lsm_store;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
lsm_error lsm_store_init(lsm_store **ptr);
 | 
					lsm_error lsm_store_init(lsm_store **ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Open the given database file and load it into a new store object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param ptr pointer to store newly allocated store
 | 
				
			||||||
 | 
					 * @param db_path path to the database file
 | 
				
			||||||
 | 
					 * @param data_path path to the data directory
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					lsm_error lsm_store_open(lsm_store **ptr, char *db_path, char *data_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Dealocate an existing lsm_store object.
 | 
					 * Dealocate an existing lsm_store object.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -102,4 +113,34 @@ lsm_error lsm_store_init(lsm_store **ptr);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void lsm_store_free(lsm_store *store);
 | 
					void lsm_store_free(lsm_store *store);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Search for an entry in the store.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param out pointer to store entry pointer in
 | 
				
			||||||
 | 
					 * @param store store to search in
 | 
				
			||||||
 | 
					 * @param key key to look with
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					lsm_error lsm_store_search(lsm_entry **out, lsm_store *store, lsm_str *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new entry in the store with the specified key.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @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 **out, lsm_store *store, lsm_str *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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_store_data_append(lsm_store *store, lsm_entry *entry, lsm_str *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,4 +151,12 @@ lsm_error lsm_str_truncate(lsm_str *s, uint64_t new_len);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
lsm_error lsm_str_split(lsm_str *s, lsm_str *s2, uint64_t index);
 | 
					lsm_error lsm_str_split(lsm_str *s, lsm_str *s2, uint64_t index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Append s2 to s. s2 is left untouched.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param s string to append s2 to
 | 
				
			||||||
 | 
					 * @param s2 string to append to s
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					lsm_error lsm_str_append(lsm_str *s, lsm_str *s2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
#ifndef LSM_STORE_INTERNAL
 | 
					#ifndef LSM_STORE_INTERNAL
 | 
				
			||||||
#define LSM_STORE_INTERNAL
 | 
					#define LSM_STORE_INTERNAL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "lsm/store.h"
 | 
					#include "lsm/store.h"
 | 
				
			||||||
#include "lsm/str_internal.h"
 | 
					#include "lsm/str_internal.h"
 | 
				
			||||||
#include "lsm/trie.h"
 | 
					#include "lsm/trie.h"
 | 
				
			||||||
| 
						 | 
					@ -11,17 +13,26 @@ typedef struct lsm_attr {
 | 
				
			||||||
} lsm_attr;
 | 
					} lsm_attr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lsm_entry {
 | 
					struct lsm_entry {
 | 
				
			||||||
  lsm_str key;
 | 
					  lsm_str *key;
 | 
				
			||||||
  struct {
 | 
					  struct {
 | 
				
			||||||
    uint64_t count;
 | 
					    uint64_t count;
 | 
				
			||||||
    uint64_t bitmap;
 | 
					    uint64_t bitmap;
 | 
				
			||||||
    lsm_attr *items;
 | 
					    lsm_attr *items;
 | 
				
			||||||
  } attrs;
 | 
					  } attrs;
 | 
				
			||||||
  lsm_str data;
 | 
					  struct {
 | 
				
			||||||
 | 
					    uint64_t len;
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					      FILE *file;
 | 
				
			||||||
 | 
					      char *ptr;
 | 
				
			||||||
 | 
					    } value;
 | 
				
			||||||
 | 
					    bool on_disk;
 | 
				
			||||||
 | 
					  } data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lsm_store {
 | 
					struct lsm_store {
 | 
				
			||||||
  lsm_trie *trie;
 | 
					  lsm_trie *trie;
 | 
				
			||||||
 | 
					  char *data_path;
 | 
				
			||||||
 | 
					  char *db_path;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,81 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lsm.h"
 | 
				
			||||||
#include "lsm/store.h"
 | 
					#include "lsm/store.h"
 | 
				
			||||||
 | 
					#include "lsm/trie.h"
 | 
				
			||||||
#include "lsm/store_internal.h"
 | 
					#include "lsm/store_internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* lsm_error lsm_store_init(lsm_store **ptr) { */
 | 
					lsm_error lsm_store_init(lsm_store **ptr) {
 | 
				
			||||||
/*   lsm_store *store = */
 | 
					  lsm_store *store = calloc(1, sizeof(lsm_store));
 | 
				
			||||||
/* } */
 | 
					
 | 
				
			||||||
 | 
					  if (store == NULL) {
 | 
				
			||||||
 | 
					    return lsm_error_failed_alloc;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  lsm_error res = lsm_trie_init(&store->trie);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (res != lsm_error_ok) {
 | 
				
			||||||
 | 
					    free(store);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return res;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  *ptr = store;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lsm_error_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lsm_error lsm_store_open(lsm_store **ptr, char *db_path, char *data_path) {
 | 
				
			||||||
 | 
					  lsm_store *store;
 | 
				
			||||||
 | 
					  LSM_RES(lsm_store_init(&store));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // TODO implement all of reading the db file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  store->db_path = db_path;
 | 
				
			||||||
 | 
					  store->data_path = data_path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  *ptr = store;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lsm_error_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lsm_error lsm_store_search(lsm_entry **out, lsm_store *store, lsm_str *key) {
 | 
				
			||||||
 | 
					  return lsm_trie_search((void **)out, store->trie, key);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lsm_error lsm_store_insert(lsm_entry **out, lsm_store *store, lsm_str *key) {
 | 
				
			||||||
 | 
					  lsm_entry *entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LSM_RES(lsm_entry_init(&entry));
 | 
				
			||||||
 | 
					  LSM_RES(lsm_trie_insert(store->trie, key, entry));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  entry->key = key;
 | 
				
			||||||
 | 
					  *out = entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lsm_error_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lsm_error lsm_store_data_append(lsm_store *store, lsm_entry *entry, lsm_str *data) {
 | 
				
			||||||
 | 
					  uint64_t new_len = entry->data.len + lsm_str_len(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Data is in memory and still fits -> keep it in memory
 | 
				
			||||||
 | 
					  if ((new_len <= LSM_STORE_DISK_THRESHOLD) && (!entry->data.on_disk)) {
 | 
				
			||||||
 | 
					    char *buf = realloc(entry->data.value.ptr, new_len * sizeof(char));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (buf == NULL) {
 | 
				
			||||||
 | 
					      return lsm_error_failed_alloc;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(&buf[entry->data.len], lsm_str_ptr(data), lsm_str_len(data));
 | 
				
			||||||
 | 
					    entry->data.value.ptr = buf;
 | 
				
			||||||
 | 
					    entry->data.len = new_len;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // Data will end up on disk
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    // Data is not yet on disk, so we create the file
 | 
				
			||||||
 | 
					    if (!entry->data.on_disk) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,15 +27,15 @@ lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry *entry,
 | 
				
			||||||
    return lsm_error_not_found;
 | 
					    return lsm_error_not_found;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (uint64_t i = 0; i < entry->attrs.count; i++) {
 | 
					  uint64_t i = 0;
 | 
				
			||||||
    if (entry->attrs.items[i].type == type) {
 | 
					 | 
				
			||||||
      *out = entry->attrs.items[i].str;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return lsm_error_ok;
 | 
					  while (entry->attrs.items[i].type != type) {
 | 
				
			||||||
    }
 | 
					    i++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return lsm_error_not_found;
 | 
					  *out = entry->attrs.items[i].str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lsm_error_ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry *entry,
 | 
					lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry *entry,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,3 +196,40 @@ bool lsm_str_eq(lsm_str *s1, lsm_str *s2) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return memcmp(lsm_str_ptr(s1), lsm_str_ptr(s2), s1->len) == 0;
 | 
					  return memcmp(lsm_str_ptr(s1), lsm_str_ptr(s2), s1->len) == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lsm_error lsm_str_append(lsm_str *s, lsm_str *s2) {
 | 
				
			||||||
 | 
					  if (s2->len == 0) {
 | 
				
			||||||
 | 
					    return lsm_error_ok;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64_t new_len = s->len + s2->len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (new_len <= 8) {
 | 
				
			||||||
 | 
					    memcpy(&s->data.val[s->len], s2->data.val, s2->len);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    char *buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s->len <= 8) {
 | 
				
			||||||
 | 
					      buf = malloc(new_len * sizeof(char));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (buf == NULL) {
 | 
				
			||||||
 | 
					        return lsm_error_failed_alloc;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      memcpy(buf, s->data.val, s->len);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      buf = realloc(s->data.ptr, new_len * sizeof(char));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (buf == NULL) {
 | 
				
			||||||
 | 
					        return lsm_error_failed_alloc;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(&buf[s->len], lsm_str_ptr(s2), s2->len);
 | 
				
			||||||
 | 
					    s->data.ptr = buf;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  s->len += s2->len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lsm_error_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue