diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/datastore/Makefile.am | 87 | ||||
-rw-r--r-- | src/datastore/perf_datastore_api.c | 27 | ||||
-rw-r--r-- | src/datastore/perf_plugin_datastore.c | 26 | ||||
-rw-r--r-- | src/datastore/perf_plugin_datastore_data_mysql.conf | 25 | ||||
-rw-r--r-- | src/datastore/perf_plugin_datastore_data_sqlite.conf (renamed from src/datastore/perf_plugin_datastore_data.conf) | 2 | ||||
-rw-r--r-- | src/datastore/plugin_datastore_mysql.c | 770 | ||||
-rw-r--r-- | src/datastore/test_datastore_api.c | 31 | ||||
-rw-r--r-- | src/datastore/test_datastore_api_data_mysql.conf | 46 | ||||
-rw-r--r-- | src/datastore/test_datastore_api_data_sqlite.conf (renamed from src/datastore/test_datastore_api_data.conf) | 3 | ||||
-rw-r--r-- | src/datastore/test_datastore_api_management.c | 28 |
12 files changed, 641 insertions, 407 deletions
@@ -3,6 +3,8 @@ - only connect() sockets that are ready (select()) [Nils] [On W32, we need to select after calling socket before doing connect etc.] * CORE: + - Jun 27 11:51:54 core-7670 ERROR Assertion failed at gnunet-service-core.c:3616. + (transport notified us that we connected to ourselves!!!) - transport-level disconnect (i.e. TCP) does not cause core-level disconnect in a timely fashion (waits for connection timeout); need to figure a way to make it near-instant in those cases diff --git a/configure.ac b/configure.ac index c3832bb897..7295b68f3f 100644 --- a/configure.ac +++ b/configure.ac @@ -162,6 +162,7 @@ AM_CONDITIONAL(SOLARIS, test "$build_target" = "solaris") AM_CONDITIONAL(XFREEBSD, test "$build_target" = "freebsd") AM_CONDITIONAL(OPENBSD, test "$build_target" = "openbsd") AM_CONDITIONAL(LINUX, test "$build_target" = "linux") + AC_MSG_RESULT([$build_target]) AC_SUBST(build_target) AM_CONDITIONAL([am__fastdepOBJC], false) diff --git a/src/datastore/Makefile.am b/src/datastore/Makefile.am index 6fdf73d1ae..fac20f1912 100644 --- a/src/datastore/Makefile.am +++ b/src/datastore/Makefile.am @@ -35,12 +35,26 @@ gnunet_service_datastore_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) +if HAVE_MYSQL + MYSQL_PLUGIN = libgnunet_plugin_datastore_mysql.la + MYSQL_TESTS = \ + test_datastore_api_mysql \ + test_datastore_api_management_mysql \ + perf_datastore_api_mysql \ + perf_plugin_datastore_mysql +endif if HAVE_SQLITE - SQLITE_PLUGIN = libgnunet_plugin_datastore_sqlite.la + SQLITE_PLUGIN = libgnunet_plugin_datastore_sqlite.la + SQLITE_TESTS = \ + test_datastore_api_sqlite \ + test_datastore_api_management_sqlite \ + perf_datastore_api_sqlite \ + perf_plugin_datastore_sqlite endif plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ + $(MYSQL_PLUGIN) \ libgnunet_plugin_datastore_template.la @@ -52,6 +66,18 @@ libgnunet_plugin_datastore_sqlite_la_LIBADD = \ libgnunet_plugin_datastore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) + +libgnunet_plugin_datastore_mysql_la_SOURCES = \ + plugin_datastore_mysql.c +libgnunet_plugin_datastore_mysql_la_LIBADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lz -lsqlite3 +libgnunet_plugin_datastore_mysql_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) +libgnunet_plugin_datastore_sqlite_la_CPFLAGS = \ + $(MYSQL_CPPFLAGS) + + libgnunet_plugin_datastore_template_la_SOURCES = \ plugin_datastore_template.c libgnunet_plugin_datastore_template_la_LIBADD = \ @@ -59,47 +85,64 @@ libgnunet_plugin_datastore_template_la_LIBADD = \ libgnunet_plugin_datastore_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) - -if HAVE_SQLITE -SQLITE_TESTS = \ - test_datastore_api \ - test_datastore_api_management \ - perf_datastore_api \ - perf_plugin_datastore - -endif - check_PROGRAMS = \ - $(SQLITE_TESTS) + $(SQLITE_TESTS) \ + $(MYSQL_TESTS) if !DISABLE_TEST_RUN TESTS = $(check_PROGRAMS) endif -test_datastore_api_SOURCES = \ +test_datastore_api_sqlite_SOURCES = \ + test_datastore_api.c +test_datastore_api_sqlite_LDADD = \ + $(top_builddir)/src/datastore/libgnunetdatastore.la \ + $(top_builddir)/src/util/libgnunetutil.la + +test_datastore_api_management_sqlite_SOURCES = \ + test_datastore_api_management.c +test_datastore_api_management_sqlite_LDADD = \ + $(top_builddir)/src/datastore/libgnunetdatastore.la \ + $(top_builddir)/src/util/libgnunetutil.la + +perf_datastore_api_sqlite_SOURCES = \ + perf_datastore_api.c +perf_datastore_api_sqlite_LDADD = \ + $(top_builddir)/src/datastore/libgnunetdatastore.la \ + $(top_builddir)/src/util/libgnunetutil.la + +perf_plugin_datastore_sqlite_SOURCES = \ + perf_plugin_datastore.c +perf_plugin_datastore_sqlite_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la + + +test_datastore_api_mysql_SOURCES = \ test_datastore_api.c -test_datastore_api_LDADD = \ +test_datastore_api_mysql_LDADD = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la -test_datastore_api_management_SOURCES = \ +test_datastore_api_management_mysql_SOURCES = \ test_datastore_api_management.c -test_datastore_api_management_LDADD = \ +test_datastore_api_management_mysql_LDADD = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la -perf_datastore_api_SOURCES = \ +perf_datastore_api_mysql_SOURCES = \ perf_datastore_api.c -perf_datastore_api_LDADD = \ +perf_datastore_api_mysql_LDADD = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la -perf_plugin_datastore_SOURCES = \ +perf_plugin_datastore_mysql_SOURCES = \ perf_plugin_datastore.c -perf_plugin_datastore_LDADD = \ +perf_plugin_datastore_mysql_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ - test_datastore_api_data.conf \ - perf_plugin_datastore_data.conf + test_datastore_api_data_sqlite.conf \ + perf_plugin_datastore_data_sqlite.conf \ + test_datastore_api_data_mysql.conf \ + perf_plugin_datastore_data_mysql.conf diff --git a/src/datastore/perf_datastore_api.c b/src/datastore/perf_datastore_api.c index 90cdf44b33..8b040c2225 100644 --- a/src/datastore/perf_datastore_api.c +++ b/src/datastore/perf_datastore_api.c @@ -44,6 +44,7 @@ */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) +static const char *plugin_name; static struct GNUNET_DATASTORE_Handle *datastore; @@ -339,10 +340,11 @@ static int check () { pid_t pid; + char cfg_name[128]; char *const argv[] = { "perf-datastore-api", "-c", - "test_datastore_api_data.conf", + cfg_name, #if VERBOSE "-L", "DEBUG", #endif @@ -351,6 +353,11 @@ check () struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; + + GNUNET_snprintf (cfg_name, + sizeof (cfg_name), + "test_datastore_api_data_%s.conf", + plugin_name); pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm", "gnunet-service-arm", #if VERBOSE @@ -374,8 +381,19 @@ int main (int argc, char *argv[]) { int ret; - - GNUNET_DISK_directory_remove ("/tmp/test-gnunet-datastore"); + const char *pos; + char dir_name[128]; + + /* determine name of plugin to use */ + plugin_name = argv[0]; + while (NULL != (pos = strstr(plugin_name, "_"))) + plugin_name = pos+1; + + GNUNET_snprintf (dir_name, + sizeof (dir_name), + "/tmp/test-gnunet-datastore-%s", + plugin_name); + GNUNET_DISK_directory_remove (dir_name); GNUNET_log_setup ("perf-datastore-api", #if VERBOSE "DEBUG", @@ -387,9 +405,8 @@ main (int argc, char *argv[]) #if REPORT_ID fprintf (stderr, "\n"); #endif - GNUNET_DISK_directory_remove ("/tmp/test-gnunet-datastore"); + GNUNET_DISK_directory_remove (dir_name); return ret; } - /* end of perf_datastore_api.c */ diff --git a/src/datastore/perf_plugin_datastore.c b/src/datastore/perf_plugin_datastore.c index e6a631b29c..4efb684a5a 100644 --- a/src/datastore/perf_plugin_datastore.c +++ b/src/datastore/perf_plugin_datastore.c @@ -51,6 +51,8 @@ static unsigned long long stored_entries; static unsigned long long stored_ops; +static const char *plugin_name; + static int ok; enum RunPhase @@ -365,10 +367,11 @@ run (void *cls, static int check () { + char cfg_name[128]; char *const argv[] = { "perf-plugin-datastore", "-c", - "perf_plugin_datastore_data.conf", + cfg_name, #if VERBOSE "-L", "DEBUG", #endif @@ -377,6 +380,11 @@ check () struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; + + GNUNET_snprintf (cfg_name, + sizeof (cfg_name), + "perf_plugin_datastore_data_%s.conf", + plugin_name); GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "perf-plugin-datastore", "nohelp", options, &run, NULL); @@ -390,8 +398,19 @@ int main (int argc, char *argv[]) { int ret; - - GNUNET_DISK_directory_remove ("/tmp/perf-gnunet-datastore"); + const char *pos; + char dir_name[128]; + + /* determine name of plugin to use */ + plugin_name = argv[0]; + while (NULL != (pos = strstr(plugin_name, "_"))) + plugin_name = pos+1; + + GNUNET_snprintf (dir_name, + sizeof (dir_name), + "/tmp/perf-gnunet-datastore-%s", + plugin_name); + GNUNET_DISK_directory_remove (dir_name); GNUNET_log_setup ("perf-plugin-datastore", #if VERBOSE "DEBUG", @@ -405,7 +424,6 @@ main (int argc, char *argv[]) return ret; } - /* end of perf_plugin_datastore.c */ diff --git a/src/datastore/perf_plugin_datastore_data_mysql.conf b/src/datastore/perf_plugin_datastore_data_mysql.conf new file mode 100644 index 0000000000..2a5afbd9dc --- /dev/null +++ b/src/datastore/perf_plugin_datastore_data_mysql.conf @@ -0,0 +1,25 @@ +[PATHS] +SERVICEHOME = /tmp/perf-gnunet-datastore-mysql/ + +[datastore] +PORT = 22654 +HOSTNAME = localhost +HOME = $SERVICEHOME +CONFIG = $DEFAULTCONFIG +BINARY = gnunet-service-datastore +ACCEPT_FROM = 127.0.0.1; +ACCEPT_FROM6 = ::1; +QUOTA = 1000000 +BLOOMFILTER = $SERVICEHOME/fs/bloomfilter +DATABASE = mysql +# USERNAME = +# MAXBUF = +# TIMEOUT = +# DISABLEV6 = +# BINDTO = +# REJECT_FROM = +# REJECT_FROM6 = +# PREFIX = + +[dht] +AUTOSTART = NO diff --git a/src/datastore/perf_plugin_datastore_data.conf b/src/datastore/perf_plugin_datastore_data_sqlite.conf index c5973a07a5..90cf9f1036 100644 --- a/src/datastore/perf_plugin_datastore_data.conf +++ b/src/datastore/perf_plugin_datastore_data_sqlite.conf @@ -1,5 +1,5 @@ [PATHS] -SERVICEHOME = /tmp/perf-gnunet-datastore/ +SERVICEHOME = /tmp/perf-gnunet-datastore-sqlite/ [datastore] PORT = 22654 diff --git a/src/datastore/plugin_datastore_mysql.c b/src/datastore/plugin_datastore_mysql.c index fb0ea05573..234e2fd934 100644 --- a/src/datastore/plugin_datastore_mysql.c +++ b/src/datastore/plugin_datastore_mysql.c @@ -121,10 +121,17 @@ * is that mysql is basically operational, that you can connect * to it, create tables, issue queries etc. * + * TODO: + * - implement GET + * - remove 'size' field in gn080. + * - use FOREIGN KEY for 'uid/vkey' + * - consistent naming of uid/vkey */ #include "platform.h" #include "plugin_datastore.h" +#include "gnunet_util_lib.h" +#include <mysql/mysql.h> #define DEBUG_MYSQL GNUNET_NO @@ -204,6 +211,27 @@ struct GNUNET_MysqlStatementHandle }; +struct NextRequestClosure +{ + struct Plugin *plugin; + + unsigned int type; + + unsigned int iter_select; + + PluginIterator dviter; + + void *dviter_cls; + + unsigned int last_prio; + + unsigned long long last_expire; + + unsigned long long last_vkey; + + int end_it; +}; + /** * Context for all functions in this plugin. @@ -226,13 +254,24 @@ struct Plugin */ char *cnffile; + + /** + * Closure of the 'next_task' (must be freed if 'next_task' is cancelled). + */ + struct NextRequestClosure *next_task_nc; + + /** + * Pending task with scheduler for running the next request. + */ + GNUNET_SCHEDULER_TaskIdentifier next_task; + /** * Statements dealing with gn072 table */ #define SELECT_VALUE "SELECT value FROM gn072 WHERE vkey=?" struct GNUNET_MysqlStatementHandle *select_value; -#define DELETE_VALUE "DELETE FROM gn072 WHERE vkey=?"o +#define DELETE_VALUE "DELETE FROM gn072 WHERE vkey=?" struct GNUNET_MysqlStatementHandle *delete_value; #define INSERT_VALUE "INSERT INTO gn072 (value) VALUES (?)" @@ -291,7 +330,7 @@ struct Plugin * @return NULL on error */ static char * -get_my_cnf_path (struct GNUNET_ConfigurationHandle *cfg) +get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg) { char *cnffile; char *home_dir; @@ -308,18 +347,23 @@ get_my_cnf_path (struct GNUNET_ConfigurationHandle *cfg) "getpwuid"); return NULL; } - home_dir = GNUNET_strdup (pw->pw_dir); + if (GNUNET_YES == + GNUNET_CONFIGURATION_have_value (cfg, + "MYSQL", "CONFIG")) + { + GNUNET_CONFIGURATION_get_value_filename (cfg, + "MYSQL", "CONFIG", &cnffile); + } + else + { + home_dir = GNUNET_strdup (pw->pw_dir); #else - home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); - plibc_conv_to_win_path ("~/", home_dir); + home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); + plibc_conv_to_win_path ("~/", home_dir); #endif - GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); - GNUNET_free (home_dir); - GNUNET_CONFIUGRATION_get_value_filename (cfg, - "MYSQL", "CONFIG", cnffile, - &home_dir); - GNUNET_free (cnffile); - cnffile = home_dir; + GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); + GNUNET_free (home_dir); + } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Trying to use file `%s' for MySQL configuration.\n"), cnffile); @@ -418,25 +462,25 @@ iopen (struct Plugin *ret) "MYSQL", "PASSWORD")) { GNUNET_break (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (ret->cfg, + GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, "MYSQL", "PASSWORD", &mysql_password)); } mysql_server = NULL; - if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->cfg, + if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, "MYSQL", "HOST")) { GNUNET_break (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (ret->cfg, - "MYSQL", "HOST", "", + GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, + "MYSQL", "HOST", &mysql_server)); } mysql_port = 0; - if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->cfg, + if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, "MYSQL", "PORT")) { GNUNET_break (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (ret->cfg, "MYSQL", + GNUNET_CONFIGURATION_get_value_number (ret->env->cfg, "MYSQL", "PORT", &mysql_port)); } @@ -450,7 +494,6 @@ iopen (struct Plugin *ret) "mysql_real_connect", ret); return GNUNET_SYSERR; } - ret->valid = GNUNET_YES; return GNUNET_OK; } @@ -464,7 +507,7 @@ static int run_statement (struct Plugin *plugin, const char *statement) { - if ((NULL == plugin->dbh) && (GNUNET_OK != iopen (plugin))) + if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) return GNUNET_SYSERR; mysql_query (plugin->dbf, statement); if (mysql_error (plugin->dbf)[0]) @@ -492,7 +535,7 @@ run_statement_select (struct Plugin *plugin, MYSQL_ROW sql_row; char *ret; - if ((NULL == plugin->dbh) && (GNUNET_OK != iopen (plugin))) + if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) return NULL; mysql_query (plugin->dbf, statement); if ((mysql_error (plugin->dbf)[0]) || @@ -547,7 +590,7 @@ prepare_statement (struct Plugin *plugin, { if (GNUNET_YES == ret->valid) return GNUNET_OK; - if ((NULL == plugin->dbh) && + if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) return GNUNET_SYSERR; ret->statement = mysql_stmt_init (plugin->dbf); @@ -816,14 +859,16 @@ prepared_statement_run (struct Plugin *plugin, * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error */ static int -do_delete_value (unsigned long long vkey) +do_delete_value (struct Plugin *plugin, + unsigned long long vkey) { int ret; - ret = GNUNET_MYSQL_prepared_statement_run (delete_value, - NULL, - MYSQL_TYPE_LONGLONG, - &vkey, GNUNET_YES, -1); + ret = prepared_statement_run (plugin, + plugin->delete_value, + NULL, + MYSQL_TYPE_LONGLONG, + &vkey, GNUNET_YES, -1); if (ret > 0) ret = GNUNET_OK; return ret; @@ -838,15 +883,17 @@ do_delete_value (unsigned long long vkey) * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int -do_insert_value (const void *value, unsigned int size, +do_insert_value (struct Plugin *plugin, + const void *value, unsigned int size, unsigned long long *vkey) { unsigned long length = size; - return GNUNET_MYSQL_prepared_statement_run (insert_value, - vkey, - MYSQL_TYPE_BLOB, - value, length, &length, -1); + return prepared_statement_run (plugin, + plugin->insert_value, + vkey, + MYSQL_TYPE_BLOB, + value, length, &length, -1); } /** @@ -856,14 +903,16 @@ do_insert_value (const void *value, unsigned int size, * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error */ static int -do_delete_entry_by_vkey (unsigned long long vkey) +do_delete_entry_by_vkey (struct Plugin *plugin, + unsigned long long vkey) { int ret; - ret = GNUNET_MYSQL_prepared_statement_run (delete_entry_by_vkey, - NULL, - MYSQL_TYPE_LONGLONG, - &vkey, GNUNET_YES, -1); + ret = prepared_statement_run (plugin, + plugin->delete_entry_by_vkey, + NULL, + MYSQL_TYPE_LONGLONG, + &vkey, GNUNET_YES, -1); if (ret > 0) ret = GNUNET_OK; return ret; @@ -875,106 +924,256 @@ return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values) return GNUNET_OK; } + /** - * Given a full (SELECT *) result set from gn080 table, - * assemble it into a GNUNET_DatastoreValue representation. - * - * Call *without* holding the lock, but while within - * mysql_thread_start/end. + * Continuation of "sqlite_next_request". * - * @param result location where mysql_stmt_fetch stored the results - * @return NULL on error + * @param next_cls the next context + * @param tc the task context (unused) */ -static GNUNET_DatastoreValue * -assembleDatum (MYSQL_BIND * result) +static void +sqlite_next_request_cont (void *next_cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { - GNUNET_DatastoreValue *datum; - unsigned int contentSize; + struct NextRequestClosure *nrc = next_cls; + struct Plugin *plugin; + int ret; + unsigned int size; unsigned int type; - unsigned int prio; - unsigned int level; + unsigned int priority; + unsigned int anonymity; unsigned long long exp; unsigned long long vkey; + unsigned long hashSize; + GNUNET_HashCode key; + struct GNUNET_TIME_Absolute now; + struct GNUNET_TIME_Absolute expiration; + MYSQL_BIND rbind[7]; + unsigned int contentSize; unsigned long length; - MYSQL_BIND rbind[1]; - int ret; + MYSQL_BIND dbind[1]; + char datum[GNUNET_SERVER_MAX_MESSAGE_SIZE]; + + AGAIN: + plugin = nrc->plugin; + plugin->next_task = GNUNET_SCHEDULER_NO_TASK; + plugin->next_task_nc = NULL; + hashSize = sizeof (GNUNET_HashCode); + memset (rbind, 0, sizeof (rbind)); + rbind[0].buffer_type = MYSQL_TYPE_LONG; + rbind[0].buffer = &size; + rbind[0].is_unsigned = 1; + rbind[1].buffer_type = MYSQL_TYPE_LONG; + rbind[1].buffer = &type; + rbind[1].is_unsigned = 1; + rbind[2].buffer_type = MYSQL_TYPE_LONG; + rbind[2].buffer = &priority; + rbind[2].is_unsigned = 1; + rbind[3].buffer_type = MYSQL_TYPE_LONG; + rbind[3].buffer = &anonymity; + rbind[3].is_unsigned = 1; + rbind[4].buffer_type = MYSQL_TYPE_LONGLONG; + rbind[4].buffer = &exp; + rbind[4].is_unsigned = 1; + rbind[5].buffer_type = MYSQL_TYPE_BLOB; + rbind[5].buffer = &key; + rbind[5].buffer_length = hashSize; + rbind[5].length = &hashSize; + rbind[6].buffer_type = MYSQL_TYPE_LONGLONG; + rbind[6].buffer = &vkey; + rbind[6].is_unsigned = GNUNET_YES; - if ((result[0].buffer_type != MYSQL_TYPE_LONG) || - (!result[0].is_unsigned) || - (result[1].buffer_type != MYSQL_TYPE_LONG) || - (!result[1].is_unsigned) || - (result[2].buffer_type != MYSQL_TYPE_LONG) || - (!result[2].is_unsigned) || - (result[3].buffer_type != MYSQL_TYPE_LONG) || - (!result[3].is_unsigned) || - (result[4].buffer_type != MYSQL_TYPE_LONGLONG) || - (!result[4].is_unsigned) || - (result[5].buffer_type != MYSQL_TYPE_BLOB) || - (result[5].buffer_length != sizeof (GNUNET_HashCode)) || - (*result[5].length != sizeof (GNUNET_HashCode)) || - (result[6].buffer_type != MYSQL_TYPE_LONGLONG) || - (!result[6].is_unsigned)) + now = GNUNET_TIME_absolute_get (); + switch (nrc->iter_select) { - GNUNET_break (0); - return NULL; /* error */ + case 0: + case 1: + ret = prepared_statement_run_select (plugin, + plugin->iter[nrc->iter_select], + 7, + rbind, + &return_ok, + NULL, + MYSQL_TYPE_LONG, + &nrc->last_prio, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &nrc->last_vkey, + GNUNET_YES, + MYSQL_TYPE_LONG, + &nrc->last_prio, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &nrc->last_vkey, + GNUNET_YES, -1); + break; + case 2: + ret = prepared_statement_run_select (plugin, + plugin->iter[nrc->iter_select], + 7, + rbind, + &return_ok, + NULL, + MYSQL_TYPE_LONGLONG, + &nrc->last_expire, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &nrc->last_vkey, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &nrc->last_expire, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &nrc->last_vkey, + GNUNET_YES, -1); + break; + case 3: + ret = prepared_statement_run_select (plugin, + plugin->iter[nrc->iter_select], + 7, + rbind, + &return_ok, + NULL, + MYSQL_TYPE_LONGLONG, + &nrc->last_expire, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &nrc->last_vkey, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &now.value, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &nrc->last_expire, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &nrc->last_vkey, + GNUNET_YES, + MYSQL_TYPE_LONGLONG, + &now.value, + GNUNET_YES, -1); + break; + default: + GNUNET_assert (0); + return; } - - contentSize = *(unsigned int *) result[0].buffer; - if (contentSize < sizeof (GNUNET_DatastoreValue)) - return NULL; /* error */ - if (contentSize > GNUNET_MAX_BUFFER_SIZE) + if (ret != GNUNET_OK) + goto END_SET; + nrc->last_vkey = vkey; + nrc->last_prio = priority; + nrc->last_expire = exp; + if ((rbind[0].buffer_type != MYSQL_TYPE_LONG) || + (!rbind[0].is_unsigned) || + (rbind[1].buffer_type != MYSQL_TYPE_LONG) || + (!rbind[1].is_unsigned) || + (rbind[2].buffer_type != MYSQL_TYPE_LONG) || + (!rbind[2].is_unsigned) || + (rbind[3].buffer_type != MYSQL_TYPE_LONG) || + (!rbind[3].is_unsigned) || + (rbind[4].buffer_type != MYSQL_TYPE_LONGLONG) || + (!rbind[4].is_unsigned) || + (rbind[5].buffer_type != MYSQL_TYPE_BLOB) || + (rbind[5].buffer_length != sizeof (GNUNET_HashCode)) || + (*rbind[5].length != sizeof (GNUNET_HashCode)) || + (rbind[6].buffer_type != MYSQL_TYPE_LONGLONG) || + (!rbind[6].is_unsigned)) { - GNUNET_break (0); /* far too big */ - return NULL; + GNUNET_break (0); + goto END_SET; + } + contentSize = *(unsigned int *) rbind[0].buffer; + if (contentSize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + { + GNUNET_break (0); /* far too big */ + goto END_SET; } - contentSize -= sizeof (GNUNET_DatastoreValue); - type = *(unsigned int *) result[1].buffer; - prio = *(unsigned int *) result[2].buffer; - level = *(unsigned int *) result[3].buffer; - exp = *(unsigned long long *) result[4].buffer; - vkey = *(unsigned long long *) result[6].buffer; - datum = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + contentSize); - datum->size = htonl (contentSize + sizeof (GNUNET_DatastoreValue)); - datum->type = htonl (type); - datum->priority = htonl (prio); - datum->anonymity_level = htonl (level); - datum->expiration_time = GNUNET_htonll (exp); - /* now do query on gn072 */ length = contentSize; memset (rbind, 0, sizeof (rbind)); rbind[0].buffer_type = MYSQL_TYPE_BLOB; rbind[0].buffer_length = contentSize; rbind[0].length = &length; - rbind[0].buffer = &datum[1]; - ret = GNUNET_MYSQL_prepared_statement_run_select (select_value, - 1, - rbind, - &return_ok, - NULL, - MYSQL_TYPE_LONGLONG, - &vkey, GNUNET_YES, -1); - GNUNET_break (ret <= 1); /* should only have one result! */ + rbind[0].buffer = datum; + ret = prepared_statement_run_select (plugin, + plugin->select_value, + 1, + dbind, + &return_ok, + NULL, + MYSQL_TYPE_LONGLONG, + &vkey, GNUNET_YES, -1); + GNUNET_break (ret <= 1); /* should only have one rbind! */ if (ret > 0) ret = GNUNET_OK; if ((ret != GNUNET_OK) || - (rbind[0].buffer_length != contentSize) || (length != contentSize)) + (dbind[0].buffer_length != contentSize) || (length != contentSize)) { - GNUNET_break (ret != 0); /* should have one result! */ + GNUNET_break (ret != 0); /* should have one rbind! */ GNUNET_break (length == contentSize); /* length should match! */ - GNUNET_break (rbind[0].buffer_length == contentSize); /* length should be internally consistent! */ - do_delete_value (vkey); + GNUNET_break (dbind[0].buffer_length == contentSize); /* length should be internally consistent! */ + do_delete_value (plugin, vkey); if (ret != 0) - do_delete_entry_by_vkey (vkey); - content_size -= ntohl (datum->size); - GNUNET_free (datum); - return NULL; + do_delete_entry_by_vkey (plugin, vkey); + plugin->content_size -= contentSize; + goto AGAIN; + } + expiration.value = exp; + ret = nrc->dviter (nrc->dviter_cls, + nrc, + &key, + contentSize, + datum, + type, + priority, + anonymity, + expiration, + vkey); + if (ret == GNUNET_SYSERR) + { + /* is this correct, or should we not call iter again period? */ + goto END_SET; + } + if (ret == GNUNET_NO) + { + do_delete_value (plugin, vkey); + do_delete_entry_by_vkey (plugin, vkey); + plugin->content_size -= contentSize; } - return datum; + return; + END_SET: + /* call dviter with "end of set" */ + return; } /** + * Function invoked on behalf of a "PluginIterator" + * asking the database plugin to call the iterator + * with the next item. + * + * @param next_cls whatever argument was given + * to the PluginIterator as "next_cls". + * @param end_it set to GNUNET_YES if we + * should terminate the iteration early + * (iterator should be still called once more + * to signal the end of the iteration). + */ +static void +mysql_plugin_next_request (void *next_cls, + int end_it) +{ + struct NextRequestClosure *nrc = next_cls; + + if (GNUNET_YES == end_it) + nrc->end_it = GNUNET_YES; + nrc->plugin->next_task_nc = nrc; + nrc->plugin->next_task = GNUNET_SCHEDULER_add_now (nrc->plugin->env->sched, + &sqlite_next_request_cont, + nrc); +} + + +/** * Iterate over the items in the datastore * using the given query to select and order * the items. @@ -983,175 +1182,40 @@ assembleDatum (MYSQL_BIND * result) * Use 0 for any type. * @param iter never NULL * @param is_asc are we using ascending order? - * @return the number of results, GNUNET_SYSERR if the - * iter is non-NULL and aborted the iteration */ -static int +static void iterateHelper (struct Plugin *plugin, unsigned int type, int is_asc, - unsigned int iter_select, GNUNET_DatastoreValueIterator dviter, - void *closure) + unsigned int iter_select, + PluginIterator dviter, + void *dviter_cls) { - GNUNET_DatastoreValue *datum; - int count; - int ret; - unsigned int last_prio; - unsigned long long last_expire; - unsigned long long last_vkey; - unsigned int size; - unsigned int rtype; - unsigned int prio; - unsigned int level; - unsigned long long expiration; - unsigned long long vkey; - unsigned long hashSize; - GNUNET_HashCode key; - GNUNET_CronTime now; - MYSQL_BIND rbind[7]; + struct NextRequestClosure *nrc; + + nrc = GNUNET_malloc (sizeof (struct NextRequestClosure)); + nrc->plugin = plugin; + nrc->type = type; + nrc->iter_select = iter_select; + nrc->dviter = dviter; + nrc->dviter_cls = dviter_cls; if (is_asc) { - last_prio = 0; - last_vkey = 0; - last_expire = 0; + nrc->last_prio = 0; + nrc->last_vkey = 0; + nrc->last_expire = 0; } else { - last_prio = 0x7FFFFFFFL; - last_vkey = 0x7FFFFFFFFFFFFFFFLL; /* MySQL only supports 63 bits */ - last_expire = 0x7FFFFFFFFFFFFFFFLL; /* MySQL only supports 63 bits */ + nrc->last_prio = 0x7FFFFFFFL; + nrc->last_vkey = 0x7FFFFFFFFFFFFFFFLL; /* MySQL only supports 63 bits */ + nrc->last_expire = 0x7FFFFFFFFFFFFFFFLL; /* MySQL only supports 63 bits */ } - hashSize = sizeof (GNUNET_HashCode); - memset (rbind, 0, sizeof (rbind)); - rbind[0].buffer_type = MYSQL_TYPE_LONG; - rbind[0].buffer = &size; - rbind[0].is_unsigned = 1; - rbind[1].buffer_type = MYSQL_TYPE_LONG; - rbind[1].buffer = &rtype; - rbind[1].is_unsigned = 1; - rbind[2].buffer_type = MYSQL_TYPE_LONG; - rbind[2].buffer = &prio; - rbind[2].is_unsigned = 1; - rbind[3].buffer_type = MYSQL_TYPE_LONG; - rbind[3].buffer = &level; - rbind[3].is_unsigned = 1; - rbind[4].buffer_type = MYSQL_TYPE_LONGLONG; - rbind[4].buffer = &expiration; - rbind[4].is_unsigned = 1; - rbind[5].buffer_type = MYSQL_TYPE_BLOB; - rbind[5].buffer = &key; - rbind[5].buffer_length = hashSize; - rbind[5].length = &hashSize; - rbind[6].buffer_type = MYSQL_TYPE_LONGLONG; - rbind[6].buffer = &vkey; - rbind[6].is_unsigned = GNUNET_YES; - - now = GNUNET_get_time (); - count = 0; - while (1) - { - switch (iter_select) - { - case 0: - case 1: - ret = prepared_statement_run_select (iter[iter_select], - 7, - rbind, - &return_ok, - NULL, - MYSQL_TYPE_LONG, - &last_prio, - GNUNET_YES, - MYSQL_TYPE_LONGLONG, - &last_vkey, - GNUNET_YES, - MYSQL_TYPE_LONG, - &last_prio, - GNUNET_YES, - MYSQL_TYPE_LONGLONG, - &last_vkey, - GNUNET_YES, -1); - break; - case 2: - ret = prepared_statement_run_select (iter[iter_select], - 7, - rbind, - &return_ok, - NULL, - MYSQL_TYPE_LONGLONG, - &last_expire, |