aboutsummaryrefslogtreecommitdiff
path: root/src/datastore
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-04-04 14:04:46 +0000
committerChristian Grothoff <christian@grothoff.org>2011-04-04 14:04:46 +0000
commitae64def363d4eeeaf8acfe586f00ae962da479fb (patch)
tree848d9e9eb579c17d9eef231e4caccc30b42c07f3 /src/datastore
parent0faff46cb3a4cc085ea2876eb6cdccfc59cb2bbe (diff)
downloadgnunet-ae64def363d4eeeaf8acfe586f00ae962da479fb.tar.gz
gnunet-ae64def363d4eeeaf8acfe586f00ae962da479fb.zip
sqlite clean up
Diffstat (limited to 'src/datastore')
-rw-r--r--src/datastore/gnunet-service-datastore.c3
-rw-r--r--src/datastore/perf_plugin_datastore.c5
-rw-r--r--src/datastore/plugin_datastore_sqlite.c482
-rw-r--r--src/datastore/test_datastore_api.c26
4 files changed, 328 insertions, 188 deletions
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c
index 1fa2bbccb..1d092a619 100644
--- a/src/datastore/gnunet-service-datastore.c
+++ b/src/datastore/gnunet-service-datastore.c
@@ -672,7 +672,8 @@ get_next(void *next_cls,
672 plugin->api->next_request (next_cls, GNUNET_YES); 672 plugin->api->next_request (next_cls, GNUNET_YES);
673 return; 673 return;
674 } 674 }
675 plugin->api->next_request (next_cls, GNUNET_NO); 675 if (next_cls != NULL)
676 plugin->api->next_request (next_cls, GNUNET_NO);
676} 677}
677 678
678 679
diff --git a/src/datastore/perf_plugin_datastore.c b/src/datastore/perf_plugin_datastore.c
index f7216a5a6..676fa8d9d 100644
--- a/src/datastore/perf_plugin_datastore.c
+++ b/src/datastore/perf_plugin_datastore.c
@@ -284,6 +284,11 @@ test (void *cls,
284 struct CpsRunContext *crc = cls; 284 struct CpsRunContext *crc = cls;
285 int j; 285 int j;
286 286
287 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
288 {
289 crc->phase = RP_DONE;
290 ok = 1;
291 }
287 switch (crc->phase) 292 switch (crc->phase)
288 { 293 {
289 case RP_PUT: 294 case RP_PUT:
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c
index b05a0a9c1..f14855219 100644
--- a/src/datastore/plugin_datastore_sqlite.c
+++ b/src/datastore/plugin_datastore_sqlite.c
@@ -28,35 +28,17 @@
28#include "gnunet_datastore_plugin.h" 28#include "gnunet_datastore_plugin.h"
29#include <sqlite3.h> 29#include <sqlite3.h>
30 30
31/**
32 * Enable or disable logging debug messages.
33 */
31#define DEBUG_SQLITE GNUNET_NO 34#define DEBUG_SQLITE GNUNET_NO
32 35
33
34/** 36/**
35 * Log an error message at log-level 'level' that indicates 37 * We allocate items on the stack at times. To prevent a stack
36 * a failure of the command 'cmd' on file 'filename' 38 * overflow, we impose a limit on the maximum size for the data per
37 * with the message given by strerror(errno). 39 * item. 64k should be enough.
38 */ 40 */
39#define LOG_SQLITE(db, msg, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); if (msg != NULL) GNUNET_asprintf(msg, _("`%s' failed at %s:%u with error: %s"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) 41#define MAX_ITEM_SIZE 65536
40
41
42#define SELECT_IT_NON_ANONYMOUS_1 \
43 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (prio = ?1 AND expire > %llu AND anonLevel = 0 AND hash < ?2) "\
44 " ORDER BY hash DESC LIMIT 1"
45
46#define SELECT_IT_NON_ANONYMOUS_2 \
47 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (prio < ?1 AND expire > %llu AND anonLevel = 0)"\
48 " ORDER BY prio DESC, hash DESC LIMIT 1"
49
50
51#define SELECT_IT_REPLICATION_ORDER \
52 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire > ?1) "\
53 " ORDER BY repl DESC, Random() LIMIT 1"
54
55#define SELECT_IT_EXPIRATION_ORDER \
56 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire < ?1) "\
57 " OR NOT EXISTS (SELECT 1 from gn090 WHERE (expire < ?1)) "\
58 " ORDER BY prio ASC LIMIT 1"
59
60 42
61/** 43/**
62 * After how many ms "busy" should a DB operation fail for good? 44 * After how many ms "busy" should a DB operation fail for good?
@@ -71,6 +53,14 @@
71#define BUSY_TIMEOUT_MS 250 53#define BUSY_TIMEOUT_MS 250
72 54
73 55
56/**
57 * Log an error message at log-level 'level' that indicates
58 * a failure of the command 'cmd' on file 'filename'
59 * with the message given by strerror(errno).
60 */
61#define LOG_SQLITE(db, msg, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); if (msg != NULL) GNUNET_asprintf(msg, _("`%s' failed at %s:%u with error: %s"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
62
63
74 64
75/** 65/**
76 * Context for all functions in this plugin. 66 * Context for all functions in this plugin.
@@ -155,15 +145,17 @@ sq_prepare (sqlite3 * dbh,
155{ 145{
156 char *dummy; 146 char *dummy;
157 int result; 147 int result;
148
158 result = sqlite3_prepare_v2 (dbh, 149 result = sqlite3_prepare_v2 (dbh,
159 zSql, 150 zSql,
160 strlen (zSql), 151 strlen (zSql),
161 ppStmt, 152 ppStmt,
162 (const char **) &dummy); 153 (const char **) &dummy);
163#if DEBUG_SQLITE 154#if DEBUG_SQLITE && 0
164 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 155 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
165 "sqlite", 156 "sqlite",
166 "Prepared %p: %d\n", 157 "Prepared `%s' / %p: %d\n",
158 zSql,
167 *ppStmt, 159 *ppStmt,
168 result); 160 result);
169#endif 161#endif
@@ -194,7 +186,6 @@ create_indices (sqlite3 * dbh)
194} 186}
195 187
196 188
197
198#if 0 189#if 0
199#define CHECK(a) GNUNET_break(a) 190#define CHECK(a) GNUNET_break(a)
200#define ENULL NULL 191#define ENULL NULL
@@ -205,8 +196,6 @@ create_indices (sqlite3 * dbh)
205#endif 196#endif
206 197
207 198
208
209
210/** 199/**
211 * Initialize the database connections and associated 200 * Initialize the database connections and associated
212 * data structures (create tables and indices 201 * data structures (create tables and indices
@@ -341,10 +330,13 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
341 "_ROWID_ = ?", 330 "_ROWID_ = ?",
342 &plugin->updRepl) != SQLITE_OK) || 331 &plugin->updRepl) != SQLITE_OK) ||
343 (sq_prepare (plugin->dbh, 332 (sq_prepare (plugin->dbh,
344 SELECT_IT_REPLICATION_ORDER, 333 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire > ?1) "
334 " ORDER BY repl DESC, Random() LIMIT 1",
345 &plugin->selRepl) != SQLITE_OK) || 335 &plugin->selRepl) != SQLITE_OK) ||
346 (sq_prepare (plugin->dbh, 336 (sq_prepare (plugin->dbh,
347 SELECT_IT_EXPIRATION_ORDER, 337 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire < ?1) "
338 " OR NOT EXISTS (SELECT 1 from gn090 WHERE (expire < ?1)) "
339 " ORDER BY prio ASC LIMIT 1",
348 &plugin->selExpi) != SQLITE_OK) || 340 &plugin->selExpi) != SQLITE_OK) ||
349 (sq_prepare (plugin->dbh, 341 (sq_prepare (plugin->dbh,
350 "INSERT INTO gn090 (repl, type, prio, " 342 "INSERT INTO gn090 (repl, type, prio, "
@@ -542,7 +534,7 @@ struct NextContext
542/** 534/**
543 * Continuation of "sqlite_next_request". 535 * Continuation of "sqlite_next_request".
544 * 536 *
545 * @param cls the next context 537 * @param cls the 'struct NextContext*'
546 * @param tc the task context (unused) 538 * @param tc the task context (unused)
547 */ 539 */
548static void 540static void
@@ -554,12 +546,12 @@ sqlite_next_request_cont (void *cls,
554 unsigned long long rowid; 546 unsigned long long rowid;
555 int ret; 547 int ret;
556 unsigned int size; 548 unsigned int size;
549 unsigned int hsize;
557 uint32_t anonymity; 550 uint32_t anonymity;
558 uint32_t priority; 551 uint32_t priority;
559 enum GNUNET_BLOCK_Type type; 552 enum GNUNET_BLOCK_Type type;
560 const GNUNET_HashCode *key; 553 const GNUNET_HashCode *key;
561 struct GNUNET_TIME_Absolute expiration; 554 struct GNUNET_TIME_Absolute expiration;
562 char data[GNUNET_SERVER_MAX_MESSAGE_SIZE];
563 555
564 plugin = nc->plugin; 556 plugin = nc->plugin;
565 plugin->next_task = GNUNET_SCHEDULER_NO_TASK; 557 plugin->next_task = GNUNET_SCHEDULER_NO_TASK;
@@ -568,6 +560,12 @@ sqlite_next_request_cont (void *cls,
568 (GNUNET_OK != (nc->prep(nc->prep_cls, 560 (GNUNET_OK != (nc->prep(nc->prep_cls,
569 nc))) ) 561 nc))) )
570 { 562 {
563#if DEBUG_SQLITE
564 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
565 "sqlite",
566 "Iteration completes after %u results\n",
567 nc->count);
568#endif
571 END: 569 END:
572 nc->iter (nc->iter_cls, 570 nc->iter (nc->iter_cls,
573 NULL, NULL, 0, NULL, 0, 0, 0, 571 NULL, NULL, 0, NULL, 0, 0, 0,
@@ -581,15 +579,13 @@ sqlite_next_request_cont (void *cls,
581 priority = sqlite3_column_int (nc->stmt, 1); 579 priority = sqlite3_column_int (nc->stmt, 1);
582 anonymity = sqlite3_column_int (nc->stmt, 2); 580 anonymity = sqlite3_column_int (nc->stmt, 2);
583 expiration.abs_value = sqlite3_column_int64 (nc->stmt, 3); 581 expiration.abs_value = sqlite3_column_int64 (nc->stmt, 3);
582 hsize = sqlite3_column_bytes (nc->stmt, 4);
584 key = sqlite3_column_blob (nc->stmt, 4); 583 key = sqlite3_column_blob (nc->stmt, 4);
585 size = sqlite3_column_bytes (nc->stmt, 5); 584 size = sqlite3_column_bytes (nc->stmt, 5);
586 memcpy (data, sqlite3_column_blob (nc->stmt, 5), size);
587 rowid = sqlite3_column_int64 (nc->stmt, 6); 585 rowid = sqlite3_column_int64 (nc->stmt, 6);
588 if (sqlite3_column_bytes (nc->stmt, 4) != sizeof (GNUNET_HashCode)) 586 if (hsize != sizeof (GNUNET_HashCode))
589 { 587 {
590 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, 588 GNUNET_break (0);
591 "sqlite",
592 _("Invalid data in database. Trying to fix (by deletion).\n"));
593 if (SQLITE_OK != sqlite3_reset (nc->stmt)) 589 if (SQLITE_OK != sqlite3_reset (nc->stmt))
594 LOG_SQLITE (plugin, NULL, 590 LOG_SQLITE (plugin, NULL,
595 GNUNET_ERROR_TYPE_ERROR | 591 GNUNET_ERROR_TYPE_ERROR |
@@ -599,37 +595,55 @@ sqlite_next_request_cont (void *cls,
599 - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); 595 - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
600 goto END; 596 goto END;
601 } 597 }
602 nc->count++; 598#if DEBUG_SQLITE
603 nc->last_rowid = rowid; 599 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
604 nc->lastPriority = priority; 600 "sqlite",
605 nc->lastKey = *key; 601 "Iterator returns value with type %u/key `%s'/priority %u/expiration %llu (%lld).\n",
606 if (SQLITE_OK != sqlite3_reset (nc->stmt)) 602 type,
607 LOG_SQLITE (plugin, NULL, 603 GNUNET_h2s(key),
608 GNUNET_ERROR_TYPE_ERROR | 604 priority,
609 GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); 605 (unsigned long long) GNUNET_TIME_absolute_get_remaining (expiration).rel_value,
610 ret = nc->iter (nc->iter_cls, nc, 606 (long long) expiration.abs_value);
611 key, 607#endif
612 size, data, 608 if (size > MAX_ITEM_SIZE)
613 type, priority, 609 {
614 anonymity, expiration, 610 GNUNET_break (0);
615 rowid); 611 if (SQLITE_OK != sqlite3_reset (nc->stmt))
612 LOG_SQLITE (plugin, NULL,
613 GNUNET_ERROR_TYPE_ERROR |
614 GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
615 if (GNUNET_OK == delete_by_rowid (plugin, rowid))
616 plugin->env->duc (plugin->env->cls,
617 - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
618 goto END;
619 }
620 {
621 char data[size];
622
623 memcpy (data, sqlite3_column_blob (nc->stmt, 5), size);
624 nc->count++;
625 nc->last_rowid = rowid;
626 nc->lastPriority = priority;
627 nc->lastKey = *key;
628 if (SQLITE_OK != sqlite3_reset (nc->stmt))
629 LOG_SQLITE (plugin, NULL,
630 GNUNET_ERROR_TYPE_ERROR |
631 GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
632 ret = nc->iter (nc->iter_cls, nc,
633 &nc->lastKey,
634 size, data,
635 type, priority,
636 anonymity, expiration,
637 rowid);
638 }
616 switch (ret) 639 switch (ret)
617 { 640 {
618 case GNUNET_SYSERR: 641 case GNUNET_SYSERR:
619 nc->end_it = GNUNET_YES; 642 nc->end_it = GNUNET_YES;
620 break; 643 break;
621 case GNUNET_NO: 644 case GNUNET_NO:
622#if DEBUG_SQLITE
623 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
624 "sqlite",
625 "Asked to remove entry %llu (%u bytes)\n",
626 (unsigned long long) rowid,
627 size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
628#endif
629 if (GNUNET_OK == delete_by_rowid (plugin, rowid)) 645 if (GNUNET_OK == delete_by_rowid (plugin, rowid))
630 { 646 {
631 plugin->env->duc (plugin->env->cls,
632 - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
633#if DEBUG_SQLITE 647#if DEBUG_SQLITE
634 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 648 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
635 "sqlite", 649 "sqlite",
@@ -637,6 +651,8 @@ sqlite_next_request_cont (void *cls,
637 (unsigned long long) rowid, 651 (unsigned long long) rowid,
638 size + GNUNET_DATASTORE_ENTRY_OVERHEAD); 652 size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
639#endif 653#endif
654 plugin->env->duc (plugin->env->cls,
655 - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
640 } 656 }
641 break; 657 break;
642 case GNUNET_YES: 658 case GNUNET_YES:
@@ -648,9 +664,8 @@ sqlite_next_request_cont (void *cls,
648 664
649 665
650/** 666/**
651 * Function invoked on behalf of a "PluginIterator" 667 * Function invoked on behalf of a "PluginIterator" asking the
652 * asking the database plugin to call the iterator 668 * database plugin to call the iterator with the next item.
653 * with the next item.
654 * 669 *
655 * @param next_cls whatever argument was given 670 * @param next_cls whatever argument was given
656 * to the PluginIterator as "next_cls". 671 * to the PluginIterator as "next_cls".
@@ -702,9 +717,12 @@ sqlite_plugin_put (void *cls,
702{ 717{
703 struct Plugin *plugin = cls; 718 struct Plugin *plugin = cls;
704 int n; 719 int n;
720 int ret;
705 sqlite3_stmt *stmt; 721 sqlite3_stmt *stmt;
706 GNUNET_HashCode vhash; 722 GNUNET_HashCode vhash;
707 723
724 if (size > MAX_ITEM_SIZE)
725 return GNUNET_SYSERR;
708#if DEBUG_SQLITE 726#if DEBUG_SQLITE
709 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 727 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
710 "sqlite", 728 "sqlite",
@@ -744,10 +762,6 @@ sqlite_plugin_put (void *cls,
744 switch (n) 762 switch (n)
745 { 763 {
746 case SQLITE_DONE: 764 case SQLITE_DONE:
747 if (SQLITE_OK != sqlite3_reset (stmt))
748 LOG_SQLITE (plugin, NULL,
749 GNUNET_ERROR_TYPE_ERROR |
750 GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
751 plugin->env->duc (plugin->env->cls, 765 plugin->env->duc (plugin->env->cls,
752 size + GNUNET_DATASTORE_ENTRY_OVERHEAD); 766 size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
753#if DEBUG_SQLITE 767#if DEBUG_SQLITE
@@ -756,24 +770,33 @@ sqlite_plugin_put (void *cls,
756 "Stored new entry (%u bytes)\n", 770 "Stored new entry (%u bytes)\n",
757 size + GNUNET_DATASTORE_ENTRY_OVERHEAD); 771 size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
758#endif 772#endif
759 return GNUNET_OK; 773 ret = GNUNET_OK;
774 break;
760 case SQLITE_BUSY: 775 case SQLITE_BUSY:
761 GNUNET_break (0); 776 GNUNET_break (0);
762 LOG_SQLITE (plugin, msg, 777 LOG_SQLITE (plugin, msg,
763 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 778 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
764 "sqlite3_step"); 779 "sqlite3_step");
765 sqlite3_reset (stmt); 780 ret = GNUNET_SYSERR;
766 return GNUNET_SYSERR; 781 break;
767 default: 782 default:
768 LOG_SQLITE (plugin, msg, 783 LOG_SQLITE (plugin, msg,
769 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 784 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
770 "sqlite3_step"); 785 "sqlite3_step");
771 sqlite3_reset (stmt); 786 if (SQLITE_OK != sqlite3_reset (stmt))
787 LOG_SQLITE (plugin, NULL,
788 GNUNET_ERROR_TYPE_ERROR |
789 GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
772 database_shutdown (plugin); 790 database_shutdown (plugin);
773 database_setup (plugin->env->cfg, 791 database_setup (plugin->env->cfg,
774 plugin); 792 plugin);
775 return GNUNET_SYSERR; 793 return GNUNET_SYSERR;
776 } 794 }
795 if (SQLITE_OK != sqlite3_reset (stmt))
796 LOG_SQLITE (plugin, NULL,
797 GNUNET_ERROR_TYPE_ERROR |
798 GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
799 return ret;
777} 800}
778 801
779 802
@@ -840,15 +863,15 @@ sqlite_plugin_update (void *cls,
840/** 863/**
841 * Internal context for an iteration. 864 * Internal context for an iteration.
842 */ 865 */
843struct IterContext 866struct ZeroIterContext
844{ 867{
845 /** 868 /**
846 * FIXME. 869 * First iterator statement for zero-anonymity iteration.
847 */ 870 */
848 sqlite3_stmt *stmt_1; 871 sqlite3_stmt *stmt_1;
849 872
850 /** 873 /**
851 * FIXME. 874 * Second iterator statement for zero-anonymity iteration.
852 */ 875 */
853 sqlite3_stmt *stmt_2; 876 sqlite3_stmt *stmt_2;
854 877
@@ -862,17 +885,17 @@ struct IterContext
862/** 885/**
863 * Prepare our SQL query to obtain the next record from the database. 886 * Prepare our SQL query to obtain the next record from the database.
864 * 887 *
865 * @param cls our "struct IterContext" 888 * @param cls our "struct ZeroIterContext"
866 * @param nc NULL to terminate the iteration, otherwise our context for 889 * @param nc NULL to terminate the iteration, otherwise our context for
867 * getting the next result. 890 * getting the next result.
868 * @return GNUNET_OK on success, GNUNET_NO if there are no more results, 891 * @return GNUNET_OK on success, GNUNET_NO if there are no more results,
869 * GNUNET_SYSERR on error (or end of iteration) 892 * GNUNET_SYSERR on error (or end of iteration)
870 */ 893 */
871static int 894static int
872iter_next_prepare (void *cls, 895zero_iter_next_prepare (void *cls,
873 struct NextContext *nc) 896 struct NextContext *nc)
874{ 897{
875 struct IterContext *ic = cls; 898 struct ZeroIterContext *ic = cls;
876 struct Plugin *plugin; 899 struct Plugin *plugin;
877 int ret; 900 int ret;
878 901
@@ -886,25 +909,30 @@ iter_next_prepare (void *cls,
886 sqlite3_finalize (ic->stmt_2); 909 sqlite3_finalize (ic->stmt_2);
887 return GNUNET_SYSERR; 910 return GNUNET_SYSERR;
888 } 911 }
889 sqlite3_reset (ic->stmt_1);
890 sqlite3_reset (ic->stmt_2);
891 plugin = nc->plugin; 912 plugin = nc->plugin;
913
914 /* first try iter 1 */
892#if DEBUG_SQLITE 915#if DEBUG_SQLITE
893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 916 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
894 "Restricting to results larger than the last priority %u\n", 917 "Restricting to results larger than the last priority %u and key `%s'\n",
895 nc->lastPriority); 918 nc->lastPriority,
896#endif 919 GNUNET_h2s (&nc->lastKey));
897 sqlite3_bind_int (ic->stmt_1, 1, nc->lastPriority);
898 sqlite3_bind_int (ic->stmt_2, 1, nc->lastPriority);
899#if DEBUG_SQLITE
900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
901 "Restricting to results larger than the last key `%s'\n",
902 GNUNET_h2s(&nc->lastKey));
903#endif 920#endif
904 sqlite3_bind_blob (ic->stmt_1, 2, 921 if ( (SQLITE_OK != sqlite3_bind_int (ic->stmt_1, 1, nc->lastPriority)) ||
905 &nc->lastKey, 922 (SQLITE_OK != sqlite3_bind_blob (ic->stmt_1, 2,
906 sizeof (GNUNET_HashCode), 923 &nc->lastKey,
907 SQLITE_TRANSIENT); 924 sizeof (GNUNET_HashCode),
925 SQLITE_TRANSIENT)) )
926 {
927 LOG_SQLITE (plugin, NULL,
928 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX");
929 if (SQLITE_OK != sqlite3_reset (ic->stmt_1))
930 LOG_SQLITE (plugin, NULL,
931 GNUNET_ERROR_TYPE_ERROR |
932 GNUNET_ERROR_TYPE_BULK,
933 "sqlite3_reset");
934 return GNUNET_SYSERR;
935 }
908 if (SQLITE_ROW == (ret = sqlite3_step (ic->stmt_1))) 936 if (SQLITE_ROW == (ret = sqlite3_step (ic->stmt_1)))
909 { 937 {
910#if DEBUG_SQLITE 938#if DEBUG_SQLITE
@@ -920,13 +948,26 @@ iter_next_prepare (void *cls,
920 GNUNET_ERROR_TYPE_ERROR | 948 GNUNET_ERROR_TYPE_ERROR |
921 GNUNET_ERROR_TYPE_BULK, 949 GNUNET_ERROR_TYPE_BULK,
922 "sqlite3_step"); 950 "sqlite3_step");
951 if (SQLITE_OK != sqlite3_reset (ic->stmt_1))
952 LOG_SQLITE (plugin, NULL,
953 GNUNET_ERROR_TYPE_ERROR |
954 GNUNET_ERROR_TYPE_BULK,
955 "sqlite3_reset");
923 return GNUNET_SYSERR; 956 return GNUNET_SYSERR;
924 } 957 }
925 if (SQLITE_OK != sqlite3_reset (ic->stmt_1)) 958 if (SQLITE_OK != sqlite3_reset (ic->stmt_1))
926 LOG_SQLITE (plugin, NULL, 959 LOG_SQLITE (plugin, NULL,
927 GNUNET_ERROR_TYPE_ERROR | 960 GNUNET_ERROR_TYPE_ERROR |
928 GNUNET_ERROR_TYPE_BULK, 961 GNUNET_ERROR_TYPE_BULK,
929 "sqlite3_reset"); 962 "sqlite3_reset");
963
964 /* now try iter 2 */
965 if (SQLITE_OK != sqlite3_bind_int (ic->stmt_2, 1, nc->lastPriority))
966 {
967 LOG_SQLITE (plugin, NULL,
968 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX");
969 return GNUNET_SYSERR;
970 }
930 if (SQLITE_ROW == (ret = sqlite3_step (ic->stmt_2))) 971 if (SQLITE_ROW == (ret = sqlite3_step (ic->stmt_2)))
931 { 972 {
932#if DEBUG_SQLITE 973#if DEBUG_SQLITE
@@ -942,6 +983,11 @@ iter_next_prepare (void *cls,
942 GNUNET_ERROR_TYPE_ERROR | 983 GNUNET_ERROR_TYPE_ERROR |
943 GNUNET_ERROR_TYPE_BULK, 984 GNUNET_ERROR_TYPE_BULK,
944 "sqlite3_step"); 985 "sqlite3_step");
986 if (SQLITE_OK != sqlite3_reset (ic->stmt_2))
987 LOG_SQLITE (plugin, NULL,
988 GNUNET_ERROR_TYPE_ERROR |
989 GNUNET_ERROR_TYPE_BULK,
990 "sqlite3_reset");
945 return GNUNET_SYSERR; 991 return GNUNET_SYSERR;
946 } 992 }
947 if (SQLITE_OK != sqlite3_reset (ic->stmt_2)) 993 if (SQLITE_OK != sqlite3_reset (ic->stmt_2))
@@ -977,13 +1023,16 @@ sqlite_plugin_iter_zero_anonymity (void *cls,
977 struct Plugin *plugin = cls; 1023 struct Plugin *plugin = cls;
978 struct GNUNET_TIME_Absolute now; 1024 struct GNUNET_TIME_Absolute now;
979 struct NextContext *nc; 1025 struct NextContext *nc;
980 struct IterContext *ic; 1026 struct ZeroIterContext *ic;
981 sqlite3_stmt *stmt_1; 1027 sqlite3_stmt *stmt_1;
982 sqlite3_stmt *stmt_2; 1028 sqlite3_stmt *stmt_2;
983 char *q; 1029 char *q;
984 1030
985 now = GNUNET_TIME_absolute_get (); 1031 now = GNUNET_TIME_absolute_get ();
986 GNUNET_asprintf (&q, SELECT_IT_NON_ANONYMOUS_1, 1032 GNUNET_asprintf (&q,
1033 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 "
1034 "WHERE (prio = ?1 AND expire > %llu AND anonLevel = 0 AND hash < ?2) "
1035 "ORDER BY hash DESC LIMIT 1",
987 (unsigned long long) now.abs_value); 1036 (unsigned long long) now.abs_value);
988 if (sq_prepare (plugin->dbh, q, &stmt_1) != SQLITE_OK) 1037 if (sq_prepare (plugin->dbh, q, &stmt_1) != SQLITE_OK)
989 { 1038 {
@@ -995,7 +1044,10 @@ sqlite_plugin_iter_zero_anonymity (void *cls,
995 return; 1044 return;
996 } 1045 }
997 GNUNET_free (q); 1046 GNUNET_free (q);
998 GNUNET_asprintf (&q, SELECT_IT_NON_ANONYMOUS_2, 1047 GNUNET_asprintf (&q,
1048 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 "
1049 "WHERE (prio < ?1 AND expire > %llu AND anonLevel = 0) "
1050 "ORDER BY prio DESC, hash DESC LIMIT 1",
999 (unsigned long long) now.abs_value); 1051 (unsigned long long) now.abs_value);
1000 if (sq_prepare (plugin->dbh, q, &stmt_2) != SQLITE_OK) 1052 if (sq_prepare (plugin->dbh, q, &stmt_2) != SQLITE_OK)
1001 { 1053 {
@@ -1009,29 +1061,52 @@ sqlite_plugin_iter_zero_anonymity (void *cls,
1009 } 1061 }
1010 GNUNET_free (q); 1062 GNUNET_free (q);
1011 nc = GNUNET_malloc (sizeof(struct NextContext) + 1063 nc = GNUNET_malloc (sizeof(struct NextContext) +
1012 sizeof(struct IterContext)); 1064 sizeof(struct ZeroIterContext));
1013 nc->plugin = plugin; 1065 nc->plugin = plugin;
1014 nc->iter = iter; 1066 nc->iter = iter;
1015 nc->iter_cls = iter_cls; 1067 nc->iter_cls = iter_cls;
1016 nc->stmt = NULL; 1068 nc->stmt = NULL;
1017 ic = (struct IterContext*) &nc[1]; 1069 ic = (struct ZeroIterContext*) &nc[1];
1018 ic->stmt_1 = stmt_1; 1070 ic->stmt_1 = stmt_1;
1019 ic->stmt_2 = stmt_2; 1071 ic->stmt_2 = stmt_2;
1020 ic->type = type; 1072 ic->type = type;
1021 nc->prep = &iter_next_prepare; 1073 nc->prep = &zero_iter_next_prepare;
1022 nc->prep_cls = ic; 1074 nc->prep_cls = ic;
1023 nc->lastPriority = 0x7FFFFFFF; 1075 nc->lastPriority = INT32_MAX;
1024 memset (&nc->lastKey, 255, sizeof (GNUNET_HashCode)); 1076 memset (&nc->lastKey, 255, sizeof (GNUNET_HashCode));
1025 sqlite_next_request (nc, GNUNET_NO); 1077 sqlite_next_request (nc, GNUNET_NO);
1026} 1078}
1027 1079
1028 1080
1029/** 1081/**
1082 * Closure for 'all_next_prepare'.
1083 */
1084struct IterateAllContext
1085{
1086
1087 /**
1088 * Offset for the current result.
1089 */
1090 unsigned int off;
1091
1092 /**
1093 * Requested block type.
1094 */
1095 enum GNUNET_BLOCK_Type type;
1096
1097 /**
1098 * Our prepared statement.
1099 */
1100 sqlite3_stmt *stmt;
1101};
1102
1103
1104/**
1030 * Call sqlite using the already prepared query to get 1105 * Call sqlite using the already prepared query to get
1031 * the next result. 1106 * the next result.
1032 * 1107 *
1033 * @param cls context with the prepared query 1108 * @param cls context with the prepared query (of type 'struct IterateAllContext')
1034 * @param nc context with the prepared query 1109 * @param nc generic context with the prepared query
1035 * @return GNUNET_OK on success, GNUNET_SYSERR on error, GNUNET_NO if 1110 * @return GNUNET_OK on success, GNUNET_SYSERR on error, GNUNET_NO if
1036 * there are no more results 1111 * there are no more results
1037 */ 1112 */
@@ -1039,8 +1114,10 @@ static int
1039all_next_prepare (void *cls, 1114all_next_prepare (void *cls,
1040 struct NextContext *nc) 1115 struct NextContext *nc)
1041{ 1116{
1117 struct IterateAllContext *iac = cls;
1042 struct Plugin *plugin; 1118 struct Plugin *plugin;
1043 int ret; 1119 int ret;
1120 unsigned int sqoff;
1044 1121
1045 if (nc == NULL) 1122 if (nc == NULL)
1046 { 1123 {
@@ -1048,13 +1125,26 @@ all_next_prepare (void *cls,
1048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1125 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1049 "Asked to clean up iterator state.\n"); 1126 "Asked to clean up iterator state.\n");
1050#endif 1127#endif
1051 nc = (struct NextContext *)cls; 1128 if (NULL != iac->stmt)
1052 if (nc->stmt) 1129 {
1053 sqlite3_finalize (nc->stmt); 1130 sqlite3_finalize (iac->stmt);
1054 nc->stmt = NULL; 1131 iac->stmt = NULL;
1132 }
1055 return GNUNET_SYSERR; 1133 return GNUNET_SYSERR;
1056 } 1134 }
1057 plugin = nc->plugin; 1135 plugin = nc->plugin;
1136 sqoff = 1;
1137 ret = SQLITE_OK;
1138 if (iac->type != 0)
1139 ret = sqlite3_bind_int (nc->stmt, sqoff++, iac->type);
1140 if (SQLITE_OK == ret)
1141 ret = sqlite3_bind_int64 (nc->stmt, sqoff++, iac->off++);
1142 if (ret != SQLITE_OK)
1143 {
1144 LOG_SQLITE (plugin, NULL,
1145 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX");
1146 return GNUNET_SYSERR;
1147 }
1058 ret = sqlite3_step (nc->stmt); 1148 ret = sqlite3_step (nc->stmt);
1059 switch (ret) 1149 switch (ret)
1060 { 1150 {
@@ -1091,11 +1181,15 @@ sqlite_plugin_iter_all_now (void *cls,
1091{ 1181{
1092 struct Plugin *plugin = cls; 1182 struct Plugin *plugin = cls;
1093 struct NextContext *nc; 1183 struct NextContext *nc;
1184 struct IterateAllContext *iac;
1094 sqlite3_stmt *stmt; 1185 sqlite3_stmt *stmt;
1186 const char *q;
1095 1187
1096 if (sq_prepare (plugin->dbh, 1188 if (type == 0)
1097 "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090", 1189 q = "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?";
1098 &stmt) != SQLITE_OK) 1190 else
1191 q = "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE type=? ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?";
1192 if (sq_prepare (plugin->dbh, q, &stmt) != SQLITE_OK)
1099 { 1193 {
1100 LOG_SQLITE (plugin, NULL, 1194 LOG_SQLITE (plugin, NULL,
1101 GNUNET_ERROR_TYPE_ERROR | 1195 GNUNET_ERROR_TYPE_ERROR |
@@ -1103,66 +1197,77 @@ sqlite_plugin_iter_all_now (void *cls,
1103 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1197 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1104 return; 1198 return;
1105 } 1199 }
1106 nc = GNUNET_malloc (sizeof(struct NextContext)); 1200 nc = GNUNET_malloc (sizeof(struct NextContext) +
1201 sizeof(struct IterateAllContext));
1202 iac = (struct IterateAllContext*) &nc[1];
1107 nc->plugin = plugin; 1203 nc->plugin = plugin;
1108 nc->iter = iter; 1204 nc->iter = iter;
1109 nc->iter_cls = iter_cls; 1205 nc->iter_cls = iter_cls;
1110 nc->stmt = stmt; 1206 nc->stmt = stmt;
1111 nc->prep = &all_next_prepare; 1207 nc->prep = &all_next_prepare;
1112 nc->prep_cls = nc; 1208 nc->prep_cls = iac;
1209 iac->off = 0;
1210 iac->type = type;
1211 iac->stmt = stmt; /* alias used for freeing at the end */
1113 sqlite_next_request (nc, GNUNET_NO); 1212 sqlite_next_request (nc, GNUNET_NO);
1114} 1213}
1115 1214
1116 1215
1117/** 1216/**
1118 * FIXME. 1217 * Context for get_next_prepare.
1119 */ 1218 */
1120struct GetNextContext 1219struct GetNextContext
1121{ 1220{
1122 1221
1123 /** 1222 /**
1124 * FIXME. 1223 * Our prepared statement.
1125 */ 1224 */
1126 int total; 1225 sqlite3_stmt *stmt;
1127 1226
1128 /** 1227 /**
1129 * FIXME. 1228 * Plugin handle.
1130 */ 1229 */
1131 int off; 1230 struct Plugin *plugin;
1132 1231
1133 /** 1232 /**
1134 * FIXME. 1233 * Key for the query.
1135 */ 1234 */
1136 int have_vhash; 1235 GNUNET_HashCode key;
1137 1236
1138 /** 1237 /**
1139 * FIXME. 1238 * Vhash for the query.
1140 */ 1239 */
1141 unsigned int type; 1240 GNUNET_HashCode vhash;
1142 1241
1143 /** 1242 /**
1144 * FIXME. 1243 * Expected total number of results.
1145 */ 1244 */
1146 sqlite3_stmt *stmt; 1245 unsigned int total;
1147 1246
1148 /** 1247 /**
1149 * FIXME. 1248 * Offset to add for the selected result.
1150 */ 1249 */
1151 GNUNET_HashCode key; 1250 unsigned int off;
1152 1251
1153 /** 1252 /**
1154 * FIXME. 1253 * Is vhash set?
1155 */ 1254 */
1156 GNUNET_HashCode vhash; 1255 int have_vhash;
1157};
1158 1256
1257 /**
1258 * Desired block type.
1259 */
1260 enum GNUNET_BLOCK_Type type;
1261
1262};
1159 1263
1160 1264
1161/** 1265/**
1162 * FIXME. 1266 * Prepare the stmt in 'nc' for the next round of execution, selecting the
1267 * next return value.
1163 * 1268 *
1164 * @param cls our "struct GetNextContext*" 1269 * @param cls our "struct GetNextContext*"
1165 * @param nc FIXME 1270 * @param nc the general context
1166 * @return GNUNET_YES if there are more results, 1271 * @return GNUNET_YES if there are more results,
1167 * GNUNET_NO if there are no more results, 1272 * GNUNET_NO if there are no more results,
1168 * GNUNET_SYSERR on internal error 1273 * GNUNET_SYSERR on internal error
@@ -1172,9 +1277,9 @@ get_next_prepare (void *cls,
1172 struct NextContext *nc) 1277 struct NextContext *nc)
1173{ 1278{
1174 struct GetNextContext *gnc = cls; 1279 struct GetNextContext *gnc = cls;
1175 int sqoff;
1176 int ret; 1280 int ret;
1177 int limit_off; 1281 int limit_off;
1282 unsigned int sqoff;
1178 1283
1179 if (nc == NULL) 1284 if (nc == NULL)
1180 { 1285 {
@@ -1189,8 +1294,8 @@ get_next_prepare (void *cls,
1189 limit_off = gnc->off; 1294 limit_off = gnc->off;
1190 else 1295 else
1191 limit_off = 0; 1296 limit_off = 0;
1192 sqoff = 1;
1193 sqlite3_reset (nc->stmt); 1297 sqlite3_reset (nc->stmt);
1298 sqoff = 1;
1194 ret = sqlite3_bind_blob (nc->stmt, 1299 ret = sqlite3_bind_blob (nc->stmt,
1195 sqoff++, 1300 sqoff++,
1196 &gnc->key, 1301 &gnc->key,
@@ -1204,14 +1309,31 @@ get_next_prepare (void *cls,
1204 if ((gnc->type != 0) && (ret == SQLITE_OK)) 1309 if ((gnc->type != 0) && (ret == SQLITE_OK))
1205 ret = sqlite3_bind_int (nc->stmt, sqoff++, gnc->type); 1310 ret = sqlite3_bind_int (nc->stmt, sqoff++, gnc->type);
1206 if (ret == SQLITE_OK) 1311 if (ret == SQLITE_OK)
1207 ret = sqlite3_bind_int64 (nc->stmt, sqoff++, nc->last_rowid + 1); 1312 ret = sqlite3_bind_int64 (nc->stmt, sqoff++, limit_off);
1208 if (ret == SQLITE_OK)
1209 ret = sqlite3_bind_int (nc->stmt, sqoff++, limit_off);
1210 if (ret != SQLITE_OK) 1313 if (ret != SQLITE_OK)
1211 return GNUNET_SYSERR; 1314 return GNUNET_SYSERR;
1212 if (SQLITE_ROW != sqlite3_step (nc->stmt)) 1315#if DEBUG_SQLITE
1213 return GNUNET_NO; 1316 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1214 return GNUNET_OK; 1317 "sqlite",
1318 "Preparing to GET for key `%s' with type %d at offset %u\n",
1319 GNUNET_h2s (&gnc->key),
1320 gnc->type,
1321 limit_off);
1322#endif
1323 ret = sqlite3_step (nc->stmt);
1324 switch (ret)
1325 {
1326 case SQLITE_ROW:
1327 return GNUNET_OK;
1328 case SQLITE_DONE:
1329 return GNUNET_NO;
1330 default:
1331 LOG_SQLITE (gnc->plugin, NULL,
1332 GNUNET_ERROR_TYPE_ERROR |
1333 GNUNET_ERROR_TYPE_BULK,
1334 "sqlite3_step");
1335 return GNUNET_SYSERR;
1336 }
1215} 1337}
1216 1338
1217 1339
@@ -1220,7 +1342,7 @@ get_next_prepare (void *cls,
1220 * in the datastore. 1342 * in the datastore.
1221 * 1343 *
1222 * @param cls closure 1344 * @param cls closure
1223 * @param key maybe NULL (to match all entries) 1345 * @param key key to match, never NULL
1224 * @param vhash hash of the value, maybe NULL (to 1346 * @param vhash hash of the value, maybe NULL (to
1225 * match all values that have the right key). 1347 * match all values that have the right key).
1226 * Note that for DBlocks there is no difference 1348 * Note that for DBlocks there is no difference
@@ -1234,31 +1356,26 @@ get_next_prepare (void *cls,
1234 */ 1356 */
1235static void 1357static void
1236sqlite_plugin_get (void *cls, 1358sqlite_plugin_get (void *cls,
1237 const GNUNET_HashCode * key, 1359 const GNUNET_HashCode *key,
1238 const GNUNET_HashCode * vhash, 1360 const GNUNET_HashCode *vhash,
1239 enum GNUNET_BLOCK_Type type, 1361 enum GNUNET_BLOCK_Type type,
1240 PluginIterator iter, void *iter_cls) 1362 PluginIterator iter, void *iter_cls)
1241{ 1363{
1242 struct Plugin *plugin = cls; 1364 struct Plugin *plugin = cls;
1243 struct GetNextContext *gpc; 1365 struct GetNextContext *gnc;
1244 struct NextContext *nc; 1366 struct NextContext *nc;
1245 int ret; 1367 int ret;
1246 int total; 1368 int total;
1247 sqlite3_stmt *stmt; 1369 sqlite3_stmt *stmt;
1248 char scratch[256]; 1370 char scratch[256];
1249 int sqoff; 1371 unsigned int sqoff;
1250 1372
1251 GNUNET_assert (iter != NULL); 1373 GNUNET_assert (iter != NULL);
1252 if (key == NULL) 1374 GNUNET_assert (key != NULL);
1253 {
1254 sqlite_plugin_iter_all_now (cls, type, iter, iter_cls);
1255 return;
1256 }
1257 GNUNET_snprintf (scratch, sizeof (scratch), 1375 GNUNET_snprintf (scratch, sizeof (scratch),
1258 "SELECT count(*) FROM gn090 WHERE hash=:1%s%s", 1376 "SELECT count(*) FROM gn090 WHERE hash=?%s%s",
1259 vhash == NULL ? "" : " AND vhash=:2", 1377 vhash == NULL ? "" : " AND vhash=?",
1260 type == 0 ? "" : (vhash == 1378 type == 0 ? "" : " AND type=?");
1261 NULL) ? " AND type=:2" : " AND type=:3");
1262 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) 1379 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK)
1263 { 1380 {
1264 LOG_SQLITE (plugin, NULL, 1381 LOG_SQLITE (plugin, NULL,
@@ -1267,12 +1384,10 @@ sqlite_plugin_get (void *cls,
1267 return; 1384 return;
1268 } 1385 }
1269 sqoff = 1; 1386 sqoff = 1;
1270 ret = sqlite3_bind_blob (stmt, 1387 ret = sqlite3_bind_blob (stmt, sqoff++,
1271 sqoff++,
1272 key, sizeof (GNUNET_HashCode), SQLITE_TRANSIENT); 1388 key, sizeof (GNUNET_HashCode), SQLITE_TRANSIENT);
1273 if ((vhash != NULL) && (ret == SQLITE_OK)) 1389 if ((vhash != NULL) && (ret == SQLITE_OK))
1274 ret = sqlite3_bind_blob (stmt, 1390 ret = sqlite3_bind_blob (stmt, sqoff++,
1275 sqoff++,
1276 vhash, 1391 vhash,
1277 sizeof (GNUNET_HashCode), SQLITE_TRANSIENT); 1392 sizeof (GNUNET_HashCode), SQLITE_TRANSIENT);
1278 if ((type != 0) && (ret == SQLITE_OK)) 1393 if ((type != 0) && (ret == SQLITE_OK))
@@ -1281,7 +1396,6 @@ sqlite_plugin_get (void *cls,
1281 { 1396 {
1282 LOG_SQLITE (plugin, NULL, 1397 LOG_SQLITE (plugin, NULL,
1283 GNUNET_ERROR_TYPE_ERROR, "sqlite_bind"); 1398 GNUNET_ERROR_TYPE_ERROR, "sqlite_bind");
1284 sqlite3_reset (stmt);
1285 sqlite3_finalize (stmt); 1399 sqlite3_finalize (stmt);
1286 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1400 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1287 return; 1401 return;
@@ -1292,28 +1406,24 @@ sqlite_plugin_get (void *cls,
1292 LOG_SQLITE (plugin, NULL, 1406 LOG_SQLITE (plugin, NULL,
1293 GNUNET_ERROR_TYPE_ERROR| GNUNET_ERROR_TYPE_BULK, 1407 GNUNET_ERROR_TYPE_ERROR| GNUNET_ERROR_TYPE_BULK,
1294 "sqlite_step"); 1408 "sqlite_step");
1295 sqlite3_reset (stmt);
1296 sqlite3_finalize (stmt); 1409 sqlite3_finalize (stmt);
1297 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1410 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1298 return; 1411 return;
1299 } 1412 }
1300 total = sqlite3_column_int (stmt, 0); 1413 total = sqlite3_column_int (stmt, 0);
1301 sqlite3_reset (stmt);
1302 sqlite3_finalize (stmt); 1414 sqlite3_finalize (stmt);
1303 if (0 == total) 1415 if (0 == total)
1304 { 1416 {
1305 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 1417 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1306 return; 1418 return;
1307 } 1419 }
1308
1309 GNUNET_snprintf (scratch, sizeof (scratch), 1420 GNUNET_snprintf (scratch, sizeof (scratch),
1310 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ " 1421 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ "
1311 "FROM gn090 WHERE hash=:1%s%s AND _ROWID_ >= :%d " 1422 "FROM gn090 WHERE hash=?%s%s "
1312 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET :d", 1423 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
1313 vhash == NULL ? "" : " AND vhash=:2", 1424 vhash == NULL ? "" : " AND vhash=?",
1314 type == 0 ? "" : (vhash == 1425 type == 0 ? "" : " AND type=?");
1315 NULL) ? " AND type=:2" : " AND type=:3", 1426
1316 sqoff, sqoff + 1);
1317 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) 1427 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK)
1318 { 1428 {
1319 LOG_SQLITE (plugin, NULL, 1429 LOG_SQLITE (plugin, NULL,
@@ -1328,25 +1438,26 @@ sqlite_plugin_get (void *cls,
1328 nc->iter = iter; 1438 nc->iter = iter;
1329 nc->iter_cls = iter_cls; 1439 nc->iter_cls = iter_cls;
1330 nc->stmt = stmt; 1440 nc->stmt = stmt;
1331 gpc = (struct GetNextContext*) &nc[1]; 1441 gnc = (struct GetNextContext*) &nc[1];
1332 gpc->total = total; 1442 gnc->total = total;
1333 gpc->type = type; 1443 gnc->type = type;
1334 gpc->key = *key; 1444 gnc->key = *key;
1335 gpc->stmt = stmt; /* alias used for freeing at the end! */ 1445 gnc->plugin = plugin;
1446 gnc->stmt = stmt; /* alias used for freeing at the end! */
1336 if (NULL != vhash) 1447 if (NULL != vhash)
1337 { 1448 {
1338 gpc->have_vhash = GNUNET_YES; 1449 gnc->have_vhash = GNUNET_YES;
1339 gpc->vhash = *vhash; 1450 gnc->vhash = *vhash;
1340 } 1451 }
1341 gpc->off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); 1452 gnc->off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
1342 nc->prep = &get_next_prepare; 1453 nc->prep = &get_next_prepare;
1343 nc->prep_cls = gpc; 1454 nc->prep_cls = gnc;
1344 sqlite_next_request (nc, GNUNET_NO); 1455 sqlite_next_request (nc, GNUNET_NO);
1345} 1456}
1346 1457
1347 1458
1348/** 1459/**
1349 * Execute statement that gets a row and call the iterator 1460 * Execute statement that gets a row and call the callback
1350 * with the result. Resets the statement afterwards. 1461 * with the result. Resets the statement afterwards.
1351 * 1462 *
1352 * @param plugin the plugin 1463 * @param plugin the plugin
@@ -1419,7 +1530,11 @@ execute_get (struct Plugin *plugin,
1419 LOG_SQLITE (plugin, NULL, 1530 LOG_SQLITE (plugin, NULL,
1420 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1531 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1421 "sqlite3_step"); 1532 "sqlite3_step");
1422 (void) sqlite3_reset (stmt); 1533 if (SQLITE_OK != sqlite3_reset (stmt))
1534 LOG_SQLITE (plugin, NULL,
1535 GNUNET_ERROR_TYPE_ERROR |
1536 GNUNET_ERROR_TYPE_BULK,
1537 "sqlite3_reset");
1423 GNUNET_break (0); 1538 GNUNET_break (0);
1424 database_shutdown (plugin); 1539 database_shutdown (plugin);
1425 database_setup (plugin->env->cfg, 1540 database_setup (plugin->env->cfg,
@@ -1524,7 +1639,8 @@ sqlite_plugin_drop (void *cls)
1524 1639
1525 1640
1526/** 1641/**
1527 * FIXME. 1642 * Get an estimate of how much space the database is
1643 * currently using.
1528 * 1644 *
1529 * @param cls the 'struct Plugin' 1645 * @param cls the 'struct Plugin'
1530 * @return the size of the database on disk (estimate) 1646 * @return the size of the database on disk (estimate)
@@ -1547,6 +1663,10 @@ sqlite_plugin_get_size (void *cls)
1547 _("sqlite version to old to determine size, assuming zero\n")); 1663 _("sqlite version to old to determine size, assuming zero\n"));
1548 return 0; 1664 return 0;
1549 } 1665 }
1666 if (SQLITE_OK !=
1667 sqlite3_exec (plugin->dbh,
1668 "VACUUM", NULL, NULL, ENULL))
1669 abort ();
1550 CHECK (SQLITE_OK == 1670 CHECK (SQLITE_OK ==
1551 sqlite3_exec (plugin->dbh, 1671 sqlite3_exec (plugin->dbh,
1552 "VACUUM", NULL, NULL, ENULL)); 1672 "VACUUM", NULL, NULL, ENULL));
diff --git a/src/datastore/test_datastore_api.c b/src/datastore/test_datastore_api.c
index 6280907ad..2cca1da69 100644
--- a/src/datastore/test_datastore_api.c
+++ b/src/datastore/test_datastore_api.c
@@ -188,6 +188,7 @@ check_value (void *cls,
188 struct GNUNET_TIME_Absolute 188 struct GNUNET_TIME_Absolute
189 expiration, uint64_t uid) 189 expiration, uint64_t uid)
190{ 190{
191 static int matched;
191 struct CpsRunContext *crc = cls; 192 struct CpsRunContext *crc = cls;
192 int i; 193 int i;
193 194
@@ -198,6 +199,8 @@ check_value (void *cls,
198 crc->phase = RP_DEL; 199 crc->phase = RP_DEL;
199 crc->i = ITERATIONS; 200 crc->i = ITERATIONS;
200 } 201 }
202 GNUNET_assert (matched == GNUNET_YES);
203 matched = GNUNET_NO;
201 GNUNET_SCHEDULER_add_continuation (&run_continuation, 204 GNUNET_SCHEDULER_add_continuation (&run_continuation,
202 crc, 205 crc,
203 GNUNET_SCHEDULER_REASON_PREREQ_DONE); 206 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
@@ -210,6 +213,7 @@ check_value (void *cls,
210 GNUNET_assert (priority == get_priority (i)); 213 GNUNET_assert (priority == get_priority (i));
211 GNUNET_assert (anonymity == get_anonymity(i)); 214 GNUNET_assert (anonymity == get_anonymity(i));
212 GNUNET_assert (expiration.abs_value == get_expiration(i).abs_value); 215 GNUNET_assert (expiration.abs_value == get_expiration(i).abs_value);
216 matched = GNUNET_YES;
213 GNUNET_DATASTORE_iterate_get_next (datastore); 217 GNUNET_DATASTORE_iterate_get_next (datastore);
214} 218}
215 219
@@ -579,22 +583,32 @@ run_continuation (void *cls,
579 583
580static void 584static void
581run_tests (void *cls, 585run_tests (void *cls,
582 int success, 586 int32_t success,
583 const char *msg) 587 const char *msg)
584{ 588{
585 struct CpsRunContext *crc = cls; 589 struct CpsRunContext *crc = cls;
586 590
587 if (success != GNUNET_YES) 591 switch (success)
588 { 592 {
593 case GNUNET_YES:
594 GNUNET_SCHEDULER_add_continuation (&run_continuation,
595 crc,
596 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
597 return;
598 case GNUNET_NO:
599 fprintf (stderr,
600 "Test 'put' operation failed, key already exists (!?)\n");
601 GNUNET_free (crc);
602 return;
603 case GNUNET_SYSERR:
589 fprintf (stderr, 604 fprintf (stderr,
590 "Test 'put' operation failed with error `%s' database likely not setup, skipping test.", 605 "Test 'put' operation failed with error `%s' database likely not setup, skipping test.\n",
591 msg); 606 msg);
592 GNUNET_free (crc); 607 GNUNET_free (crc);
593 return; 608 return;
609 default:
610 GNUNET_assert (0);
594 } 611 }
595 GNUNET_SCHEDULER_add_continuation (&run_continuation,
596 crc,
597 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
598} 612}
599 613
600 614