aboutsummaryrefslogtreecommitdiff
path: root/src/datastore/plugin_datastore_mysql.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/datastore/plugin_datastore_mysql.c')
-rw-r--r--src/datastore/plugin_datastore_mysql.c770
1 files changed, 410 insertions, 360 deletions
diff --git a/src/datastore/plugin_datastore_mysql.c b/src/datastore/plugin_datastore_mysql.c
index fb0ea0557..234e2fd93 100644
--- a/src/datastore/plugin_datastore_mysql.c
+++ b/src/datastore/plugin_datastore_mysql.c
@@ -121,10 +121,17 @@
121 * is that mysql is basically operational, that you can connect 121 * is that mysql is basically operational, that you can connect
122 * to it, create tables, issue queries etc. 122 * to it, create tables, issue queries etc.
123 * 123 *
124 * TODO:
125 * - implement GET
126 * - remove 'size' field in gn080.
127 * - use FOREIGN KEY for 'uid/vkey'
128 * - consistent naming of uid/vkey
124 */ 129 */
125 130
126#include "platform.h" 131#include "platform.h"
127#include "plugin_datastore.h" 132#include "plugin_datastore.h"
133#include "gnunet_util_lib.h"
134#include <mysql/mysql.h>
128 135
129#define DEBUG_MYSQL GNUNET_NO 136#define DEBUG_MYSQL GNUNET_NO
130 137
@@ -204,6 +211,27 @@ struct GNUNET_MysqlStatementHandle
204 211
205}; 212};
206 213
214struct NextRequestClosure
215{
216 struct Plugin *plugin;
217
218 unsigned int type;
219
220 unsigned int iter_select;
221
222 PluginIterator dviter;
223
224 void *dviter_cls;
225
226 unsigned int last_prio;
227
228 unsigned long long last_expire;
229
230 unsigned long long last_vkey;
231
232 int end_it;
233};
234
207 235
208/** 236/**
209 * Context for all functions in this plugin. 237 * Context for all functions in this plugin.
@@ -226,13 +254,24 @@ struct Plugin
226 */ 254 */
227 char *cnffile; 255 char *cnffile;
228 256
257
258 /**
259 * Closure of the 'next_task' (must be freed if 'next_task' is cancelled).
260 */
261 struct NextRequestClosure *next_task_nc;
262
263 /**
264 * Pending task with scheduler for running the next request.
265 */
266 GNUNET_SCHEDULER_TaskIdentifier next_task;
267
229 /** 268 /**
230 * Statements dealing with gn072 table 269 * Statements dealing with gn072 table
231 */ 270 */
232#define SELECT_VALUE "SELECT value FROM gn072 WHERE vkey=?" 271#define SELECT_VALUE "SELECT value FROM gn072 WHERE vkey=?"
233 struct GNUNET_MysqlStatementHandle *select_value; 272 struct GNUNET_MysqlStatementHandle *select_value;
234 273
235#define DELETE_VALUE "DELETE FROM gn072 WHERE vkey=?"o 274#define DELETE_VALUE "DELETE FROM gn072 WHERE vkey=?"
236 struct GNUNET_MysqlStatementHandle *delete_value; 275 struct GNUNET_MysqlStatementHandle *delete_value;
237 276
238#define INSERT_VALUE "INSERT INTO gn072 (value) VALUES (?)" 277#define INSERT_VALUE "INSERT INTO gn072 (value) VALUES (?)"
@@ -291,7 +330,7 @@ struct Plugin
291 * @return NULL on error 330 * @return NULL on error
292 */ 331 */
293static char * 332static char *
294get_my_cnf_path (struct GNUNET_ConfigurationHandle *cfg) 333get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg)
295{ 334{
296 char *cnffile; 335 char *cnffile;
297 char *home_dir; 336 char *home_dir;
@@ -308,18 +347,23 @@ get_my_cnf_path (struct GNUNET_ConfigurationHandle *cfg)
308 "getpwuid"); 347 "getpwuid");
309 return NULL; 348 return NULL;
310 } 349 }
311 home_dir = GNUNET_strdup (pw->pw_dir); 350 if (GNUNET_YES ==
351 GNUNET_CONFIGURATION_have_value (cfg,
352 "MYSQL", "CONFIG"))
353 {
354 GNUNET_CONFIGURATION_get_value_filename (cfg,
355 "MYSQL", "CONFIG", &cnffile);
356 }
357 else
358 {
359 home_dir = GNUNET_strdup (pw->pw_dir);
312#else 360#else
313 home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); 361 home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1);
314 plibc_conv_to_win_path ("~/", home_dir); 362 plibc_conv_to_win_path ("~/", home_dir);
315#endif 363#endif
316 GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); 364 GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir);
317 GNUNET_free (home_dir); 365 GNUNET_free (home_dir);
318 GNUNET_CONFIUGRATION_get_value_filename (cfg, 366 }
319 "MYSQL", "CONFIG", cnffile,
320 &home_dir);
321 GNUNET_free (cnffile);
322 cnffile = home_dir;
323 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 367 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
324 _("Trying to use file `%s' for MySQL configuration.\n"), 368 _("Trying to use file `%s' for MySQL configuration.\n"),
325 cnffile); 369 cnffile);
@@ -418,25 +462,25 @@ iopen (struct Plugin *ret)
418 "MYSQL", "PASSWORD")) 462 "MYSQL", "PASSWORD"))
419 { 463 {
420 GNUNET_break (GNUNET_OK == 464 GNUNET_break (GNUNET_OK ==
421 GNUNET_CONFIGURATION_get_value_string (ret->cfg, 465 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
422 "MYSQL", "PASSWORD", 466 "MYSQL", "PASSWORD",
423 &mysql_password)); 467 &mysql_password));
424 } 468 }
425 mysql_server = NULL; 469 mysql_server = NULL;
426 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->cfg, 470 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
427 "MYSQL", "HOST")) 471 "MYSQL", "HOST"))
428 { 472 {
429 GNUNET_break (GNUNET_OK == 473 GNUNET_break (GNUNET_OK ==
430 GNUNET_CONFIGURATION_get_value_string (ret->cfg, 474 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
431 "MYSQL", "HOST", "", 475 "MYSQL", "HOST",
432 &mysql_server)); 476 &mysql_server));
433 } 477 }
434 mysql_port = 0; 478 mysql_port = 0;
435 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->cfg, 479 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
436 "MYSQL", "PORT")) 480 "MYSQL", "PORT"))
437 { 481 {
438 GNUNET_break (GNUNET_OK == 482 GNUNET_break (GNUNET_OK ==
439 GNUNET_CONFIGURATION_get_value_number (ret->cfg, "MYSQL", 483 GNUNET_CONFIGURATION_get_value_number (ret->env->cfg, "MYSQL",
440 "PORT", &mysql_port)); 484 "PORT", &mysql_port));
441 } 485 }
442 486
@@ -450,7 +494,6 @@ iopen (struct Plugin *ret)
450 "mysql_real_connect", ret); 494 "mysql_real_connect", ret);
451 return GNUNET_SYSERR; 495 return GNUNET_SYSERR;
452 } 496 }
453 ret->valid = GNUNET_YES;
454 return GNUNET_OK; 497 return GNUNET_OK;
455} 498}
456 499
@@ -464,7 +507,7 @@ static int
464run_statement (struct Plugin *plugin, 507run_statement (struct Plugin *plugin,
465 const char *statement) 508 const char *statement)
466{ 509{
467 if ((NULL == plugin->dbh) && (GNUNET_OK != iopen (plugin))) 510 if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin)))
468 return GNUNET_SYSERR; 511 return GNUNET_SYSERR;
469 mysql_query (plugin->dbf, statement); 512 mysql_query (plugin->dbf, statement);
470 if (mysql_error (plugin->dbf)[0]) 513 if (mysql_error (plugin->dbf)[0])
@@ -492,7 +535,7 @@ run_statement_select (struct Plugin *plugin,
492 MYSQL_ROW sql_row; 535 MYSQL_ROW sql_row;
493 char *ret; 536 char *ret;
494 537
495 if ((NULL == plugin->dbh) && (GNUNET_OK != iopen (plugin))) 538 if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin)))
496 return NULL; 539 return NULL;
497 mysql_query (plugin->dbf, statement); 540 mysql_query (plugin->dbf, statement);
498 if ((mysql_error (plugin->dbf)[0]) || 541 if ((mysql_error (plugin->dbf)[0]) ||
@@ -547,7 +590,7 @@ prepare_statement (struct Plugin *plugin,
547{ 590{
548 if (GNUNET_YES == ret->valid) 591 if (GNUNET_YES == ret->valid)
549 return GNUNET_OK; 592 return GNUNET_OK;
550 if ((NULL == plugin->dbh) && 593 if ((NULL == plugin->dbf) &&
551 (GNUNET_OK != iopen (plugin))) 594 (GNUNET_OK != iopen (plugin)))
552 return GNUNET_SYSERR; 595 return GNUNET_SYSERR;
553 ret->statement = mysql_stmt_init (plugin->dbf); 596 ret->statement = mysql_stmt_init (plugin->dbf);
@@ -816,14 +859,16 @@ prepared_statement_run (struct Plugin *plugin,
816 * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error 859 * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error
817 */ 860 */
818static int 861static int
819do_delete_value (unsigned long long vkey) 862do_delete_value (struct Plugin *plugin,
863 unsigned long long vkey)
820{ 864{
821 int ret; 865 int ret;
822 866
823 ret = GNUNET_MYSQL_prepared_statement_run (delete_value, 867 ret = prepared_statement_run (plugin,
824 NULL, 868 plugin->delete_value,
825 MYSQL_TYPE_LONGLONG, 869 NULL,
826 &vkey, GNUNET_YES, -1); 870 MYSQL_TYPE_LONGLONG,
871 &vkey, GNUNET_YES, -1);
827 if (ret > 0) 872 if (ret > 0)
828 ret = GNUNET_OK; 873 ret = GNUNET_OK;
829 return ret; 874 return ret;
@@ -838,15 +883,17 @@ do_delete_value (unsigned long long vkey)
838 * @return GNUNET_OK on success, GNUNET_SYSERR on error 883 * @return GNUNET_OK on success, GNUNET_SYSERR on error
839 */ 884 */
840static int 885static int
841do_insert_value (const void *value, unsigned int size, 886do_insert_value (struct Plugin *plugin,
887 const void *value, unsigned int size,
842 unsigned long long *vkey) 888 unsigned long long *vkey)
843{ 889{
844 unsigned long length = size; 890 unsigned long length = size;
845 891
846 return GNUNET_MYSQL_prepared_statement_run (insert_value, 892 return prepared_statement_run (plugin,
847 vkey, 893 plugin->insert_value,
848 MYSQL_TYPE_BLOB, 894 vkey,
849 value, length, &length, -1); 895 MYSQL_TYPE_BLOB,
896 value, length, &length, -1);
850} 897}
851 898
852/** 899/**
@@ -856,14 +903,16 @@ do_insert_value (const void *value, unsigned int size,
856 * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error 903 * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error
857 */ 904 */
858static int 905static int
859do_delete_entry_by_vkey (unsigned long long vkey) 906do_delete_entry_by_vkey (struct Plugin *plugin,
907 unsigned long long vkey)
860{ 908{
861 int ret; 909 int ret;
862 910
863 ret = GNUNET_MYSQL_prepared_statement_run (delete_entry_by_vkey, 911 ret = prepared_statement_run (plugin,
864 NULL, 912 plugin->delete_entry_by_vkey,
865 MYSQL_TYPE_LONGLONG, 913 NULL,
866 &vkey, GNUNET_YES, -1); 914 MYSQL_TYPE_LONGLONG,
915 &vkey, GNUNET_YES, -1);
867 if (ret > 0) 916 if (ret > 0)
868 ret = GNUNET_OK; 917 ret = GNUNET_OK;
869 return ret; 918 return ret;
@@ -875,106 +924,256 @@ return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values)
875 return GNUNET_OK; 924 return GNUNET_OK;
876} 925}
877 926
927
878/** 928/**
879 * Given a full (SELECT *) result set from gn080 table, 929 * Continuation of "sqlite_next_request".
880 * assemble it into a GNUNET_DatastoreValue representation.
881 *
882 * Call *without* holding the lock, but while within
883 * mysql_thread_start/end.
884 * 930 *
885 * @param result location where mysql_stmt_fetch stored the results 931 * @param next_cls the next context
886 * @return NULL on error 932 * @param tc the task context (unused)
887 */ 933 */
888static GNUNET_DatastoreValue * 934static void
889assembleDatum (MYSQL_BIND * result) 935sqlite_next_request_cont (void *next_cls,
936 const struct GNUNET_SCHEDULER_TaskContext *tc)
890{ 937{
891 GNUNET_DatastoreValue *datum; 938 struct NextRequestClosure *nrc = next_cls;
892 unsigned int contentSize; 939 struct Plugin *plugin;
940 int ret;
941 unsigned int size;
893 unsigned int type; 942 unsigned int type;
894 unsigned int prio; 943 unsigned int priority;
895 unsigned int level; 944 unsigned int anonymity;
896 unsigned long long exp; 945 unsigned long long exp;
897 unsigned long long vkey; 946 unsigned long long vkey;
947 unsigned long hashSize;
948 GNUNET_HashCode key;
949 struct GNUNET_TIME_Absolute now;
950 struct GNUNET_TIME_Absolute expiration;
951 MYSQL_BIND rbind[7];
952 unsigned int contentSize;
898 unsigned long length; 953 unsigned long length;
899 MYSQL_BIND rbind[1]; 954 MYSQL_BIND dbind[1];
900 int ret; 955 char datum[GNUNET_SERVER_MAX_MESSAGE_SIZE];
956
957 AGAIN:
958 plugin = nrc->plugin;
959 plugin->next_task = GNUNET_SCHEDULER_NO_TASK;
960 plugin->next_task_nc = NULL;
961 hashSize = sizeof (GNUNET_HashCode);
962 memset (rbind, 0, sizeof (rbind));
963 rbind[0].buffer_type = MYSQL_TYPE_LONG;
964 rbind[0].buffer = &size;
965 rbind[0].is_unsigned = 1;
966 rbind[1].buffer_type = MYSQL_TYPE_LONG;
967 rbind[1].buffer = &type;
968 rbind[1].is_unsigned = 1;
969 rbind[2].buffer_type = MYSQL_TYPE_LONG;
970 rbind[2].buffer = &priority;
971 rbind[2].is_unsigned = 1;
972 rbind[3].buffer_type = MYSQL_TYPE_LONG;
973 rbind[3].buffer = &anonymity;
974 rbind[3].is_unsigned = 1;
975 rbind[4].buffer_type = MYSQL_TYPE_LONGLONG;
976 rbind[4].buffer = &exp;
977 rbind[4].is_unsigned = 1;
978 rbind[5].buffer_type = MYSQL_TYPE_BLOB;
979 rbind[5].buffer = &key;
980 rbind[5].buffer_length = hashSize;
981 rbind[5].length = &hashSize;
982 rbind[6].buffer_type = MYSQL_TYPE_LONGLONG;
983 rbind[6].buffer = &vkey;
984 rbind[6].is_unsigned = GNUNET_YES;
901 985
902 if ((result[0].buffer_type != MYSQL_TYPE_LONG) || 986 now = GNUNET_TIME_absolute_get ();
903 (!result[0].is_unsigned) || 987 switch (nrc->iter_select)
904 (result[1].buffer_type != MYSQL_TYPE_LONG) ||
905 (!result[1].is_unsigned) ||
906 (result[2].buffer_type != MYSQL_TYPE_LONG) ||
907 (!result[2].is_unsigned) ||
908 (result[3].buffer_type != MYSQL_TYPE_LONG) ||
909 (!result[3].is_unsigned) ||
910 (result[4].buffer_type != MYSQL_TYPE_LONGLONG) ||
911 (!result[4].is_unsigned) ||
912 (result[5].buffer_type != MYSQL_TYPE_BLOB) ||
913 (result[5].buffer_length != sizeof (GNUNET_HashCode)) ||
914 (*result[5].length != sizeof (GNUNET_HashCode)) ||
915 (result[6].buffer_type != MYSQL_TYPE_LONGLONG) ||
916 (!result[6].is_unsigned))
917 { 988 {
918 GNUNET_break (0); 989 case 0:
919 return NULL; /* error */ 990 case 1:
991 ret = prepared_statement_run_select (plugin,
992 plugin->iter[nrc->iter_select],
993 7,
994 rbind,
995 &return_ok,
996 NULL,
997 MYSQL_TYPE_LONG,
998 &nrc->last_prio,
999 GNUNET_YES,
1000 MYSQL_TYPE_LONGLONG,
1001 &nrc->last_vkey,
1002 GNUNET_YES,
1003 MYSQL_TYPE_LONG,
1004 &nrc->last_prio,
1005 GNUNET_YES,
1006 MYSQL_TYPE_LONGLONG,
1007 &nrc->last_vkey,
1008 GNUNET_YES, -1);
1009 break;
1010 case 2:
1011 ret = prepared_statement_run_select (plugin,
1012 plugin->iter[nrc->iter_select],
1013 7,
1014 rbind,
1015 &return_ok,
1016 NULL,
1017 MYSQL_TYPE_LONGLONG,
1018 &nrc->last_expire,
1019 GNUNET_YES,
1020 MYSQL_TYPE_LONGLONG,
1021 &nrc->last_vkey,
1022 GNUNET_YES,
1023 MYSQL_TYPE_LONGLONG,
1024 &nrc->last_expire,
1025 GNUNET_YES,
1026 MYSQL_TYPE_LONGLONG,
1027 &nrc->last_vkey,
1028 GNUNET_YES, -1);
1029 break;
1030 case 3:
1031 ret = prepared_statement_run_select (plugin,
1032 plugin->iter[nrc->iter_select],
1033 7,
1034 rbind,
1035 &return_ok,
1036 NULL,
1037 MYSQL_TYPE_LONGLONG,
1038 &nrc->last_expire,
1039 GNUNET_YES,
1040 MYSQL_TYPE_LONGLONG,
1041 &nrc->last_vkey,
1042 GNUNET_YES,
1043 MYSQL_TYPE_LONGLONG,
1044 &now.value,
1045 GNUNET_YES,
1046 MYSQL_TYPE_LONGLONG,
1047 &nrc->last_expire,
1048 GNUNET_YES,
1049 MYSQL_TYPE_LONGLONG,
1050 &nrc->last_vkey,
1051 GNUNET_YES,
1052 MYSQL_TYPE_LONGLONG,
1053 &now.value,
1054 GNUNET_YES, -1);
1055 break;
1056 default:
1057 GNUNET_assert (0);
1058 return;
920 } 1059 }
921 1060 if (ret != GNUNET_OK)
922 contentSize = *(unsigned int *) result[0].buffer; 1061 goto END_SET;
923 if (contentSize < sizeof (GNUNET_DatastoreValue)) 1062 nrc->last_vkey = vkey;
924 return NULL; /* error */ 1063 nrc->last_prio = priority;
925 if (contentSize > GNUNET_MAX_BUFFER_SIZE) 1064 nrc->last_expire = exp;
1065 if ((rbind[0].buffer_type != MYSQL_TYPE_LONG) ||
1066 (!rbind[0].is_unsigned) ||
1067 (rbind[1].buffer_type != MYSQL_TYPE_LONG) ||
1068 (!rbind[1].is_unsigned) ||
1069 (rbind[2].buffer_type != MYSQL_TYPE_LONG) ||
1070 (!rbind[2].is_unsigned) ||
1071 (rbind[3].buffer_type != MYSQL_TYPE_LONG) ||
1072 (!rbind[3].is_unsigned) ||
1073 (rbind[4].buffer_type != MYSQL_TYPE_LONGLONG) ||
1074 (!rbind[4].is_unsigned) ||
1075 (rbind[5].buffer_type != MYSQL_TYPE_BLOB) ||
1076 (rbind[5].buffer_length != sizeof (GNUNET_HashCode)) ||
1077 (*rbind[5].length != sizeof (GNUNET_HashCode)) ||
1078 (rbind[6].buffer_type != MYSQL_TYPE_LONGLONG) ||
1079 (!rbind[6].is_unsigned))
926 { 1080 {
927 GNUNET_break (0); /* far too big */ 1081 GNUNET_break (0);
928 return NULL; 1082 goto END_SET;
1083 }
1084 contentSize = *(unsigned int *) rbind[0].buffer;
1085 if (contentSize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1086 {
1087 GNUNET_break (0); /* far too big */
1088 goto END_SET;
929 } 1089 }
930 contentSize -= sizeof (GNUNET_DatastoreValue);
931 type = *(unsigned int *) result[1].buffer;
932 prio = *(unsigned int *) result[2].buffer;
933 level = *(unsigned int *) result[3].buffer;
934 exp = *(unsigned long long *) result[4].buffer;
935 vkey = *(unsigned long long *) result[6].buffer;
936 datum = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + contentSize);
937 datum->size = htonl (contentSize + sizeof (GNUNET_DatastoreValue));
938 datum->type = htonl (type);
939 datum->priority = htonl (prio);
940 datum->anonymity_level = htonl (level);
941 datum->expiration_time = GNUNET_htonll (exp);
942
943 /* now do query on gn072 */ 1090 /* now do query on gn072 */
944 length = contentSize; 1091 length = contentSize;
945 memset (rbind, 0, sizeof (rbind)); 1092 memset (rbind, 0, sizeof (rbind));
946 rbind[0].buffer_type = MYSQL_TYPE_BLOB; 1093 rbind[0].buffer_type = MYSQL_TYPE_BLOB;
947 rbind[0].buffer_length = contentSize; 1094 rbind[0].buffer_length = contentSize;
948 rbind[0].length = &length; 1095 rbind[0].length = &length;
949 rbind[0].buffer = &datum[1]; 1096 rbind[0].buffer = datum;
950 ret = GNUNET_MYSQL_prepared_statement_run_select (select_value, 1097 ret = prepared_statement_run_select (plugin,
951 1, 1098 plugin->select_value,
952 rbind, 1099 1,
953 &return_ok, 1100 dbind,
954 NULL, 1101 &return_ok,
955 MYSQL_TYPE_LONGLONG, 1102 NULL,
956 &vkey, GNUNET_YES, -1); 1103 MYSQL_TYPE_LONGLONG,
957 GNUNET_break (ret <= 1); /* should only have one result! */ 1104 &vkey, GNUNET_YES, -1);
1105 GNUNET_break (ret <= 1); /* should only have one rbind! */
958 if (ret > 0) 1106 if (ret > 0)
959 ret = GNUNET_OK; 1107 ret = GNUNET_OK;
960 if ((ret != GNUNET_OK) || 1108 if ((ret != GNUNET_OK) ||
961 (rbind[0].buffer_length != contentSize) || (length != contentSize)) 1109 (dbind[0].buffer_length != contentSize) || (length != contentSize))
962 { 1110 {
963 GNUNET_break (ret != 0); /* should have one result! */ 1111 GNUNET_break (ret != 0); /* should have one rbind! */
964 GNUNET_break (length == contentSize); /* length should match! */ 1112 GNUNET_break (length == contentSize); /* length should match! */
965 GNUNET_break (rbind[0].buffer_length == contentSize); /* length should be internally consistent! */ 1113 GNUNET_break (dbind[0].buffer_length == contentSize); /* length should be internally consistent! */
966 do_delete_value (vkey); 1114 do_delete_value (plugin, vkey);
967 if (ret != 0) 1115 if (ret != 0)
968 do_delete_entry_by_vkey (vkey); 1116 do_delete_entry_by_vkey (plugin, vkey);
969 content_size -= ntohl (datum->size); 1117 plugin->content_size -= contentSize;
970 GNUNET_free (datum); 1118 goto AGAIN;
971 return NULL; 1119 }
1120 expiration.value = exp;
1121 ret = nrc->dviter (nrc->dviter_cls,
1122 nrc,
1123 &key,
1124 contentSize,
1125 datum,
1126 type,
1127 priority,
1128 anonymity,
1129 expiration,
1130 vkey);
1131 if (ret == GNUNET_SYSERR)
1132 {
1133 /* is this correct, or should we not call iter again period? */
1134 goto END_SET;
1135 }
1136 if (ret == GNUNET_NO)
1137 {
1138 do_delete_value (plugin, vkey);
1139 do_delete_entry_by_vkey (plugin, vkey);
1140 plugin->content_size -= contentSize;
972 } 1141 }
973 return datum; 1142 return;
1143 END_SET:
1144 /* call dviter with "end of set" */
1145 return;
974} 1146}
975 1147
976 1148
977/** 1149/**
1150 * Function invoked on behalf of a "PluginIterator"
1151 * asking the database plugin to call the iterator
1152 * with the next item.
1153 *
1154 * @param next_cls whatever argument was given
1155 * to the PluginIterator as "next_cls".
1156 * @param end_it set to GNUNET_YES if we
1157 * should terminate the iteration early
1158 * (iterator should be still called once more
1159 * to signal the end of the iteration).
1160 */
1161static void
1162mysql_plugin_next_request (void *next_cls,
1163 int end_it)
1164{
1165 struct NextRequestClosure *nrc = next_cls;
1166
1167 if (GNUNET_YES == end_it)
1168 nrc->end_it = GNUNET_YES;
1169 nrc->plugin->next_task_nc = nrc;
1170 nrc->plugin->next_task = GNUNET_SCHEDULER_add_now (nrc->plugin->env->sched,
1171 &sqlite_next_request_cont,
1172 nrc);
1173}
1174
1175
1176/**
978 * Iterate over the items in the datastore 1177 * Iterate over the items in the datastore
979 * using the given query to select and order 1178 * using the given query to select and order
980 * the items. 1179 * the items.
@@ -983,175 +1182,40 @@ assembleDatum (MYSQL_BIND * result)
983 * Use 0 for any type. 1182 * Use 0 for any type.
984 * @param iter never NULL 1183 * @param iter never NULL
985 * @param is_asc are we using ascending order? 1184 * @param is_asc are we using ascending order?
986 * @return the number of results, GNUNET_SYSERR if the
987 * iter is non-NULL and aborted the iteration
988 */ 1185 */
989static int 1186static void
990iterateHelper (struct Plugin *plugin, 1187iterateHelper (struct Plugin *plugin,
991 unsigned int type, 1188 unsigned int type,
992 int is_asc, 1189 int is_asc,
993 unsigned int iter_select, GNUNET_DatastoreValueIterator dviter, 1190 unsigned int iter_select,
994 void *closure) 1191 PluginIterator dviter,
1192 void *dviter_cls)
995{ 1193{
996 GNUNET_DatastoreValue *datum; 1194 struct NextRequestClosure *nrc;
997 int count; 1195
998 int ret; 1196 nrc = GNUNET_malloc (sizeof (struct NextRequestClosure));
999 unsigned int last_prio; 1197 nrc->plugin = plugin;
1000 unsigned long long last_expire; 1198 nrc->type = type;
1001 unsigned long long last_vkey; 1199 nrc->iter_select = iter_select;
1002 unsigned int size; 1200 nrc->dviter = dviter;
1003 unsigned int rtype; 1201 nrc->dviter_cls = dviter_cls;
1004 unsigned int prio;
1005 unsigned int level;
1006 unsigned long long expiration;
1007 unsigned long long vkey;
1008 unsigned long hashSize;
1009 GNUNET_HashCode key;
1010 GNUNET_CronTime now;
1011 MYSQL_BIND rbind[7];
1012 1202
1013 if (is_asc) 1203 if (is_asc)
1014 { 1204 {
1015 last_prio = 0; 1205 nrc->last_prio = 0;
1016 last_vkey = 0; 1206 nrc->last_vkey = 0;
1017 last_expire = 0; 1207 nrc->last_expire = 0;
1018 } 1208 }
1019 else 1209 else
1020 { 1210 {
1021 last_prio = 0x7FFFFFFFL; 1211 nrc->last_prio = 0x7FFFFFFFL;
1022 last_vkey = 0x7FFFFFFFFFFFFFFFLL; /* MySQL only supports 63 bits */ 1212 nrc->last_vkey = 0x7FFFFFFFFFFFFFFFLL; /* MySQL only supports 63 bits */
1023 last_expire = 0x7FFFFFFFFFFFFFFFLL; /* MySQL only supports 63 bits */ 1213 nrc->last_expire = 0x7FFFFFFFFFFFFFFFLL; /* MySQL only supports 63 bits */
1024 } 1214 }
1025 hashSize = sizeof (GNUNET_HashCode); 1215 mysql_plugin_next_request (nrc, GNUNET_NO);
1026 memset (rbind, 0, sizeof (rbind));
1027 rbind[0].buffer_type = MYSQL_TYPE_LONG;
1028 rbind[0].buffer = &size;
1029 rbind[0].is_unsigned = 1;
1030 rbind[1].buffer_type = MYSQL_TYPE_LONG;
1031 rbind[1].buffer = &rtype;
1032 rbind[1].is_unsigned = 1;
1033 rbind[2].buffer_type = MYSQL_TYPE_LONG;
1034 rbind[2].buffer = &prio;
1035 rbind[2].is_unsigned = 1;
1036 rbind[3].buffer_type = MYSQL_TYPE_LONG;
1037 rbind[3].buffer = &level;
1038 rbind[3].is_unsigned = 1;
1039 rbind[4].buffer_type = MYSQL_TYPE_LONGLONG;
1040 rbind[4].buffer = &expiration;
1041 rbind[4].is_unsigned = 1;
1042 rbind[5].buffer_type = MYSQL_TYPE_BLOB;
1043 rbind[5].buffer = &key;
1044 rbind[5].buffer_length = hashSize;
1045 rbind[5].length = &hashSize;
1046 rbind[6].buffer_type = MYSQL_TYPE_LONGLONG;
1047 rbind[6].buffer = &vkey;
1048 rbind[6].is_unsigned = GNUNET_YES;
1049
1050 now = GNUNET_get_time ();
1051 count = 0;
1052 while (1)
1053 {
1054 switch (iter_select)
1055 {
1056 case 0:
1057 case 1:
1058 ret = prepared_statement_run_select (iter[iter_select],
1059 7,
1060 rbind,
1061 &return_ok,
1062 NULL,
1063 MYSQL_TYPE_LONG,
1064 &last_prio,
1065 GNUNET_YES,
1066 MYSQL_TYPE_LONGLONG,
1067 &last_vkey,
1068 GNUNET_YES,
1069 MYSQL_TYPE_LONG,
1070 &last_prio,
1071 GNUNET_YES,
1072 MYSQL_TYPE_LONGLONG,
1073 &last_vkey,
1074 GNUNET_YES, -1);
1075 break;
1076 case 2:
1077 ret = prepared_statement_run_select (iter[iter_select],
1078 7,
1079 rbind,
1080 &return_ok,
1081 NULL,
1082 MYSQL_TYPE_LONGLONG,
1083 &last_expire,
1084 GNUNET_YES,
1085 MYSQL_TYPE_LONGLONG,
1086 &last_vkey,
1087 GNUNET_YES,
1088 MYSQL_TYPE_LONGLONG,
1089 &last_expire,
1090 GNUNET_YES,
1091 MYSQL_TYPE_LONGLONG,
1092 &last_vkey,
1093 GNUNET_YES, -1);
1094 break;
1095 case 3:
1096 ret = prepared_statement_run_select (iter[iter_select],
1097 7,
1098 rbind,
1099 &return_ok,
1100 NULL,
1101 MYSQL_TYPE_LONGLONG,
1102 &last_expire,
1103 GNUNET_YES,
1104 MYSQL_TYPE_LONGLONG,
1105 &last_vkey,
1106 GNUNET_YES,
1107 MYSQL_TYPE_LONGLONG,
1108 &now,
1109 GNUNET_YES,
1110 MYSQL_TYPE_LONGLONG,
1111 &last_expire,
1112 GNUNET_YES,
1113 MYSQL_TYPE_LONGLONG,
1114 &last_vkey,
1115 GNUNET_YES,
1116 MYSQL_TYPE_LONGLONG,
1117 &now,
1118 GNUNET_YES, -1);
1119 break;
1120 default:
1121 GNUNET_break (0);
1122 return GNUNET_SYSERR;
1123 }
1124 if (ret != GNUNET_OK)
1125 break;
1126 last_vkey = vkey;
1127 last_prio = prio;
1128 last_expire = expiration;
1129 count++;
1130 if (dviter != NULL)
1131 {
1132 datum = assembleDatum (rbind);
1133 if (datum == NULL)
1134 continue;
1135 ret = dviter (&key, datum, closure, vkey);
1136 if (ret == GNUNET_SYSERR)
1137 {
1138 GNUNET_free (datum);
1139 break;
1140 }
1141 if (ret == GNUNET_NO)
1142 {
1143 do_delete_value (vkey);
1144 do_delete_entry_by_vkey (vkey);
1145 content_size -= ntohl (datum->size);
1146 }
1147 GNUNET_free (datum);
1148 }
1149 }
1150 return count;
1151} 1216}
1152 1217
1153 1218
1154
1155/** 1219/**
1156 * Get an estimate of how much space the database is 1220 * Get an estimate of how much space the database is
1157 * currently using. 1221 * currently using.
@@ -1193,39 +1257,25 @@ mysql_plugin_put (void *cls,
1193 char **msg) 1257 char **msg)
1194{ 1258{
1195 struct Plugin *plugin = cls; 1259 struct Plugin *plugin = cls;
1196
1197 unsigned long contentSize;
1198 unsigned long hashSize; 1260 unsigned long hashSize;
1199 unsigned long hashSize2; 1261 unsigned long hashSize2;
1200 unsigned int size;
1201 unsigned int type;
1202 unsigned int prio;
1203 unsigned int level;
1204 unsigned long long expiration;
1205 unsigned long long vkey; 1262 unsigned long long vkey;
1206 GNUNET_HashCode vhash; 1263 GNUNET_HashCode vhash;
1207 1264
1208 if (((ntohl (value->size) < sizeof (GNUNET_DatastoreValue))) || 1265 if (size > MAX_DATUM_SIZE)
1209 ((ntohl (value->size) - sizeof (GNUNET_DatastoreValue)) >
1210 MAX_DATUM_SIZE))
1211 { 1266 {
1212 GNUNET_break (0); 1267 GNUNET_break (0);
1213 return GNUNET_SYSERR; 1268 return GNUNET_SYSERR;
1214 } 1269 }
1215 hashSize = sizeof (GNUNET_HashCode); 1270 hashSize = sizeof (GNUNET_HashCode);
1216 hashSize2 = sizeof (GNUNET_HashCode); 1271 hashSize2 = sizeof (GNUNET_HashCode);
1217 size = ntohl (value->size); 1272 GNUNET_CRYPTO_hash (data, size, &vhash);
1218 type = ntohl (value->type); 1273 if (GNUNET_OK != do_insert_value (plugin,
1219 prio = ntohl (value->priority); 1274 data, size, &vkey))
1220 level = ntohl (value->anonymity_level);
1221 expiration = GNUNET_ntohll (value->expiration_time);
1222 contentSize = ntohl (value->size) - sizeof (GNUNET_DatastoreValue);
1223 GNUNET_hash (&value[1], contentSize, &vhash);
1224
1225 if (GNUNET_OK != do_insert_value (&value[1], contentSize, &vkey))
1226 return GNUNET_SYSERR; 1275 return GNUNET_SYSERR;
1227 if (GNUNET_OK != 1276 if (GNUNET_OK !=
1228 prepared_statement_run (insert_entry, 1277 prepared_statement_run (plugin,
1278 plugin->insert_entry,
1229 NULL, 1279 NULL,
1230 MYSQL_TYPE_LONG, 1280 MYSQL_TYPE_LONG,
1231 &size, 1281 &size,
@@ -1234,13 +1284,13 @@ mysql_plugin_put (void *cls,
1234 &type, 1284 &type,
1235 GNUNET_YES, 1285 GNUNET_YES,
1236 MYSQL_TYPE_LONG, 1286 MYSQL_TYPE_LONG,
1237 &prio, 1287 &priority,
1238 GNUNET_YES, 1288 GNUNET_YES,
1239 MYSQL_TYPE_LONG, 1289 MYSQL_TYPE_LONG,
1240 &level, 1290 &anonymity,
1241 GNUNET_YES, 1291 GNUNET_YES,
1242 MYSQL_TYPE_LONGLONG, 1292 MYSQL_TYPE_LONGLONG,
1243 &expiration, 1293 &expiration.value,
1244 GNUNET_YES, 1294 GNUNET_YES,
1245 MYSQL_TYPE_BLOB, 1295 MYSQL_TYPE_BLOB,
1246 key, 1296 key,
@@ -1253,32 +1303,34 @@ mysql_plugin_put (void *cls,
1253 MYSQL_TYPE_LONGLONG, 1303 MYSQL_TYPE_LONGLONG,
1254 &vkey, GNUNET_YES, -1)) 1304 &vkey, GNUNET_YES, -1))
1255 { 1305 {
1256 do_delete_value (vkey); 1306 do_delete_value (plugin, vkey);
1257 return GNUNET_SYSERR; 1307 return GNUNET_SYSERR;
1258 } 1308 }
1259 plugin->content_size += ntohl (value->size); 1309 plugin->content_size += size;
1260 return GNUNET_OK; 1310 return GNUNET_OK;
1261} 1311}
1262 1312
1263 1313
1264/** 1314/**
1265 * Function invoked on behalf of a "PluginIterator" 1315 * Select a subset of the items in the datastore and call
1266 * asking the database plugin to call the iterator 1316 * the given iterator for each of them.
1267 * with the next item.
1268 * 1317 *
1269 * @param next_cls whatever argument was given 1318 * @param cls our "struct Plugin*"
1270 * to the PluginIterator as "next_cls". 1319 * @param type entries of which type should be considered?
1271 * @param end_it set to GNUNET_YES if we 1320 * Use 0 for any type.
1272 * should terminate the iteration early 1321 * @param iter function to call on each matching value;
1273 * (iterator should be still called once more 1322 * will be called once with a NULL value at the end
1274 * to signal the end of the iteration). 1323 * @param iter_cls closure for iter
1275 */ 1324 */
1276static void 1325static void
1277mysql_plugin_next_request (void *next_cls, 1326mysql_plugin_iter_low_priority (void *cls,
1278 int end_it) 1327 enum GNUNET_BLOCK_Type type,
1328 PluginIterator iter,
1329 void *iter_cls)
1279{ 1330{
1280 struct Plugin *plugin = cls; 1331 struct Plugin *plugin = cls;
1281 GNUNET_break (0); 1332 iterateHelper (plugin, type, GNUNET_YES,
1333 0, iter, iter_cls);
1282} 1334}
1283 1335
1284 1336
@@ -1319,14 +1371,19 @@ mysql_plugin_get (void *cls,
1319 unsigned long long expiration; 1371 unsigned long long expiration;
1320 unsigned long long vkey; 1372 unsigned long long vkey;
1321 unsigned long long last_vkey; 1373 unsigned long long last_vkey;
1322 GNUNET_DatastoreValue *datum;
1323 GNUNET_HashCode key;
1324 unsigned long hashSize; 1374 unsigned long hashSize;
1325 unsigned long hashSize2; 1375 unsigned long hashSize2;
1326 MYSQL_BIND rbind[7]; 1376 MYSQL_BIND rbind[7];
1327 1377
1378 if (iter == NULL)
1379 return;
1328 if (key == NULL) 1380 if (key == NULL)
1329 return iterateLowPriority (type, iter, closure); 1381 {
1382 mysql_plugin_iter_low_priority (plugin,
1383 type,
1384 iter, iter_cls);
1385 return;
1386 }
1330 hashSize = sizeof (GNUNET_HashCode); 1387 hashSize = sizeof (GNUNET_HashCode);
1331 hashSize2 = sizeof (GNUNET_HashCode); 1388 hashSize2 = sizeof (GNUNET_HashCode);
1332 memset (rbind, 0, sizeof (rbind)); 1389 memset (rbind, 0, sizeof (rbind));
@@ -1340,7 +1397,8 @@ mysql_plugin_get (void *cls,
1340 { 1397 {
1341 ret = 1398 ret =
1342 prepared_statement_run_select 1399 prepared_statement_run_select
1343 (count_entry_by_hash_vhash_and_type, 1, rbind, &return_ok, NULL, 1400 (plugin,
1401 plugin->count_entry_by_hash_vhash_and_type, 1, rbind, &return_ok, NULL,
1344 MYSQL_TYPE_BLOB, key, hashSize2, &hashSize2, MYSQL_TYPE_BLOB, 1402 MYSQL_TYPE_BLOB, key, hashSize2, &hashSize2, MYSQL_TYPE_BLOB,
1345 vhash, hashSize2, &hashSize2, MYSQL_TYPE_LONG, &type, GNUNET_YES, 1403 vhash, hashSize2, &hashSize2, MYSQL_TYPE_LONG, &type, GNUNET_YES,
1346 -1); 1404 -1);
@@ -1349,7 +1407,8 @@ mysql_plugin_get (void *cls,
1349 { 1407 {
1350 ret = 1408 ret =
1351 prepared_statement_run_select 1409 prepared_statement_run_select
1352 (count_entry_by_hash_and_type, 1, rbind, &return_ok, NULL, 1410 (plugin,
1411 plugin->count_entry_by_hash_and_type, 1, rbind, &return_ok, NULL,
1353 MYSQL_TYPE_BLOB, key, hashSize2, &hashSize2, MYSQL_TYPE_LONG, 1412 MYSQL_TYPE_BLOB, key, hashSize2, &hashSize2, MYSQL_TYPE_LONG,
1354 &type, GNUNET_YES, -1); 1413 &type, GNUNET_YES, -1);
1355 1414
@@ -1361,7 +1420,8 @@ mysql_plugin_get (void *cls,
1361 { 1420 {
1362 ret = 1421 ret =
1363 prepared_statement_run_select 1422 prepared_statement_run_select
1364 (count_entry_by_hash_and_vhash, 1, rbind, &return_ok, NULL, 1423 (plugin,
1424 plugin->count_entry_by_hash_and_vhash, 1, rbind, &return_ok, NULL,
1365 MYSQL_TYPE_BLOB, key, hashSize2, &hashSize2, MYSQL_TYPE_BLOB, 1425 MYSQL_TYPE_BLOB, key, hashSize2, &hashSize2, MYSQL_TYPE_BLOB,
1366 vhash, hashSize2, &hashSize2, -1); 1426 vhash, hashSize2, &hashSize2, -1);
1367 1427
@@ -1369,21 +1429,22 @@ mysql_plugin_get (void *cls,
1369 else 1429 else
1370 { 1430 {
1371 ret = 1431 ret =
1372 GNUNET_MYSQL_prepared_statement_run_select (count_entry_by_hash, 1432 prepared_statement_run_select (plugin,
1373 1, rbind, &return_ok, 1433 plugin->count_entry_by_hash,
1374 NULL, MYSQL_TYPE_BLOB, 1434 1, rbind, &return_ok,
1375 key, hashSize2, 1435 NULL, MYSQL_TYPE_BLOB,
1376 &hashSize2, -1); 1436 key, hashSize2,
1437 &hashSize2, -1);
1377 } 1438 }
1378 } 1439 }
1379 if ((ret != GNUNET_OK) || (-1 == total)) 1440 if ((ret != GNUNET_OK) || (-1 == total))
1380 return GNUNET_SYSERR; 1441 return;
1381 if ((iter == NULL) || (total == 0)) 1442 if (total == 0)
1382 return (int) total; 1443 return;
1383 1444
1384 last_vkey = 0; 1445 last_vkey = 0;
1385 count = 0; 1446 count = 0;
1386 off = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, total); 1447 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
1387 1448
1388 memset (rbind, 0, sizeof (rbind)); 1449 memset (rbind, 0, sizeof (rbind));
1389 rbind[0].buffer_type = MYSQL_TYPE_LONG; 1450 rbind[0].buffer_type = MYSQL_TYPE_LONG;
@@ -1402,7 +1463,7 @@ mysql_plugin_get (void *cls,
1402 rbind[4].buffer = &expiration; 1463 rbind[4].buffer = &expiration;
1403 rbind[4].is_unsigned = GNUNET_YES; 1464 rbind[4].is_unsigned = GNUNET_YES;
1404 rbind[5].buffer_type = MYSQL_TYPE_BLOB; 1465 rbind[5].buffer_type = MYSQL_TYPE_BLOB;
1405 rbind[5].buffer = &key; 1466 rbind[5].buffer = (void*) key;
1406 rbind[5].buffer_length = hashSize; 1467 rbind[5].buffer_length = hashSize;
1407 rbind[5].length = &hashSize; 1468 rbind[5].length = &hashSize;
1408 rbind[6].buffer_type = MYSQL_TYPE_LONGLONG; 1469 rbind[6].buffer_type = MYSQL_TYPE_LONGLONG;
@@ -1420,7 +1481,8 @@ mysql_plugin_get (void *cls,
1420 { 1481 {
1421 ret = 1482 ret =
1422 prepared_statement_run_select 1483 prepared_statement_run_select
1423 (select_entry_by_hash_vhash_and_type, 7, rbind, &return_ok, 1484 (plugin,
1485 plugin->select_entry_by_hash_vhash_and_type, 7, rbind, &return_ok,
1424 NULL, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, 1486 NULL, MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
1425 MYSQL_TYPE_BLOB, vhash, hashSize2, &hashSize2, 1487 MYSQL_TYPE_BLOB, vhash, hashSize2, &hashSize2,
1426 MYSQL_TYPE_LONGLONG, &last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, 1488 MYSQL_TYPE_LONGLONG, &last_vkey, GNUNET_YES, MYSQL_TYPE_LONG,
@@ -1431,7 +1493,8 @@ mysql_plugin_get (void *cls,
1431 { 1493 {
1432 ret = 1494 ret =
1433 prepared_statement_run_select 1495 prepared_statement_run_select
1434 (select_entry_by_hash_and_type, 7, rbind, &return_ok, NULL, 1496 (plugin,
1497 plugin->select_entry_by_hash_and_type, 7, rbind, &return_ok, NULL,
1435 MYSQL_TYPE_BLOB, key, hashSize, &hashSize, 1498 MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
1436 MYSQL_TYPE_LONGLONG, &last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, 1499 MYSQL_TYPE_LONGLONG, &last_vkey, GNUNET_YES, MYSQL_TYPE_LONG,
1437 &type, GNUNET_YES, MYSQL_TYPE_LONG, &limit_off, GNUNET_YES, 1500 &type, GNUNET_YES, MYSQL_TYPE_LONG, &limit_off, GNUNET_YES,
@@ -1444,7 +1507,8 @@ mysql_plugin_get (void *cls,
1444 { 1507 {
1445 ret = 1508 ret =
1446 prepared_statement_run_select 1509 prepared_statement_run_select
1447 (select_entry_by_hash_and_vhash, 7, rbind, &return_ok, NULL, 1510 (plugin,
1511 plugin->select_entry_by_hash_and_vhash, 7, rbind, &return_ok, NULL,
1448 MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, 1512 MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB,
1449 vhash, hashSize2, &hashSize2, MYSQL_TYPE_LONGLONG, 1513 vhash, hashSize2, &hashSize2, MYSQL_TYPE_LONGLONG,
1450 &last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, &limit_off, 1514 &last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, &limit_off,
@@ -1454,7 +1518,8 @@ mysql_plugin_get (void *cls,
1454 { 1518 {
1455 ret = 1519 ret =
1456 prepared_statement_run_select 1520 prepared_statement_run_select
1457 (select_entry_by_hash, 7, rbind, &return_ok, NULL, 1521 (plugin,
1522 plugin->select_entry_by_hash, 7, rbind, &return_ok, NULL,
1458 MYSQL_TYPE_BLOB, key, hashSize, &hashSize, 1523 MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
1459 MYSQL_TYPE_LONGLONG, &last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, 1524 MYSQL_TYPE_LONGLONG, &last_vkey, GNUNET_YES, MYSQL_TYPE_LONG,
1460 &limit_off, GNUNET_YES, -1); 1525 &limit_off, GNUNET_YES, -1);
@@ -1463,23 +1528,24 @@ mysql_plugin_get (void *cls,
1463 if (ret != GNUNET_OK) 1528 if (ret != GNUNET_OK)
1464 break; 1529 break;
1465 last_vkey = vkey; 1530 last_vkey = vkey;
1531#if FIXME
1466 datum = assembleDatum (rbind); 1532 datum = assembleDatum (rbind);
1467 if (datum == NULL) 1533 if (datum == NULL)
1468 continue; 1534 continue;
1469 count++; 1535 count++;
1470 ret = iter (&key, datum, closure, vkey); 1536 ret = iter (iter_cls, key, datum, vkey);
1537#endif
1538 ret = GNUNET_SYSERR;
1471 if (ret == GNUNET_SYSERR) 1539 if (ret == GNUNET_SYSERR)
1472 { 1540 {
1473 GNUNET_free (datum);
1474 break; 1541 break;
1475 } 1542 }
1476 if (ret == GNUNET_NO) 1543 if (ret == GNUNET_NO)
1477 { 1544 {
1478 do_delete_value (vkey); 1545 do_delete_value (plugin, vkey);
1479 do_delete_entry_by_vkey (vkey); 1546 do_delete_entry_by_vkey (plugin, vkey);
1480 content_size -= ntohl (datum->size); 1547 plugin->content_size -= size;
1481 } 1548 }
1482 GNUNET_free (datum);
1483 if (count + off == total) 1549 if (count + off == total)
1484 last_vkey = 0; /* back to start */ 1550 last_vkey = 0; /* back to start */
1485 if (count == total) 1551 if (count == total)
@@ -1551,36 +1617,13 @@ mysql_plugin_update (void *cls,
1551 * @param iter_cls closure for iter 1617 * @param iter_cls closure for iter
1552 */ 1618 */
1553static void 1619static void
1554mysql_plugin_iter_low_priority (void *cls,
1555 enum GNUNET_BLOCK_Type type,
1556 PluginIterator iter,
1557 void *iter_cls)
1558{
1559 struct Plugin *plugin = cls;
1560 iterateHelper (plugin, type, GNUNET_YES,
1561 0, iter, iter_cls);
1562}
1563
1564
1565/**
1566 * Select a subset of the items in the datastore and call
1567 * the given iterator for each of them.
1568 *
1569 * @param cls our "struct Plugin*"
1570 * @param type entries of which type should be considered?
1571 * Use 0 for any type.
1572 * @param iter function to call on each matching value;
1573 * will be called once with a NULL value at the end
1574 * @param iter_cls closure for iter
1575 */
1576static void
1577mysql_plugin_iter_zero_anonymity (void *cls, 1620mysql_plugin_iter_zero_anonymity (void *cls,
1578 enum GNUNET_BLOCK_Type type, 1621 enum GNUNET_BLOCK_Type type,
1579 PluginIterator iter, 1622 PluginIterator iter,
1580 void *iter_cls) 1623 void *iter_cls)
1581{ 1624{
1582 struct Plugin *plugin = cls; 1625 struct Plugin *plugin = cls;
1583 iterateHelper (plugin, type, GNUNET_NO, 1, iter, closure); 1626 iterateHelper (plugin, type, GNUNET_NO, 1, iter, iter_cls);
1584} 1627}
1585 1628
1586 1629
@@ -1602,7 +1645,7 @@ mysql_plugin_iter_ascending_expiration (void *cls,
1602 void *iter_cls) 1645 void *iter_cls)
1603{ 1646{
1604 struct Plugin *plugin = cls; 1647 struct Plugin *plugin = cls;
1605 iterateHelper (plugin, type, GNUNET_YES, 2, iter, closure); 1648 iterateHelper (plugin, type, GNUNET_YES, 2, iter, iter_cls);
1606} 1649}
1607 1650
1608 1651
@@ -1624,7 +1667,7 @@ mysql_plugin_iter_migration_order (void *cls,
1624 void *iter_cls) 1667 void *iter_cls)
1625{ 1668{
1626 struct Plugin *plugin = cls; 1669 struct Plugin *plugin = cls;
1627 iterateHelper (plugin, 0, GNUNET_NO, 3, iter, closure); 1670 iterateHelper (plugin, 0, GNUNET_NO, 3, iter, iter_cls);
1628} 1671}
1629 1672
1630 1673
@@ -1641,12 +1684,12 @@ mysql_plugin_iter_migration_order (void *cls,
1641 */ 1684 */
1642static void 1685static void
1643mysql_plugin_iter_all_now (void *cls, 1686mysql_plugin_iter_all_now (void *cls,
1644 enum GNUNET_BLOCK_Type type, 1687 enum GNUNET_BLOCK_Type type,
1645 PluginIterator iter, 1688 PluginIterator iter,
1646 void *iter_cls) 1689 void *iter_cls)
1647{ 1690{
1648 struct Plugin *plugin = cls; 1691 struct Plugin *plugin = cls;
1649 iterateHelper (plugin, 0, GNUNET_YES, 0, iter, closure); 1692 iterateHelper (plugin, 0, GNUNET_YES, 0, iter, iter_cls);
1650} 1693}
1651 1694
1652 1695
@@ -1734,14 +1777,14 @@ libgnunet_plugin_datastore_mysql_init (void *cls)
1734 || PINIT (plugin->iter[2], SELECT_IT_EXPIRATION_TIME) 1777 || PINIT (plugin->iter[2], SELECT_IT_EXPIRATION_TIME)
1735 || PINIT (plugin->iter[3], SELECT_IT_MIGRATION_ORDER)) 1778 || PINIT (plugin->iter[3], SELECT_IT_MIGRATION_ORDER))
1736 { 1779 {
1737 GNUNET_MYSQL_database_close (db); 1780 iclose (plugin);
1738 db = NULL; 1781 GNUNET_free_non_null (plugin->cnffile);
1739 return GNUNET_SYSERR; 1782 GNUNET_free (plugin);
1783 return NULL;
1740 } 1784 }
1741#undef PINIT 1785#undef PINIT
1742#undef MRUNS 1786#undef MRUNS
1743 1787
1744
1745 api = GNUNET_malloc (sizeof (struct GNUNET_DATASTORE_PluginFunctions)); 1788 api = GNUNET_malloc (sizeof (struct GNUNET_DATASTORE_PluginFunctions));
1746 api->cls = plugin; 1789 api->cls = plugin;
1747 api->get_size = &mysql_plugin_get_size; 1790 api->get_size = &mysql_plugin_get_size;
@@ -1773,9 +1816,16 @@ libgnunet_plugin_datastore_mysql_done (void *cls)
1773 struct Plugin *plugin = api->cls; 1816 struct Plugin *plugin = api->cls;
1774 1817
1775 iclose (plugin); 1818 iclose (plugin);
1819 if (plugin->next_task != GNUNET_SCHEDULER_NO_TASK)
1820 {
1821 GNUNET_SCHEDULER_cancel (plugin->env->sched,
1822 plugin->next_task);
1823 plugin->next_task = GNUNET_SCHEDULER_NO_TASK;
1824 GNUNET_free (plugin->next_task_nc);
1825 plugin->next_task_nc = NULL;
1826 }
1776 GNUNET_free_non_null (plugin->cnffile); 1827 GNUNET_free_non_null (plugin->cnffile);
1777 GNUNET_free (plugin); 1828 GNUNET_free (plugin);
1778 GNUNET_free (plugin);
1779 GNUNET_free (api); 1829 GNUNET_free (api);
1780 mysql_library_end (); 1830 mysql_library_end ();
1781 return NULL; 1831 return NULL;