aboutsummaryrefslogtreecommitdiff
path: root/src/datastore/plugin_datastore_sqlite.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-07-17 21:09:54 +0000
committerChristian Grothoff <christian@grothoff.org>2009-07-17 21:09:54 +0000
commita1f0c51bc626efeab9d842765fd1aede65035f93 (patch)
tree3cace958e8aa5cafd5774aa8671a1c27c3d441d4 /src/datastore/plugin_datastore_sqlite.c
parent4524a128f4f6e72a802dd7b1c4130d5c746467f2 (diff)
downloadgnunet-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.c169
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 */
436typedef int (*PrepareFunction)(void *cls, 436typedef 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 */
516static void 514static void
517sqlite_next_request (void *next_cls, 515sqlite_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 */
634static void
635sqlite_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
1117static int
1118all_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,