feat(lsm): require changes to be explicitely committed
ci/woodpecker/push/build Pipeline was successful Details

bug/16-failed-uploads
Jef Roosens 2024-08-27 16:00:35 +02:00
parent d64fec048f
commit 4bec73e10f
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
6 changed files with 64 additions and 22 deletions

View File

@ -51,6 +51,8 @@ lnm_http_step_err lander_post_paste_secure(lnm_http_conn *conn);
lnm_http_step_err lander_stream_body_to_entry(lnm_http_conn *conn);
lnm_http_step_err lander_commit_entry(lnm_http_conn *conn);
lnm_http_step_err lander_post_redirect_body_to_attr(lnm_http_conn *conn);
lnm_http_step_err lander_remove_entry(lnm_http_conn *conn);

View File

@ -159,6 +159,15 @@ lsm_error lsm_store_open_read(lsm_entry_handle **out, lsm_store *store,
lsm_error lsm_store_open_write(lsm_entry_handle **out, lsm_store *store,
const lsm_str *key);
/**
* Commit any changes to the persistent storage. Any changes, insertions or
* deletions that occured without a commit are reverted when the handle is
* closed.
*
* @param handle handle to the entry
*/
lsm_error lsm_entry_commit(lsm_entry_handle *handle);
/**
* Close an open entry handle.
*

View File

@ -157,7 +157,8 @@ lsm_error lsm_entry_data_open_read(lsm_entry_handle *handle);
lsm_error lsm_entry_data_open_write(lsm_entry_handle *handle);
/**
* Remove the entry's data file if present and close its handle.
* Remove the entry's data file if present and close its handle. Any uncommitted
* changes will be reverted.
*
* @param handle handle to the entry
*/

View File

@ -58,31 +58,42 @@ lsm_error lsm_entry_handle_init(lsm_entry_handle **out) {
return lsm_error_ok;
}
void lsm_entry_close(lsm_entry_handle *handle) {
if (handle->f != NULL) {
fclose(handle->f);
}
bool state_new = handle->states & lsm_entry_handle_state_new;
bool state_removed = handle->states & lsm_entry_handle_state_removed;
/* bool state_updated = handle->states & lsm_entry_handle_state_updated; */
lsm_error lsm_entry_commit(lsm_entry_handle *handle) {
uint8_t state_new = handle->states & lsm_entry_handle_state_new;
uint8_t state_removed = handle->states & lsm_entry_handle_state_removed;
// Clean new entry
if (state_new && !state_removed) {
lsm_entry_disk_insert(handle);
}
// New entry that was removed before being written to disk; only its data file
// needs to be removed if present
else if (state_new && state_removed) {
lsm_entry_data_remove(handle);
lsm_entry_free(handle->wrapper->entry);
handle->wrapper->entry = NULL;
LSM_RES(lsm_entry_disk_insert(handle));
}
// Previously stored entry that needs to be removed; should be removed from db
// file as well
else if (state_removed && !state_new) {
lsm_entry_disk_remove(handle);
LSM_RES(lsm_entry_disk_remove(handle));
lsm_entry_free(handle->wrapper->entry);
handle->wrapper->entry = NULL;
}
// Reset states after committing current changes
handle->states = 0;
return lsm_error_ok;
}
void lsm_entry_close(lsm_entry_handle *handle) {
if (handle->f != NULL) {
fclose(handle->f);
handle->f = NULL;
}
uint8_t state_new = handle->states & lsm_entry_handle_state_new;
/* bool state_updated = handle->states & lsm_entry_handle_state_updated; */
// New entries create a wrapper in the trie that should be removed if not
// committed
if (state_new) {
lsm_entry_data_remove(handle);
lsm_entry_free(handle->wrapper->entry);
handle->wrapper->entry = NULL;
@ -328,7 +339,6 @@ lsm_error lsm_entry_data_open_read(lsm_entry_handle *handle) {
return lsm_error_ok;
}
lsm_error lsm_entry_data_remove(lsm_entry_handle *handle) {
const lsm_entry *entry = handle->wrapper->entry;

View File

@ -1,6 +1,7 @@
#include <string.h>
#include "lnm/http/loop.h"
#include "lnm/log.h"
#include "lnm/loop.h"
#include "lander.h"
@ -25,3 +26,12 @@ lnm_http_step_err lander_stream_body_to_entry(lnm_http_conn *conn) {
? lnm_http_step_err_done
: lnm_http_step_err_io_needed;
}
lnm_http_step_err lander_commit_entry(lnm_http_conn *conn) {
lnm_http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
lsm_entry_commit(c_ctx->entry);
return lnm_http_step_err_done;
}

View File

@ -30,54 +30,64 @@ lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) {
lnm_http_router_add(&route, router, lnm_http_method_delete, "/:key");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_remove_entry, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/s/");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_redirect, false);
lnm_http_route_step_append(route, lnm_http_loop_step_body_to_buf, false);
lnm_http_route_step_append(route, lander_post_redirect_body_to_attr, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/sl/");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_redirect_secure, false);
lnm_http_route_step_append(route, lnm_http_loop_step_body_to_buf, false);
lnm_http_route_step_append(route, lander_post_redirect_body_to_attr, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/s/:key");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_redirect, false);
lnm_http_route_step_append(route, lnm_http_loop_step_body_to_buf, false);
lnm_http_route_step_append(route, lander_post_redirect_body_to_attr, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/p/");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_paste, false);
lnm_http_route_step_append(route, lander_stream_body_to_entry, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/pl/");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_paste_secure, false);
lnm_http_route_step_append(route, lander_stream_body_to_entry, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/p/:key");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_paste, false);
lnm_http_route_step_append(route, lander_stream_body_to_entry, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/f/");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_file, false);
lnm_http_route_step_append(route, lander_stream_body_to_entry, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/fl/");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_file_secure, false);
lnm_http_route_step_append(route, lander_stream_body_to_entry, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_router_add(&route, router, lnm_http_method_post, "/f/:key");
lnm_http_route_step_append(route, lnm_http_loop_step_auth, false);
lnm_http_route_step_append(route, lander_post_file, false);
lnm_http_route_step_append(route, lander_stream_body_to_entry, false);
lnm_http_route_step_append(route, lander_commit_entry, true);
lnm_http_loop_router_set(hl, router);
@ -101,7 +111,7 @@ int main() {
srand(time(NULL));
lnm_log_init_global();
lnm_log_register_stdout(lnm_log_level_info);
lnm_log_register_stdout(lnm_log_level_debug);
ENV(api_key, "LANDER_API_KEY");
ENV_OPT(port_str, "LANDER_PORT", "18080");
@ -129,5 +139,5 @@ int main() {
lnm_linfo("main", "Store loaded containing %lu entries",
lsm_store_size(c_gctx->store));
lnm_http_loop *hl = loop_init(c_gctx, api_key);
lnm_http_loop_run(hl, port, 1, 0);
lnm_http_loop_run(hl, port, 4, 0);
}