feat(lander): integrate persistent insert & get lsm store
parent
226873219b
commit
535b92a6b6
|
@ -6,3 +6,4 @@ lander.data*
|
||||||
pastes/
|
pastes/
|
||||||
.cache/
|
.cache/
|
||||||
vgcore.*
|
vgcore.*
|
||||||
|
data/
|
||||||
|
|
|
@ -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_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
|
#endif
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
*/
|
*/
|
||||||
typedef enum lsm_attr_type : uint64_t {
|
typedef enum lsm_attr_type : uint64_t {
|
||||||
lsm_attr_type_entry_type = 1 << 0,
|
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;
|
} lsm_attr_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
res = lsm_entry_write_uint64_t(store->idx_file, new_block_count);
|
||||||
|
|
||||||
if (res == lsm_error_ok) {
|
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_size += entry_size;
|
||||||
store->idx_file_block_count = new_block_count;
|
store->idx_file_block_count = new_block_count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,9 @@ http_route lander_routes[] = {
|
||||||
.type = http_route_regex,
|
.type = http_route_regex,
|
||||||
.method = http_post,
|
.method = http_post,
|
||||||
.path = "^/s(l?)/([^/]*)$",
|
.path = "^/s(l?)/([^/]*)$",
|
||||||
.steps = {http_loop_step_auth, http_loop_step_parse_content_length,
|
.steps = {http_loop_step_auth, lander_post_redirect_lsm,
|
||||||
lander_post_redirect_lsm, lander_stream_body_to_entry, NULL},
|
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,
|
.steps_res = {http_loop_step_write_header, http_loop_step_write_body,
|
||||||
NULL},
|
NULL},
|
||||||
},
|
},
|
||||||
|
@ -32,7 +33,8 @@ http_route lander_routes[] = {
|
||||||
.method = http_post,
|
.method = http_post,
|
||||||
.path = "^/p(l?)/([^/]*)$",
|
.path = "^/p(l?)/([^/]*)$",
|
||||||
.steps = {http_loop_step_auth, http_loop_step_parse_content_length,
|
.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,
|
.steps_res = {http_loop_step_write_header, http_loop_step_write_body,
|
||||||
NULL}},
|
NULL}},
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "event_loop.h"
|
#include "event_loop.h"
|
||||||
#include "http/types.h"
|
#include "http/types.h"
|
||||||
#include "lander.h"
|
#include "lander.h"
|
||||||
|
#include "log.h"
|
||||||
#include "lsm/store.h"
|
#include "lsm/store.h"
|
||||||
|
|
||||||
static const char index_page[] =
|
static const char index_page[] =
|
||||||
|
@ -82,19 +83,25 @@ bool lander_get_entry_lsm(event_loop_conn *conn) {
|
||||||
lsm_attr_type_entry_type);
|
lsm_attr_type_entry_type);
|
||||||
|
|
||||||
if (t == lander_entry_type_redirect) {
|
if (t == lander_entry_type_redirect) {
|
||||||
// Stream entire redirect data into buffer to set as header
|
// For redirects, the URL is stored as an in-memory attribute
|
||||||
uint64_t data_len = lsm_entry_data_len(c_ctx->entry);
|
lsm_str *url_attr_val;
|
||||||
char *buf = malloc(data_len + 1);
|
|
||||||
uint64_t read = 0;
|
|
||||||
uint64_t total_read = 0;
|
|
||||||
|
|
||||||
while (total_read < data_len) {
|
// This shouldn't be able to happen
|
||||||
lsm_entry_data_read(&read, &buf[total_read], c_ctx->entry,
|
if (lsm_entry_attr_get(&url_attr_val, c_ctx->entry, lsm_attr_type_url) !=
|
||||||
data_len - total_read);
|
lsm_error_ok) {
|
||||||
total_read += read;
|
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;
|
ctx->res.status = http_moved_permanently;
|
||||||
http_res_add_header(&ctx->res, http_header_location, buf, true);
|
http_res_add_header(&ctx->res, http_header_location, buf, true);
|
||||||
|
|
|
@ -138,6 +138,30 @@ bool lander_post_redirect_lsm(event_loop_conn *conn) {
|
||||||
return true;
|
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) {
|
bool lander_post_paste_lsm(event_loop_conn *conn) {
|
||||||
http_loop_ctx *ctx = conn->ctx;
|
http_loop_ctx *ctx = conn->ctx;
|
||||||
lander_ctx *c_ctx = ctx->c;
|
lander_ctx *c_ctx = ctx->c;
|
||||||
|
|
12
src/main.c
12
src/main.c
|
@ -23,7 +23,7 @@ int main() {
|
||||||
|
|
||||||
ENV(api_key, "LANDER_API_KEY");
|
ENV(api_key, "LANDER_API_KEY");
|
||||||
ENV_OPT(port_str, "LANDER_PORT", "18080");
|
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);
|
int port = atoi(port_str);
|
||||||
|
|
||||||
|
@ -46,12 +46,14 @@ int main() {
|
||||||
/* info("Trie initialized and populated with %i entries", trie_size(trie)); */
|
/* info("Trie initialized and populated with %i entries", trie_size(trie)); */
|
||||||
|
|
||||||
lander_gctx *c_gctx = lander_gctx_init();
|
lander_gctx *c_gctx = lander_gctx_init();
|
||||||
c_gctx->data_dir = data_dir;
|
c_gctx->data_dir = data_dir_s;
|
||||||
/* c_gctx->trie = trie; */
|
/* c_gctx->trie = trie; */
|
||||||
|
|
||||||
lsm_str *data_dir2;
|
lsm_str *data_dir;
|
||||||
lsm_str_init_copy(&data_dir2, "data");
|
lsm_str_init_copy(&data_dir, (char *)data_dir_s);
|
||||||
lsm_store_load(&c_gctx->store, data_dir2);
|
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(
|
http_loop *hl = http_loop_init(
|
||||||
lander_routes, sizeof(lander_routes) / sizeof(lander_routes[0]), c_gctx,
|
lander_routes, sizeof(lander_routes) / sizeof(lander_routes[0]), c_gctx,
|
||||||
|
|
Loading…
Reference in New Issue