diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-04-04 14:04:46 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-04-04 14:04:46 +0000 |
commit | ae64def363d4eeeaf8acfe586f00ae962da479fb (patch) | |
tree | 848d9e9eb579c17d9eef231e4caccc30b42c07f3 /src/datastore | |
parent | 0faff46cb3a4cc085ea2876eb6cdccfc59cb2bbe (diff) | |
download | gnunet-ae64def363d4eeeaf8acfe586f00ae962da479fb.tar.gz gnunet-ae64def363d4eeeaf8acfe586f00ae962da479fb.zip |
sqlite clean up
Diffstat (limited to 'src/datastore')
-rw-r--r-- | src/datastore/gnunet-service-datastore.c | 3 | ||||
-rw-r--r-- | src/datastore/perf_plugin_datastore.c | 5 | ||||
-rw-r--r-- | src/datastore/plugin_datastore_sqlite.c | 482 | ||||
-rw-r--r-- | src/datastore/test_datastore_api.c | 26 |
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 | */ |
548 | static void | 540 | static 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 | */ |
843 | struct IterContext | 866 | struct 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 | */ |
871 | static int | 894 | static int |
872 | iter_next_prepare (void *cls, | 895 | zero_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 | */ | ||
1084 | struct 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 | |||
1039 | all_next_prepare (void *cls, | 1114 | all_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 | */ |
1120 | struct GetNextContext | 1219 | struct 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 | */ |
1235 | static void | 1357 | static void |
1236 | sqlite_plugin_get (void *cls, | 1358 | sqlite_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 | ||
580 | static void | 584 | static void |
581 | run_tests (void *cls, | 585 | run_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 | ||