diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-07-17 21:09:54 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-07-17 21:09:54 +0000 |
commit | a1f0c51bc626efeab9d842765fd1aede65035f93 (patch) | |
tree | 3cace958e8aa5cafd5774aa8671a1c27c3d441d4 /src/datastore/plugin_datastore_sqlite.c | |
parent | 4524a128f4f6e72a802dd7b1c4130d5c746467f2 (diff) | |
download | gnunet-a1f0c51bc626efeab9d842765fd1aede65035f93.tar.gz gnunet-a1f0c51bc626efeab9d842765fd1aede65035f93.zip |
implementing all-now iterator
Diffstat (limited to 'src/datastore/plugin_datastore_sqlite.c')
-rw-r--r-- | src/datastore/plugin_datastore_sqlite.c | 169 |
1 files changed, 140 insertions, 29 deletions
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index edf17b377..3cedbd5d6 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "plugin_datastore.h" | 29 | #include "plugin_datastore.h" |
30 | #include <sqlite3.h> | 30 | #include <sqlite3.h> |
31 | 31 | ||
32 | #define DEBUG_SQLITE GNUNET_YES | 32 | #define DEBUG_SQLITE GNUNET_NO |
33 | 33 | ||
34 | /** | 34 | /** |
35 | * After how many payload-changing operations | 35 | * After how many payload-changing operations |
@@ -431,7 +431,7 @@ struct NextContext; | |||
431 | * call which gives the callback a chance to | 431 | * call which gives the callback a chance to |
432 | * clean up the closure | 432 | * clean up the closure |
433 | * @return GNUNET_OK on success, GNUNET_NO if there are | 433 | * @return GNUNET_OK on success, GNUNET_NO if there are |
434 | * no more values, GNUNET_SYSERR on error | 434 | * no more values, GNUNET_SYSERR on error |
435 | */ | 435 | */ |
436 | typedef int (*PrepareFunction)(void *cls, | 436 | typedef int (*PrepareFunction)(void *cls, |
437 | struct NextContext *nc); | 437 | struct NextContext *nc); |
@@ -480,6 +480,11 @@ struct NextContext | |||
480 | unsigned long long last_rowid; | 480 | unsigned long long last_rowid; |
481 | 481 | ||
482 | /** | 482 | /** |
483 | * Key of the last result. | ||
484 | */ | ||
485 | GNUNET_HashCode lastKey; | ||
486 | |||
487 | /** | ||
483 | * Expiration time of the last value visited. | 488 | * Expiration time of the last value visited. |
484 | */ | 489 | */ |
485 | struct GNUNET_TIME_Absolute lastExpiration; | 490 | struct GNUNET_TIME_Absolute lastExpiration; |
@@ -502,23 +507,16 @@ struct NextContext | |||
502 | 507 | ||
503 | 508 | ||
504 | /** | 509 | /** |
505 | * Function invoked on behalf of a "PluginIterator" | 510 | * Continuation of "sqlite_next_request". |
506 | * asking the database plugin to call the iterator | ||
507 | * with the next item. | ||
508 | * | 511 | * |
509 | * @param next_cls whatever argument was given | 512 | * @param cls the next context |
510 | * to the PluginIterator as "next_cls". | ||
511 | * @param end_it set to GNUNET_YES if we | ||
512 | * should terminate the iteration early | ||
513 | * (iterator should be still called once more | ||
514 | * to signal the end of the iteration). | ||
515 | */ | 513 | */ |
516 | static void | 514 | static void |
517 | sqlite_next_request (void *next_cls, | 515 | sqlite_next_request_cont (void *cls, |
518 | int end_it) | 516 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
519 | { | 517 | { |
520 | static struct GNUNET_TIME_Absolute zero; | 518 | static struct GNUNET_TIME_Absolute zero; |
521 | struct NextContext * nc= next_cls; | 519 | struct NextContext * nc= cls; |
522 | struct Plugin *plugin; | 520 | struct Plugin *plugin; |
523 | unsigned long long rowid; | 521 | unsigned long long rowid; |
524 | sqlite3_stmt *stmtd; | 522 | sqlite3_stmt *stmtd; |
@@ -531,13 +529,11 @@ sqlite_next_request (void *next_cls, | |||
531 | const GNUNET_HashCode *key; | 529 | const GNUNET_HashCode *key; |
532 | const void *data; | 530 | const void *data; |
533 | 531 | ||
532 | |||
534 | plugin = nc->plugin; | 533 | plugin = nc->plugin; |
535 | sqlite3_reset (nc->stmt); | 534 | if ( (GNUNET_YES == nc->end_it) || |
536 | if ( (GNUNET_YES == end_it) || | ||
537 | (GNUNET_YES == nc->end_it) || | ||
538 | (GNUNET_OK != (nc->prep(nc->prep_cls, | 535 | (GNUNET_OK != (nc->prep(nc->prep_cls, |
539 | nc))) || | 536 | nc))) ) |
540 | (SQLITE_ROW != sqlite3_step (nc->stmt)) ) | ||
541 | { | 537 | { |
542 | END: | 538 | END: |
543 | nc->iter (nc->iter_cls, | 539 | nc->iter (nc->iter_cls, |
@@ -589,11 +585,12 @@ sqlite_next_request (void *next_cls, | |||
589 | } | 585 | } |
590 | 586 | ||
591 | priority = sqlite3_column_int (nc->stmt, 2); | 587 | priority = sqlite3_column_int (nc->stmt, 2); |
592 | nc->lastPriority = priority; | ||
593 | anonymity = sqlite3_column_int (nc->stmt, 3); | 588 | anonymity = sqlite3_column_int (nc->stmt, 3); |
594 | expiration.value = sqlite3_column_int64 (nc->stmt, 4); | 589 | expiration.value = sqlite3_column_int64 (nc->stmt, 4); |
595 | nc->lastExpiration = expiration; | ||
596 | key = sqlite3_column_blob (nc->stmt, 5); | 590 | key = sqlite3_column_blob (nc->stmt, 5); |
591 | nc->lastPriority = priority; | ||
592 | nc->lastExpiration = expiration; | ||
593 | memcpy (&nc->lastKey, key, sizeof(GNUNET_HashCode)); | ||
597 | data = sqlite3_column_blob (nc->stmt, 6); | 594 | data = sqlite3_column_blob (nc->stmt, 6); |
598 | nc->count++; | 595 | nc->count++; |
599 | ret = nc->iter (nc->iter_cls, | 596 | ret = nc->iter (nc->iter_cls, |
@@ -623,6 +620,35 @@ sqlite_next_request (void *next_cls, | |||
623 | 620 | ||
624 | 621 | ||
625 | /** | 622 | /** |
623 | * Function invoked on behalf of a "PluginIterator" | ||
624 | * asking the database plugin to call the iterator | ||
625 | * with the next item. | ||
626 | * | ||
627 | * @param next_cls whatever argument was given | ||
628 | * to the PluginIterator as "next_cls". | ||
629 | * @param end_it set to GNUNET_YES if we | ||
630 | * should terminate the iteration early | ||
631 | * (iterator should be still called once more | ||
632 | * to signal the end of the iteration). | ||
633 | */ | ||
634 | static void | ||
635 | sqlite_next_request (void *next_cls, | ||
636 | int end_it) | ||
637 | { | ||
638 | struct NextContext * nc= next_cls; | ||
639 | |||
640 | if (GNUNET_YES == end_it) | ||
641 | nc->end_it = GNUNET_YES; | ||
642 | GNUNET_SCHEDULER_add_continuation (nc->plugin->env->sched, | ||
643 | GNUNET_NO, | ||
644 | &sqlite_next_request_cont, | ||
645 | nc, | ||
646 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
647 | } | ||
648 | |||
649 | |||
650 | |||
651 | /** | ||
626 | * Store an item in the datastore. | 652 | * Store an item in the datastore. |
627 | * | 653 | * |
628 | * @param cls closure | 654 | * @param cls closure |
@@ -776,7 +802,6 @@ struct IterContext | |||
776 | int is_migr; | 802 | int is_migr; |
777 | int limit_nonanonymous; | 803 | int limit_nonanonymous; |
778 | uint32_t type; | 804 | uint32_t type; |
779 | GNUNET_HashCode key; | ||
780 | }; | 805 | }; |
781 | 806 | ||
782 | 807 | ||
@@ -790,27 +815,52 @@ iter_next_prepare (void *cls, | |||
790 | 815 | ||
791 | if (nc == NULL) | 816 | if (nc == NULL) |
792 | { | 817 | { |
818 | #if DEBUG_SQLITE | ||
819 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
820 | "Asked to clean up iterator state.\n"); | ||
821 | #endif | ||
793 | sqlite3_finalize (ic->stmt_1); | 822 | sqlite3_finalize (ic->stmt_1); |
794 | sqlite3_finalize (ic->stmt_2); | 823 | sqlite3_finalize (ic->stmt_2); |
795 | return GNUNET_SYSERR; | 824 | return GNUNET_SYSERR; |
796 | } | 825 | } |
826 | sqlite3_reset (ic->stmt_1); | ||
827 | sqlite3_reset (ic->stmt_2); | ||
797 | plugin = nc->plugin; | 828 | plugin = nc->plugin; |
798 | if (ic->is_prio) | 829 | if (ic->is_prio) |
799 | { | 830 | { |
831 | #if DEBUG_SQLITE | ||
832 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
833 | "Restricting to results larger than the last priority %u\n", | ||
834 | nc->lastPriority); | ||
835 | #endif | ||
800 | sqlite3_bind_int (ic->stmt_1, 1, nc->lastPriority); | 836 | sqlite3_bind_int (ic->stmt_1, 1, nc->lastPriority); |
801 | sqlite3_bind_int (ic->stmt_2, 1, nc->lastPriority); | 837 | sqlite3_bind_int (ic->stmt_2, 1, nc->lastPriority); |
802 | } | 838 | } |
803 | else | 839 | else |
804 | { | 840 | { |
841 | #if DEBUG_SQLITE | ||
842 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
843 | "Restricting to results larger than the last expiration %llu\n", | ||
844 | (unsigned long long) nc->lastExpiration.value); | ||
845 | #endif | ||
805 | sqlite3_bind_int64 (ic->stmt_1, 1, nc->lastExpiration.value); | 846 | sqlite3_bind_int64 (ic->stmt_1, 1, nc->lastExpiration.value); |
806 | sqlite3_bind_int64 (ic->stmt_2, 1, nc->lastExpiration.value); | 847 | sqlite3_bind_int64 (ic->stmt_2, 1, nc->lastExpiration.value); |
807 | } | 848 | } |
849 | #if DEBUG_SQLITE | ||
850 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
851 | "Restricting to results larger than the last key `%s'\n", | ||
852 | GNUNET_h2s(&nc->lastKey)); | ||
853 | #endif | ||
808 | sqlite3_bind_blob (ic->stmt_1, 2, | 854 | sqlite3_bind_blob (ic->stmt_1, 2, |
809 | &ic->key, | 855 | &nc->lastKey, |
810 | sizeof (GNUNET_HashCode), | 856 | sizeof (GNUNET_HashCode), |
811 | SQLITE_TRANSIENT); | 857 | SQLITE_TRANSIENT); |
812 | if (SQLITE_ROW == (ret = sqlite3_step (ic->stmt_1))) | 858 | if (SQLITE_ROW == (ret = sqlite3_step (ic->stmt_1))) |
813 | { | 859 | { |
860 | #if DEBUG_SQLITE | ||
861 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
862 | "Result found using iterator 1\n"); | ||
863 | #endif | ||
814 | nc->stmt = ic->stmt_1; | 864 | nc->stmt = ic->stmt_1; |
815 | return GNUNET_OK; | 865 | return GNUNET_OK; |
816 | } | 866 | } |
@@ -829,6 +879,10 @@ iter_next_prepare (void *cls, | |||
829 | "sqlite3_reset"); | 879 | "sqlite3_reset"); |
830 | if (SQLITE_ROW == (ret = sqlite3_step (ic->stmt_2))) | 880 | if (SQLITE_ROW == (ret = sqlite3_step (ic->stmt_2))) |
831 | { | 881 | { |
882 | #if DEBUG_SQLITE | ||
883 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
884 | "Result found using iterator 2\n"); | ||
885 | #endif | ||
832 | nc->stmt = ic->stmt_2; | 886 | nc->stmt = ic->stmt_2; |
833 | return GNUNET_OK; | 887 | return GNUNET_OK; |
834 | } | 888 | } |
@@ -915,13 +969,13 @@ basic_iter (struct Plugin *plugin, | |||
915 | { | 969 | { |
916 | nc->lastPriority = 0; | 970 | nc->lastPriority = 0; |
917 | nc->lastExpiration.value = 0; | 971 | nc->lastExpiration.value = 0; |
918 | memset (&ic->key, 0, sizeof (GNUNET_HashCode)); | 972 | memset (&nc->lastKey, 0, sizeof (GNUNET_HashCode)); |
919 | } | 973 | } |
920 | else | 974 | else |
921 | { | 975 | { |
922 | nc->lastPriority = 0x7FFFFFFF; | 976 | nc->lastPriority = 0x7FFFFFFF; |
923 | nc->lastExpiration.value = 0x7FFFFFFFFFFFFFFFLL; | 977 | nc->lastExpiration.value = 0x7FFFFFFFFFFFFFFFLL; |
924 | memset (&ic->key, 255, sizeof (GNUNET_HashCode)); | 978 | memset (&nc->lastKey, 255, sizeof (GNUNET_HashCode)); |
925 | } | 979 | } |
926 | sqlite_next_request (nc, GNUNET_NO); | 980 | sqlite_next_request (nc, GNUNET_NO); |
927 | } | 981 | } |
@@ -974,9 +1028,9 @@ sqlite_plugin_iter_zero_anonymity (void *cls, | |||
974 | char *q2; | 1028 | char *q2; |
975 | 1029 | ||
976 | now = GNUNET_TIME_absolute_get (); | 1030 | now = GNUNET_TIME_absolute_get (); |
977 | GNUNET_asprintf (&q1, SELECT_IT_EXPIRATION_TIME_1, | 1031 | GNUNET_asprintf (&q1, SELECT_IT_NON_ANONYMOUS_1, |
978 | now.value); | 1032 | now.value); |
979 | GNUNET_asprintf (&q2, SELECT_IT_EXPIRATION_TIME_2, | 1033 | GNUNET_asprintf (&q2, SELECT_IT_NON_ANONYMOUS_2, |
980 | now.value); | 1034 | now.value); |
981 | basic_iter (cls, | 1035 | basic_iter (cls, |
982 | type, | 1036 | type, |
@@ -1060,6 +1114,41 @@ sqlite_plugin_iter_migration_order (void *cls, | |||
1060 | } | 1114 | } |
1061 | 1115 | ||
1062 | 1116 | ||
1117 | static int | ||
1118 | all_next_prepare (void *cls, | ||
1119 | struct NextContext *nc) | ||
1120 | { | ||
1121 | struct Plugin *plugin; | ||
1122 | int ret; | ||
1123 | |||
1124 | if (nc == NULL) | ||
1125 | { | ||
1126 | #if DEBUG_SQLITE | ||
1127 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1128 | "Asked to clean up iterator state.\n"); | ||
1129 | #endif | ||
1130 | return GNUNET_SYSERR; | ||
1131 | } | ||
1132 | plugin = nc->plugin; | ||
1133 | if (SQLITE_ROW == (ret = sqlite3_step (nc->stmt))) | ||
1134 | { | ||
1135 | #if DEBUG_SQLITE | ||
1136 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1137 | "Result found\n"); | ||
1138 | #endif | ||
1139 | return GNUNET_OK; | ||
1140 | } | ||
1141 | if (ret != SQLITE_DONE) | ||
1142 | { | ||
1143 | LOG_SQLITE (plugin, NULL, | ||
1144 | GNUNET_ERROR_TYPE_ERROR | | ||
1145 | GNUNET_ERROR_TYPE_BULK, | ||
1146 | "sqlite3_step"); | ||
1147 | return GNUNET_SYSERR; | ||
1148 | } | ||
1149 | return GNUNET_NO; | ||
1150 | } | ||
1151 | |||
1063 | 1152 | ||
1064 | /** | 1153 | /** |
1065 | * Select a subset of the items in the datastore and call | 1154 | * Select a subset of the items in the datastore and call |
@@ -1078,7 +1167,28 @@ sqlite_plugin_iter_all_now (void *cls, | |||
1078 | void *iter_cls) | 1167 | void *iter_cls) |
1079 | { | 1168 | { |
1080 | static struct GNUNET_TIME_Absolute zero; | 1169 | static struct GNUNET_TIME_Absolute zero; |
1081 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, zero, 0); | 1170 | struct Plugin *plugin = cls; |
1171 | struct NextContext *nc; | ||
1172 | sqlite3_stmt *stmt; | ||
1173 | |||
1174 | if (sq_prepare (plugin->dbh, | ||
1175 | "SELECT size,type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn080", | ||
1176 | &stmt) != SQLITE_OK) | ||
1177 | { | ||
1178 | LOG_SQLITE (plugin, NULL, | ||
1179 | GNUNET_ERROR_TYPE_ERROR | | ||
1180 | GNUNET_ERROR_TYPE_BULK, "sqlite3_prepare"); | ||
1181 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, zero, 0); | ||
1182 | return; | ||
1183 | } | ||
1184 | nc = GNUNET_malloc (sizeof(struct NextContext)); | ||
1185 | nc->plugin = plugin; | ||
1186 | nc->iter = iter; | ||
1187 | nc->iter_cls = iter_cls; | ||
1188 | nc->stmt = stmt; | ||
1189 | nc->prep = &all_next_prepare; | ||
1190 | nc->prep_cls = NULL; | ||
1191 | sqlite_next_request (nc, GNUNET_NO); | ||
1082 | } | 1192 | } |
1083 | 1193 | ||
1084 | 1194 | ||
@@ -1117,6 +1227,7 @@ get_next_prepare (void *cls, | |||
1117 | else | 1227 | else |
1118 | limit_off = 0; | 1228 | limit_off = 0; |
1119 | sqoff = 1; | 1229 | sqoff = 1; |
1230 | sqlite3_reset (nc->stmt); | ||
1120 | ret = sqlite3_bind_blob (nc->stmt, | 1231 | ret = sqlite3_bind_blob (nc->stmt, |
1121 | sqoff++, | 1232 | sqoff++, |
1122 | &gnc->key, | 1233 | &gnc->key, |