diff --git a/include/lander.h b/include/lander.h index 5abea75..0ffca46 100644 --- a/include/lander.h +++ b/include/lander.h @@ -18,12 +18,6 @@ typedef struct lander_ctx { uint64_t remaining_data; } lander_ctx; -typedef enum lander_attr_type : uint8_t { - lander_attr_type_entry_type = 0, - lander_attr_type_content_type = 1, - lander_attr_type_url = 2, -} lander_attr_type; - typedef enum lander_entry_type { lander_entry_type_redirect = 0, lander_entry_type_paste = 1, diff --git a/lsm/include/lsm/store.h b/lsm/include/lsm/store.h index cf0c9f7..16798f2 100644 --- a/lsm/include/lsm/store.h +++ b/lsm/include/lsm/store.h @@ -9,6 +9,18 @@ #define LSM_STORE_DISK_THRESHOLD 1024 +/** + * The type of an entry attribute. + * + * Each type is represented as a single bit of an + * integer, so they can be easily combined into a bitmap. + */ +typedef enum lsm_attr_type : uint64_t { + lsm_attr_type_entry_type = 1 << 0, + lsm_attr_type_content_type = 1 << 1, + lsm_attr_type_url = 1 << 2, +} lsm_attr_type; + /** * A handle referencing an entry inside a store. Read/write operations from/to * the entry go through this handle. @@ -21,7 +33,7 @@ typedef struct lsm_entry_handle lsm_entry_handle; * @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); +bool lsm_entry_attr_present(lsm_entry_handle *handle, lsm_attr_type type); /** * Retrieve the contents of an attribute from an entry, if present @@ -31,7 +43,7 @@ bool lsm_entry_attr_present(lsm_entry_handle *handle, uint8_t type); * @param type type of attribute to return */ lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry_handle *handle, - uint8_t type); + lsm_attr_type type); /** * Convenience wrapper around `lsm_entry_attr_get` that can be used if we know @@ -42,7 +54,7 @@ lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry_handle *handle, * @param type type of attribute to return */ lsm_error lsm_entry_attr_get_num(uint64_t *out, lsm_entry_handle *handle, - uint8_t type); + lsm_attr_type type); /** * Add a new attribute to the entry. @@ -51,7 +63,7 @@ lsm_error lsm_entry_attr_get_num(uint64_t *out, lsm_entry_handle *handle, * @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_error lsm_entry_attr_insert(lsm_entry_handle *handle, lsm_attr_type type, lsm_str *data); /** @@ -62,8 +74,8 @@ lsm_error lsm_entry_attr_insert(lsm_entry_handle *handle, uint8_t type, * @param type type of attribute to add * @param data data of attribute */ -lsm_error lsm_entry_attr_insert_num(lsm_entry_handle *handle, uint8_t type, - uint64_t data); +lsm_error lsm_entry_attr_insert_num(lsm_entry_handle *handle, + lsm_attr_type type, uint64_t data); /** * Remove an atribute from the given entry, if present. @@ -74,7 +86,7 @@ lsm_error lsm_entry_attr_insert_num(lsm_entry_handle *handle, uint8_t type, * @param type type of attribute to remove */ lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry_handle *handle, - uint8_t type); + lsm_attr_type type); /** * A store consisting of LSM entries. diff --git a/lsm/src/_include/lsm/store_internal.h b/lsm/src/_include/lsm/store_internal.h index b8c24dc..b9546e9 100644 --- a/lsm/src/_include/lsm/store_internal.h +++ b/lsm/src/_include/lsm/store_internal.h @@ -12,7 +12,7 @@ #define LSM_IDX_FILE_NAME "lsm.idx" typedef struct lsm_attr { - uint8_t type; + lsm_attr_type type; lsm_str *str; } lsm_attr; @@ -26,8 +26,8 @@ typedef struct lsm_attr { typedef struct lsm_entry { lsm_str *key; struct { - uint64_t bitmap[4]; - uint8_t count; + uint64_t count; + uint64_t bitmap; lsm_attr *items; } attrs; struct { diff --git a/lsm/src/store/lsm_store_disk_read.c b/lsm/src/store/lsm_store_disk_read.c index e644846..4c76b76 100644 --- a/lsm/src/store/lsm_store_disk_read.c +++ b/lsm/src/store/lsm_store_disk_read.c @@ -1,7 +1,6 @@ #include #include -#include "lsm.h" #include "lsm/store_internal.h" lsm_error lsm_store_load(lsm_store **ptr, lsm_str *data_path) { @@ -80,59 +79,48 @@ lsm_error lsm_store_load(lsm_store **ptr, lsm_str *data_path) { return lsm_error_ok; } -static lsm_error lsm_fread(void *out, uint64_t *sum, FILE *f, uint64_t size, - uint64_t count) { - size_t res = fread(out, size, count, f); +static lsm_error lsm_entry_read_attrs(lsm_entry_handle *handle, FILE *db_file) { + uint64_t attr_count; + size_t res = fread(&attr_count, sizeof(uint64_t), 1, db_file); - if (res < count) { + if (res == 0) { return lsm_error_failed_io; } - *sum += size * count; - - return lsm_error_ok; -} - -static lsm_error lsm_entry_read_str(lsm_str **out, uint64_t *sum, FILE *f) { - uint64_t len; - LSM_RES(lsm_fread(&len, sum, f, sizeof(uint64_t), 1)); - - char *buf = malloc(len + 1); - - if (buf == NULL) { - return lsm_error_failed_alloc; - } - - uint64_t read = 0; - - while (read < len) { - read += fread(&buf[read], 1, len - read, f); - } - - *sum += len; - - return lsm_str_init(out, buf); -} - -static lsm_error lsm_entry_read_attrs(uint64_t *sum, lsm_entry_handle *handle, - FILE *db_file) { - uint8_t attr_count; - LSM_RES(lsm_fread(&attr_count, sum, db_file, sizeof(uint8_t), 1)); - // attr_type, val_len - uint8_t attr_type; + uint64_t nums[2]; lsm_str *val; for (uint64_t i = 0; i < attr_count; i++) { - LSM_RES(lsm_fread(&attr_type, sum, db_file, sizeof(uint8_t), 1)); - LSM_RES(lsm_entry_read_str(&val, sum, db_file)); - lsm_entry_attr_insert(handle, attr_type, val); + res = fread(nums, sizeof(uint64_t), 2, db_file); + + if (res < 2) { + return lsm_error_failed_io; + } + + char *val_s = malloc(nums[1] + 1); + val_s[nums[1]] = '\0'; + + if (val_s == NULL) { + return lsm_error_failed_alloc; + } + + uint64_t read = 0; + + while (read < nums[1]) { + read += fread(&val_s[read], 1, nums[1] - read, db_file); + } + + LSM_RES(lsm_str_init(&val, val_s)); + ; + lsm_entry_attr_insert(handle, nums[0], val); } return lsm_error_ok; } lsm_error lsm_store_load_db(lsm_store *store) { + uint64_t key_len; uint64_t db_dim[2]; lsm_str *key; lsm_entry_handle *handle; @@ -140,13 +128,43 @@ lsm_error lsm_store_load_db(lsm_store *store) { rewind(store->idx_file); // idx file starts with block count - LSM_RES(lsm_fread(&store->idx_file_block_count, &store->idx_file_size, - store->idx_file, sizeof(uint64_t), 1)); + size_t res = + fread(&store->idx_file_block_count, sizeof(uint64_t), 1, store->idx_file); + + if (res == 0) { + return lsm_error_failed_io; + } + + store->idx_file_size += sizeof(uint64_t); for (uint64_t i = 0; i < store->idx_file_block_count; i++) { - LSM_RES(lsm_entry_read_str(&key, &store->idx_file_size, store->idx_file)); - LSM_RES(lsm_fread(&db_dim, &store->idx_file_size, store->idx_file, - sizeof(uint64_t), 2)); + // Read in idx metadata + res = fread(&key_len, sizeof(uint64_t), 1, store->idx_file); + + if (res == 0) { + return lsm_error_failed_io; + } + + char *key_s = malloc(key_len + 1); + key_s[key_len] = '\0'; + + if (key_s == NULL) { + return lsm_error_failed_alloc; + } + + res = fread(key_s, 1, key_len, store->idx_file); + + if (res < key_len) { + return lsm_error_failed_io; + } + + res = fread(db_dim, sizeof(uint64_t), 2, store->idx_file); + + if (res < 2) { + return lsm_error_failed_io; + } + + LSM_RES(lsm_str_init(&key, key_s)); LSM_RES(lsm_store_insert(&handle, store, key)); // Read attributes from database file @@ -154,10 +172,10 @@ lsm_error lsm_store_load_db(lsm_store *store) { return lsm_error_failed_io; } - LSM_RES( - lsm_entry_read_attrs(&store->idx_file_size, handle, store->db_file)); + LSM_RES(lsm_entry_read_attrs(handle, store->db_file)); lsm_entry_close(handle); + store->idx_file_size += 3 * sizeof(uint64_t) + key_len; store->db_file_size += db_dim[1]; } diff --git a/lsm/src/store/lsm_store_disk_write.c b/lsm/src/store/lsm_store_disk_write.c index 4bdd297..07034a1 100644 --- a/lsm/src/store/lsm_store_disk_write.c +++ b/lsm/src/store/lsm_store_disk_write.c @@ -1,8 +1,9 @@ #include "lsm/store_internal.h" -static lsm_error lsm_entry_write_single(FILE *f, uint64_t size, void *val) { - size_t res = fwrite(val, size, 1, f); +static lsm_error lsm_entry_write_uint64_t(FILE *f, uint64_t num) { + size_t res = fwrite(&num, sizeof(uint64_t), 1, f); + // Such a small write should succeed in one go if (res == 0) { return lsm_error_failed_io; } @@ -10,10 +11,6 @@ static lsm_error lsm_entry_write_single(FILE *f, uint64_t size, void *val) { return lsm_error_ok; } -static lsm_error lsm_entry_write_uint64_t(FILE *f, uint64_t num) { - return lsm_entry_write_single(f, sizeof(uint64_t), &num); -} - static lsm_error lsm_entry_write_str(FILE *f, lsm_str *s) { uint64_t to_write = lsm_str_len(s); uint64_t written = 0; @@ -38,19 +35,17 @@ lsm_error lsm_entry_write_db(uint64_t *size, FILE *db_file, lsm_entry *entry, LSM_RES(lsm_seek(db_file, pos)); // First we write how many attributes follow - LSM_RES( - lsm_entry_write_single(db_file, sizeof(uint8_t), &entry->attrs.count)); - *size = sizeof(uint8_t); + LSM_RES(lsm_entry_write_uint64_t(db_file, entry->attrs.count)); + *size = sizeof(uint64_t); - for (uint8_t i = 0; i < entry->attrs.count; i++) { + for (uint64_t i = 0; i < entry->attrs.count; i++) { // Write attribute type, length & value - LSM_RES(lsm_entry_write_single(db_file, sizeof(uint8_t), - &entry->attrs.items[i].type)); + LSM_RES(lsm_entry_write_uint64_t(db_file, entry->attrs.items[i].type)); LSM_RES(lsm_entry_write_uint64_t(db_file, lsm_str_len(entry->attrs.items[i].str))); LSM_RES(lsm_entry_write_str(db_file, entry->attrs.items[i].str)); - *size += sizeof(uint8_t) + sizeof(uint64_t) + + *size += 2 * sizeof(uint64_t) + lsm_str_len(entry->attrs.items[i].str) * sizeof(char); } diff --git a/lsm/src/store/lsm_store_entry.c b/lsm/src/store/lsm_store_entry.c index 51dd998..2878996 100644 --- a/lsm/src/store/lsm_store_entry.c +++ b/lsm/src/store/lsm_store_entry.c @@ -56,13 +56,12 @@ void lsm_entry_close(lsm_entry_handle *handle) { free(handle); } -bool lsm_entry_attr_present(lsm_entry_handle *handle, uint8_t type) { - return (handle->wrapper->entry->attrs.bitmap[type / 64] & - (((uint64_t)1) << (type % 64))) != 0; +bool lsm_entry_attr_present(lsm_entry_handle *handle, lsm_attr_type type) { + return (handle->wrapper->entry->attrs.bitmap & type) != 0; } lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry_handle *handle, - uint8_t type) { + lsm_attr_type type) { if (!lsm_entry_attr_present(handle, type)) { return lsm_error_not_found; } @@ -80,7 +79,7 @@ lsm_error lsm_entry_attr_get(lsm_str **out, lsm_entry_handle *handle, } lsm_error lsm_entry_attr_get_num(uint64_t *out, lsm_entry_handle *handle, - uint8_t type) { + lsm_attr_type type) { lsm_str *s; LSM_RES(lsm_entry_attr_get(&s, handle, type)); @@ -97,7 +96,7 @@ lsm_error lsm_entry_attr_get_num(uint64_t *out, lsm_entry_handle *handle, } lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry_handle *handle, - uint8_t type) { + lsm_attr_type type) { if (!lsm_entry_attr_present(handle, type)) { return lsm_error_not_found; } @@ -110,7 +109,7 @@ lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry_handle *handle, free(entry->attrs.items); entry->attrs.items = NULL; entry->attrs.count = 0; - entry->attrs.bitmap[type / 64] &= ~(((uint64_t)1) << (type % 64)); + entry->attrs.bitmap = 0; return lsm_error_ok; } @@ -139,12 +138,12 @@ lsm_error lsm_entry_attr_remove(lsm_str **out, lsm_entry_handle *handle, entry->attrs.items = new_attrs; entry->attrs.count--; - entry->attrs.bitmap[type / 64] &= ~(((uint64_t)1) << (type % 64)); + entry->attrs.bitmap &= ~type; return lsm_error_ok; } -lsm_error lsm_entry_attr_insert(lsm_entry_handle *handle, uint8_t type, +lsm_error lsm_entry_attr_insert(lsm_entry_handle *handle, lsm_attr_type type, lsm_str *data) { if (lsm_entry_attr_present(handle, type)) { return lsm_error_already_present; @@ -164,13 +163,13 @@ lsm_error lsm_entry_attr_insert(lsm_entry_handle *handle, uint8_t type, entry->attrs.items = new_attrs; entry->attrs.count++; - entry->attrs.bitmap[type / 64] |= ((uint64_t)1) << (type % 64); + entry->attrs.bitmap |= type; return lsm_error_ok; } -lsm_error lsm_entry_attr_insert_num(lsm_entry_handle *handle, uint8_t type, - uint64_t data) { +lsm_error lsm_entry_attr_insert_num(lsm_entry_handle *handle, + lsm_attr_type type, uint64_t data) { lsm_str *s; LSM_RES( lsm_str_init_copy_n(&s, (char *)&data, sizeof(uint64_t) / sizeof(char))); diff --git a/src/lander/lander_get.c b/src/lander/lander_get.c index b063e29..026f449 100644 --- a/src/lander/lander_get.c +++ b/src/lander/lander_get.c @@ -80,14 +80,14 @@ bool lander_get_entry_lsm(event_loop_conn *conn) { lander_entry_type t; lsm_entry_attr_get_num((uint64_t *)&t, c_ctx->entry, - lander_attr_type_entry_type); + lsm_attr_type_entry_type); if (t == lander_entry_type_redirect) { // For redirects, the URL is stored as an in-memory attribute lsm_str *url_attr_val; // This shouldn't be able to happen - if (lsm_entry_attr_get(&url_attr_val, c_ctx->entry, lander_attr_type_url) != + if (lsm_entry_attr_get(&url_attr_val, c_ctx->entry, lsm_attr_type_url) != lsm_error_ok) { error("Entry of type redirect detected without URL attribute"); diff --git a/src/lander/lander_post.c b/src/lander/lander_post.c index 05dc662..b03cd53 100644 --- a/src/lander/lander_post.c +++ b/src/lander/lander_post.c @@ -132,7 +132,7 @@ bool lander_post_redirect_lsm(event_loop_conn *conn) { return true; } - lsm_entry_attr_insert_num(c_ctx->entry, lander_attr_type_entry_type, + lsm_entry_attr_insert_num(c_ctx->entry, lsm_attr_type_entry_type, lander_entry_type_redirect); return true; @@ -144,7 +144,7 @@ bool lander_post_redirect_body_to_attr(event_loop_conn *conn) { lsm_str *attr_value; lsm_str_init_copy_n(&attr_value, ctx->req.body.buf, ctx->req.body.len); - lsm_entry_attr_insert(c_ctx->entry, lander_attr_type_url, attr_value); + lsm_entry_attr_insert(c_ctx->entry, lsm_attr_type_url, attr_value); return true; } @@ -171,7 +171,7 @@ bool lander_post_paste_lsm(event_loop_conn *conn) { return true; } - lsm_entry_attr_insert_num(c_ctx->entry, lander_attr_type_entry_type, + lsm_entry_attr_insert_num(c_ctx->entry, lsm_attr_type_entry_type, lander_entry_type_paste); return true;