aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <me@fwei.tk>2018-06-27 23:38:36 -0400
committerFranklin Wei <me@fwei.tk>2018-06-27 23:38:36 -0400
commitbe7238d18b06b726f1c688c39c21800ef22f72c1 (patch)
treedbffd58a595b53ed9dc80a21cd9888b5c0187128
parent3b232072565e54293466f8ba477547686be578bd (diff)
downloadcsaa-be7238d18b06b726f1c688c39c21800ef22f72c1.zip
csaa-be7238d18b06b726f1c688c39c21800ef22f72c1.tar.gz
csaa-be7238d18b06b726f1c688c39c21800ef22f72c1.tar.bz2
csaa-be7238d18b06b726f1c688c39c21800ef22f72c1.tar.xz
Optimize DB code
-rw-r--r--Makefile2
-rw-r--r--iomt.c320
-rw-r--r--iomt.h11
-rw-r--r--main.c2
-rw-r--r--service_provider.c182
-rw-r--r--service_provider.h2
-rwxr-xr-xtestcreate.sh4
-rwxr-xr-xtestmodify.sh4
8 files changed, 316 insertions, 211 deletions
diff --git a/Makefile b/Makefile
index 91e294a..925c342 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
all: client server Makefile
-CFLAGS = -g -Wall -O0 -lsqlite3
+CFLAGS = -g -Wall -O3 -lsqlite3
client: client.o crypto.o test.o iomt.o
cc -o $@ $^ -lcrypto $(CFLAGS)
diff --git a/iomt.c b/iomt.c
index aa3f52b..8bf4cbd 100644
--- a/iomt.c
+++ b/iomt.c
@@ -21,30 +21,8 @@ hash_t iomt_getnode(const struct iomt *tree, int idx)
return tree->mem.mt_nodes[idx];
else
{
- sqlite3 *handle = tree->db.db;
-
- char sql[1000];
- if(tree->db.key1_name)
- {
- if(tree->db.key2_name)
- {
- snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE %s = ?3 AND %s = ?5 AND NodeIdx = ?6;",
- tree->db.nodes_table,
- tree->db.key1_name,
- tree->db.key2_name);
- }
- else
- snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE %s = ?3 AND NodeIdx = ?6;",
- tree->db.nodes_table,
- tree->db.key1_name);
- }
- else
- snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE NodeIdx = ?6;",
- tree->db.nodes_table);
-
- sqlite3_stmt *st;
-
- sqlite3_prepare_v2(handle, sql, -1, &st, 0);
+ sqlite3_stmt *st = tree->db.getnode;
+ sqlite3_reset(st);
if(tree->db.key1_name)
{
@@ -80,32 +58,13 @@ void iomt_setnode(const struct iomt *tree, int idx, hash_t val)
tree->mem.mt_nodes[idx] = val;
else
{
- printf("Setting node idx = %d in %s\n", idx, tree->db.nodes_table);
+ //printf("Setting node idx = %d in %s\n", idx, tree->db.nodes_table);
sqlite3 *handle = tree->db.db;
- char sql[1000];
- if(tree->db.key1_name)
- {
- if(tree->db.key2_name)
- {
- snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE %s = ?4 AND %s = ?6 AND NodeIdx = ?7;",
- tree->db.nodes_table,
- tree->db.key1_name,
- tree->db.key2_name);
- }
- else
- snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE %s = ?4 AND NodeIdx = ?7;",
- tree->db.nodes_table,
- tree->db.key1_name);
- }
- else
- snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE NodeIdx = ?7;",
- tree->db.nodes_table);
+ sqlite3_stmt *st = tree->db.updatenode;
+ sqlite3_reset(st);
- sqlite3_stmt *st;
-
- sqlite3_prepare_v2(handle, sql, -1, &st, 0);
sqlite3_bind_blob(st, 2, &val, sizeof(val), SQLITE_TRANSIENT);
if(tree->db.key1_name)
@@ -124,29 +83,11 @@ void iomt_setnode(const struct iomt *tree, int idx, hash_t val)
int changes = sqlite3_changes(handle);
- sqlite3_finalize(st);
-
/* Failure, likely because node doesn't exist */
if(rc != SQLITE_DONE || !changes)
{
- printf("Update failed, (%s) inserting...\n", sqlite3_errmsg(handle));
- if(tree->db.key1_name)
- {
- if(tree->db.key2_name)
- snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val, %s, %s ) VALUES ( ?4, ?5, ?6, ?7 );",
- tree->db.nodes_table,
- tree->db.key1_name,
- tree->db.key2_name);
- else
- snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val, %s ) VALUES ( ?4, ?5, ?6 );",
- tree->db.nodes_table,
- tree->db.key1_name);
- }
- else
- snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val ) VALUES ( ?4, ?5 );",
- tree->db.nodes_table);
-
- sqlite3_prepare_v2(handle, sql, -1, &st, 0);
+ st = tree->db.insertnode;
+ sqlite3_reset(st);
sqlite3_bind_int(st, 4, idx);
sqlite3_bind_blob(st, 5, &val, sizeof(val), SQLITE_TRANSIENT);
@@ -160,10 +101,12 @@ void iomt_setnode(const struct iomt *tree, int idx, hash_t val)
if(sqlite3_step(st) != SQLITE_DONE)
{
- printf("Failed 1: %s\n", sqlite3_errmsg(tree->db.db));
+ //printf("Failed 1: %s\n", sqlite3_errmsg(tree->db.db));
}
-
- sqlite3_finalize(st);
+ }
+ else
+ {
+ //printf("Successfully updated node %d\n", idx);
}
}
}
@@ -174,32 +117,8 @@ struct iomt_node iomt_getleaf(const struct iomt *tree, uint64_t leafidx)
return tree->mem.mt_leaves[leafidx];
else
{
- sqlite3 *handle = tree->db.db;
-
- char sql[1000];
- if(tree->db.key1_name)
- {
- if(tree->db.key2_name)
- {
- snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE %s = ?3 AND %s = ?5 AND LeafIdx = ?6;",
- tree->db.leaves_table,
- tree->db.key1_name,
- tree->db.key2_name);
- }
- else
- {
- snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE %s = ?3 AND LeafIdx = ?6;",
- tree->db.leaves_table,
- tree->db.key1_name);
- }
- }
- else
- snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE LeafIdx = ?6;",
- tree->db.leaves_table);
-
- sqlite3_stmt *st;
-
- sqlite3_prepare_v2(handle, sql, -1, &st, 0);
+ sqlite3_stmt *st = tree->db.getleaf;
+ sqlite3_reset(st);
if(tree->db.key1_name)
{
@@ -226,8 +145,8 @@ struct iomt_node iomt_getleaf(const struct iomt *tree, uint64_t leafidx)
}
else
{
- printf("Failed 2: %s\n", sqlite3_errmsg(tree->db.db));
- printf("Failed to look up leaf %d in %s\n", leafidx, tree->db.leaves_table);
+ //printf("Failed 2: %s\n", sqlite3_errmsg(tree->db.db));
+ //printf("Failed to look up leaf %lu in %s\n", leafidx, tree->db.leaves_table);
return node_null;
}
}
@@ -239,36 +158,13 @@ void iomt_setleaf(struct iomt *tree, uint64_t leafidx, struct iomt_node val)
tree->mem.mt_leaves[leafidx] = val;
else
{
- printf("Setting leaf idx = %d in %s\n", leafidx, tree->db.leaves_table);
+ //printf("Setting leaf idx = %lu in %s\n", leafidx, tree->db.leaves_table);
sqlite3 *handle = tree->db.db;
- char sql[1000];
- if(tree->db.key1_name)
- {
- if(tree->db.key2_name)
- {
- snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE %s = ?6 AND %s = ?8 AND LeafIdx = ?9;",
- tree->db.leaves_table,
- tree->db.key1_name,
- tree->db.key2_name);
- }
- else
- {
- snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE %s = ?6 AND LeafIdx = ?9;",
- tree->db.leaves_table,
- tree->db.key1_name);
- }
- }
- else
- snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE LeafIdx = ?9;",
- tree->db.leaves_table);
-
- printf("Statement is %s\n", sql);
-
- sqlite3_stmt *st;
+ sqlite3_stmt *st = tree->db.updateleaf;
+ sqlite3_reset(st);
- sqlite3_prepare_v2(handle, sql, -1, &st, 0);
sqlite3_bind_int(st, 2, val.idx);
sqlite3_bind_int(st, 3, val.next_idx);
sqlite3_bind_blob(st, 4, &val.val, sizeof(val.val), SQLITE_TRANSIENT);
@@ -289,31 +185,11 @@ void iomt_setleaf(struct iomt *tree, uint64_t leafidx, struct iomt_node val)
int changes = sqlite3_changes(handle);
- sqlite3_finalize(st);
-
/* Failure, likely because node doesn't exist */
if(rc != SQLITE_DONE || !changes)
{
- printf("Update failed (%s), inserting...\n", sqlite3_errmsg(handle));
-
- if(tree->db.key1_name)
- {
- if(tree->db.key2_name)
- snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val, %s, %s ) VALUES ( ?5, ?6, ?7, ?8, ?9, ?10 );",
- tree->db.leaves_table,
- tree->db.key1_name,
- tree->db.key2_name);
- else
- snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val, %s ) VALUES ( ?5, ?6, ?7, ?8, ?9 );",
- tree->db.leaves_table,
- tree->db.key1_name);
- }
- else
- snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val ) VALUES ( ?5, ?6, ?7, ?8 );",
- tree->db.leaves_table);
-
-
- sqlite3_prepare_v2(handle, sql, -1, &st, 0);
+ st = tree->db.insertleaf;
+ sqlite3_reset(st);
if(tree->db.key1_name)
{
@@ -335,9 +211,7 @@ void iomt_setleaf(struct iomt *tree, uint64_t leafidx, struct iomt_node val)
printf("Failed 3: %s\n", sqlite3_errmsg(handle));
}
- printf("Successfully inserted (%s)\n", sqlite3_errmsg(handle));
-
- sqlite3_finalize(st);
+ //printf("Successfully inserted (%s)\n", sqlite3_errmsg(handle));
}
}
}
@@ -436,6 +310,7 @@ hash_t iomt_getroot(const struct iomt *tree)
}
/* find a node with given idx */
+/* TODO: replace with database update */
struct iomt_node iomt_find_leaf(const struct iomt *tree, uint64_t idx, uint64_t *leafidx)
{
for(int i = 0; i < tree->mt_leafcount; ++i)
@@ -443,7 +318,7 @@ struct iomt_node iomt_find_leaf(const struct iomt *tree, uint64_t idx, uint64_t
{
if(leafidx)
*leafidx = i;
- return tree->mem.mt_leaves[i];
+ return iomt_getleaf(tree, i);
}
return node_null;
}
@@ -455,7 +330,7 @@ struct iomt_node iomt_find_encloser(const struct iomt *tree, uint64_t idx, uint6
{
if(leafidx)
*leafidx = i;
- return tree->mem.mt_leaves[i];
+ return iomt_getleaf(tree, i);
}
return node_null;
}
@@ -469,7 +344,7 @@ struct iomt_node iomt_find_leaf_or_encloser(const struct iomt *tree, uint64_t id
{
if(leafidx)
*leafidx = i;
- return tree->mem.mt_leaves[i];
+ return iomt_getleaf(tree, i);
}
}
return node_null;
@@ -478,7 +353,7 @@ struct iomt_node iomt_find_leaf_or_encloser(const struct iomt *tree, uint64_t id
void iomt_update(struct iomt *tree, uint64_t idx, hash_t newval)
{
/* update the leaf first, then use merkle_update */
- uint64_t leafidx;
+ uint64_t leafidx = 0;
struct iomt_node leaf = iomt_find_leaf(tree, idx, &leafidx);
leaf.val = newval;
iomt_setleaf(tree, leafidx, leaf);
@@ -566,13 +441,134 @@ struct iomt *iomt_new_from_db(void *db,
tree->db.key2_name = key2_name;
tree->db.key2_val = key2_val;
+ /* compile statements now to save time */
+ char sql[1000];
+
+ /* TODO: refactor! */
+
+ if(tree->db.key1_name)
+ {
+ if(tree->db.key2_name)
+ {
+ snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE %s = ?3 AND %s = ?5 AND NodeIdx = ?6;",
+ tree->db.nodes_table,
+ tree->db.key1_name,
+ tree->db.key2_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.getnode, 0);
+
+ snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE %s = ?4 AND %s = ?6 AND NodeIdx = ?7;",
+ tree->db.nodes_table,
+ tree->db.key1_name,
+ tree->db.key2_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.updatenode, 0);
+ snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val, %s, %s ) VALUES ( ?4, ?5, ?6, ?7 );",
+ tree->db.nodes_table,
+ tree->db.key1_name,
+ tree->db.key2_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.insertnode, 0);
+ snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE %s = ?3 AND %s = ?5 AND LeafIdx = ?6;",
+ tree->db.leaves_table,
+ tree->db.key1_name,
+ tree->db.key2_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.getleaf, 0);
+ snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE %s = ?6 AND %s = ?8 AND LeafIdx = ?9;",
+ tree->db.leaves_table,
+ tree->db.key1_name,
+ tree->db.key2_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.updateleaf, 0);
+ snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val, %s, %s ) VALUES ( ?5, ?6, ?7, ?8, ?9, ?10 );",
+ tree->db.leaves_table,
+ tree->db.key1_name,
+ tree->db.key2_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.insertleaf, 0);
+ }
+ else
+ {
+ snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE %s = ?3 AND NodeIdx = ?6;",
+ tree->db.nodes_table,
+ tree->db.key1_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.getnode, 0);
+ snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE %s = ?4 AND NodeIdx = ?7;",
+ tree->db.nodes_table,
+ tree->db.key1_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.updatenode, 0);
+ snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val, %s ) VALUES ( ?4, ?5, ?6 );",
+ tree->db.nodes_table,
+ tree->db.key1_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.insertnode, 0);
+ snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE %s = ?3 AND LeafIdx = ?6;",
+ tree->db.leaves_table,
+ tree->db.key1_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.getleaf, 0);
+ snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE %s = ?6 AND LeafIdx = ?9;",
+ tree->db.leaves_table,
+ tree->db.key1_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.updateleaf, 0);
+ snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val, %s ) VALUES ( ?5, ?6, ?7, ?8, ?9 );",
+ tree->db.leaves_table,
+ tree->db.key1_name);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.insertleaf, 0);
+ }
+ }
+ else
+ {
+ snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE NodeIdx = ?6;",
+ tree->db.nodes_table);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.getnode, 0);
+ snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE NodeIdx = ?7;",
+ tree->db.nodes_table);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.updatenode, 0);
+ snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val ) VALUES ( ?4, ?5 );",
+ tree->db.nodes_table);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.insertnode, 0);
+ snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE LeafIdx = ?6;",
+ tree->db.leaves_table);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.getleaf, 0);
+ snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE LeafIdx = ?9;",
+ tree->db.leaves_table);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.updateleaf, 0);
+ snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val ) VALUES ( ?5, ?6, ?7, ?8 );",
+ tree->db.leaves_table);
+ sqlite3_prepare_v2(db, sql, -1, &tree->db.insertleaf, 0);
+ }
+
return tree;
}
+/* make a copy of the IOMT with database backing (there will be no
+ * pointer semantics between the two trees when this function
+ * returns) */
+struct iomt *iomt_dup_in_db(void *db,
+ const char *nodes_table, const char *leaves_table,
+ const char *key1_name, int key1_val,
+ const char *key2_name, int key2_val,
+ const struct iomt *oldtree)
+{
+ struct iomt *newtree = iomt_new_from_db(db, nodes_table, leaves_table,
+ key1_name, key1_val,
+ key2_name, key2_val,
+ oldtree->mt_logleaves);
+
+ /* copy nodes, leaves (we do not recalculate the tree) */
+ for(int i = 0; i < newtree->mt_leafcount; ++i)
+ iomt_setleaf(newtree, i, iomt_getleaf(oldtree, i));
+
+ for(int i = 0; i < 2 * newtree->mt_leafcount - 1; ++i)
+ iomt_setnode(newtree, i, iomt_getnode(oldtree, i));
+
+ return newtree;
+}
+
+/* produces a new IOMT with no relation with the old one (no pointer
+ * semantics) */
struct iomt *iomt_dup(const struct iomt *tree)
{
if(!tree)
return NULL;
+
+ if(!tree->in_memory)
+ assert(false);
+
struct iomt *newtree = calloc(1, sizeof(struct iomt));
newtree->mt_leafcount = tree->mt_leafcount;
newtree->mt_logleaves = tree->mt_logleaves;
@@ -649,10 +645,13 @@ struct iomt *iomt_deserialize(int (*read_fn)(void *userdata, void *buf, size_t l
void iomt_free(struct iomt *tree)
{
- if(tree && tree->in_memory)
+ if(tree)
{
- free(tree->mem.mt_nodes);
- free(tree->mem.mt_leaves);
+ if(tree->in_memory)
+ {
+ free(tree->mem.mt_nodes);
+ free(tree->mem.mt_leaves);
+ }
free(tree);
}
}
@@ -712,17 +711,18 @@ struct iomt *iomt_from_lines(const char *filename)
void iomt_dump(const struct iomt *tree)
{
- if(tree && tree->in_memory)
+ if(tree)
{
for(int i = 0; i < tree->mt_leafcount; ++i)
{
+ struct iomt_node node = iomt_getleaf(tree, i);
printf("(%lu, %s, %lu)%s",
- tree->mem.mt_leaves[i].idx,
- hash_format(tree->mem.mt_leaves[i].val, 4).str,
- tree->mem.mt_leaves[i].next_idx,
+ node.idx,
+ hash_format(node.val, 4).str,
+ node.next_idx,
(i == tree->mt_leafcount - 1) ? "\n" : ", ");
}
}
else
- printf("(empty IOMT)\n");
+ printf("(null IOMT)\n");
}
diff --git a/iomt.h b/iomt.h
index 2162bd6..a4fafc1 100644
--- a/iomt.h
+++ b/iomt.h
@@ -1,6 +1,7 @@
#ifndef CSAA_IOMT_H
#define CSAA_IOMT_H
#include "crypto.h"
+#include <sqlite3.h>
struct iomt_node {
uint64_t idx, next_idx; /* idx cannot be zero */
@@ -37,6 +38,9 @@ struct iomt {
* not NULL) key2_name = key2_val */
const char *key1_name, *key2_name;
int key1_val, key2_val;
+
+ sqlite3_stmt *getnode, *updatenode, *insertnode;
+ sqlite3_stmt *getleaf, *updateleaf, *insertleaf;
} db;
struct {
hash_t *mt_nodes; /* this has 2 * mt_leafcount - 1 elements. Note
@@ -66,7 +70,14 @@ struct iomt *iomt_new_from_db(void *db,
const char *key1_name, int key1_val,
const char *key2_name, int key2_val,
int logleaves);
+
struct iomt *iomt_dup(const struct iomt *tree);
+struct iomt *iomt_dup_in_db(void *db,
+ const char *nodes_table, const char *leaves_table,
+ const char *key1_name, int key1_val,
+ const char *key2_name, int key2_val,
+ const struct iomt *oldtree);
+
void iomt_free(struct iomt *tree);
/* Find a leaf with IOMT index `idx' and change its value, propagating
diff --git a/main.c b/main.c
index 4dc2d9e..0707216 100644
--- a/main.c
+++ b/main.c
@@ -46,7 +46,7 @@ void run_tests(void)
int main()
{
- run_tests();
+ //run_tests();
const char *socket_name = "socket";
int sockfd;
diff --git a/service_provider.c b/service_provider.c
index 2e119b6..074ab3d 100644
--- a/service_provider.c
+++ b/service_provider.c
@@ -8,8 +8,9 @@
#include <stdio.h>
#include <unistd.h>
-#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <sqlite3.h>
@@ -22,6 +23,8 @@
/* arbitrary */
#define ACL_LOGLEAVES 4
+#define MAX_PATH 260
+
/* free with free_version */
struct file_version {
uint64_t version;
@@ -54,6 +57,8 @@ struct file_record {
struct service_provider {
struct trusted_module *tm;
+ const char *data_dir;
+
void *db; /* sqlite3 handle */
struct iomt *iomt; /* backed by database */
};
@@ -128,16 +133,54 @@ struct tm_cert cert_eq(struct service_provider *sp,
return tm_cert_equiv(sp->tm, &nu1, nu1_hmac, &nu2, nu2_hmac, encloser, placeholder_nodeidx, hmac_out);
}
-/* write to file CSAA_FILES/file_idx/version */
-void write_contents(int file_idx, int version,
+/* write to file data_dir/file_idx/version */
+void write_contents(const struct service_provider *sp,
+ int file_idx, int version,
const void *data, size_t len)
{
+ mkdir(sp->data_dir, 0755);
+
+ char dirname[MAX_PATH];
+ snprintf(dirname, sizeof(dirname), "%s/%d", sp->data_dir, file_idx);
+
+ mkdir(dirname, 0755);
+
+ char filename[MAX_PATH];
+ snprintf(filename, sizeof(filename), "%s/%d/%d", sp->data_dir, file_idx, version);
+
+ FILE *f = fopen(filename, "w");
+
+ fwrite(data, 1, len, f);
+
+ fclose(f);
+}
+
+size_t file_len(FILE *f)
+{
+ off_t orig = ftell(f);
+ fseek(f, 0, SEEK_END);
+ off_t len = ftell(f);
+ fseek(f, orig, SEEK_SET);
+
+ return (size_t)len;
}
-void *read_contents(int file_idx, int version,
+void *read_contents(const struct service_provider *sp,
+ int file_idx, int version,
size_t *len)
{
+ char filename[MAX_PATH];
+ snprintf(filename, sizeof(filename), "%s/%d/%d", sp->data_dir, file_idx, version);
+ FILE *f = fopen(filename, "r");
+
+ *len = file_len(f);
+
+ void *buf = malloc(*len);
+ fread(buf, 1, *len, f);
+
+ fclose(f);
+ return buf;
}
void *db_init(const char *filename)
@@ -146,11 +189,26 @@ void *db_init(const char *filename)
if(sqlite3_open(filename, &db) != SQLITE_OK)
return NULL;
+ sqlite3_exec(db, "PRAGMA synchronous = 0;", 0, 0, 0);
+ sqlite3_exec(db, "PRAGMA journal_mode = memory;", 0, 0, 0);
+
return db;
}
+void begin_transaction(void *db)
+{
+ sqlite3 *handle = db;
+ sqlite3_exec(handle, "BEGIN;", 0, 0, 0);
+}
+
+void commit_transaction(void *db)
+{
+ sqlite3 *handle = db;
+ sqlite3_exec(handle, "COMMIT;", 0, 0, 0);
+}
+
/* leaf count will be 2^logleaves */
-struct service_provider *sp_new(const void *key, size_t keylen, int logleaves)
+struct service_provider *sp_new(const void *key, size_t keylen, int logleaves, const char *data_dir)
{
assert(logleaves > 0);
struct service_provider *sp = calloc(1, sizeof(*sp));
@@ -165,6 +223,10 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves)
NULL, 0,
logleaves);
+ begin_transaction(sp->db);
+
+ sp->data_dir = data_dir;
+
/* The trusted module initializes itself with a single placeholder
* node (1,0,1). We first update our list of IOMT leaves. Then we
* insert our desired number of nodes by using EQ certificates to
@@ -193,28 +255,50 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves)
* next node, if any */
iomt_update_leaf_full(sp->iomt, i, i + 1, 1, hash_null);
+#if 0
+ if(i % 10 == 0)
+ {
+ commit_transaction(sp->db);
+ begin_transaction(sp->db);
+ }
+#endif
+
assert(tm_set_equiv_root(sp->tm, &eq, hmac));
+ printf("%d\n", i);
}
+ commit_transaction(sp->db);
+
return sp;
}
static void free_version(struct file_version *ver)
{
- iomt_free(ver->buildcode);
- iomt_free(ver->composefile);
+ if(ver)
+ {
+ iomt_free(ver->buildcode);
+ iomt_free(ver->composefile);
+ free(ver);
+ }
}
static void free_record(struct file_record *rec)
{
- iomt_free(rec->acl);
+ if(rec)
+ {
+ iomt_free(rec->acl);
+ free(rec);
+ }
}
void sp_free(struct service_provider *sp)
{
- tm_free(sp->tm);
- iomt_free(sp->iomt);
- free(sp);
+ if(sp)
+ {
+ tm_free(sp->tm);
+ iomt_free(sp->iomt);
+ free(sp);
+ }
}
/* linear search for record given idx */
@@ -246,7 +330,10 @@ static struct file_record *lookup_record(struct service_provider *sp, uint64_t i
"FileIdx", idx,
NULL, 0,
acl_logleaves);
+
+ return rec;
}
+ //printf("Failed to find file record with index %lu (%s), ret %d\n", idx, sqlite3_errmsg(handle), rc);
return NULL;
}
@@ -256,9 +343,11 @@ static struct file_record *lookup_record(struct service_provider *sp, uint64_t i
* there are no duplicate file indices; that is up to the caller. */
static void insert_record(struct service_provider *sp, const struct file_record *rec)
{
+ //printf("Inserting record %lu\n", rec->idx);
+
sqlite3 *handle = sp->db;
- const char *sql = "INSERT INTO FileRecords VALUES ( ?1, ?2, ?3, ?4, ?5, ?6 )";
+ const char *sql = "INSERT INTO FileRecords VALUES ( ?1, ?2, ?3, ?4, ?5, ?6 );";
sqlite3_stmt *st;
sqlite3_prepare_v2(handle, sql, -1, &st, 0);
sqlite3_bind_int(st, 1, rec->idx);
@@ -282,7 +371,7 @@ static void update_record(struct service_provider *sp,
{
sqlite3 *handle = sp->db;
- const char *sql = "UPDATE FileRecords SET Idx = ?1, Version = ?2, Counter = ?3, Cert = ?4, HMAC = ?5, ACL_logleaves = ?6 WHERE Idx = ?7";
+ const char *sql = "UPDATE FileRecords SET Idx = ?1, Ver = ?2, Ctr = ?3, Cert = ?4, HMAC = ?5, ACL_logleaves = ?6 WHERE Idx = ?7;";
sqlite3_stmt *st;
sqlite3_prepare_v2(handle, sql, -1, &st, 0);
@@ -305,7 +394,7 @@ static void insert_version(struct service_provider *sp,
{
sqlite3 *handle = sp->db;
- const char *sql = "INSERT INTO Versions VALUES ( ?1, ?2, ?3, ?4, ?5, ?6 ?7 ?8 )";
+ const char *sql = "INSERT INTO Versions VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8 );";
sqlite3_stmt *st;
sqlite3_prepare_v2(handle, sql, -1, &st, 0);
sqlite3_bind_int(st, 1, rec->idx);
@@ -314,10 +403,16 @@ static void insert_version(struct service_provider *sp,
sqlite3_bind_blob(st, 4, &ver->encrypted_secret, sizeof(ver->encrypted_secret), SQLITE_TRANSIENT);
sqlite3_bind_blob(st, 5, &ver->vr_cert, sizeof(ver->vr_cert), SQLITE_TRANSIENT);
sqlite3_bind_blob(st, 6, &ver->vr_hmac, sizeof(ver->vr_hmac), SQLITE_TRANSIENT);
- sqlite3_bind_int(st, 7, ver->buildcode->mt_logleaves);
- sqlite3_bind_int(st, 8, ver->composefile->mt_logleaves);
- assert(sqlite3_step(st) == SQLITE_DONE);
+ sqlite3_bind_int(st, 7, ver->buildcode ? ver->buildcode->mt_logleaves : -1);
+
+ sqlite3_bind_int(st, 8, ver->composefile ? ver->composefile->mt_logleaves : -1);
+
+ int rc = sqlite3_step(st);
+ if(rc != SQLITE_DONE)
+ {
+ printf("Failed (%s)\n", sqlite3_errmsg(handle));
+ }
sqlite3_finalize(st);
}
@@ -380,6 +475,7 @@ static struct file_version *lookup_version(struct service_provider *sp,
"FileIdx", file_idx,
"Version", version,
cf_logleaves);
+ return ver;
}
return NULL;
}
@@ -399,8 +495,9 @@ static struct file_version *lookup_version(struct service_provider *sp,
* HMAC(encryption secret, file index).
*
* If the request is to either modify the ACL or create a file (which
- * is essentially an ACL update), the ACL will be set to
- * new_acl. `new_acl' must be in persistent storage. */
+ * is essentially an ACL update), the ACL will be set to new_acl. This
+ * function will make a copy of new_acl, so it can safely be freed
+ * after calling this function. */
struct tm_cert sp_request(struct service_provider *sp,
const struct tm_request *req, hash_t req_hmac,
hash_t *hmac_out,
@@ -427,8 +524,8 @@ struct tm_cert sp_request(struct service_provider *sp,
bool need_insert = false;
if(!rec)
{
- need_insert = true;
rec = calloc(1, sizeof(struct file_record));
+ need_insert = true;
}
rec->idx = fr.fr.idx;
@@ -441,9 +538,14 @@ struct tm_cert sp_request(struct service_provider *sp,
/* check that the passed value matches the calculated root */
assert(hash_equals(req->val, iomt_getroot(new_acl)));
- /* update our ACL */
iomt_free(rec->acl);
- rec->acl = iomt_dup(new_acl);
+
+ /* copy the ACL into our database tables */
+ rec->acl = iomt_dup_in_db(sp->db,
+ "ACLNodes", "ACLLeaves",
+ "FileIdx", fr.fr.idx,
+ NULL, 0,
+ new_acl);
}
if(rec->version != fr.fr.version)
@@ -472,6 +574,7 @@ struct tm_cert sp_request(struct service_provider *sp,
ver.encrypted_secret = hash_null;
}
+ ver.version = fr.fr.version;
ver.vr_cert = vr;
ver.vr_hmac = vr_hmac;
@@ -484,7 +587,7 @@ struct tm_cert sp_request(struct service_provider *sp,
if(encrypted_contents)
{
/* write to disk */
- write_contents(fr.fr.idx, fr.fr.version,
+ write_contents(sp, fr.fr.idx, fr.fr.version,
encrypted_contents, contents_len);
}
@@ -512,6 +615,9 @@ struct tm_cert sp_request(struct service_provider *sp,
if(ack_hmac_out)
*ack_hmac_out = ack_hmac;
+ if(is_zero(*ack_hmac_out))
+ printf("Failed: %s\n", tm_geterror());
+
return fr;
}
@@ -541,7 +647,7 @@ struct tm_request sp_createfile(struct service_provider *sp,
struct iomt *acl = iomt_new_from_db(sp->db,
"ACLNodes", "ACLLeaves",
- "FileIdx", i,
+ "FileIdx", iomt_getleaf(sp->iomt, i).idx,
NULL, 0,
ACL_LOGLEAVES);
@@ -567,13 +673,12 @@ struct tm_request sp_createfile(struct service_provider *sp,
NULL, 0,
acl);
- iomt_free(acl);
-
free(file_comp);
free(file_orders);
if(fr_cert.type == FR)
return req;
+
return req_null;
}
@@ -825,7 +930,7 @@ void *sp_retrieve_file(struct service_provider *sp,
{
struct file_record *rec = lookup_record(sp, file_idx);
- if(!rec || count_versions(sp, file_idx))
+ if(!rec || !count_versions(sp, file_idx))
{
/* Newly created file, no contents. We don't bother to set
* *encrypted_secret or *len. Or, file does not exist. */
@@ -863,7 +968,7 @@ void *sp_retrieve_file(struct service_provider *sp,
if(kf)
*kf = ver->kf;
- void *ret = read_contents(file_idx, version, len);
+ void *ret = read_contents(sp, file_idx, version, len);
/* duplicate compose and build files */
if(buildcode)
@@ -923,7 +1028,6 @@ 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;
@@ -1033,7 +1137,7 @@ int sp_main(int sockfd)
signal(SIGPIPE, SIG_IGN);
int logleaves = 10;
- struct service_provider *sp = sp_new("a", 1, logleaves);
+ struct service_provider *sp = sp_new("a", 1, logleaves, "files");
while(1)
{
@@ -1064,7 +1168,7 @@ void sp_test(void)
printf("Initializing IOMT with %llu nodes.\n", 1ULL << logleaves);
clock_t start = clock();
- struct service_provider *sp = sp_new("a", 1, logleaves);
+ struct service_provider *sp = sp_new("a", 1, logleaves, "files");
clock_t stop = clock();
printf("%.1f placeholder insertions per second\n", (double)(1ULL << logleaves) * CLOCKS_PER_SEC / (stop - start));
@@ -1086,7 +1190,7 @@ void sp_test(void)
hash_t correct_root = merkle_parent(hash_node(node1), hash_node(node2), 0);
check("IOMT generation from file 2", hash_equals(iomt_getroot(buildcode), correct_root));
-#define N_MODIFY 1
+#define N_MODIFY 10
start = clock();
for(int i = 0; i < N_MODIFY; ++i)
req = sp_modifyfile(sp, 1, test_sign_request, "a", 1, hash_null, hash_null, buildcode, NULL, "contents", 8, &ack_hmac);
@@ -1150,8 +1254,8 @@ void sp_test(void)
hash_t ack;
bool success = true;
-#define N_ACLMODIFY 100
- for(int i = 0; i < 100; ++i)
+#define N_ACLMODIFY 10
+ for(int i = 0; i < N_ACLMODIFY; ++i)
{
struct tm_request req = sp_modifyacl(sp,
1,
@@ -1163,8 +1267,6 @@ void sp_test(void)
success &= ack_verify(&req, "a", 1, ack);
}
- iomt_free(newacl);
-
check("ACL modification 1", success);
}
@@ -1174,13 +1276,5 @@ void sp_test(void)
iomt_dump(sp->iomt);
}
- /* test tree initialization (only simple case) */
- if(logleaves == 1)
- {
- struct iomt_node a = { 1, 2, u64_to_hash(2) };
- struct iomt_node b = { 2, 1, hash_null };
- check("Merkle tree initialization", hash_equals(iomt_getroot(sp->iomt), merkle_parent(hash_node(a), hash_node(b), 0)));
- }
-
sp_free(sp);
}
diff --git a/service_provider.h b/service_provider.h
index 1150dad..2f2434a 100644
--- a/service_provider.h
+++ b/service_provider.h
@@ -65,7 +65,7 @@ struct user_request {
} __attribute__((packed));
#ifndef CLIENT
-struct service_provider *sp_new(const void *key, size_t keylen, int logleaves);
+struct service_provider *sp_new(const void *key, size_t keylen, int logleaves, const char *data_dir);
void sp_free(struct service_provider *sp);
/* see .c file for documentation */
diff --git a/testcreate.sh b/testcreate.sh
index 457d75d..5f3e47f 100755
--- a/testcreate.sh
+++ b/testcreate.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-for i in $(seq 1 1000)
+for i in $(seq 1 100)
do
- ./client -u 1 -k a create
+ ./client -u 1 -k a create > /dev/null
done
diff --git a/testmodify.sh b/testmodify.sh
index 88ca9d7..1e03f29 100755
--- a/testmodify.sh
+++ b/testmodify.sh
@@ -1,6 +1,6 @@
#!/bin/bash
./client -u 1 -k a create
-for i in $(seq 1 1000)
+for i in $(seq 1 100)
do
- ./client -u 1 -k a modifyfile -f 1 -i container1/hello-world.tar
+ ./client -u 1 -k a modifyfile -f 1 -i container1/hello-world.tar > /dev/null
done