feat(lander): integrate persistent insert & get lsm store

lsm
Jef Roosens 2023-11-08 11:19:33 +01:00
parent 226873219b
commit 535b92a6b6
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
8 changed files with 63 additions and 19 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ lander.data*
pastes/
.cache/
vgcore.*
data/

View File

@ -49,4 +49,8 @@ bool lander_stream_body_to_client(event_loop_conn *conn);
bool lander_get_entry_lsm(event_loop_conn *conn);
bool lander_post_redirect_body_to_attr(event_loop_conn *conn);
bool lander_entry_sync(event_loop_conn *conn);
#endif

View File

@ -17,7 +17,8 @@
*/
typedef enum lsm_attr_type : uint64_t {
lsm_attr_type_entry_type = 1 << 0,
lsm_attr_type_content_type = 1 << 1
lsm_attr_type_content_type = 1 << 1,
lsm_attr_type_url = 1 << 2,
} lsm_attr_type;
/**

View File

@ -100,6 +100,9 @@ lsm_error lsm_entry_sync(lsm_store *store, lsm_entry_handle *handle) {
res = lsm_entry_write_uint64_t(store->idx_file, new_block_count);
if (res == lsm_error_ok) {
// Only if we successfully updated the on-disk counter do we make the code
// aware that the file's size has increased. This way, if a write to the
// counter fails, the code will simply reuse the already written content.
store->idx_file_size += entry_size;
store->idx_file_block_count = new_block_count;
}

View File

@ -23,8 +23,9 @@ http_route lander_routes[] = {
.type = http_route_regex,
.method = http_post,
.path = "^/s(l?)/([^/]*)$",
.steps = {http_loop_step_auth, http_loop_step_parse_content_length,
lander_post_redirect_lsm, lander_stream_body_to_entry, NULL},
.steps = {http_loop_step_auth, lander_post_redirect_lsm,
http_loop_step_body_to_buf, lander_post_redirect_body_to_attr,
lander_entry_sync, NULL},
.steps_res = {http_loop_step_write_header, http_loop_step_write_body,
NULL},
},
@ -32,7 +33,8 @@ http_route lander_routes[] = {
.method = http_post,
.path = "^/p(l?)/([^/]*)$",
.steps = {http_loop_step_auth, http_loop_step_parse_content_length,
lander_post_paste_lsm, lander_stream_body_to_entry, NULL},
lander_post_paste_lsm, lander_stream_body_to_entry,
lander_entry_sync, NULL},
.steps_res = {http_loop_step_write_header, http_loop_step_write_body,
NULL}},
};

View File

@ -3,6 +3,7 @@
#include "event_loop.h"
#include "http/types.h"
#include "lander.h"
#include "log.h"
#include "lsm/store.h"
static const char index_page[] =
@ -82,19 +83,25 @@ bool lander_get_entry_lsm(event_loop_conn *conn) {
lsm_attr_type_entry_type);
if (t == lander_entry_type_redirect) {
// Stream entire redirect data into buffer to set as header
uint64_t data_len = lsm_entry_data_len(c_ctx->entry);
char *buf = malloc(data_len + 1);
uint64_t read = 0;
uint64_t total_read = 0;
// For redirects, the URL is stored as an in-memory attribute
lsm_str *url_attr_val;
while (total_read < data_len) {
lsm_entry_data_read(&read, &buf[total_read], c_ctx->entry,
data_len - total_read);
total_read += read;
// This shouldn't be able to happen
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");
ctx->res.status = http_internal_server_error;
lsm_entry_close(c_ctx->entry);
c_ctx->entry = NULL;
return true;
}
buf[data_len] = '\0';
char *buf = malloc(lsm_str_len(url_attr_val) + 1);
memcpy(buf, lsm_str_ptr(url_attr_val), lsm_str_len(url_attr_val));
buf[lsm_str_len(url_attr_val)] = '\0';
ctx->res.status = http_moved_permanently;
http_res_add_header(&ctx->res, http_header_location, buf, true);

View File

@ -138,6 +138,30 @@ bool lander_post_redirect_lsm(event_loop_conn *conn) {
return true;
}
bool lander_post_redirect_body_to_attr(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
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, lsm_attr_type_url, attr_value);
return true;
}
bool lander_entry_sync(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx;
http_loop_gctx *gctx = ctx->g;
lander_gctx *c_gctx = gctx->c;
lander_ctx *c_ctx = ctx->c;
if (lsm_entry_sync(c_gctx->store, c_ctx->entry) != lsm_error_ok) {
ctx->res.status = http_internal_server_error;
}
return true;
}
bool lander_post_paste_lsm(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;

View File

@ -23,7 +23,7 @@ int main() {
ENV(api_key, "LANDER_API_KEY");
ENV_OPT(port_str, "LANDER_PORT", "18080");
ENV_OPT(data_dir, "LANDER_DATA_DIR", ".");
ENV_OPT(data_dir_s, "LANDER_DATA_DIR", ".");
int port = atoi(port_str);
@ -46,12 +46,14 @@ int main() {
/* info("Trie initialized and populated with %i entries", trie_size(trie)); */
lander_gctx *c_gctx = lander_gctx_init();
c_gctx->data_dir = data_dir;
c_gctx->data_dir = data_dir_s;
/* c_gctx->trie = trie; */
lsm_str *data_dir2;
lsm_str_init_copy(&data_dir2, "data");
lsm_store_load(&c_gctx->store, data_dir2);
lsm_str *data_dir;
lsm_str_init_copy(&data_dir, (char *)data_dir_s);
if (lsm_store_load(&c_gctx->store, data_dir) != lsm_error_ok) {
critical(2, "Failed to load existing store.");
}
http_loop *hl = http_loop_init(
lander_routes, sizeof(lander_routes) / sizeof(lander_routes[0]), c_gctx,