Compare commits
4 Commits
51e4a203e9
...
3d48ee8019
| Author | SHA1 | Date |
|---|---|---|
|
|
3d48ee8019 | |
|
|
a4ad8c246e | |
|
|
c8728f2371 | |
|
|
b40389bbe2 |
|
|
@ -4,7 +4,7 @@
|
||||||
#include "http_loop.h"
|
#include "http_loop.h"
|
||||||
#include "lsm/store.h"
|
#include "lsm/store.h"
|
||||||
|
|
||||||
extern http_route lander_routes[4];
|
extern http_route lander_routes[5];
|
||||||
|
|
||||||
typedef struct lander_gctx {
|
typedef struct lander_gctx {
|
||||||
const char *data_dir;
|
const char *data_dir;
|
||||||
|
|
@ -57,4 +57,6 @@ bool lander_get_entry_lsm(event_loop_conn *conn);
|
||||||
|
|
||||||
bool lander_post_redirect_body_to_attr(event_loop_conn *conn);
|
bool lander_post_redirect_body_to_attr(event_loop_conn *conn);
|
||||||
|
|
||||||
|
bool lander_remove_entry(event_loop_conn *conn);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -20,18 +20,13 @@ int main() {
|
||||||
|
|
||||||
lsm_str *attr;
|
lsm_str *attr;
|
||||||
lsm_str_init_copy(&attr, "some attribute value");
|
lsm_str_init_copy(&attr, "some attribute value");
|
||||||
lsm_entry_attr_insert(handle, lsm_attr_type_content_type, attr);
|
lsm_entry_attr_insert(handle, 1, attr);
|
||||||
|
|
||||||
lsm_str *data;
|
lsm_str *data;
|
||||||
lsm_str_init_copy(&data, "hello");
|
lsm_str_init_copy(&data, "hello");
|
||||||
|
|
||||||
for (int i = 0; i < 50; i++) {
|
for (int i = 0; i < 50; i++) {
|
||||||
lsm_entry_data_append(store, handle, data);
|
lsm_entry_data_append(handle, data);
|
||||||
}
|
|
||||||
|
|
||||||
if (lsm_entry_sync(store, handle) != lsm_error_ok) {
|
|
||||||
printf("godver");
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
lsm_entry_close(handle);
|
lsm_entry_close(handle);
|
||||||
|
|
||||||
|
|
@ -50,4 +45,12 @@ int main() {
|
||||||
total += read;
|
total += read;
|
||||||
}
|
}
|
||||||
printf("\n%lu", total);
|
printf("\n%lu", total);
|
||||||
|
|
||||||
|
lsm_entry_close(handle);
|
||||||
|
|
||||||
|
assert(lsm_store_open_write(&handle, store, key) == lsm_error_ok);
|
||||||
|
lsm_entry_remove(handle);
|
||||||
|
lsm_entry_close(handle);
|
||||||
|
|
||||||
|
assert(lsm_store_open_read(&handle, store, key) == lsm_error_not_found);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,13 @@ void lsm_entry_close(lsm_entry_handle *handle);
|
||||||
lsm_error lsm_store_insert(lsm_entry_handle **out, lsm_store *store,
|
lsm_error lsm_store_insert(lsm_entry_handle **out, lsm_store *store,
|
||||||
lsm_str *key);
|
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.
|
* Append new data to the given entry, which is expected to be in the store.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#define LSM_DB_FILE_NAME "lsm.db"
|
#define LSM_DB_FILE_NAME "lsm.db"
|
||||||
#define LSM_IDX_FILE_NAME "lsm.idx"
|
#define LSM_IDX_FILE_NAME "lsm.idx"
|
||||||
|
#define LSM_DATA_FILE_SUFFIX ".data"
|
||||||
|
|
||||||
typedef struct lsm_attr {
|
typedef struct lsm_attr {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
|
@ -40,6 +41,13 @@ typedef struct lsm_entry {
|
||||||
*/
|
*/
|
||||||
lsm_error lsm_entry_init(lsm_entry **ptr);
|
lsm_error lsm_entry_init(lsm_entry **ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deallocate an existing entry
|
||||||
|
*
|
||||||
|
* @param entry pointer to entry
|
||||||
|
*/
|
||||||
|
void lsm_entry_free(lsm_entry *entry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deallocate an existing lsm_entry object.
|
* Deallocate an existing lsm_entry object.
|
||||||
*
|
*
|
||||||
|
|
@ -122,4 +130,15 @@ lsm_error lsm_entry_disk_remove(lsm_entry_handle *handle);
|
||||||
*/
|
*/
|
||||||
lsm_error lsm_entry_disk_update(lsm_entry_handle *handle);
|
lsm_error lsm_entry_disk_update(lsm_entry_handle *handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the length of the path to this entry's data file
|
||||||
|
*/
|
||||||
|
uint64_t lsm_entry_data_path_len(lsm_entry_handle *handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill in the entry's data file path in the provided buffer. Use
|
||||||
|
* `lsm_entry_data_path_len` to allocate an appropriately-sized buffer
|
||||||
|
*/
|
||||||
|
void lsm_entry_data_path(char *buf, lsm_entry_handle *handle);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,10 @@ lsm_error lsm_store_insert(lsm_entry_handle **out, lsm_store *store,
|
||||||
return lsm_error_ok;
|
return lsm_error_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lsm_entry_remove(lsm_entry_handle *handle) {
|
||||||
|
handle->states |= lsm_entry_handle_state_removed;
|
||||||
|
}
|
||||||
|
|
||||||
lsm_error lsm_entry_data_append(lsm_entry_handle *handle, lsm_str *data) {
|
lsm_error lsm_entry_data_append(lsm_entry_handle *handle, lsm_str *data) {
|
||||||
if (lsm_str_len(data) == 0) {
|
if (lsm_str_len(data) == 0) {
|
||||||
return lsm_error_ok;
|
return lsm_error_ok;
|
||||||
|
|
@ -170,11 +174,10 @@ lsm_error lsm_entry_data_append(lsm_entry_handle *handle, lsm_str *data) {
|
||||||
|
|
||||||
// Entries don't open their file unless needed
|
// Entries don't open their file unless needed
|
||||||
if (handle->f == NULL) {
|
if (handle->f == NULL) {
|
||||||
char path[handle->store->data_path->len + entry->key->len + 2];
|
char data_path[lsm_entry_data_path_len(handle) + 1];
|
||||||
sprintf(path, "%s/%s", lsm_str_ptr(handle->store->data_path),
|
lsm_entry_data_path(data_path, handle);
|
||||||
lsm_str_ptr(entry->key));
|
|
||||||
|
|
||||||
FILE *f = fopen(path, "ab");
|
FILE *f = fopen(data_path, "ab");
|
||||||
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
return lsm_error_failed_io;
|
return lsm_error_failed_io;
|
||||||
|
|
@ -209,11 +212,10 @@ lsm_error lsm_entry_data_read(uint64_t *out, char *buf,
|
||||||
|
|
||||||
// Entries don't open their file unless needed
|
// Entries don't open their file unless needed
|
||||||
if (handle->f == NULL) {
|
if (handle->f == NULL) {
|
||||||
char path[handle->store->data_path->len + entry->key->len + 2];
|
char data_path[lsm_entry_data_path_len(handle) + 1];
|
||||||
sprintf(path, "%s/%s", lsm_str_ptr(handle->store->data_path),
|
lsm_entry_data_path(data_path, handle);
|
||||||
lsm_str_ptr(entry->key));
|
|
||||||
|
|
||||||
FILE *f = fopen(path, "rb");
|
FILE *f = fopen(data_path, "rb");
|
||||||
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
return lsm_error_failed_io;
|
return lsm_error_failed_io;
|
||||||
|
|
|
||||||
|
|
@ -124,3 +124,49 @@ lsm_error lsm_entry_disk_insert(lsm_entry_handle *handle) {
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marking an entry as removed in the idx file is simply setting the length of
|
||||||
|
// its entry to zero
|
||||||
|
lsm_error lsm_entry_disk_remove(lsm_entry_handle *handle) {
|
||||||
|
lsm_store *store = handle->store;
|
||||||
|
lsm_entry *entry = handle->wrapper->entry;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&store->idx.lock);
|
||||||
|
|
||||||
|
lsm_error res =
|
||||||
|
lsm_fseek(store->idx.f, entry->idx_file_offset + sizeof(uint64_t));
|
||||||
|
|
||||||
|
if (res != lsm_error_ok) {
|
||||||
|
pthread_mutex_unlock(&store->idx.lock);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t val = 0;
|
||||||
|
res = lsm_fwrite(NULL, store->idx.f, sizeof(uint64_t), 1, &val);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&store->idx.lock);
|
||||||
|
|
||||||
|
if (res != lsm_error_ok) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(store->idx.f);
|
||||||
|
|
||||||
|
// Remove data file if present
|
||||||
|
if (entry->data_len > 0) {
|
||||||
|
if (handle->f != NULL) {
|
||||||
|
fclose(handle->f);
|
||||||
|
handle->f = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char data_path[lsm_entry_data_path_len(handle) + 1];
|
||||||
|
lsm_entry_data_path(data_path, handle);
|
||||||
|
|
||||||
|
if (remove(data_path) != 0) {
|
||||||
|
return lsm_error_failed_io;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lsm_error_ok;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,14 @@ lsm_error lsm_entry_init(lsm_entry **ptr) {
|
||||||
return lsm_error_ok;
|
return lsm_error_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lsm_entry_free(lsm_entry *entry) {
|
||||||
|
if (entry->attrs.count > 0) {
|
||||||
|
free(entry->attrs.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
lsm_error lsm_entry_wrapper_init(lsm_entry_wrapper **ptr) {
|
lsm_error lsm_entry_wrapper_init(lsm_entry_wrapper **ptr) {
|
||||||
lsm_entry_wrapper *wrap = calloc(1, sizeof(lsm_entry_wrapper));
|
lsm_entry_wrapper *wrap = calloc(1, sizeof(lsm_entry_wrapper));
|
||||||
|
|
||||||
|
|
@ -58,7 +66,10 @@ void lsm_entry_close(lsm_entry_handle *handle) {
|
||||||
lsm_entry_disk_insert(handle);
|
lsm_entry_disk_insert(handle);
|
||||||
} else if ((handle->states & lsm_entry_handle_state_removed) &&
|
} else if ((handle->states & lsm_entry_handle_state_removed) &&
|
||||||
!(handle->states & lsm_entry_handle_state_new)) {
|
!(handle->states & lsm_entry_handle_state_new)) {
|
||||||
/* lsm_entry_disk_remove(handle); */
|
lsm_entry_disk_remove(handle);
|
||||||
|
|
||||||
|
lsm_entry_free(handle->wrapper->entry);
|
||||||
|
handle->wrapper->entry = NULL;
|
||||||
} else if (handle->states & lsm_entry_handle_state_updated) {
|
} else if (handle->states & lsm_entry_handle_state_updated) {
|
||||||
/* lsm_entry_disk_update(handle); */
|
/* lsm_entry_disk_update(handle); */
|
||||||
}
|
}
|
||||||
|
|
@ -216,3 +227,25 @@ lsm_error lsm_entry_attr_insert_uint8_t(lsm_entry_handle *handle, uint8_t type,
|
||||||
uint64_t lsm_entry_data_len(lsm_entry_handle *handle) {
|
uint64_t lsm_entry_data_len(lsm_entry_handle *handle) {
|
||||||
return handle->wrapper->entry->data_len;
|
return handle->wrapper->entry->data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t lsm_entry_data_path_len(lsm_entry_handle *handle) {
|
||||||
|
// [data path]/[entry key][data file suffix]
|
||||||
|
return lsm_str_len(handle->store->data_path) +
|
||||||
|
lsm_str_len(handle->wrapper->entry->key) +
|
||||||
|
strlen(LSM_DATA_FILE_SUFFIX) + 1;
|
||||||
|
}
|
||||||
|
void lsm_entry_data_path(char *buf, lsm_entry_handle *handle) {
|
||||||
|
lsm_str *data_path = handle->store->data_path;
|
||||||
|
lsm_str *key = handle->wrapper->entry->key;
|
||||||
|
|
||||||
|
memcpy(buf, lsm_str_ptr(data_path), lsm_str_len(data_path));
|
||||||
|
|
||||||
|
uint64_t index = lsm_str_len(data_path);
|
||||||
|
buf[index] = '/';
|
||||||
|
|
||||||
|
index += 1;
|
||||||
|
memcpy(&buf[index], lsm_str_ptr(key), lsm_str_len(key));
|
||||||
|
|
||||||
|
index += lsm_str_len(key);
|
||||||
|
strcpy(&buf[index], LSM_DATA_FILE_SUFFIX);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,14 @@ http_route lander_routes[] = {
|
||||||
.steps_res = {http_loop_step_write_header, lander_stream_body_to_client,
|
.steps_res = {http_loop_step_write_header, lander_stream_body_to_client,
|
||||||
NULL},
|
NULL},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.type = http_route_regex,
|
||||||
|
.method = http_delete,
|
||||||
|
.path = "^/([^/]+)$",
|
||||||
|
.steps = {http_loop_step_auth, lander_remove_entry, NULL},
|
||||||
|
.steps_res = {http_loop_step_write_header, http_loop_step_write_body,
|
||||||
|
NULL},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.type = http_route_regex,
|
.type = http_route_regex,
|
||||||
.method = http_post,
|
.method = http_post,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "lander.h"
|
||||||
|
|
||||||
|
bool lander_remove_entry(event_loop_conn *conn) {
|
||||||
|
http_loop_ctx *ctx = conn->ctx;
|
||||||
|
lander_ctx *c_ctx = ctx->c;
|
||||||
|
http_loop_gctx *gctx = ctx->g;
|
||||||
|
lander_gctx *c_gctx = gctx->c;
|
||||||
|
|
||||||
|
const char *key_s = &ctx->req.path[ctx->req.regex_groups[1].rm_so];
|
||||||
|
int key_len = ctx->req.regex_groups[1].rm_eo - ctx->req.regex_groups[1].rm_so;
|
||||||
|
|
||||||
|
lsm_str *key;
|
||||||
|
lsm_str_init_copy_n(&key, (char *)key_s, key_len);
|
||||||
|
|
||||||
|
switch (lsm_store_open_write(&c_ctx->entry, c_gctx->store, key)) {
|
||||||
|
case lsm_error_ok:
|
||||||
|
break;
|
||||||
|
case lsm_error_not_found:
|
||||||
|
ctx->res.status = http_not_found;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
ctx->res.status = http_internal_server_error;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lsm_entry_remove(c_ctx->entry);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue