diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-04-03 20:00:42 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-04-03 20:00:42 +0000 |
commit | e8f35bb025c25839a52fb502e452393831e4e6f0 (patch) | |
tree | 7a056253bddc61b1e6a3258567e176af128c2b67 /src/datastore/plugin_datastore_sqlite.c | |
parent | 9f871785d57da57ba128ac2279fda1db1d9b8bfb (diff) | |
download | gnunet-e8f35bb025c25839a52fb502e452393831e4e6f0.tar.gz gnunet-e8f35bb025c25839a52fb502e452393831e4e6f0.zip |
improving datastore API --- not working yet
Diffstat (limited to 'src/datastore/plugin_datastore_sqlite.c')
-rw-r--r-- | src/datastore/plugin_datastore_sqlite.c | 706 |
1 files changed, 282 insertions, 424 deletions
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index b8661f46d..b05a0a9c1 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c | |||
@@ -38,43 +38,25 @@ | |||
38 | */ | 38 | */ |
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) | 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) |
40 | 40 | ||
41 | #define SELECT_IT_LOW_PRIORITY_1 \ | ||
42 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (prio = ? AND hash > ?) "\ | ||
43 | "ORDER BY hash ASC LIMIT 1" | ||
44 | |||
45 | #define SELECT_IT_LOW_PRIORITY_2 \ | ||
46 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (prio > ?) "\ | ||
47 | "ORDER BY prio ASC, hash ASC LIMIT 1" | ||
48 | 41 | ||
49 | #define SELECT_IT_NON_ANONYMOUS_1 \ | 42 | #define SELECT_IT_NON_ANONYMOUS_1 \ |
50 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (prio = ? AND hash < ? AND anonLevel = 0 AND expire > %llu) "\ | 43 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (prio = ?1 AND expire > %llu AND anonLevel = 0 AND hash < ?2) "\ |
51 | " ORDER BY hash DESC LIMIT 1" | 44 | " ORDER BY hash DESC LIMIT 1" |
52 | 45 | ||
53 | #define SELECT_IT_NON_ANONYMOUS_2 \ | 46 | #define SELECT_IT_NON_ANONYMOUS_2 \ |
54 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (prio < ? AND anonLevel = 0 AND expire > %llu)"\ | 47 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (prio < ?1 AND expire > %llu AND anonLevel = 0)"\ |
55 | " ORDER BY prio DESC, hash DESC LIMIT 1" | 48 | " ORDER BY prio DESC, hash DESC LIMIT 1" |
56 | 49 | ||
57 | #define SELECT_IT_EXPIRATION_TIME_1 \ | ||
58 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire = ? AND hash > ?) "\ | ||
59 | " ORDER BY hash ASC LIMIT 1" | ||
60 | |||
61 | #define SELECT_IT_EXPIRATION_TIME_2 \ | ||
62 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire > ?) "\ | ||
63 | " ORDER BY expire ASC, hash ASC LIMIT 1" | ||
64 | |||
65 | #define SELECT_IT_MIGRATION_ORDER_1 \ | ||
66 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire = ? AND hash < ?) "\ | ||
67 | " ORDER BY hash DESC LIMIT 1" | ||
68 | |||
69 | #define SELECT_IT_MIGRATION_ORDER_2 \ | ||
70 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire < ? AND expire > %llu) "\ | ||
71 | " ORDER BY expire DESC, hash DESC LIMIT 1" | ||
72 | |||
73 | 50 | ||
74 | #define SELECT_IT_REPLICATION_ORDER \ | 51 | #define SELECT_IT_REPLICATION_ORDER \ |
75 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire > ?) "\ | 52 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire > ?1) "\ |
76 | " ORDER BY repl DESC, Random() LIMIT 1" | 53 | " ORDER BY repl DESC, Random() LIMIT 1" |
77 | 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 | |||
78 | 60 | ||
79 | /** | 61 | /** |
80 | * After how many ms "busy" should a DB operation fail for good? | 62 | * After how many ms "busy" should a DB operation fail for good? |
@@ -126,11 +108,16 @@ struct Plugin | |||
126 | sqlite3_stmt *updRepl; | 108 | sqlite3_stmt *updRepl; |
127 | 109 | ||
128 | /** | 110 | /** |
129 | * Precompiled SQL for replication decrement. | 111 | * Precompiled SQL for replication selection. |
130 | */ | 112 | */ |
131 | sqlite3_stmt *selRepl; | 113 | sqlite3_stmt *selRepl; |
132 | 114 | ||
133 | /** | 115 | /** |
116 | * Precompiled SQL for expiration selection. | ||
117 | */ | ||
118 | sqlite3_stmt *selExpi; | ||
119 | |||
120 | /** | ||
134 | * Precompiled SQL for insertion. | 121 | * Precompiled SQL for insertion. |
135 | */ | 122 | */ |
136 | sqlite3_stmt *insertContent; | 123 | sqlite3_stmt *insertContent; |
@@ -162,18 +149,23 @@ struct Plugin | |||
162 | * @return 0 on success | 149 | * @return 0 on success |
163 | */ | 150 | */ |
164 | static int | 151 | static int |
165 | sq_prepare (sqlite3 * dbh, const char *zSql, | 152 | sq_prepare (sqlite3 * dbh, |
153 | const char *zSql, | ||
166 | sqlite3_stmt ** ppStmt) | 154 | sqlite3_stmt ** ppStmt) |
167 | { | 155 | { |
168 | char *dummy; | 156 | char *dummy; |
169 | int result; | 157 | int result; |
170 | result = sqlite3_prepare_v2 (dbh, | 158 | result = sqlite3_prepare_v2 (dbh, |
171 | zSql, | 159 | zSql, |
172 | strlen (zSql), ppStmt, (const char **) &dummy); | 160 | strlen (zSql), |
161 | ppStmt, | ||
162 | (const char **) &dummy); | ||
173 | #if DEBUG_SQLITE | 163 | #if DEBUG_SQLITE |
174 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 164 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
175 | "sqlite", | 165 | "sqlite", |
176 | "Prepared %p: %d\n", *ppStmt, result); | 166 | "Prepared %p: %d\n", |
167 | *ppStmt, | ||
168 | result); | ||
177 | #endif | 169 | #endif |
178 | return result; | 170 | return result; |
179 | } | 171 | } |
@@ -190,21 +182,15 @@ create_indices (sqlite3 * dbh) | |||
190 | /* create indices */ | 182 | /* create indices */ |
191 | sqlite3_exec (dbh, | 183 | sqlite3_exec (dbh, |
192 | "CREATE INDEX idx_hash ON gn090 (hash)", NULL, NULL, NULL); | 184 | "CREATE INDEX idx_hash ON gn090 (hash)", NULL, NULL, NULL); |
193 | sqlite3_exec (dbh, | ||
194 | "CREATE INDEX idx_hash_vhash ON gn090 (hash,vhash)", NULL, | ||
195 | NULL, NULL); | ||
196 | sqlite3_exec (dbh, "CREATE INDEX idx_prio ON gn090 (prio)", NULL, NULL, | 185 | sqlite3_exec (dbh, "CREATE INDEX idx_prio ON gn090 (prio)", NULL, NULL, |
197 | NULL); | 186 | NULL); |
198 | sqlite3_exec (dbh, "CREATE INDEX idx_expire ON gn090 (expire)", NULL, NULL, | 187 | sqlite3_exec (dbh, "CREATE INDEX idx_expire_prio ON gn090 (expire,prio)", NULL, NULL, |
199 | NULL); | 188 | NULL); |
200 | sqlite3_exec (dbh, "CREATE INDEX idx_comb3 ON gn090 (prio,anonLevel)", NULL, | 189 | sqlite3_exec (dbh, |
190 | "CREATE INDEX idx_hash_vhash ON gn090 (hash,vhash)", NULL, | ||
201 | NULL, NULL); | 191 | NULL, NULL); |
202 | sqlite3_exec (dbh, "CREATE INDEX idx_comb4 ON gn090 (prio,hash,anonLevel)", | 192 | sqlite3_exec (dbh, "CREATE INDEX idx_comb ON gn090 (prio,expire,anonLevel,hash)", |
203 | NULL, NULL, NULL); | 193 | NULL, NULL, NULL); |
204 | sqlite3_exec (dbh, "CREATE INDEX idx_comb7 ON gn090 (expire,hash)", NULL, | ||
205 | NULL, NULL); | ||
206 | sqlite3_exec (dbh, "CREATE INDEX idx_comb8 ON gn090 (expire)", NULL, | ||
207 | NULL, NULL); | ||
208 | } | 194 | } |
209 | 195 | ||
210 | 196 | ||
@@ -358,6 +344,9 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
358 | SELECT_IT_REPLICATION_ORDER, | 344 | SELECT_IT_REPLICATION_ORDER, |
359 | &plugin->selRepl) != SQLITE_OK) || | 345 | &plugin->selRepl) != SQLITE_OK) || |
360 | (sq_prepare (plugin->dbh, | 346 | (sq_prepare (plugin->dbh, |
347 | SELECT_IT_EXPIRATION_ORDER, | ||
348 | &plugin->selExpi) != SQLITE_OK) || | ||
349 | (sq_prepare (plugin->dbh, | ||
361 | "INSERT INTO gn090 (repl, type, prio, " | 350 | "INSERT INTO gn090 (repl, type, prio, " |
362 | "anonLevel, expire, hash, vhash, value) VALUES " | 351 | "anonLevel, expire, hash, vhash, value) VALUES " |
363 | "(?, ?, ?, ?, ?, ?, ?, ?)", | 352 | "(?, ?, ?, ?, ?, ?, ?, ?)", |
@@ -396,6 +385,8 @@ database_shutdown (struct Plugin *plugin) | |||
396 | sqlite3_finalize (plugin->updRepl); | 385 | sqlite3_finalize (plugin->updRepl); |
397 | if (plugin->selRepl != NULL) | 386 | if (plugin->selRepl != NULL) |
398 | sqlite3_finalize (plugin->selRepl); | 387 | sqlite3_finalize (plugin->selRepl); |
388 | if (plugin->selExpi != NULL) | ||
389 | sqlite3_finalize (plugin->selExpi); | ||
399 | if (plugin->insertContent != NULL) | 390 | if (plugin->insertContent != NULL) |
400 | sqlite3_finalize (plugin->insertContent); | 391 | sqlite3_finalize (plugin->insertContent); |
401 | result = sqlite3_close(plugin->dbh); | 392 | result = sqlite3_close(plugin->dbh); |
@@ -457,9 +448,9 @@ delete_by_rowid (struct Plugin* plugin, | |||
457 | return GNUNET_SYSERR; | 448 | return GNUNET_SYSERR; |
458 | } | 449 | } |
459 | if (SQLITE_OK != sqlite3_reset (plugin->delRow)) | 450 | if (SQLITE_OK != sqlite3_reset (plugin->delRow)) |
460 | LOG_SQLITE (plugin, NULL, | 451 | LOG_SQLITE (plugin, NULL, |
461 | GNUNET_ERROR_TYPE_ERROR | | 452 | GNUNET_ERROR_TYPE_ERROR | |
462 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); | 453 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); |
463 | return GNUNET_OK; | 454 | return GNUNET_OK; |
464 | } | 455 | } |
465 | 456 | ||
@@ -532,11 +523,6 @@ struct NextContext | |||
532 | GNUNET_HashCode lastKey; | 523 | GNUNET_HashCode lastKey; |
533 | 524 | ||
534 | /** | 525 | /** |
535 | * Expiration time of the last value visited. | ||
536 | */ | ||
537 | struct GNUNET_TIME_Absolute lastExpiration; | ||
538 | |||
539 | /** | ||
540 | * Priority of the last value visited. | 526 | * Priority of the last value visited. |
541 | */ | 527 | */ |
542 | unsigned int lastPriority; | 528 | unsigned int lastPriority; |
@@ -566,15 +552,14 @@ sqlite_next_request_cont (void *cls, | |||
566 | struct NextContext * nc = cls; | 552 | struct NextContext * nc = cls; |
567 | struct Plugin *plugin; | 553 | struct Plugin *plugin; |
568 | unsigned long long rowid; | 554 | unsigned long long rowid; |
569 | sqlite3_stmt *stmtd; | ||
570 | int ret; | 555 | int ret; |
571 | unsigned int type; | ||
572 | unsigned int size; | 556 | unsigned int size; |
573 | unsigned int priority; | 557 | uint32_t anonymity; |
574 | unsigned int anonymity; | 558 | uint32_t priority; |
575 | struct GNUNET_TIME_Absolute expiration; | 559 | enum GNUNET_BLOCK_Type type; |
576 | const GNUNET_HashCode *key; | 560 | const GNUNET_HashCode *key; |
577 | const void *data; | 561 | struct GNUNET_TIME_Absolute expiration; |
562 | char data[GNUNET_SERVER_MAX_MESSAGE_SIZE]; | ||
578 | 563 | ||
579 | plugin = nc->plugin; | 564 | plugin = nc->plugin; |
580 | plugin->next_task = GNUNET_SCHEDULER_NO_TASK; | 565 | plugin->next_task = GNUNET_SCHEDULER_NO_TASK; |
@@ -592,90 +577,72 @@ sqlite_next_request_cont (void *cls, | |||
592 | return; | 577 | return; |
593 | } | 578 | } |
594 | 579 | ||
595 | rowid = sqlite3_column_int64 (nc->stmt, 6); | ||
596 | nc->last_rowid = rowid; | ||
597 | type = sqlite3_column_int (nc->stmt, 0); | 580 | type = sqlite3_column_int (nc->stmt, 0); |
581 | priority = sqlite3_column_int (nc->stmt, 1); | ||
582 | anonymity = sqlite3_column_int (nc->stmt, 2); | ||
583 | expiration.abs_value = sqlite3_column_int64 (nc->stmt, 3); | ||
584 | key = sqlite3_column_blob (nc->stmt, 4); | ||
598 | size = sqlite3_column_bytes (nc->stmt, 5); | 585 | 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); | ||
599 | if (sqlite3_column_bytes (nc->stmt, 4) != sizeof (GNUNET_HashCode)) | 588 | if (sqlite3_column_bytes (nc->stmt, 4) != sizeof (GNUNET_HashCode)) |
600 | { | 589 | { |
601 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | 590 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, |
602 | "sqlite", | 591 | "sqlite", |
603 | _("Invalid data in database. Trying to fix (by deletion).\n")); | 592 | _("Invalid data in database. Trying to fix (by deletion).\n")); |
604 | if (SQLITE_OK != sqlite3_reset (nc->stmt)) | 593 | if (SQLITE_OK != sqlite3_reset (nc->stmt)) |
605 | LOG_SQLITE (nc->plugin, NULL, | 594 | LOG_SQLITE (plugin, NULL, |
606 | GNUNET_ERROR_TYPE_ERROR | | 595 | GNUNET_ERROR_TYPE_ERROR | |
607 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); | 596 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); |
608 | if (sq_prepare | 597 | if (GNUNET_OK == delete_by_rowid (plugin, rowid)) |
609 | (nc->plugin->dbh, | 598 | plugin->env->duc (plugin->env->cls, |
610 | "DELETE FROM gn090 WHERE NOT LENGTH(hash) = ?", | 599 | - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); |
611 | &stmtd) != SQLITE_OK) | ||
612 | { | ||
613 | LOG_SQLITE (nc->plugin, NULL, | ||
614 | GNUNET_ERROR_TYPE_ERROR | | ||
615 | GNUNET_ERROR_TYPE_BULK, | ||
616 | "sq_prepare"); | ||
617 | goto END; | ||
618 | } | ||
619 | |||
620 | if (SQLITE_OK != sqlite3_bind_int (stmtd, 1, sizeof (GNUNET_HashCode))) | ||
621 | LOG_SQLITE (nc->plugin, NULL, | ||
622 | GNUNET_ERROR_TYPE_ERROR | | ||
623 | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_int"); | ||
624 | if (SQLITE_DONE != sqlite3_step (stmtd)) | ||
625 | LOG_SQLITE (nc->plugin, NULL, | ||
626 | GNUNET_ERROR_TYPE_ERROR | | ||
627 | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); | ||
628 | if (SQLITE_OK != sqlite3_finalize (stmtd)) | ||
629 | LOG_SQLITE (nc->plugin, NULL, | ||
630 | GNUNET_ERROR_TYPE_ERROR | | ||
631 | GNUNET_ERROR_TYPE_BULK, "sqlite3_finalize"); | ||
632 | goto END; | 600 | goto END; |
633 | } | 601 | } |
634 | |||
635 | priority = sqlite3_column_int (nc->stmt, 1); | ||
636 | anonymity = sqlite3_column_int (nc->stmt, 2); | ||
637 | expiration.abs_value = sqlite3_column_int64 (nc->stmt, 3); | ||
638 | key = sqlite3_column_blob (nc->stmt, 4); | ||
639 | nc->lastPriority = priority; | ||
640 | nc->lastExpiration = expiration; | ||
641 | memcpy (&nc->lastKey, key, sizeof(GNUNET_HashCode)); | ||
642 | data = sqlite3_column_blob (nc->stmt, 5); | ||
643 | nc->count++; | 602 | nc->count++; |
644 | ret = nc->iter (nc->iter_cls, | 603 | nc->last_rowid = rowid; |
645 | nc, | 604 | nc->lastPriority = priority; |
605 | nc->lastKey = *key; | ||
606 | if (SQLITE_OK != sqlite3_reset (nc->stmt)) | ||
607 | LOG_SQLITE (plugin, NULL, | ||
608 | GNUNET_ERROR_TYPE_ERROR | | ||
609 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); | ||
610 | ret = nc->iter (nc->iter_cls, nc, | ||
646 | key, | 611 | key, |
647 | size, | 612 | size, data, |
648 | data, | 613 | type, priority, |
649 | type, | 614 | anonymity, expiration, |
650 | priority, | ||
651 | anonymity, | ||
652 | expiration, | ||
653 | rowid); | 615 | rowid); |
654 | if (ret == GNUNET_SYSERR) | 616 | switch (ret) |
655 | { | 617 | { |
618 | case GNUNET_SYSERR: | ||
656 | nc->end_it = GNUNET_YES; | 619 | nc->end_it = GNUNET_YES; |
657 | return; | 620 | break; |
658 | } | 621 | case GNUNET_NO: |
659 | #if DEBUG_SQLITE | ||
660 | if (ret == GNUNET_NO) | ||
661 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
662 | "sqlite", | ||
663 | "Asked to remove entry %llu (%u bytes)\n", | ||
664 | (unsigned long long) rowid, | ||
665 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | ||
666 | #endif | ||
667 | if ( (ret == GNUNET_NO) && | ||
668 | (GNUNET_OK == delete_by_rowid (plugin, rowid)) ) | ||
669 | { | ||
670 | plugin->env->duc (plugin->env->cls, | ||
671 | - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); | ||
672 | #if DEBUG_SQLITE | 622 | #if DEBUG_SQLITE |
673 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 623 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
674 | "sqlite", | 624 | "sqlite", |
675 | "Removed entry %llu (%u bytes)\n", | 625 | "Asked to remove entry %llu (%u bytes)\n", |
676 | (unsigned long long) rowid, | 626 | (unsigned long long) rowid, |
677 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | 627 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); |
678 | #endif | 628 | #endif |
629 | if (GNUNET_OK == delete_by_rowid (plugin, rowid)) | ||
630 | { | ||
631 | plugin->env->duc (plugin->env->cls, | ||
632 | - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); | ||
633 | #if DEBUG_SQLITE | ||
634 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
635 | "sqlite", | ||
636 | "Removed entry %llu (%u bytes)\n", | ||
637 | (unsigned long long) rowid, | ||
638 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | ||
639 | #endif | ||
640 | } | ||
641 | break; | ||
642 | case GNUNET_YES: | ||
643 | break; | ||
644 | default: | ||
645 | GNUNET_break (0); | ||
679 | } | 646 | } |
680 | } | 647 | } |
681 | 648 | ||
@@ -723,7 +690,7 @@ sqlite_next_request (void *next_cls, | |||
723 | */ | 690 | */ |
724 | static int | 691 | static int |
725 | sqlite_plugin_put (void *cls, | 692 | sqlite_plugin_put (void *cls, |
726 | const GNUNET_HashCode * key, | 693 | const GNUNET_HashCode *key, |
727 | uint32_t size, | 694 | uint32_t size, |
728 | const void *data, | 695 | const void *data, |
729 | enum GNUNET_BLOCK_Type type, | 696 | enum GNUNET_BLOCK_Type type, |
@@ -774,37 +741,39 @@ sqlite_plugin_put (void *cls, | |||
774 | return GNUNET_SYSERR; | 741 | return GNUNET_SYSERR; |
775 | } | 742 | } |
776 | n = sqlite3_step (stmt); | 743 | n = sqlite3_step (stmt); |
777 | if (n != SQLITE_DONE) | 744 | switch (n) |
778 | { | 745 | { |
779 | if (n == SQLITE_BUSY) | 746 | case SQLITE_DONE: |
780 | { | 747 | if (SQLITE_OK != sqlite3_reset (stmt)) |
781 | LOG_SQLITE (plugin, msg, | 748 | LOG_SQLITE (plugin, NULL, |
782 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); | 749 | GNUNET_ERROR_TYPE_ERROR | |
783 | sqlite3_reset (stmt); | 750 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); |
784 | GNUNET_break (0); | 751 | plugin->env->duc (plugin->env->cls, |
785 | return GNUNET_NO; | 752 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); |
786 | } | 753 | #if DEBUG_SQLITE |
754 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
755 | "sqlite", | ||
756 | "Stored new entry (%u bytes)\n", | ||
757 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | ||
758 | #endif | ||
759 | return GNUNET_OK; | ||
760 | case SQLITE_BUSY: | ||
761 | GNUNET_break (0); | ||
762 | LOG_SQLITE (plugin, msg, | ||
763 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
764 | "sqlite3_step"); | ||
765 | sqlite3_reset (stmt); | ||
766 | return GNUNET_SYSERR; | ||
767 | default: | ||
787 | LOG_SQLITE (plugin, msg, | 768 | LOG_SQLITE (plugin, msg, |
788 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); | 769 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
770 | "sqlite3_step"); | ||
789 | sqlite3_reset (stmt); | 771 | sqlite3_reset (stmt); |
790 | database_shutdown (plugin); | 772 | database_shutdown (plugin); |
791 | database_setup (plugin->env->cfg, | 773 | database_setup (plugin->env->cfg, |
792 | plugin); | 774 | plugin); |
793 | return GNUNET_SYSERR; | 775 | return GNUNET_SYSERR; |
794 | } | 776 | } |
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 | plugin->env->duc (plugin->env->cls, | ||
800 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | ||
801 | #if DEBUG_SQLITE | ||
802 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
803 | "sqlite", | ||
804 | "Stored new entry (%u bytes)\n", | ||
805 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | ||
806 | #endif | ||
807 | return GNUNET_OK; | ||
808 | } | 777 | } |
809 | 778 | ||
810 | 779 | ||
@@ -844,21 +813,27 @@ sqlite_plugin_update (void *cls, | |||
844 | sqlite3_bind_int64 (plugin->updPrio, 2, expire.abs_value); | 813 | sqlite3_bind_int64 (plugin->updPrio, 2, expire.abs_value); |
845 | sqlite3_bind_int64 (plugin->updPrio, 3, uid); | 814 | sqlite3_bind_int64 (plugin->updPrio, 3, uid); |
846 | n = sqlite3_step (plugin->updPrio); | 815 | n = sqlite3_step (plugin->updPrio); |
847 | if (n != SQLITE_DONE) | 816 | sqlite3_reset (plugin->updPrio); |
848 | LOG_SQLITE (plugin, msg, | 817 | switch (n) |
849 | GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | 818 | { |
850 | "sqlite3_step"); | 819 | case SQLITE_DONE: |
851 | #if DEBUG_SQLITE | 820 | #if DEBUG_SQLITE |
852 | else | 821 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
853 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 822 | "sqlite", |
854 | "sqlite", | 823 | "Block updated\n"); |
855 | "Block updated\n"); | ||
856 | #endif | 824 | #endif |
857 | sqlite3_reset (plugin->updPrio); | 825 | return GNUNET_OK; |
858 | 826 | case SQLITE_BUSY: | |
859 | if (n == SQLITE_BUSY) | 827 | LOG_SQLITE (plugin, msg, |
860 | return GNUNET_NO; | 828 | GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, |
861 | return n == SQLITE_DONE ? GNUNET_OK : GNUNET_SYSERR; | 829 | "sqlite3_step"); |
830 | return GNUNET_NO; | ||
831 | default: | ||
832 | LOG_SQLITE (plugin, msg, | ||
833 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
834 | "sqlite3_step"); | ||
835 | return GNUNET_SYSERR; | ||
836 | } | ||
862 | } | 837 | } |
863 | 838 | ||
864 | 839 | ||
@@ -878,26 +853,6 @@ struct IterContext | |||
878 | sqlite3_stmt *stmt_2; | 853 | sqlite3_stmt *stmt_2; |
879 | 854 | ||
880 | /** | 855 | /** |
881 | * FIXME. | ||
882 | */ | ||
883 | int is_asc; | ||
884 | |||
885 | /** | ||
886 | * FIXME. | ||
887 | */ | ||
888 | int is_prio; | ||
889 | |||
890 | /** | ||
891 | * FIXME. | ||
892 | */ | ||
893 | int is_migr; | ||
894 | |||
895 | /** | ||
896 | * FIXME. | ||
897 | */ | ||
898 | int limit_nonanonymous; | ||
899 | |||
900 | /** | ||
901 | * Desired type for blocks returned by this iterator. | 856 | * Desired type for blocks returned by this iterator. |
902 | */ | 857 | */ |
903 | enum GNUNET_BLOCK_Type type; | 858 | enum GNUNET_BLOCK_Type type; |
@@ -934,26 +889,13 @@ iter_next_prepare (void *cls, | |||
934 | sqlite3_reset (ic->stmt_1); | 889 | sqlite3_reset (ic->stmt_1); |
935 | sqlite3_reset (ic->stmt_2); | 890 | sqlite3_reset (ic->stmt_2); |
936 | plugin = nc->plugin; | 891 | plugin = nc->plugin; |
937 | if (ic->is_prio) | ||
938 | { | ||
939 | #if DEBUG_SQLITE | ||
940 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
941 | "Restricting to results larger than the last priority %u\n", | ||
942 | nc->lastPriority); | ||
943 | #endif | ||
944 | sqlite3_bind_int (ic->stmt_1, 1, nc->lastPriority); | ||
945 | sqlite3_bind_int (ic->stmt_2, 1, nc->lastPriority); | ||
946 | } | ||
947 | else | ||
948 | { | ||
949 | #if DEBUG_SQLITE | 892 | #if DEBUG_SQLITE |
950 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 893 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
951 | "Restricting to results larger than the last expiration %llu\n", | 894 | "Restricting to results larger than the last priority %u\n", |
952 | (unsigned long long) nc->lastExpiration.abs_value); | 895 | nc->lastPriority); |
953 | #endif | 896 | #endif |
954 | sqlite3_bind_int64 (ic->stmt_1, 1, nc->lastExpiration.abs_value); | 897 | sqlite3_bind_int (ic->stmt_1, 1, nc->lastPriority); |
955 | sqlite3_bind_int64 (ic->stmt_2, 1, nc->lastExpiration.abs_value); | 898 | sqlite3_bind_int (ic->stmt_2, 1, nc->lastPriority); |
956 | } | ||
957 | #if DEBUG_SQLITE | 899 | #if DEBUG_SQLITE |
958 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 900 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
959 | "Restricting to results larger than the last key `%s'\n", | 901 | "Restricting to results larger than the last key `%s'\n", |
@@ -1016,63 +958,56 @@ iter_next_prepare (void *cls, | |||
1016 | 958 | ||
1017 | 959 | ||
1018 | /** | 960 | /** |
1019 | * Call a method for each key in the database and | 961 | * Select a subset of the items in the datastore and call |
1020 | * call the callback method on it. | 962 | * the given iterator for each of them. |
1021 | * | 963 | * |
1022 | * @param plugin our plugin context | 964 | * @param cls our plugin context |
1023 | * @param type entries of which type should be considered? | 965 | * @param type entries of which type should be considered? |
1024 | * @param is_asc are we iterating in ascending order? | 966 | * Use 0 for any type. |
1025 | * @param is_prio are we iterating by priority (otherwise by expiration) | ||
1026 | * @param is_migr are we iterating in migration order? | ||
1027 | * @param limit_nonanonymous are we restricting results to those with anonymity | ||
1028 | * level zero? | ||
1029 | * @param stmt_str_1 first SQL statement to execute | ||
1030 | * @param stmt_str_2 SQL statement to execute to get "more" results (inner iteration) | ||
1031 | * @param iter function to call on each matching value; | 967 | * @param iter function to call on each matching value; |
1032 | * will be called once with a NULL value at the end | 968 | * will be called once with a NULL value at the end |
1033 | * @param iter_cls closure for iter | 969 | * @param iter_cls closure for iter |
1034 | */ | 970 | */ |
1035 | static void | 971 | static void |
1036 | basic_iter (struct Plugin *plugin, | 972 | sqlite_plugin_iter_zero_anonymity (void *cls, |
1037 | enum GNUNET_BLOCK_Type type, | 973 | enum GNUNET_BLOCK_Type type, |
1038 | int is_asc, | 974 | PluginIterator iter, |
1039 | int is_prio, | 975 | void *iter_cls) |
1040 | int is_migr, | ||
1041 | int limit_nonanonymous, | ||
1042 | const char *stmt_str_1, | ||
1043 | const char *stmt_str_2, | ||
1044 | PluginIterator iter, | ||
1045 | void *iter_cls) | ||
1046 | { | 976 | { |
977 | struct Plugin *plugin = cls; | ||
978 | struct GNUNET_TIME_Absolute now; | ||
1047 | struct NextContext *nc; | 979 | struct NextContext *nc; |
1048 | struct IterContext *ic; | 980 | struct IterContext *ic; |
1049 | sqlite3_stmt *stmt_1; | 981 | sqlite3_stmt *stmt_1; |
1050 | sqlite3_stmt *stmt_2; | 982 | sqlite3_stmt *stmt_2; |
983 | char *q; | ||
1051 | 984 | ||
1052 | #if DEBUG_SQLITE | 985 | now = GNUNET_TIME_absolute_get (); |
1053 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 986 | GNUNET_asprintf (&q, SELECT_IT_NON_ANONYMOUS_1, |
1054 | "At %llu, using queries `%s' and `%s'\n", | 987 | (unsigned long long) now.abs_value); |
1055 | (unsigned long long) GNUNET_TIME_absolute_get ().abs_value, | 988 | if (sq_prepare (plugin->dbh, q, &stmt_1) != SQLITE_OK) |
1056 | stmt_str_1, | ||
1057 | stmt_str_2); | ||
1058 | #endif | ||
1059 | if (sq_prepare (plugin->dbh, stmt_str_1, &stmt_1) != SQLITE_OK) | ||
1060 | { | 989 | { |
1061 | LOG_SQLITE (plugin, NULL, | 990 | LOG_SQLITE (plugin, NULL, |
1062 | GNUNET_ERROR_TYPE_ERROR | | 991 | GNUNET_ERROR_TYPE_ERROR | |
1063 | GNUNET_ERROR_TYPE_BULK, "sqlite3_prepare_v2"); | 992 | GNUNET_ERROR_TYPE_BULK, "sqlite3_prepare_v2"); |
1064 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 993 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
994 | GNUNET_free (q); | ||
1065 | return; | 995 | return; |
1066 | } | 996 | } |
1067 | if (sq_prepare (plugin->dbh, stmt_str_2, &stmt_2) != SQLITE_OK) | 997 | GNUNET_free (q); |
998 | GNUNET_asprintf (&q, SELECT_IT_NON_ANONYMOUS_2, | ||
999 | (unsigned long long) now.abs_value); | ||
1000 | if (sq_prepare (plugin->dbh, q, &stmt_2) != SQLITE_OK) | ||
1068 | { | 1001 | { |
1069 | LOG_SQLITE (plugin, NULL, | 1002 | LOG_SQLITE (plugin, NULL, |
1070 | GNUNET_ERROR_TYPE_ERROR | | 1003 | GNUNET_ERROR_TYPE_ERROR | |
1071 | GNUNET_ERROR_TYPE_BULK, "sqlite3_prepare_v2"); | 1004 | GNUNET_ERROR_TYPE_BULK, "sqlite3_prepare_v2"); |
1072 | sqlite3_finalize (stmt_1); | 1005 | sqlite3_finalize (stmt_1); |
1073 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 1006 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
1007 | GNUNET_free (q); | ||
1074 | return; | 1008 | return; |
1075 | } | 1009 | } |
1010 | GNUNET_free (q); | ||
1076 | nc = GNUNET_malloc (sizeof(struct NextContext) + | 1011 | nc = GNUNET_malloc (sizeof(struct NextContext) + |
1077 | sizeof(struct IterContext)); | 1012 | sizeof(struct IterContext)); |
1078 | nc->plugin = plugin; | 1013 | nc->plugin = plugin; |
@@ -1083,166 +1018,15 @@ basic_iter (struct Plugin *plugin, | |||
1083 | ic->stmt_1 = stmt_1; | 1018 | ic->stmt_1 = stmt_1; |
1084 | ic->stmt_2 = stmt_2; | 1019 | ic->stmt_2 = stmt_2; |
1085 | ic->type = type; | 1020 | ic->type = type; |
1086 | ic->is_asc = is_asc; | ||
1087 | ic->is_prio = is_prio; | ||
1088 | ic->is_migr = is_migr; | ||
1089 | ic->limit_nonanonymous = limit_nonanonymous; | ||
1090 | nc->prep = &iter_next_prepare; | 1021 | nc->prep = &iter_next_prepare; |
1091 | nc->prep_cls = ic; | 1022 | nc->prep_cls = ic; |
1092 | if (is_asc) | 1023 | nc->lastPriority = 0x7FFFFFFF; |
1093 | { | 1024 | memset (&nc->lastKey, 255, sizeof (GNUNET_HashCode)); |
1094 | nc->lastPriority = 0; | ||
1095 | nc->lastExpiration.abs_value = 0; | ||
1096 | memset (&nc->lastKey, 0, sizeof (GNUNET_HashCode)); | ||
1097 | } | ||
1098 | else | ||
1099 | { | ||
1100 | nc->lastPriority = 0x7FFFFFFF; | ||
1101 | nc->lastExpiration.abs_value = 0x7FFFFFFFFFFFFFFFLL; | ||
1102 | memset (&nc->lastKey, 255, sizeof (GNUNET_HashCode)); | ||
1103 | } | ||
1104 | sqlite_next_request (nc, GNUNET_NO); | 1025 | sqlite_next_request (nc, GNUNET_NO); |
1105 | } | 1026 | } |
1106 | 1027 | ||
1107 | 1028 | ||
1108 | /** | 1029 | /** |
1109 | * Select a subset of the items in the datastore and call | ||
1110 | * the given iterator for each of them. | ||
1111 | * | ||
1112 | * @param cls our plugin context | ||
1113 | * @param type entries of which type should be considered? | ||
1114 | * Use 0 for any type. | ||
1115 | * @param iter function to call on each matching value; | ||
1116 | * will be called once with a NULL value at the end | ||
1117 | * @param iter_cls closure for iter | ||
1118 | */ | ||
1119 | static void | ||
1120 | sqlite_plugin_iter_low_priority (void *cls, | ||
1121 | enum GNUNET_BLOCK_Type type, | ||
1122 | PluginIterator iter, | ||
1123 | void *iter_cls) | ||
1124 | { | ||
1125 | basic_iter (cls, | ||
1126 | type, | ||
1127 | GNUNET_YES, GNUNET_YES, | ||
1128 | GNUNET_NO, GNUNET_NO, | ||
1129 | SELECT_IT_LOW_PRIORITY_1, | ||
1130 | SELECT_IT_LOW_PRIORITY_2, | ||
1131 | iter, iter_cls); | ||
1132 | } | ||
1133 | |||
1134 | |||
1135 | /** | ||
1136 | * Select a subset of the items in the datastore and call | ||
1137 | * the given iterator for each of them. | ||
1138 | * | ||
1139 | * @param cls our plugin context | ||
1140 | * @param type entries of which type should be considered? | ||
1141 | * Use 0 for any type. | ||
1142 | * @param iter function to call on each matching value; | ||
1143 | * will be called once with a NULL value at the end | ||
1144 | * @param iter_cls closure for iter | ||
1145 | */ | ||
1146 | static void | ||
1147 | sqlite_plugin_iter_zero_anonymity (void *cls, | ||
1148 | enum GNUNET_BLOCK_Type type, | ||
1149 | PluginIterator iter, | ||
1150 | void *iter_cls) | ||
1151 | { | ||
1152 | struct GNUNET_TIME_Absolute now; | ||
1153 | char *q1; | ||
1154 | char *q2; | ||
1155 | |||
1156 | now = GNUNET_TIME_absolute_get (); | ||
1157 | GNUNET_asprintf (&q1, SELECT_IT_NON_ANONYMOUS_1, | ||
1158 | (unsigned long long) now.abs_value); | ||
1159 | GNUNET_asprintf (&q2, SELECT_IT_NON_ANONYMOUS_2, | ||
1160 | (unsigned long long) now.abs_value); | ||
1161 | basic_iter (cls, | ||
1162 | type, | ||
1163 | GNUNET_NO, GNUNET_YES, | ||
1164 | GNUNET_NO, GNUNET_YES, | ||
1165 | q1, | ||
1166 | q2, | ||
1167 | iter, iter_cls); | ||
1168 | GNUNET_free (q1); | ||
1169 | GNUNET_free (q2); | ||
1170 | } | ||
1171 | |||
1172 | |||
1173 | |||
1174 | /** | ||
1175 | * Select a subset of the items in the datastore and call | ||
1176 | * the given iterator for each of them. | ||
1177 | * | ||
1178 | * @param cls our plugin context | ||
1179 | * @param type entries of which type should be considered? | ||
1180 | * Use 0 for any type. | ||
1181 | * @param iter function to call on each matching value; | ||
1182 | * will be called once with a NULL value at the end | ||
1183 | * @param iter_cls closure for iter | ||
1184 | */ | ||
1185 | static void | ||
1186 | sqlite_plugin_iter_ascending_expiration (void *cls, | ||
1187 | enum GNUNET_BLOCK_Type type, | ||
1188 | PluginIterator iter, | ||
1189 | void *iter_cls) | ||
1190 | { | ||
1191 | struct GNUNET_TIME_Absolute now; | ||
1192 | char *q1; | ||
1193 | char *q2; | ||
1194 | |||
1195 | now = GNUNET_TIME_absolute_get (); | ||
1196 | GNUNET_asprintf (&q1, SELECT_IT_EXPIRATION_TIME_1, | ||
1197 | (unsigned long long) 0*now.abs_value); | ||
1198 | GNUNET_asprintf (&q2, SELECT_IT_EXPIRATION_TIME_2, | ||
1199 | (unsigned long long) 0*now.abs_value); | ||
1200 | basic_iter (cls, | ||
1201 | type, | ||
1202 | GNUNET_YES, GNUNET_NO, | ||
1203 | GNUNET_NO, GNUNET_NO, | ||
1204 | q1, q2, | ||
1205 | iter, iter_cls); | ||
1206 | GNUNET_free (q1); | ||
1207 | GNUNET_free (q2); | ||
1208 | } | ||
1209 | |||
1210 | |||
1211 | /** | ||
1212 | * Select a subset of the items in the datastore and call | ||
1213 | * the given iterator for each of them. | ||
1214 | * | ||
1215 | * @param cls our plugin context | ||
1216 | * @param type entries of which type should be considered? | ||
1217 | * Use 0 for any type. | ||
1218 | * @param iter function to call on each matching value; | ||
1219 | * will be called once with a NULL value at the end | ||
1220 | * @param iter_cls closure for iter | ||
1221 | */ | ||
1222 | static void | ||
1223 | sqlite_plugin_iter_migration_order (void *cls, | ||
1224 | enum GNUNET_BLOCK_Type type, | ||
1225 | PluginIterator iter, | ||
1226 | void *iter_cls) | ||
1227 | { | ||
1228 | struct GNUNET_TIME_Absolute now; | ||
1229 | char *q; | ||
1230 | |||
1231 | now = GNUNET_TIME_absolute_get (); | ||
1232 | GNUNET_asprintf (&q, SELECT_IT_MIGRATION_ORDER_2, | ||
1233 | (unsigned long long) now.abs_value); | ||
1234 | basic_iter (cls, | ||
1235 | type, | ||
1236 | GNUNET_NO, GNUNET_NO, | ||
1237 | GNUNET_YES, GNUNET_NO, | ||
1238 | SELECT_IT_MIGRATION_ORDER_1, | ||
1239 | q, | ||
1240 | iter, iter_cls); | ||
1241 | GNUNET_free (q); | ||
1242 | } | ||
1243 | |||
1244 | |||
1245 | /** | ||
1246 | * Call sqlite using the already prepared query to get | 1030 | * Call sqlite using the already prepared query to get |
1247 | * the next result. | 1031 | * the next result. |
1248 | * | 1032 | * |
@@ -1271,19 +1055,20 @@ all_next_prepare (void *cls, | |||
1271 | return GNUNET_SYSERR; | 1055 | return GNUNET_SYSERR; |
1272 | } | 1056 | } |
1273 | plugin = nc->plugin; | 1057 | plugin = nc->plugin; |
1274 | if (SQLITE_ROW == (ret = sqlite3_step (nc->stmt))) | 1058 | ret = sqlite3_step (nc->stmt); |
1275 | { | 1059 | switch (ret) |
1276 | return GNUNET_OK; | ||
1277 | } | ||
1278 | if (ret != SQLITE_DONE) | ||
1279 | { | 1060 | { |
1061 | case SQLITE_ROW: | ||
1062 | return GNUNET_OK; | ||
1063 | case SQLITE_DONE: | ||
1064 | return GNUNET_NO; | ||
1065 | default: | ||
1280 | LOG_SQLITE (plugin, NULL, | 1066 | LOG_SQLITE (plugin, NULL, |
1281 | GNUNET_ERROR_TYPE_ERROR | | 1067 | GNUNET_ERROR_TYPE_ERROR | |
1282 | GNUNET_ERROR_TYPE_BULK, | 1068 | GNUNET_ERROR_TYPE_BULK, |
1283 | "sqlite3_step"); | 1069 | "sqlite3_step"); |
1284 | return GNUNET_SYSERR; | 1070 | return GNUNET_SYSERR; |
1285 | } | 1071 | } |
1286 | return GNUNET_NO; | ||
1287 | } | 1072 | } |
1288 | 1073 | ||
1289 | 1074 | ||
@@ -1466,7 +1251,7 @@ sqlite_plugin_get (void *cls, | |||
1466 | GNUNET_assert (iter != NULL); | 1251 | GNUNET_assert (iter != NULL); |
1467 | if (key == NULL) | 1252 | if (key == NULL) |
1468 | { | 1253 | { |
1469 | sqlite_plugin_iter_low_priority (cls, type, iter, iter_cls); | 1254 | sqlite_plugin_iter_all_now (cls, type, iter, iter_cls); |
1470 | return; | 1255 | return; |
1471 | } | 1256 | } |
1472 | GNUNET_snprintf (scratch, sizeof (scratch), | 1257 | GNUNET_snprintf (scratch, sizeof (scratch), |
@@ -1561,46 +1346,30 @@ sqlite_plugin_get (void *cls, | |||
1561 | 1346 | ||
1562 | 1347 | ||
1563 | /** | 1348 | /** |
1564 | * Get a random item for replication. Returns a single, not expired, random item | 1349 | * Execute statement that gets a row and call the iterator |
1565 | * from those with the highest replication counters. The item's | 1350 | * with the result. Resets the statement afterwards. |
1566 | * replication counter is decremented by one IF it was positive before. | ||
1567 | * Call 'iter' with all values ZERO or NULL if the datastore is empty. | ||
1568 | * | 1351 | * |
1569 | * @param cls closure | 1352 | * @param plugin the plugin |
1570 | * @param iter function to call the value (once only). | 1353 | * @param stmt the statement |
1571 | * @param iter_cls closure for iter | 1354 | * @param iter iterator to call |
1355 | * @param iter_cls closure for 'iter' | ||
1572 | */ | 1356 | */ |
1573 | static void | 1357 | static void |
1574 | sqlite_plugin_replication_get (void *cls, | 1358 | execute_get (struct Plugin *plugin, |
1575 | PluginIterator iter, void *iter_cls) | 1359 | sqlite3_stmt *stmt, |
1360 | PluginIterator iter, void *iter_cls) | ||
1576 | { | 1361 | { |
1577 | struct Plugin *plugin = cls; | ||
1578 | int n; | 1362 | int n; |
1579 | sqlite3_stmt *stmt; | ||
1580 | struct GNUNET_TIME_Absolute expiration; | 1363 | struct GNUNET_TIME_Absolute expiration; |
1581 | unsigned long long rowid; | 1364 | unsigned long long rowid; |
1365 | unsigned int size; | ||
1366 | int ret; | ||
1582 | 1367 | ||
1583 | #if DEBUG_SQLITE | ||
1584 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1585 | "sqlite", | ||
1586 | "Getting random block based on replication order.\n"); | ||
1587 | #endif | ||
1588 | stmt = plugin->selRepl; | ||
1589 | if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, expiration.abs_value)) | ||
1590 | { | ||
1591 | LOG_SQLITE (plugin, NULL, | ||
1592 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); | ||
1593 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
1594 | LOG_SQLITE (plugin, NULL, | ||
1595 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); | ||
1596 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, | ||
1597 | GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
1598 | return; | ||
1599 | } | ||
1600 | n = sqlite3_step (stmt); | 1368 | n = sqlite3_step (stmt); |
1601 | switch (n) | 1369 | switch (n) |
1602 | { | 1370 | { |
1603 | case SQLITE_ROW: | 1371 | case SQLITE_ROW: |
1372 | size = sqlite3_column_bytes (stmt, 5); | ||
1604 | rowid = sqlite3_column_int64 (stmt, 6); | 1373 | rowid = sqlite3_column_int64 (stmt, 6); |
1605 | if (sqlite3_column_bytes (stmt, 4) != sizeof (GNUNET_HashCode)) | 1374 | if (sqlite3_column_bytes (stmt, 4) != sizeof (GNUNET_HashCode)) |
1606 | { | 1375 | { |
@@ -1611,24 +1380,30 @@ sqlite_plugin_replication_get (void *cls, | |||
1611 | LOG_SQLITE (plugin, NULL, | 1380 | LOG_SQLITE (plugin, NULL, |
1612 | GNUNET_ERROR_TYPE_ERROR | | 1381 | GNUNET_ERROR_TYPE_ERROR | |
1613 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); | 1382 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); |
1614 | delete_by_rowid (plugin, rowid); | 1383 | if (GNUNET_OK == delete_by_rowid (plugin, rowid)) |
1384 | plugin->env->duc (plugin->env->cls, | ||
1385 | - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); | ||
1615 | break; | 1386 | break; |
1616 | } | 1387 | } |
1617 | expiration.abs_value = sqlite3_column_int64 (stmt, 3); | 1388 | expiration.abs_value = sqlite3_column_int64 (stmt, 3); |
1618 | (void) iter (iter_cls, | 1389 | ret = iter (iter_cls, |
1619 | NULL, | 1390 | NULL, |
1620 | sqlite3_column_blob (stmt, 4) /* key */, | 1391 | sqlite3_column_blob (stmt, 4) /* key */, |
1621 | sqlite3_column_bytes (stmt, 5) /* size of data */, | 1392 | size, |
1622 | sqlite3_column_blob (stmt, 5) /* data */, | 1393 | sqlite3_column_blob (stmt, 5) /* data */, |
1623 | sqlite3_column_int (stmt, 0) /* type */, | 1394 | sqlite3_column_int (stmt, 0) /* type */, |
1624 | sqlite3_column_int (stmt, 1) /* priority */, | 1395 | sqlite3_column_int (stmt, 1) /* priority */, |
1625 | sqlite3_column_int (stmt, 2) /* anonymity */, | 1396 | sqlite3_column_int (stmt, 2) /* anonymity */, |
1626 | expiration, | 1397 | expiration, |
1627 | rowid); | 1398 | rowid); |
1628 | if (SQLITE_OK != sqlite3_reset (stmt)) | 1399 | if (SQLITE_OK != sqlite3_reset (stmt)) |
1629 | LOG_SQLITE (plugin, NULL, | 1400 | LOG_SQLITE (plugin, NULL, |
1630 | GNUNET_ERROR_TYPE_ERROR | | 1401 | GNUNET_ERROR_TYPE_ERROR | |
1631 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); | 1402 | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); |
1403 | if ( (GNUNET_NO == ret) && | ||
1404 | (GNUNET_OK == delete_by_rowid (plugin, rowid)) ) | ||
1405 | plugin->env->duc (plugin->env->cls, | ||
1406 | - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); | ||
1632 | return; | 1407 | return; |
1633 | case SQLITE_DONE: | 1408 | case SQLITE_DONE: |
1634 | /* database must be empty */ | 1409 | /* database must be empty */ |
@@ -1657,6 +1432,85 @@ sqlite_plugin_replication_get (void *cls, | |||
1657 | 1432 | ||
1658 | 1433 | ||
1659 | /** | 1434 | /** |
1435 | * Get a random item for replication. Returns a single, not expired, random item | ||
1436 | * from those with the highest replication counters. The item's | ||
1437 | * replication counter is decremented by one IF it was positive before. | ||
1438 | * Call 'iter' with all values ZERO or NULL if the datastore is empty. | ||
1439 | * | ||
1440 | * @param cls closure | ||
1441 | * @param iter function to call the value (once only). | ||
1442 | * @param iter_cls closure for iter | ||
1443 | */ | ||
1444 | static void | ||
1445 | sqlite_plugin_replication_get (void *cls, | ||
1446 | PluginIterator iter, void *iter_cls) | ||
1447 | { | ||
1448 | struct Plugin *plugin = cls; | ||
1449 | sqlite3_stmt *stmt; | ||
1450 | struct GNUNET_TIME_Absolute now; | ||
1451 | |||
1452 | #if DEBUG_SQLITE | ||
1453 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1454 | "sqlite", | ||
1455 | "Getting random block based on replication order.\n"); | ||
1456 | #endif | ||
1457 | stmt = plugin->selRepl; | ||
1458 | now = GNUNET_TIME_absolute_get (); | ||
1459 | if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, now.abs_value)) | ||
1460 | { | ||
1461 | LOG_SQLITE (plugin, NULL, | ||
1462 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); | ||
1463 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
1464 | LOG_SQLITE (plugin, NULL, | ||
1465 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); | ||
1466 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, | ||
1467 | GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
1468 | return; | ||
1469 | } | ||
1470 | execute_get (plugin, stmt, iter, iter_cls); | ||
1471 | } | ||
1472 | |||
1473 | |||
1474 | |||
1475 | /** | ||
1476 | * Get a random item that has expired or has low priority. | ||
1477 | * Call 'iter' with all values ZERO or NULL if the datastore is empty. | ||
1478 | * | ||
1479 | * @param cls closure | ||
1480 | * @param iter function to call the value (once only). | ||
1481 | * @param iter_cls closure for iter | ||
1482 | */ | ||
1483 | static void | ||
1484 | sqlite_plugin_expiration_get (void *cls, | ||
1485 | PluginIterator iter, void *iter_cls) | ||
1486 | { | ||
1487 | struct Plugin *plugin = cls; | ||
1488 | sqlite3_stmt *stmt; | ||
1489 | struct GNUNET_TIME_Absolute now; | ||
1490 | |||
1491 | #if DEBUG_SQLITE | ||
1492 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1493 | "sqlite", | ||
1494 | "Getting random block based on expiration and priority order.\n"); | ||
1495 | #endif | ||
1496 | now = GNUNET_TIME_absolute_get (); | ||
1497 | stmt = plugin->selExpi; | ||
1498 | if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, now.abs_value)) | ||
1499 | { | ||
1500 | LOG_SQLITE (plugin, NULL, | ||
1501 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); | ||
1502 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
1503 | LOG_SQLITE (plugin, NULL, | ||
1504 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); | ||
1505 | iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, | ||
1506 | GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
1507 | return; | ||
1508 | } | ||
1509 | execute_get (plugin, stmt, iter, iter_cls); | ||
1510 | } | ||
1511 | |||
1512 | |||
1513 | /** | ||
1660 | * Drop database. | 1514 | * Drop database. |
1661 | * | 1515 | * |
1662 | * @param cls our plugin context | 1516 | * @param cls our plugin context |
@@ -1669,6 +1523,12 @@ sqlite_plugin_drop (void *cls) | |||
1669 | } | 1523 | } |
1670 | 1524 | ||
1671 | 1525 | ||
1526 | /** | ||
1527 | * FIXME. | ||
1528 | * | ||
1529 | * @param cls the 'struct Plugin' | ||
1530 | * @return the size of the database on disk (estimate) | ||
1531 | */ | ||
1672 | static unsigned long long | 1532 | static unsigned long long |
1673 | sqlite_plugin_get_size (void *cls) | 1533 | sqlite_plugin_get_size (void *cls) |
1674 | { | 1534 | { |
@@ -1749,11 +1609,9 @@ libgnunet_plugin_datastore_sqlite_init (void *cls) | |||
1749 | api->next_request = &sqlite_next_request; | 1609 | api->next_request = &sqlite_next_request; |
1750 | api->get = &sqlite_plugin_get; | 1610 | api->get = &sqlite_plugin_get; |
1751 | api->replication_get = &sqlite_plugin_replication_get; | 1611 | api->replication_get = &sqlite_plugin_replication_get; |
1612 | api->expiration_get = &sqlite_plugin_expiration_get; | ||
1752 | api->update = &sqlite_plugin_update; | 1613 | api->update = &sqlite_plugin_update; |
1753 | api->iter_low_priority = &sqlite_plugin_iter_low_priority; | ||
1754 | api->iter_zero_anonymity = &sqlite_plugin_iter_zero_anonymity; | 1614 | api->iter_zero_anonymity = &sqlite_plugin_iter_zero_anonymity; |
1755 | api->iter_ascending_expiration = &sqlite_plugin_iter_ascending_expiration; | ||
1756 | api->iter_migration_order = &sqlite_plugin_iter_migration_order; | ||
1757 | api->iter_all_now = &sqlite_plugin_iter_all_now; | 1615 | api->iter_all_now = &sqlite_plugin_iter_all_now; |
1758 | api->drop = &sqlite_plugin_drop; | 1616 | api->drop = &sqlite_plugin_drop; |
1759 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, | 1617 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, |