diff options
author | Franklin Wei <me@fwei.tk> | 2018-07-05 19:45:07 -0400 |
---|---|---|
committer | Franklin Wei <me@fwei.tk> | 2018-07-05 19:45:07 -0400 |
commit | 9aa64e1c89fae3efc92297657f2a8cf3de5b1047 (patch) | |
tree | 265befebafae978a0f1e7549f4c6f9f5389dfdcf /service_provider.c | |
parent | 626224ade749f4429d5c098d8f27798da8405ca1 (diff) | |
download | csaa-9aa64e1c89fae3efc92297657f2a8cf3de5b1047.zip csaa-9aa64e1c89fae3efc92297657f2a8cf3de5b1047.tar.gz csaa-9aa64e1c89fae3efc92297657f2a8cf3de5b1047.tar.bz2 csaa-9aa64e1c89fae3efc92297657f2a8cf3de5b1047.tar.xz |
Add method to save module state; allows resuming from a previous run
Diffstat (limited to 'service_provider.c')
-rw-r--r-- | service_provider.c | 111 |
1 files changed, 97 insertions, 14 deletions
diff --git a/service_provider.c b/service_provider.c index 1b68a25..d31e833 100644 --- a/service_provider.c +++ b/service_provider.c @@ -67,6 +67,9 @@ struct service_provider { void *db; /* sqlite3 handle */ struct iomt *iomt; /* backed by database */ + + sqlite3_stmt *lookup_record, *insert_record, *update_record, + *insert_version, *count_versions, *lookup_version, *find_empty; }; /* Generate an EQ certificate for inserting a placeholder with index @@ -208,6 +211,11 @@ int count_rows(void *db, const char *table) return rows; } +void db_free(void *handle) +{ + sqlite3_close(handle); +} + void *db_init(const char *filename, bool overwrite, bool *need_init) { sqlite3 *db; @@ -222,8 +230,7 @@ void *db_init(const char *filename, bool overwrite, bool *need_init) extern unsigned char sqlinit_txt[]; /* create tables */ - char *msg; - assert(sqlite3_exec(db, (const char*)sqlinit_txt, NULL, NULL, &msg) == SQLITE_OK); + assert(sqlite3_exec(db, (const char*)sqlinit_txt, NULL, NULL, NULL) == SQLITE_OK); *need_init = true; } @@ -245,6 +252,46 @@ void commit_transaction(void *db) sqlite3_exec(handle, "COMMIT;", 0, 0, 0); } +int count_placeholders(void *db) +{ + sqlite3 *handle = db; + const char *sql = "SELECT COUNT(*) FROM FileLeaves WHERE Val = ?1;"; + + sqlite3_stmt *st; + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + + sqlite3_bind_blob(st, 1, &hash_null, sizeof(hash_null), SQLITE_STATIC); + + assert(sqlite3_step(st) == SQLITE_ROW); + + int count = sqlite3_column_int(st, 0); + + sqlite3_finalize(st); + + printf("Counted %d placeholders\n", count); + + return count; +} + +uint64_t max_fileindex(void *db) +{ + sqlite3 *handle = db; + const char *sql = "SELECT MAX(Idx) FROM FileRecords;"; + + sqlite3_stmt *st; + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + + uint64_t max = 0; + if(sqlite3_step(st) == SQLITE_ROW) + max = sqlite3_column_int64(st, 0); + + sqlite3_finalize(st); + + printf("maximum index is %lu\n", max); + + return max; +} + /* leaf count will be 2^logleaves */ /* will use old DB contents unless overwrite_db is true */ struct service_provider *sp_new(const void *key, size_t keylen, @@ -262,12 +309,12 @@ struct service_provider *sp_new(const void *key, size_t keylen, bool iomt_init = true; sp->db = db_init(dbpath, overwrite_db, &iomt_init); - sp->tm = tm_new(key, keylen); - sp->data_dir = data_dir; if(iomt_init) { + sp->tm = tm_new(key, keylen); + /* create IOMT in memory first, then commit to DB */ sp->iomt = iomt_new_from_db(sp->db, "FileNodes", "FileLeaves", @@ -297,14 +344,24 @@ struct service_provider *sp_new(const void *key, size_t keylen, NULL, 0, logleaves); - /* TODO: set placeholder count, file index */ + sp->tm = tm_new_from_savedstate("module_state"); + if(!sp->tm) + { + warn("failed to load module state; creating fresh state (will probably fail)"); + sp->tm = tm_new(key, keylen); + } + + sp->n_placeholders = count_placeholders(sp->db); + sp->next_fileidx = max_fileindex(sp->db) + 1; - warn("resuming from previous database; module will fail"); + printf("Resuming from previous state...\n"); +#if 0 int leaves = count_rows(sp->db, "FileLeaves"); if(leaves != (1ULL << logleaves)) warn("logleaves value is inconsistent with leaf count in IOMT! (have %d, expect %d)", leaves, 1 << logleaves); +#endif } return sp; @@ -335,6 +392,7 @@ void sp_free(struct service_provider *sp) { tm_free(sp->tm); iomt_free(sp->iomt); + db_free(sp->db); free(sp); } } @@ -665,17 +723,12 @@ struct tm_cert sp_request(struct service_provider *sp, /* returns a leaf idx (not a file idx!) */ static uint64_t find_empty_slot(struct service_provider *sp) { - static sqlite3_stmt *st = NULL; + sqlite3_stmt *st; sqlite3 *handle = sp->db; - if(!st) - { - const char *sql = "SELECT LeafIdx FROM FileLeaves WHERE Val = ?1 LIMIT 1;"; - sqlite3_prepare_v2(handle, sql, -1, &st, 0); - } - else - sqlite3_reset(st); + const char *sql = "SELECT LeafIdx FROM FileLeaves WHERE Val = ?1 LIMIT 1;"; + sqlite3_prepare_v2(handle, sql, -1, &st, 0); sqlite3_bind_blob(st, 1, &hash_null, sizeof(hash_null), SQLITE_STATIC); @@ -774,6 +827,7 @@ struct tm_request sp_createfile(struct service_provider *sp, acl); sp->n_placeholders--; + iomt_free(acl); free(file_comp); free(file_orders); @@ -819,6 +873,8 @@ struct tm_request sp_modifyacl(struct service_provider *sp, acl_comp, acl_orders, rec->acl->mt_logleaves, iomt_getroot(new_acl)); + free_record(rec); + free(file_comp); free(file_orders); free(acl_comp); @@ -894,6 +950,8 @@ struct tm_request sp_modifyfile(struct service_provider *sp, free(file_orders); free(acl_orders); + free_record(rec); + hash_t req_hmac = sign_request(userdata, &req); struct tm_cert vr; @@ -1015,6 +1073,7 @@ struct version_info sp_fileinfo(struct service_provider *sp, &rec->fr_cert, rec->fr_hmac, ver ? &ver->vr_cert : NULL, ver ? ver->vr_hmac : hash_null, hmac); + free_record(rec); free_version(ver); return ret; @@ -1054,6 +1113,7 @@ void *sp_retrieve_file(struct service_provider *sp, if(!ver) { + free_record(rec); *len = 0; return NULL; } @@ -1091,6 +1151,7 @@ void *sp_retrieve_file(struct service_provider *sp, if(composefile) *composefile = iomt_dup(ver->composefile); + free_record(rec); free_version(ver); return ret; @@ -1143,6 +1204,9 @@ static void sp_handle_client(struct service_provider *sp, int cl) user_req.modify_acl.file_idx, acl, &ack_hmac); + + iomt_free(acl); + if(write(cl, &ack_hmac, sizeof(ack_hmac)) != sizeof(ack_hmac)) return; break; @@ -1173,6 +1237,9 @@ static void sp_handle_client(struct service_provider *sp, int cl) { printf("Failed: %s\n", tm_geterror()); } + + free(filebuf); + iomt_free(buildcode); iomt_free(composefile); write(cl, &ack_hmac, sizeof(ack_hmac)); @@ -1227,7 +1294,10 @@ static void sp_handle_client(struct service_provider *sp, int cl) write(cl, &len, sizeof(len)); if(contents) + { write(cl, contents, len); + free(contents); + } break; } @@ -1239,6 +1309,18 @@ static void sp_handle_client(struct service_provider *sp, int cl) } } +/* will be called by main.c's signal handler to save the module's + * state */ +static struct service_provider *global_sp = NULL; + +void sp_save(void) +{ + if(global_sp) + { + tm_savestate(global_sp->tm, "module_state"); + } +} + int sp_main(int sockfd, int logleaves, const char *dbpath, bool overwrite) { #define BACKLOG 10 @@ -1252,6 +1334,7 @@ int sp_main(int sockfd, int logleaves, const char *dbpath, bool overwrite) signal(SIGPIPE, SIG_IGN); struct service_provider *sp = sp_new("a", 1, logleaves, "files", dbpath, overwrite); + global_sp = sp; while(1) { |