aboutsummaryrefslogtreecommitdiff
path: root/src/datastore
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-04-13 19:41:26 +0000
committerChristian Grothoff <christian@grothoff.org>2011-04-13 19:41:26 +0000
commit57a074bce8ef0c538d1b1906c9de7482275232fb (patch)
tree0d8730be01a7e6b42496c406e0715eb0c9ca94e7 /src/datastore
parent47f30b90cf1f18ac682b6fd3a8c9585811368ee9 (diff)
downloadgnunet-57a074bce8ef0c538d1b1906c9de7482275232fb.tar.gz
gnunet-57a074bce8ef0c538d1b1906c9de7482275232fb.zip
getting mysql code to compile again, fixes to sqlite code
Diffstat (limited to 'src/datastore')
-rw-r--r--src/datastore/plugin_datastore_mysql.c572
-rw-r--r--src/datastore/plugin_datastore_sqlite.c135
2 files changed, 288 insertions, 419 deletions
diff --git a/src/datastore/plugin_datastore_mysql.c b/src/datastore/plugin_datastore_mysql.c
index f2c4419be..c759763c7 100644
--- a/src/datastore/plugin_datastore_mysql.c
+++ b/src/datastore/plugin_datastore_mysql.c
@@ -106,7 +106,6 @@
106 * 2) by executing (inside of mysql using the GNUnet database): 106 * 2) by executing (inside of mysql using the GNUnet database):
107 * @verbatim 107 * @verbatim
108 mysql> REPAIR TABLE gn090; 108 mysql> REPAIR TABLE gn090;
109 mysql> REPAIR TABLE gn072;
110 @endverbatim 109 @endverbatim
111 * 110 *
112 * PROBLEMS? 111 * PROBLEMS?
@@ -115,10 +114,6 @@
115 * friend is probably the mysql manual. The first thing to check 114 * friend is probably the mysql manual. The first thing to check
116 * is that mysql is basically operational, that you can connect 115 * is that mysql is basically operational, that you can connect
117 * to it, create tables, issue queries etc. 116 * to it, create tables, issue queries etc.
118 *
119 * TODO:
120 * - use FOREIGN KEY for 'uid/vkey'
121 * - consistent naming of uid/vkey
122 */ 117 */
123 118
124#include "platform.h" 119#include "platform.h"
@@ -202,7 +197,7 @@ struct NextRequestClosure
202 */ 197 */
203 void *prep_cls; 198 void *prep_cls;
204 199
205 MYSQL_BIND rbind[6]; 200 MYSQL_BIND rbind[7];
206 201
207 enum GNUNET_BLOCK_Type type; 202 enum GNUNET_BLOCK_Type type;
208 203
@@ -210,9 +205,7 @@ struct NextRequestClosure
210 205
211 void *dviter_cls; 206 void *dviter_cls;
212 207
213 unsigned long long last_vkey; 208 unsigned int count;
214
215 unsigned int last_prio;
216 209
217 int end_it; 210 int end_it;
218}; 211};
@@ -228,10 +221,19 @@ struct Plugin
228 */ 221 */
229 struct GNUNET_DATASTORE_PluginEnvironment *env; 222 struct GNUNET_DATASTORE_PluginEnvironment *env;
230 223
224 /**
225 * Handle to talk to MySQL.
226 */
231 MYSQL *dbf; 227 MYSQL *dbf;
232 228
229 /**
230 * We keep all prepared statements in a DLL. This is the head.
231 */
233 struct GNUNET_MysqlStatementHandle *shead; 232 struct GNUNET_MysqlStatementHandle *shead;
234 233
234 /**
235 * We keep all prepared statements in a DLL. This is the tail.
236 */
235 struct GNUNET_MysqlStatementHandle *stail; 237 struct GNUNET_MysqlStatementHandle *stail;
236 238
237 /** 239 /**
@@ -250,79 +252,54 @@ struct Plugin
250 GNUNET_SCHEDULER_TaskIdentifier next_task; 252 GNUNET_SCHEDULER_TaskIdentifier next_task;
251 253
252 /** 254 /**
253 * Statements dealing with gn072 table 255 * Prepared statements.
254 */ 256 */
255#define SELECT_VALUE "SELECT value FROM gn072 WHERE vkey=?" 257#define INSERT_ENTRY "INSERT INTO gn090 (repl,type,prio,anonLevel,expire,hash,vhash,value) VALUES (?,?,?,?,?,?,?,?)"
256 struct GNUNET_MysqlStatementHandle *select_value;
257
258#define DELETE_VALUE "DELETE FROM gn072 WHERE vkey=?"
259 struct GNUNET_MysqlStatementHandle *delete_value;
260
261#define INSERT_VALUE "INSERT INTO gn072 (value) VALUES (?)"
262 struct GNUNET_MysqlStatementHandle *insert_value;
263
264 /**
265 * Statements dealing with gn090 table
266 */
267#define INSERT_ENTRY "INSERT INTO gn090 (repl,type,prio,anonLevel,expire,hash,vhash,vkey) VALUES (?,?,?,?,?,?,?,?)"
268 struct GNUNET_MysqlStatementHandle *insert_entry; 258 struct GNUNET_MysqlStatementHandle *insert_entry;
269 259
270#define DELETE_ENTRY_BY_VKEY "DELETE FROM gn090 WHERE vkey=?" 260#define DELETE_ENTRY_BY_UID "DELETE FROM gn090 WHERE uid=?"
271 struct GNUNET_MysqlStatementHandle *delete_entry_by_vkey; 261 struct GNUNET_MysqlStatementHandle *delete_entry_by_uid;
272
273#define SELECT_ENTRY_BY_HASH "SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX (hash_vkey) WHERE hash=? AND vkey > ? ORDER BY vkey ASC LIMIT 1 OFFSET ?"
274 struct GNUNET_MysqlStatementHandle *select_entry_by_hash;
275
276#define SELECT_ENTRY_BY_HASH_AND_VHASH "SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX (hash_vhash_vkey) WHERE hash=? AND vhash=? AND vkey > ? ORDER BY vkey ASC LIMIT 1 OFFSET ?"
277 struct GNUNET_MysqlStatementHandle *select_entry_by_hash_and_vhash;
278 262
279#define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX (hash_vkey) WHERE hash=? AND vkey > ? AND type=? ORDER BY vkey ASC LIMIT 1 OFFSET ?" 263#define COUNT_ENTRY_BY_HASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash) WHERE hash=?"
280 struct GNUNET_MysqlStatementHandle *select_entry_by_hash_and_type;
281
282#define SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX (hash_vhash_vkey) WHERE hash=? AND vhash=? AND vkey > ? AND type=? ORDER BY vkey ASC LIMIT 1 OFFSET ?"
283 struct GNUNET_MysqlStatementHandle *select_entry_by_hash_vhash_and_type;
284
285#define COUNT_ENTRY_BY_HASH "SELECT count(*) FROM gn090 FORCE INDEX (hash) WHERE hash=?"
286 struct GNUNET_MysqlStatementHandle *count_entry_by_hash; 264 struct GNUNET_MysqlStatementHandle *count_entry_by_hash;
265
266#define SELECT_ENTRY_BY_HASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_uid) WHERE hash=? ORDER BY uid LIMIT 1 OFFSET ?"
267 struct GNUNET_MysqlStatementHandle *select_entry_by_hash;
287 268
288#define COUNT_ENTRY_BY_HASH_AND_VHASH "SELECT count(*) FROM gn090 FORCE INDEX (hash_vhash_vkey) WHERE hash=? AND vhash=?" 269#define COUNT_ENTRY_BY_HASH_AND_VHASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=?"
289 struct GNUNET_MysqlStatementHandle *count_entry_by_hash_and_vhash; 270 struct GNUNET_MysqlStatementHandle *count_entry_by_hash_and_vhash;
290 271
291#define COUNT_ENTRY_BY_HASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (hash) WHERE hash=? AND type=?" 272#define SELECT_ENTRY_BY_HASH_AND_VHASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? ORDER BY uid LIMIT 1 OFFSET ?"
273 struct GNUNET_MysqlStatementHandle *select_entry_by_hash_and_vhash;
274
275#define COUNT_ENTRY_BY_HASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=?"
292 struct GNUNET_MysqlStatementHandle *count_entry_by_hash_and_type; 276 struct GNUNET_MysqlStatementHandle *count_entry_by_hash_and_type;
293 277
294#define COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (hash_vhash) WHERE hash=? AND vhash=? AND type=?" 278#define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=? ORDER BY uid LIMIT 1 OFFSET ?"
279 struct GNUNET_MysqlStatementHandle *select_entry_by_hash_and_type;
280
281#define COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=?"
295 struct GNUNET_MysqlStatementHandle *count_entry_by_hash_vhash_and_type; 282 struct GNUNET_MysqlStatementHandle *count_entry_by_hash_vhash_and_type;
283
284#define SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=? ORDER BY uid ASC LIMIT 1 OFFSET ?"
285 struct GNUNET_MysqlStatementHandle *select_entry_by_hash_vhash_and_type;
296 286
297#define UPDATE_ENTRY "UPDATE gn090 SET prio=prio+?,expire=IF(expire>=?,expire,?) WHERE vkey=?" 287#define UPDATE_ENTRY "UPDATE gn090 FORCE INDEX (uid) SET prio=prio+?,expire=IF(expire>=?,expire,?) WHERE uid=? LIMIT 1"
298 struct GNUNET_MysqlStatementHandle *update_entry; 288 struct GNUNET_MysqlStatementHandle *update_entry;
299 289
300#define SELECT_SIZE "SELECT SUM(BIT_LENGTH(value) DIV 8) FROM gn072" 290#define SELECT_SIZE "SELECT SUM(BIT_LENGTH(value) DIV 8) FROM gn090"
301 struct GNUNET_MysqlStatementHandle *get_size; 291 struct GNUNET_MysqlStatementHandle *get_size;
302 292
303/* warning, slighly crazy mysql statements ahead. Essentially, MySQL does not handle 293#define SELECT_IT_NON_ANONYMOUS "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX(idx_anonLevel_uid) WHERE anonLevel=0 ORDER BY uid DESC LIMIT 1 OFFSET ?"
304 "OR" very well, so we need to use UNION instead. And UNION does not
305 automatically apply a LIMIT on the outermost clause, so we need to
306 repeat ourselves quite a bit. All hail the performance gods (and thanks
307 to #mysql on freenode) */
308#define SELECT_IT_NON_ANONYMOUS "(SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX(prio) WHERE (prio = ? AND vkey < ?)"\
309 " AND anonLevel=0 ORDER BY prio DESC,vkey DESC LIMIT 1) "\
310 "UNION "\
311 "(SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX(prio) WHERE (prio < ? AND vkey != ?)"\
312 " AND anonLevel=0 ORDER BY prio DESC,vkey DESC LIMIT 1) "\
313 "ORDER BY prio DESC,vkey DESC LIMIT 1"
314 struct GNUNET_MysqlStatementHandle *zero_iter; 294 struct GNUNET_MysqlStatementHandle *zero_iter;
315 295
316#define SELECT_IT_EXPIRATION "(SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX(expire) WHERE (expire < ?) "\ 296#define SELECT_IT_EXPIRATION "(SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX(idx_expire_prio) WHERE expire < ? ORDER BY prio ASC LIMIT 1) "\
317 "ORDER BY prio ASC LIMIT 1) "\
318 "UNION "\ 297 "UNION "\
319 "(SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX(prio) "\ 298 "(SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX(idx_prio) ORDER BY prio ASC LIMIT 1) "\
320 "ORDER BY prio ASC LIMIT 1) ORDER BY expire ASC LIMIT 1" 299 "ORDER BY expire ASC LIMIT 1"
321 struct GNUNET_MysqlStatementHandle *select_expiration; 300 struct GNUNET_MysqlStatementHandle *select_expiration;
322 301
323#define SELECT_IT_REPLICATION "SELECT type,prio,anonLevel,expire,hash,vkey FROM gn090 FORCE INDEX(expire) "\ 302#define SELECT_IT_REPLICATION "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX(idx_repl) ORDER BY repl DESC,RAND() LIMIT 1"
324 "WHERE expire > ?"\
325 " ORDER BY repl DESC,RAND() LIMIT 1"
326 struct GNUNET_MysqlStatementHandle *select_replication; 303 struct GNUNET_MysqlStatementHandle *select_replication;
327 304
328}; 305};
@@ -837,114 +814,33 @@ prepared_statement_run (struct Plugin *plugin,
837 814
838 815
839/** 816/**
840 * Delete an value from the gn072 table.
841 *
842 * @param plugin plugin context
843 * @param vkey vkey identifying the value to delete
844 * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error
845 */
846static int
847do_delete_value (struct Plugin *plugin,
848 unsigned long long vkey)
849{
850 int ret;
851
852#if DEBUG_MYSQL
853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
854 "Deleting value %llu from gn072 table\n",
855 vkey);
856#endif
857 ret = prepared_statement_run (plugin,
858 plugin->delete_value,
859 NULL,
860 MYSQL_TYPE_LONGLONG,
861 &vkey, GNUNET_YES, -1);
862 if (ret > 0)
863 {
864 ret = GNUNET_OK;
865 }
866 else
867 {
868 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
869 "Deleting value %llu from gn072 table failed\n",
870 vkey);
871 }
872 return ret;
873}
874
875/**
876 * Insert a value into the gn072 table.
877 *
878 * @param plugin plugin context
879 * @param value the value to insert
880 * @param size size of the value
881 * @param vkey vkey identifying the value henceforth (set)
882 * @return GNUNET_OK on success, GNUNET_SYSERR on error
883 */
884static int
885do_insert_value (struct Plugin *plugin,
886 const void *value, unsigned int size,
887 unsigned long long *vkey)
888{
889 unsigned long length = size;
890 int ret;
891
892 ret = prepared_statement_run (plugin,
893 plugin->insert_value,
894 vkey,
895 MYSQL_TYPE_BLOB,
896 value, length, &length, -1);
897 if (ret == GNUNET_OK)
898 {
899#if DEBUG_MYSQL
900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
901 "Inserted value number %llu with length %u into gn072 table\n",
902 *vkey,
903 size);
904#endif
905 }
906 else
907 {
908 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
909 "Failed to insert %u byte value into gn072 table\n",
910 size);
911 }
912 return ret;
913}
914
915/**
916 * Delete an entry from the gn090 table. 817 * Delete an entry from the gn090 table.
917 * 818 *
918 * @param plugin plugin context 819 * @param plugin plugin context
919 * @param vkey vkey identifying the entry to delete 820 * @param uid unique ID of the entry to delete
920 * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error 821 * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error
921 */ 822 */
922static int 823static int
923do_delete_entry_by_vkey (struct Plugin *plugin, 824do_delete_entry (struct Plugin *plugin,
924 unsigned long long vkey) 825 unsigned long long uid)
925{ 826{
926 int ret; 827 int ret;
927 828
928#if DEBUG_MYSQL 829#if DEBUG_MYSQL
929 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
930 "Deleting value %llu from gn090 table\n", 831 "Deleting value %llu from gn090 table\n",
931 vkey); 832 uid);
932#endif 833#endif
933 ret = prepared_statement_run (plugin, 834 ret = prepared_statement_run (plugin,
934 plugin->delete_entry_by_vkey, 835 plugin->delete_entry_by_uid,
935 NULL, 836 NULL,
936 MYSQL_TYPE_LONGLONG, 837 MYSQL_TYPE_LONGLONG, uid, GNUNET_YES,
937 &vkey, GNUNET_YES, -1); 838 -1);
938 if (ret > 0) 839 if (ret > 0)
939 { 840 return GNUNET_OK;
940 ret = GNUNET_OK; 841 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
941 } 842 "Deleting value %llu from gn090 table failed\n",
942 else 843 uid);
943 {
944 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
945 "Deleting value %llu from gn090 table failed\n",
946 vkey);
947 }
948 return ret; 844 return ret;
949} 845}
950 846
@@ -983,20 +879,20 @@ mysql_next_request_cont (void *next_cls,
983 unsigned int priority; 879 unsigned int priority;
984 unsigned int anonymity; 880 unsigned int anonymity;
985 unsigned long long exp; 881 unsigned long long exp;
986 unsigned long long vkey;
987 unsigned long hashSize; 882 unsigned long hashSize;
883 unsigned long size;
884 unsigned long long uid;
885 char value[GNUNET_DATASTORE_MAX_VALUE_SIZE];
988 GNUNET_HashCode key; 886 GNUNET_HashCode key;
989 struct GNUNET_TIME_Absolute expiration; 887 struct GNUNET_TIME_Absolute expiration;
990 unsigned long length; 888 MYSQL_BIND *rbind = nrc->rbind;
991 MYSQL_BIND *rbind; /* size 7 */
992 MYSQL_BIND dbind[1];
993 char datum[GNUNET_SERVER_MAX_MESSAGE_SIZE];
994 889
995 plugin = nrc->plugin; 890 plugin = nrc->plugin;
996 plugin->next_task = GNUNET_SCHEDULER_NO_TASK; 891 plugin->next_task = GNUNET_SCHEDULER_NO_TASK;
997 plugin->next_task_nc = NULL; 892 plugin->next_task_nc = NULL;
998 893
999 AGAIN: 894 if (GNUNET_YES == nrc->end_it)
895 goto END_SET;
1000 GNUNET_assert (nrc->plugin->next_task == GNUNET_SCHEDULER_NO_TASK); 896 GNUNET_assert (nrc->plugin->next_task == GNUNET_SCHEDULER_NO_TASK);
1001 nrc->now = GNUNET_TIME_absolute_get (); 897 nrc->now = GNUNET_TIME_absolute_get ();
1002 hashSize = sizeof (GNUNET_HashCode); 898 hashSize = sizeof (GNUNET_HashCode);
@@ -1018,17 +914,19 @@ mysql_next_request_cont (void *next_cls,
1018 rbind[4].buffer = &key; 914 rbind[4].buffer = &key;
1019 rbind[4].buffer_length = hashSize; 915 rbind[4].buffer_length = hashSize;
1020 rbind[4].length = &hashSize; 916 rbind[4].length = &hashSize;
1021 rbind[5].buffer_type = MYSQL_TYPE_LONGLONG; 917 rbind[5].buffer_type = MYSQL_TYPE_BLOB;
1022 rbind[5].buffer = &vkey; 918 rbind[5].buffer = value;
1023 rbind[5].is_unsigned = GNUNET_YES; 919 rbind[5].buffer_length = size = sizeof (value);
1024 920 rbind[5].length = &size;
1025 if ( (GNUNET_YES == nrc->end_it) || 921 rbind[6].buffer_type = MYSQL_TYPE_LONGLONG;
1026 (GNUNET_OK != nrc->prep (nrc->prep_cls, 922 rbind[6].buffer = &uid;
1027 nrc))) 923 rbind[6].is_unsigned = 1;
924
925 if (GNUNET_OK != nrc->prep (nrc->prep_cls,
926 nrc))
1028 goto END_SET; 927 goto END_SET;
1029 nrc->last_vkey = vkey;
1030 nrc->last_prio = priority;
1031 GNUNET_assert (nrc->plugin->next_task == GNUNET_SCHEDULER_NO_TASK); 928 GNUNET_assert (nrc->plugin->next_task == GNUNET_SCHEDULER_NO_TASK);
929 GNUNET_assert (size <= sizeof(value));
1032 if ( (rbind[4].buffer_length != sizeof (GNUNET_HashCode)) || 930 if ( (rbind[4].buffer_length != sizeof (GNUNET_HashCode)) ||
1033 (hashSize != sizeof (GNUNET_HashCode)) ) 931 (hashSize != sizeof (GNUNET_HashCode)) )
1034 { 932 {
@@ -1037,63 +935,19 @@ mysql_next_request_cont (void *next_cls,
1037 } 935 }
1038#if DEBUG_MYSQL 936#if DEBUG_MYSQL
1039 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 937 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1040 "Found value %llu with prio %u, anon %u, expire %llu selecting from gn090 table\n", 938 "Found %u-byte value under key `%s' with prio %u, anon %u, expire %llu selecting from gn090 table\n",
1041 vkey, 939 (unsigned int) size,
1042 priority,
1043 anonymity,
1044 exp);
1045#endif
1046 /* now do query on gn072 */
1047 length = sizeof (datum);
1048 memset (dbind, 0, sizeof (dbind));
1049 dbind[0].buffer_type = MYSQL_TYPE_BLOB;
1050 dbind[0].buffer_length = length;
1051 dbind[0].length = &length;
1052 dbind[0].buffer = datum;
1053 ret = prepared_statement_run_select (plugin,
1054 plugin->select_value,
1055 1,
1056 dbind,
1057 &return_ok,
1058 NULL,
1059 MYSQL_TYPE_LONGLONG,
1060 &vkey, GNUNET_YES, -1);
1061 GNUNET_break (ret <= 1); /* should only have one rbind! */
1062 if (ret > 0)
1063 ret = GNUNET_OK;
1064 if (ret != GNUNET_OK)
1065 {
1066 GNUNET_break (0);
1067 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1068 _("Failed to obtain value %llu from table `%s'\n"),
1069 vkey,
1070 "gn072");
1071 goto AGAIN;
1072 }
1073 GNUNET_break (length <= sizeof(datum));
1074#if DEBUG_MYSQL
1075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1076 "Calling iterator with value `%s' number %llu of size %u with type %u, priority %u, anonymity %u and expiration %llu\n",
1077 GNUNET_h2s (&key), 940 GNUNET_h2s (&key),
1078 vkey,
1079 length,
1080 type,
1081 priority, 941 priority,
1082 anonymity, 942 anonymity,
1083 exp); 943 exp);
1084#endif 944#endif
1085 GNUNET_assert (nrc->plugin->next_task == GNUNET_SCHEDULER_NO_TASK);
1086 expiration.abs_value = exp; 945 expiration.abs_value = exp;
1087 ret = nrc->dviter (nrc->dviter_cls, 946 ret = nrc->dviter (nrc->dviter_cls, nrc,
1088 nrc,
1089 &key, 947 &key,
1090 length, 948 size, value,
1091 datum, 949 type, priority, anonymity, expiration,
1092 type, 950 uid);
1093 priority,
1094 anonymity,
1095 expiration,
1096 vkey);
1097 if (ret == GNUNET_SYSERR) 951 if (ret == GNUNET_SYSERR)
1098 { 952 {
1099 nrc->end_it = GNUNET_YES; 953 nrc->end_it = GNUNET_YES;
@@ -1101,11 +955,10 @@ mysql_next_request_cont (void *next_cls,
1101 } 955 }
1102 if (ret == GNUNET_NO) 956 if (ret == GNUNET_NO)
1103 { 957 {
1104 do_delete_value (plugin, vkey); 958 do_delete_entry (plugin, uid);
1105 do_delete_entry_by_vkey (plugin, vkey); 959 if (size != 0)
1106 if (length != 0)
1107 plugin->env->duc (plugin->env->cls, 960 plugin->env->duc (plugin->env->cls,
1108 - length); 961 - size);
1109 } 962 }
1110 return; 963 return;
1111 END_SET: 964 END_SET:
@@ -1212,7 +1065,7 @@ mysql_plugin_put (void *cls,
1212 unsigned long long lexpiration = expiration.abs_value; 1065 unsigned long long lexpiration = expiration.abs_value;
1213 unsigned long hashSize; 1066 unsigned long hashSize;
1214 unsigned long hashSize2; 1067 unsigned long hashSize2;
1215 unsigned long long vkey; 1068 unsigned long lsize;
1216 GNUNET_HashCode vhash; 1069 GNUNET_HashCode vhash;
1217 1070
1218 if (size > MAX_DATUM_SIZE) 1071 if (size > MAX_DATUM_SIZE)
@@ -1222,48 +1075,26 @@ mysql_plugin_put (void *cls,
1222 } 1075 }
1223 hashSize = sizeof (GNUNET_HashCode); 1076 hashSize = sizeof (GNUNET_HashCode);
1224 hashSize2 = sizeof (GNUNET_HashCode); 1077 hashSize2 = sizeof (GNUNET_HashCode);
1078 lsize = size;
1225 GNUNET_CRYPTO_hash (data, size, &vhash); 1079 GNUNET_CRYPTO_hash (data, size, &vhash);
1226 if (GNUNET_OK != do_insert_value (plugin,
1227 data, size, &vkey))
1228 return GNUNET_SYSERR;
1229 if (GNUNET_OK != 1080 if (GNUNET_OK !=
1230 prepared_statement_run (plugin, 1081 prepared_statement_run (plugin,
1231 plugin->insert_entry, 1082 plugin->insert_entry,
1232 NULL, 1083 NULL,
1233 MYSQL_TYPE_LONG, 1084 MYSQL_TYPE_LONG, &irepl, GNUNET_YES,
1234 &irepl, 1085 MYSQL_TYPE_LONG, &itype, GNUNET_YES,
1235 GNUNET_YES, 1086 MYSQL_TYPE_LONG, &ipriority, GNUNET_YES,
1236 MYSQL_TYPE_LONG, 1087 MYSQL_TYPE_LONG, &ianonymity, GNUNET_YES,
1237 &itype, 1088 MYSQL_TYPE_LONGLONG, &lexpiration, GNUNET_YES,
1238 GNUNET_YES, 1089 MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
1239 MYSQL_TYPE_LONG, 1090 MYSQL_TYPE_BLOB, &vhash, hashSize2, &hashSize2,
1240 &ipriority, 1091 MYSQL_TYPE_BLOB, data, lsize, &lsize,
1241 GNUNET_YES, 1092 -1))
1242 MYSQL_TYPE_LONG, 1093 return GNUNET_SYSERR;
1243 &ianonymity,
1244 GNUNET_YES,
1245 MYSQL_TYPE_LONGLONG,
1246 &lexpiration,
1247 GNUNET_YES,
1248 MYSQL_TYPE_BLOB,
1249 key,
1250 hashSize,
1251 &hashSize,
1252 MYSQL_TYPE_BLOB,
1253 &vhash,
1254 hashSize2,
1255 &hashSize2,
1256 MYSQL_TYPE_LONGLONG,
1257 &vkey, GNUNET_YES, -1))
1258 {
1259 do_delete_value (plugin, vkey);
1260 return GNUNET_SYSERR;
1261 }
1262#if DEBUG_MYSQL 1094#if DEBUG_MYSQL
1263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1264 "Inserted value `%s' number %llu with size %u into gn090 table\n", 1096 "Inserted value `%s' with size %u into gn090 table\n",
1265 GNUNET_h2s (key), 1097 GNUNET_h2s (key),
1266 vkey,
1267 (unsigned int) size); 1098 (unsigned int) size);
1268#endif 1099#endif
1269 if (size > 0) 1100 if (size > 0)
@@ -1318,18 +1149,11 @@ mysql_plugin_update (void *cls,
1318 ret = prepared_statement_run (plugin, 1149 ret = prepared_statement_run (plugin,
1319 plugin->update_entry, 1150 plugin->update_entry,
1320 NULL, 1151 NULL,
1321 MYSQL_TYPE_LONG, 1152 MYSQL_TYPE_LONG, &delta, GNUNET_NO,
1322 &delta, 1153 MYSQL_TYPE_LONGLONG, &lexpire, GNUNET_YES,
1323 GNUNET_NO, 1154 MYSQL_TYPE_LONGLONG, &lexpire, GNUNET_YES,
1324 MYSQL_TYPE_LONGLONG, 1155 MYSQL_TYPE_LONGLONG, &vkey, GNUNET_YES,
1325 &lexpire, 1156 -1);
1326 GNUNET_YES,
1327 MYSQL_TYPE_LONGLONG,
1328 &lexpire,
1329 GNUNET_YES,
1330 MYSQL_TYPE_LONGLONG,
1331 &vkey,
1332 GNUNET_YES, -1);
1333 if (ret != GNUNET_OK) 1157 if (ret != GNUNET_OK)
1334 { 1158 {
1335 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1159 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1350,8 +1174,8 @@ struct GetContext
1350 unsigned long long expiration; 1174 unsigned long long expiration;
1351 unsigned long long vkey; 1175 unsigned long long vkey;
1352 unsigned long long total; 1176 unsigned long long total;
1353 int off; 1177 unsigned int off;
1354 int count; 1178 unsigned int count;
1355 int have_vhash; 1179 int have_vhash;
1356}; 1180};
1357 1181
@@ -1363,9 +1187,8 @@ get_statement_prepare (void *cls,
1363 struct GetContext *gc = cls; 1187 struct GetContext *gc = cls;
1364 struct Plugin *plugin; 1188 struct Plugin *plugin;
1365 int ret; 1189 int ret;
1366 unsigned int limit_off;
1367 unsigned long hashSize; 1190 unsigned long hashSize;
1368 1191
1369 if (NULL == nrc) 1192 if (NULL == nrc)
1370 { 1193 {
1371 GNUNET_free (gc); 1194 GNUNET_free (gc);
@@ -1375,45 +1198,41 @@ get_statement_prepare (void *cls,
1375 return GNUNET_NO; 1198 return GNUNET_NO;
1376 plugin = nrc->plugin; 1199 plugin = nrc->plugin;
1377 hashSize = sizeof (GNUNET_HashCode); 1200 hashSize = sizeof (GNUNET_HashCode);
1378 if (gc->count + gc->off == gc->total) 1201 if (++gc->off >= gc->total)
1379 nrc->last_vkey = 0; /* back to start */ 1202 gc->off = 0;
1380 if (gc->count == 0)
1381 limit_off = gc->off;
1382 else
1383 limit_off = 0;
1384#if DEBUG_MYSQL 1203#if DEBUG_MYSQL
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1386 "Obtaining result number %d/%lld at offset %d with lvc %llu for GET `%s'\n", 1205 "Obtaining result number %d/%lld at offset %u for GET `%s'\n",
1387 gc->count+1, 1206 gc->count+1,
1388 gc->total, 1207 gc->total,
1389 limit_off, 1208 gc->off,
1390 nrc->last_vkey,
1391 GNUNET_h2s (&gc->key)); 1209 GNUNET_h2s (&gc->key));
1392#endif 1210#endif
1393 if (nrc->type != 0) 1211 if (nrc->type != 0)
1394 { 1212 {
1395 if (gc->have_vhash) 1213 if (gc->have_vhash)
1396 { 1214 {
1397 ret = 1215 ret = prepared_statement_run_select (plugin,
1398 prepared_statement_run_select 1216 plugin->select_entry_by_hash_vhash_and_type,
1399 (plugin, 1217 7, nrc->rbind,
1400 plugin->select_entry_by_hash_vhash_and_type, 6, nrc->rbind, &return_ok, 1218 &return_ok, NULL,
1401 NULL, MYSQL_TYPE_BLOB, &gc->key, hashSize, &hashSize, 1219 MYSQL_TYPE_BLOB, &gc->key, hashSize, &hashSize,
1402 MYSQL_TYPE_BLOB, &gc->vhash, hashSize, &hashSize, 1220 MYSQL_TYPE_BLOB, &gc->vhash, hashSize, &hashSize,
1403 MYSQL_TYPE_LONGLONG, &nrc->last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, 1221 MYSQL_TYPE_LONG, &nrc->type, GNUNET_YES,
1404 &nrc->type, GNUNET_YES, MYSQL_TYPE_LONG, &limit_off, GNUNET_YES, 1222 MYSQL_TYPE_LONG, &gc->off, GNUNET_YES,
1405 -1); 1223 -1);
1406 } 1224 }
1407 else 1225 else
1408 { 1226 {
1409 ret = 1227 ret =
1410 prepared_statement_run_select 1228 prepared_statement_run_select (plugin,
1411 (plugin, 1229 plugin->select_entry_by_hash_and_type,
1412 plugin->select_entry_by_hash_and_type, 6, nrc->rbind, &return_ok, NULL, 1230 7, nrc->rbind,
1413 MYSQL_TYPE_BLOB, &gc->key, hashSize, &hashSize, 1231 &return_ok, NULL,
1414 MYSQL_TYPE_LONGLONG, &nrc->last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, 1232 MYSQL_TYPE_BLOB, &gc->key, hashSize, &hashSize,
1415 &nrc->type, GNUNET_YES, MYSQL_TYPE_LONG, &limit_off, GNUNET_YES, 1233 MYSQL_TYPE_LONG, &nrc->type, GNUNET_YES,
1416 -1); 1234 MYSQL_TYPE_LONG, &gc->off, GNUNET_YES,
1235 -1);
1417 } 1236 }
1418 } 1237 }
1419 else 1238 else
@@ -1421,23 +1240,25 @@ get_statement_prepare (void *cls,
1421 if (gc->have_vhash) 1240 if (gc->have_vhash)
1422 { 1241 {
1423 ret = 1242 ret =
1424 prepared_statement_run_select 1243 prepared_statement_run_select (plugin,
1425 (plugin, 1244 plugin->select_entry_by_hash_and_vhash,
1426 plugin->select_entry_by_hash_and_vhash, 6, nrc->rbind, &return_ok, NULL, 1245 7, nrc->rbind,
1427 MYSQL_TYPE_BLOB, &gc->key, hashSize, &hashSize, MYSQL_TYPE_BLOB, 1246 &return_ok, NULL,
1428 &gc->vhash, hashSize, &hashSize, MYSQL_TYPE_LONGLONG, 1247 MYSQL_TYPE_BLOB, &gc->key, hashSize, &hashSize,
1429 &nrc->last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, &limit_off, 1248 MYSQL_TYPE_BLOB, &gc->vhash, hashSize, &hashSize,
1430 GNUNET_YES, -1); 1249 MYSQL_TYPE_LONG, &gc->off, GNUNET_YES,
1250 -1);
1431 } 1251 }
1432 else 1252 else
1433 { 1253 {
1434 ret = 1254 ret =
1435 prepared_statement_run_select 1255 prepared_statement_run_select (plugin,
1436 (plugin, 1256 plugin->select_entry_by_hash,
1437 plugin->select_entry_by_hash, 6, nrc->rbind, &return_ok, NULL, 1257 7, nrc->rbind,
1438 MYSQL_TYPE_BLOB, &gc->key, hashSize, &hashSize, 1258 &return_ok, NULL,
1439 MYSQL_TYPE_LONGLONG, &nrc->last_vkey, GNUNET_YES, MYSQL_TYPE_LONG, 1259 MYSQL_TYPE_BLOB, &gc->key, hashSize, &hashSize,
1440 &limit_off, GNUNET_YES, -1); 1260 MYSQL_TYPE_LONG, &gc->off, GNUNET_YES,
1261 -1);
1441 } 1262 }
1442 } 1263 }
1443 gc->count++; 1264 gc->count++;
@@ -1446,8 +1267,7 @@ get_statement_prepare (void *cls,
1446 1267
1447 1268
1448/** 1269/**
1449 * Iterate over the results for a particular key 1270 * Iterate over the results for a particular key in the datastore.
1450 * in the datastore.
1451 * 1271 *
1452 * @param cls closure 1272 * @param cls closure
1453 * @param key maybe NULL (to match all entries) 1273 * @param key maybe NULL (to match all entries)
@@ -1457,7 +1277,7 @@ get_statement_prepare (void *cls,
1457 * betwen key and vhash, but for other blocks 1277 * betwen key and vhash, but for other blocks
1458 * there may be! 1278 * there may be!
1459 * @param type entries of which type are relevant? 1279 * @param type entries of which type are relevant?
1460 * Use 0 for any type. 1280 * Use 0 for any type.
1461 * @param iter function to call on each matching value; 1281 * @param iter function to call on each matching value;
1462 * will be called once with a NULL value at the end 1282 * will be called once with a NULL value at the end
1463 * @param iter_cls closure for iter 1283 * @param iter_cls closure for iter
@@ -1492,22 +1312,25 @@ mysql_plugin_get (void *cls,
1492 if (vhash != NULL) 1312 if (vhash != NULL)
1493 { 1313 {
1494 ret = 1314 ret =
1495 prepared_statement_run_select 1315 prepared_statement_run_select (plugin,
1496 (plugin, 1316 plugin->count_entry_by_hash_vhash_and_type,
1497 plugin->count_entry_by_hash_vhash_and_type, 1, cbind, &return_ok, NULL, 1317 1, cbind,
1498 MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, 1318 &return_ok, NULL,
1499 vhash, hashSize, &hashSize, MYSQL_TYPE_LONG, &itype, GNUNET_YES, 1319 MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
1500 -1); 1320 MYSQL_TYPE_BLOB, vhash, hashSize, &hashSize,
1321 MYSQL_TYPE_LONG, &itype, GNUNET_YES,
1322 -1);
1501 } 1323 }
1502 else 1324 else
1503 { 1325 {
1504 ret = 1326 ret =
1505 prepared_statement_run_select 1327 prepared_statement_run_select (plugin,
1506 (plugin, 1328 plugin->count_entry_by_hash_and_type,
1507 plugin->count_entry_by_hash_and_type, 1, cbind, &return_ok, NULL, 1329 1, cbind,
1508 MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_LONG, 1330 &return_ok, NULL,
1509 &itype, GNUNET_YES, -1); 1331 MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
1510 1332 MYSQL_TYPE_LONG, &itype, GNUNET_YES,
1333 -1);
1511 } 1334 }
1512 } 1335 }
1513 else 1336 else
@@ -1515,11 +1338,13 @@ mysql_plugin_get (void *cls,
1515 if (vhash != NULL) 1338 if (vhash != NULL)
1516 { 1339 {
1517 ret = 1340 ret =
1518 prepared_statement_run_select 1341 prepared_statement_run_select (plugin,
1519 (plugin, 1342 plugin->count_entry_by_hash_and_vhash,
1520 plugin->count_entry_by_hash_and_vhash, 1, cbind, &return_ok, NULL, 1343 1, cbind,
1521 MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, 1344 &return_ok, NULL,
1522 vhash, hashSize, &hashSize, -1); 1345 MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
1346 MYSQL_TYPE_BLOB, vhash, hashSize, &hashSize,
1347 -1);
1523 1348
1524 } 1349 }
1525 else 1350 else
@@ -1527,10 +1352,10 @@ mysql_plugin_get (void *cls,
1527 ret = 1352 ret =
1528 prepared_statement_run_select (plugin, 1353 prepared_statement_run_select (plugin,
1529 plugin->count_entry_by_hash, 1354 plugin->count_entry_by_hash,
1530 1, cbind, &return_ok, 1355 1, cbind,
1531 NULL, MYSQL_TYPE_BLOB, 1356 &return_ok, NULL,
1532 key, hashSize, 1357 MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
1533 &hashSize, -1); 1358 -1);
1534 } 1359 }
1535 } 1360 }
1536 if ((ret != GNUNET_OK) || (0 >= total)) 1361 if ((ret != GNUNET_OK) || (0 >= total))
@@ -1564,7 +1389,6 @@ mysql_plugin_get (void *cls,
1564 nrc->dviter_cls = iter_cls; 1389 nrc->dviter_cls = iter_cls;
1565 nrc->prep = &get_statement_prepare; 1390 nrc->prep = &get_statement_prepare;
1566 nrc->prep_cls = gc; 1391 nrc->prep_cls = gc;
1567 nrc->last_vkey = 0;
1568 mysql_plugin_next_request (nrc, GNUNET_NO); 1392 mysql_plugin_next_request (nrc, GNUNET_NO);
1569} 1393}
1570 1394
@@ -1581,29 +1405,19 @@ iterator_zero_prepare (void *cls,
1581 struct NextRequestClosure *nrc) 1405 struct NextRequestClosure *nrc)
1582{ 1406{
1583 struct Plugin *plugin; 1407 struct Plugin *plugin;
1408 int ret;
1584 1409
1585 if (nrc == NULL) 1410 if (nrc == NULL)
1586 return GNUNET_NO; 1411 return GNUNET_NO;
1587 plugin = nrc->plugin; 1412 plugin = nrc->plugin;
1588 return prepared_statement_run_select (plugin, 1413 ret = prepared_statement_run_select (plugin,
1589 plugin->zero_iter, 1414 plugin->zero_iter,
1590 6, 1415 7, nrc->rbind,
1591 nrc->rbind, 1416 &return_ok, NULL,
1592 &return_ok, 1417 MYSQL_TYPE_LONG, &nrc->count, GNUNET_YES,
1593 NULL, 1418 -1);
1594 MYSQL_TYPE_LONGLONG, 1419 nrc->count++;
1595 &nrc->now.abs_value, 1420 return ret;
1596 GNUNET_YES,
1597 MYSQL_TYPE_LONGLONG,
1598 &nrc->last_vkey,
1599 GNUNET_YES,
1600 MYSQL_TYPE_LONGLONG,
1601 &nrc->last_prio,
1602 GNUNET_YES,
1603 MYSQL_TYPE_LONGLONG,
1604 &nrc->last_vkey,
1605 GNUNET_YES,
1606 -1);
1607} 1421}
1608 1422
1609 1423
@@ -1633,8 +1447,6 @@ mysql_plugin_iter_zero_anonymity (void *cls,
1633 nrc->dviter = iter; 1447 nrc->dviter = iter;
1634 nrc->dviter_cls = iter_cls; 1448 nrc->dviter_cls = iter_cls;
1635 nrc->prep = &iterator_zero_prepare; 1449 nrc->prep = &iterator_zero_prepare;
1636 nrc->last_vkey = INT64_MAX; /* MySQL only supports 63 bits, hence signed */
1637 nrc->last_prio = INT32_MAX; /* similar issue... */
1638 mysql_plugin_next_request (nrc, GNUNET_NO); 1450 mysql_plugin_next_request (nrc, GNUNET_NO);
1639} 1451}
1640 1452
@@ -1650,16 +1462,15 @@ replication_prepare (void *cls,
1650 struct NextRequestClosure *nrc) 1462 struct NextRequestClosure *nrc)
1651{ 1463{
1652 struct Plugin *plugin = cls; 1464 struct Plugin *plugin = cls;
1653 long long nt; 1465 unsigned long long nt;
1654 1466
1655 nt = (long long) nrc->now.abs_value; 1467 nt = (unsigned long long) nrc->now.abs_value;
1656 return prepared_statement_run_select 1468 return prepared_statement_run_select (plugin,
1657 (plugin, 1469 plugin->select_replication,
1658 plugin->select_replication, 1470 6, nrc->rbind,
1659 6, nrc->rbind, 1471 &return_ok, NULL,
1660 &return_ok, NULL, 1472 MYSQL_TYPE_LONGLONG, &nt, GNUNET_YES,
1661 MYSQL_TYPE_LONGLONG, &nt, GNUNET_YES, 1473 -1);
1662 -1);
1663} 1474}
1664 1475
1665 1476
@@ -1797,24 +1608,21 @@ libgnunet_plugin_datastore_mysql_init (void *cls)
1797 " expire BIGINT UNSIGNED NOT NULL DEFAULT 0," 1608 " expire BIGINT UNSIGNED NOT NULL DEFAULT 0,"
1798 " hash BINARY(64) NOT NULL DEFAULT ''," 1609 " hash BINARY(64) NOT NULL DEFAULT '',"
1799 " vhash BINARY(64) NOT NULL DEFAULT ''," 1610 " vhash BINARY(64) NOT NULL DEFAULT '',"
1800 " vkey BIGINT UNSIGNED NOT NULL DEFAULT 0," 1611 " value BLOB NOT NULL DEFAULT ''"
1801 " INDEX hash (hash(64))," 1612 " uid BIGINT NOT NULL AUTO_INCREMENT"
1802 " INDEX hash_vhash_vkey (hash(64),vhash(64),vkey)," 1613 " PRIMARY KEY (uid)"
1803 " INDEX hash_vkey (hash(64),vkey)," 1614 " INDEX idx_hash (hash(64)),"
1804 " INDEX vkey (vkey)," 1615 " INDEX idx_hash_uid (hash(64),uid),"
1805 " INDEX prio (prio,vkey)," 1616 " INDEX idx_hash_vhash (hash(64),vhash(64)),"
1806 " INDEX expire (expire,vkey,type)," 1617 " INDEX idx_hash_type_uid (hash(64),type,uid),"
1807 " INDEX anonLevel (anonLevel,prio,vkey,type)" 1618 " INDEX idx_prio (prio),"
1619 " INDEX idx_repl (repl),"
1620 " INDEX idx_expire_prio (expire,prio),"
1621 " INDEX idx_anonLevel_uid (anonLevel,uid)"
1808 ") ENGINE=InnoDB") || 1622 ") ENGINE=InnoDB") ||
1809 MRUNS ("CREATE TABLE IF NOT EXISTS gn072 ("
1810 " vkey BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,"
1811 " value BLOB NOT NULL DEFAULT '') ENGINE=MyISAM") ||
1812 MRUNS ("SET AUTOCOMMIT = 1") || 1623 MRUNS ("SET AUTOCOMMIT = 1") ||
1813 PINIT (plugin->select_value, SELECT_VALUE) ||
1814 PINIT (plugin->delete_value, DELETE_VALUE) ||
1815 PINIT (plugin->insert_value, INSERT_VALUE) ||
1816 PINIT (plugin->insert_entry, INSERT_ENTRY) || 1624 PINIT (plugin->insert_entry, INSERT_ENTRY) ||
1817 PINIT (plugin->delete_entry_by_vkey, DELETE_ENTRY_BY_VKEY) || 1625 PINIT (plugin->delete_entry_by_uid, DELETE_ENTRY_BY_UID) ||
1818 PINIT (plugin->select_entry_by_hash, SELECT_ENTRY_BY_HASH) || 1626 PINIT (plugin->select_entry_by_hash, SELECT_ENTRY_BY_HASH) ||
1819 PINIT (plugin->select_entry_by_hash_and_vhash, SELECT_ENTRY_BY_HASH_AND_VHASH) 1627 PINIT (plugin->select_entry_by_hash_and_vhash, SELECT_ENTRY_BY_HASH_AND_VHASH)
1820 || PINIT (plugin->select_entry_by_hash_and_type, SELECT_ENTRY_BY_HASH_AND_TYPE) 1628 || PINIT (plugin->select_entry_by_hash_and_type, SELECT_ENTRY_BY_HASH_AND_TYPE)
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c
index fd10a38cb..6e77ec364 100644
--- a/src/datastore/plugin_datastore_sqlite.c
+++ b/src/datastore/plugin_datastore_sqlite.c
@@ -181,7 +181,9 @@ create_indices (sqlite3 * dbh)
181 NULL); 181 NULL);
182 sqlite3_exec (dbh, "CREATE INDEX idx_comb ON gn090 (anonLevel ASC,expire ASC,prio,type,hash)", 182 sqlite3_exec (dbh, "CREATE INDEX idx_comb ON gn090 (anonLevel ASC,expire ASC,prio,type,hash)",
183 NULL, NULL, NULL); 183 NULL, NULL, NULL);
184 sqlite3_exec (dbh, "CREATE INDEX expire ON gn090 (expire)", 184 sqlite3_exec (dbh, "CREATE INDEX idx_expire ON gn090 (expire)",
185 NULL, NULL, NULL);
186 sqlite3_exec (dbh, "CREATE INDEX idx_repl ON gn090 (repl)",
185 NULL, NULL, NULL); 187 NULL, NULL, NULL);
186} 188}
187 189
@@ -309,24 +311,6 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
309 sqlite3_finalize (stmt); 311 sqlite3_finalize (stmt);
310 create_indices (plugin->dbh); 312 create_indices (plugin->dbh);
311 313
312 CHECK (SQLITE_OK ==
313 sq_prepare (plugin->dbh,
314 "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn071'",
315 &stmt));
316 if ( (sqlite3_step (stmt) == SQLITE_DONE) &&
317 (sqlite3_exec (plugin->dbh,
318 "CREATE TABLE gn071 ("
319 " key TEXT NOT NULL DEFAULT '',"
320 " value INTEGER NOT NULL DEFAULT 0)", NULL, NULL,
321 NULL) != SQLITE_OK) )
322 {
323 LOG_SQLITE (plugin, NULL,
324 GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec");
325 sqlite3_finalize (stmt);
326 return GNUNET_SYSERR;
327 }
328 sqlite3_finalize (stmt);
329
330 if ((sq_prepare (plugin->dbh, 314 if ((sq_prepare (plugin->dbh,
331 "UPDATE gn090 SET prio = prio + ?, expire = MAX(expire,?) WHERE _ROWID_ = ?", 315 "UPDATE gn090 SET prio = prio + ?, expire = MAX(expire,?) WHERE _ROWID_ = ?",
332 &plugin->updPrio) != SQLITE_OK) || 316 &plugin->updPrio) != SQLITE_OK) ||
@@ -334,7 +318,7 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
334 "UPDATE gn090 SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?", 318 "UPDATE gn090 SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?",
335 &plugin->updRepl) != SQLITE_OK) || 319 &plugin->updRepl) != SQLITE_OK) ||
336 (sq_prepare (plugin->dbh, 320 (sq_prepare (plugin->dbh,
337 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE expire > ?" 321 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090"
338 " ORDER BY repl DESC, Random() LIMIT 1", 322 " ORDER BY repl DESC, Random() LIMIT 1",
339 &plugin->selRepl) != SQLITE_OK) || 323 &plugin->selRepl) != SQLITE_OK) ||
340 (sq_prepare (plugin->dbh, 324 (sq_prepare (plugin->dbh,
@@ -1419,7 +1403,95 @@ execute_get (struct Plugin *plugin,
1419 1403
1420 1404
1421/** 1405/**
1422 * Get a random item for replication. Returns a single, not expired, random item 1406 * Context for 'repl_iter' function.
1407 */
1408struct ReplCtx
1409{
1410
1411 /**
1412 * Plugin handle.
1413 */
1414 struct Plugin *plugin;
1415
1416 /**
1417 * Function to call for the result (or the NULL).
1418 */
1419 PluginIterator iter;
1420
1421 /**
1422 * Closure for iter.
1423 */
1424 void *iter_cls;
1425};
1426
1427
1428/**
1429 * Wrapper for the iterator for 'sqlite_plugin_replication_get'.
1430 * Decrements the replication counter and calls the original
1431 * iterator.
1432 *
1433 * @param cls closure
1434 * @param next_cls closure to pass to the "next" function.
1435 * @param key key for the content
1436 * @param size number of bytes in data
1437 * @param data content stored
1438 * @param type type of the content
1439 * @param priority priority of the content
1440 * @param anonymity anonymity-level for the content
1441 * @param expiration expiration time for the content
1442 * @param uid unique identifier for the datum;
1443 * maybe 0 if no unique identifier is available
1444 *
1445 * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue
1446 * (continue on call to "next", of course),
1447 * GNUNET_NO to delete the item and continue (if supported)
1448 */
1449static int
1450repl_iter (void *cls,
1451 void *next_cls,
1452 const GNUNET_HashCode *key,
1453 uint32_t size,
1454 const void *data,
1455 enum GNUNET_BLOCK_Type type,
1456 uint32_t priority,
1457 uint32_t anonymity,
1458 struct GNUNET_TIME_Absolute expiration,
1459 uint64_t uid)
1460{
1461 struct ReplCtx *rc = cls;
1462 struct Plugin *plugin = rc->plugin;
1463 int ret;
1464
1465 ret = rc->iter (rc->iter_cls,
1466 next_cls, key,
1467 size, data,
1468 type, priority, anonymity, expiration,
1469 uid);
1470 if (NULL != key)
1471 {
1472 sqlite3_bind_int64 (plugin->updRepl, 1, uid);
1473 if (SQLITE_DONE != sqlite3_step (plugin->updRepl))
1474 {
1475 LOG_SQLITE (plugin, NULL,
1476 GNUNET_ERROR_TYPE_ERROR |
1477 GNUNET_ERROR_TYPE_BULK, "sqlite3_step");
1478 if (SQLITE_OK != sqlite3_reset (plugin->updRepl))
1479 LOG_SQLITE (plugin, NULL,
1480 GNUNET_ERROR_TYPE_ERROR |
1481 GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
1482 return GNUNET_SYSERR;
1483 }
1484 if (SQLITE_OK != sqlite3_reset (plugin->delRow))
1485 LOG_SQLITE (plugin, NULL,
1486 GNUNET_ERROR_TYPE_ERROR |
1487 GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
1488 }
1489 return ret;
1490}
1491
1492
1493/**
1494 * Get a random item for replication. Returns a single random item
1423 * from those with the highest replication counters. The item's 1495 * from those with the highest replication counters. The item's
1424 * replication counter is decremented by one IF it was positive before. 1496 * replication counter is decremented by one IF it was positive before.
1425 * Call 'iter' with all values ZERO or NULL if the datastore is empty. 1497 * Call 'iter' with all values ZERO or NULL if the datastore is empty.
@@ -1433,28 +1505,17 @@ sqlite_plugin_replication_get (void *cls,
1433 PluginIterator iter, void *iter_cls) 1505 PluginIterator iter, void *iter_cls)
1434{ 1506{
1435 struct Plugin *plugin = cls; 1507 struct Plugin *plugin = cls;
1436 sqlite3_stmt *stmt; 1508 struct ReplCtx rc;
1437 struct GNUNET_TIME_Absolute now;
1438 1509
1439#if DEBUG_SQLITE 1510#if DEBUG_SQLITE
1440 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1511 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1441 "sqlite", 1512 "sqlite",
1442 "Getting random block based on replication order.\n"); 1513 "Getting random block based on replication order.\n");
1443#endif 1514#endif
1444 stmt = plugin->selRepl; 1515 rc.plugin = plugin;
1445 now = GNUNET_TIME_absolute_get (); 1516 rc.iter = iter;
1446 if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, now.abs_value)) 1517 rc.iter_cls = iter_cls;
1447 { 1518 execute_get (plugin, plugin->selRepl, &repl_iter, &rc);
1448 LOG_SQLITE (plugin, NULL,
1449 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX");
1450 if (SQLITE_OK != sqlite3_reset (stmt))
1451 LOG_SQLITE (plugin, NULL,
1452 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
1453 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0,
1454 GNUNET_TIME_UNIT_ZERO_ABS, 0);
1455 return;
1456 }
1457 execute_get (plugin, stmt, iter, iter_cls);
1458} 1519}
1459 1520
1460 1521