summaryrefslogtreecommitdiff
path: root/src/datastore/plugin_datastore_sqlite.c
diff options
context:
space:
mode:
authorDavid Barksdale <amatus@amat.us>2017-03-19 15:55:32 -0500
committerDavid Barksdale <amatus@amat.us>2017-03-19 17:38:36 -0500
commit2dde0202c5590eeb051c1346f2b66293d83b87ce (patch)
tree7997191912ee4c70959934d6c9783a0c9f450fec /src/datastore/plugin_datastore_sqlite.c
parentd17d833dfd93a81f3540d472d1be4dfb7e9cbd03 (diff)
downloadgnunet-2dde0202c5590eeb051c1346f2b66293d83b87ce.tar.gz
gnunet-2dde0202c5590eeb051c1346f2b66293d83b87ce.zip
[datastore] Fix #3743
This change adds support for key == NULL to the datastore plugins and replaces the offset argument with a next_uid and random arguments to increase performance in the key == NULL case. With the offset argument a datastore plugin would have to count all matching keys before fetching the key at the right offset, which would iterate over the entire database in the case of key == NULL. The offset argument was used in two ways: to iterate over a set of matching values and to start iteration at a random matching value. The new API seperates these into two arguments: if random is true it will return a random matching value, otherwise next_uid can be set to uid + 1 to return the next matching value. The random argument was not added to get_zero_anonymity. This function is used to periodically insert zero anonymity values into the DHT. I don't think it's necessary to randomize this.
Diffstat (limited to 'src/datastore/plugin_datastore_sqlite.c')
-rw-r--r--src/datastore/plugin_datastore_sqlite.c261
1 files changed, 48 insertions, 213 deletions
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c
index 9ca8f056a..76f791ad4 100644
--- a/src/datastore/plugin_datastore_sqlite.c
+++ b/src/datastore/plugin_datastore_sqlite.c
@@ -130,42 +130,7 @@ struct Plugin
130 /** 130 /**
131 * Precompiled SQL for selection 131 * Precompiled SQL for selection
132 */ 132 */
133 sqlite3_stmt *count_key; 133 sqlite3_stmt *get;
134
135 /**
136 * Precompiled SQL for selection
137 */
138 sqlite3_stmt *count_key_vhash;
139
140 /**
141 * Precompiled SQL for selection
142 */
143 sqlite3_stmt *count_key_type;
144
145 /**
146 * Precompiled SQL for selection
147 */
148 sqlite3_stmt *count_key_vhash_type;
149
150 /**
151 * Precompiled SQL for selection
152 */
153 sqlite3_stmt *get_key;
154
155 /**
156 * Precompiled SQL for selection
157 */
158 sqlite3_stmt *get_key_vhash;
159
160 /**
161 * Precompiled SQL for selection
162 */
163 sqlite3_stmt *get_key_type;
164
165 /**
166 * Precompiled SQL for selection
167 */
168 sqlite3_stmt *get_key_vhash_type;
169 134
170 /** 135 /**
171 * Should the database be dropped on shutdown? 136 * Should the database be dropped on shutdown?
@@ -430,8 +395,10 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
430#if SQLITE_VERSION_NUMBER >= 3007000 395#if SQLITE_VERSION_NUMBER >= 3007000
431 "INDEXED BY idx_anon_type_hash " 396 "INDEXED BY idx_anon_type_hash "
432#endif 397#endif
433 "WHERE (anonLevel = 0 AND type=?1) " 398 "WHERE _ROWID_ >= ? AND "
434 "ORDER BY hash DESC LIMIT 1 OFFSET ?2", 399 "anonLevel = 0 AND "
400 "type = ? "
401 "ORDER BY _ROWID_ ASC LIMIT 1",
435 &plugin->selZeroAnon)) || 402 &plugin->selZeroAnon)) ||
436 (SQLITE_OK != 403 (SQLITE_OK !=
437 sq_prepare (plugin->dbh, 404 sq_prepare (plugin->dbh,
@@ -440,44 +407,14 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
440 &plugin->insertContent)) || 407 &plugin->insertContent)) ||
441 (SQLITE_OK != 408 (SQLITE_OK !=
442 sq_prepare (plugin->dbh, 409 sq_prepare (plugin->dbh,
443 "SELECT count(*) FROM gn090 WHERE hash=?",
444 &plugin->count_key)) ||
445 (SQLITE_OK !=
446 sq_prepare (plugin->dbh,
447 "SELECT count(*) FROM gn090 WHERE hash=? AND vhash=?",
448 &plugin->count_key_vhash)) ||
449 (SQLITE_OK !=
450 sq_prepare (plugin->dbh,
451 "SELECT count(*) FROM gn090 WHERE hash=? AND type=?",
452 &plugin->count_key_type)) ||
453 (SQLITE_OK !=
454 sq_prepare (plugin->dbh,
455 "SELECT count(*) FROM gn090 WHERE hash=? AND vhash=? AND type=?",
456 &plugin->count_key_vhash_type)) ||
457 (SQLITE_OK !=
458 sq_prepare (plugin->dbh,
459 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 "
460 "WHERE hash=?"
461 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
462 &plugin->get_key)) ||
463 (SQLITE_OK !=
464 sq_prepare (plugin->dbh,
465 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 "
466 "WHERE hash=? AND vhash=?"
467 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
468 &plugin->get_key_vhash)) ||
469 (SQLITE_OK !=
470 sq_prepare (plugin->dbh,
471 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 " 410 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 "
472 "WHERE hash=? AND type=?" 411 "WHERE _ROWID_ >= ? AND "
473 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?", 412 "(rvalue >= ? OR 0 = ?) AND "
474 &plugin->get_key_type)) || 413 "(hash = ? OR 0 = ?) AND "
475 (SQLITE_OK != 414 "(vhash = ? OR 0 = ?) AND "
476 sq_prepare (plugin->dbh, 415 "(type = ? OR 0 = ?) "
477 "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ FROM gn090 " 416 "ORDER BY _ROWID_ ASC LIMIT 1",
478 "WHERE hash=? AND vhash=? AND type=?" 417 &plugin->get)) ||
479 "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?",
480 &plugin->get_key_vhash_type)) ||
481 (SQLITE_OK != 418 (SQLITE_OK !=
482 sq_prepare (plugin->dbh, 419 sq_prepare (plugin->dbh,
483 "DELETE FROM gn090 WHERE _ROWID_ = ?", 420 "DELETE FROM gn090 WHERE _ROWID_ = ?",
@@ -523,22 +460,8 @@ database_shutdown (struct Plugin *plugin)
523 sqlite3_finalize (plugin->selZeroAnon); 460 sqlite3_finalize (plugin->selZeroAnon);
524 if (NULL != plugin->insertContent) 461 if (NULL != plugin->insertContent)
525 sqlite3_finalize (plugin->insertContent); 462 sqlite3_finalize (plugin->insertContent);
526 if (NULL != plugin->count_key) 463 if (NULL != plugin->get)
527 sqlite3_finalize (plugin->count_key); 464 sqlite3_finalize (plugin->get);
528 if (NULL != plugin->count_key_vhash)
529 sqlite3_finalize (plugin->count_key_vhash);
530 if (NULL != plugin->count_key_type)
531 sqlite3_finalize (plugin->count_key_type);
532 if (NULL != plugin->count_key_vhash_type)
533 sqlite3_finalize (plugin->count_key_vhash_type);
534 if (NULL != plugin->count_key)
535 sqlite3_finalize (plugin->get_key);
536 if (NULL != plugin->count_key_vhash)
537 sqlite3_finalize (plugin->get_key_vhash);
538 if (NULL != plugin->count_key_type)
539 sqlite3_finalize (plugin->get_key_type);
540 if (NULL != plugin->count_key_vhash_type)
541 sqlite3_finalize (plugin->get_key_vhash_type);
542 result = sqlite3_close (plugin->dbh); 465 result = sqlite3_close (plugin->dbh);
543#if SQLITE_VERSION_NUMBER >= 3007000 466#if SQLITE_VERSION_NUMBER >= 3007000
544 if (result == SQLITE_BUSY) 467 if (result == SQLITE_BUSY)
@@ -895,38 +818,36 @@ execute_get (struct Plugin *plugin,
895 * the given processor for the item. 818 * the given processor for the item.
896 * 819 *
897 * @param cls our plugin context 820 * @param cls our plugin context
898 * @param offset offset of the result (modulo num-results); 821 * @param next_uid return the result with lowest uid >= next_uid
899 * specific ordering does not matter for the offset
900 * @param type entries of which type should be considered? 822 * @param type entries of which type should be considered?
901 * Use 0 for any type. 823 * Must not be zero (ANY).
902 * @param proc function to call on each matching value; 824 * @param proc function to call on the matching value;
903 * will be called once with a NULL value at the end 825 * will be called with NULL if no value matches
904 * @param proc_cls closure for @a proc 826 * @param proc_cls closure for @a proc
905 */ 827 */
906static void 828static void
907sqlite_plugin_get_zero_anonymity (void *cls, 829sqlite_plugin_get_zero_anonymity (void *cls,
908 uint64_t offset, 830 uint64_t next_uid,
909 enum GNUNET_BLOCK_Type type, 831 enum GNUNET_BLOCK_Type type,
910 PluginDatumProcessor proc, 832 PluginDatumProcessor proc,
911 void *proc_cls) 833 void *proc_cls)
912{ 834{
913 struct Plugin *plugin = cls; 835 struct Plugin *plugin = cls;
914 struct GNUNET_SQ_QueryParam params[] = { 836 struct GNUNET_SQ_QueryParam params[] = {
837 GNUNET_SQ_query_param_uint64 (&next_uid),
915 GNUNET_SQ_query_param_uint32 (&type), 838 GNUNET_SQ_query_param_uint32 (&type),
916 GNUNET_SQ_query_param_uint64 (&offset),
917 GNUNET_SQ_query_param_end 839 GNUNET_SQ_query_param_end
918 }; 840 };
919 sqlite3_stmt *stmt = plugin->selZeroAnon;
920 841
921 GNUNET_assert (type != GNUNET_BLOCK_TYPE_ANY); 842 GNUNET_assert (type != GNUNET_BLOCK_TYPE_ANY);
922 if (GNUNET_OK != 843 if (GNUNET_OK !=
923 GNUNET_SQ_bind (stmt, 844 GNUNET_SQ_bind (plugin->selZeroAnon,
924 params)) 845 params))
925 { 846 {
926 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 847 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
927 return; 848 return;
928 } 849 }
929 execute_get (plugin, stmt, proc, proc_cls); 850 execute_get (plugin, plugin->selZeroAnon, proc, proc_cls);
930} 851}
931 852
932 853
@@ -934,8 +855,9 @@ sqlite_plugin_get_zero_anonymity (void *cls,
934 * Get results for a particular key in the datastore. 855 * Get results for a particular key in the datastore.
935 * 856 *
936 * @param cls closure 857 * @param cls closure
937 * @param offset offset (mod count). 858 * @param next_uid return the result with lowest uid >= next_uid
938 * @param key key to match, never NULL 859 * @param random if true, return a random result instead of using next_uid
860 * @param key maybe NULL (to match all entries)
939 * @param vhash hash of the value, maybe NULL (to 861 * @param vhash hash of the value, maybe NULL (to
940 * match all values that have the right key). 862 * match all values that have the right key).
941 * Note that for DBlocks there is no difference 863 * Note that for DBlocks there is no difference
@@ -949,7 +871,8 @@ sqlite_plugin_get_zero_anonymity (void *cls,
949 */ 871 */
950static void 872static void
951sqlite_plugin_get_key (void *cls, 873sqlite_plugin_get_key (void *cls,
952 uint64_t offset, 874 uint64_t next_uid,
875 bool random,
953 const struct GNUNET_HashCode *key, 876 const struct GNUNET_HashCode *key,
954 const struct GNUNET_HashCode *vhash, 877 const struct GNUNET_HashCode *vhash,
955 enum GNUNET_BLOCK_Type type, 878 enum GNUNET_BLOCK_Type type,
@@ -957,133 +880,45 @@ sqlite_plugin_get_key (void *cls,
957 void *proc_cls) 880 void *proc_cls)
958{ 881{
959 struct Plugin *plugin = cls; 882 struct Plugin *plugin = cls;
883 uint64_t rvalue;
884 uint16_t use_rvalue = random;
960 uint32_t type32 = (uint32_t) type; 885 uint32_t type32 = (uint32_t) type;
961 int ret; 886 uint16_t use_type = GNUNET_BLOCK_TYPE_ANY != type;
962 int total; 887 uint16_t use_key = NULL != key;
963 uint32_t limit_off; 888 uint16_t use_vhash = NULL != vhash;
964 struct GNUNET_SQ_QueryParam count_params_key[] = { 889 struct GNUNET_SQ_QueryParam params[] = {
965 GNUNET_SQ_query_param_auto_from_type (key), 890 GNUNET_SQ_query_param_uint64 (&next_uid),
966 GNUNET_SQ_query_param_end 891 GNUNET_SQ_query_param_uint64 (&rvalue),
967 }; 892 GNUNET_SQ_query_param_uint16 (&use_rvalue),
968 struct GNUNET_SQ_QueryParam count_params_key_vhash[] = {
969 GNUNET_SQ_query_param_auto_from_type (key),
970 GNUNET_SQ_query_param_auto_from_type (vhash),
971 GNUNET_SQ_query_param_end
972 };
973 struct GNUNET_SQ_QueryParam count_params_key_type[] = {
974 GNUNET_SQ_query_param_auto_from_type (key),
975 GNUNET_SQ_query_param_uint32 (&type32),
976 GNUNET_SQ_query_param_end
977 };
978 struct GNUNET_SQ_QueryParam count_params_key_vhash_type[] = {
979 GNUNET_SQ_query_param_auto_from_type (key),
980 GNUNET_SQ_query_param_auto_from_type (vhash),
981 GNUNET_SQ_query_param_uint32 (&type32),
982 GNUNET_SQ_query_param_end
983 };
984 struct GNUNET_SQ_QueryParam get_params_key[] = {
985 GNUNET_SQ_query_param_auto_from_type (key),
986 GNUNET_SQ_query_param_uint32 (&limit_off),
987 GNUNET_SQ_query_param_end
988 };
989 struct GNUNET_SQ_QueryParam get_params_key_vhash[] = {
990 GNUNET_SQ_query_param_auto_from_type (key),
991 GNUNET_SQ_query_param_auto_from_type (vhash),
992 GNUNET_SQ_query_param_uint32 (&limit_off),
993 GNUNET_SQ_query_param_end
994 };
995 struct GNUNET_SQ_QueryParam get_params_key_type[] = {
996 GNUNET_SQ_query_param_auto_from_type (key),
997 GNUNET_SQ_query_param_uint32 (&type32),
998 GNUNET_SQ_query_param_uint32 (&limit_off),
999 GNUNET_SQ_query_param_end
1000 };
1001 struct GNUNET_SQ_QueryParam get_params_key_vhash_type[] = {
1002 GNUNET_SQ_query_param_auto_from_type (key), 893 GNUNET_SQ_query_param_auto_from_type (key),
894 GNUNET_SQ_query_param_uint16 (&use_key),
1003 GNUNET_SQ_query_param_auto_from_type (vhash), 895 GNUNET_SQ_query_param_auto_from_type (vhash),
896 GNUNET_SQ_query_param_uint16 (&use_vhash),
1004 GNUNET_SQ_query_param_uint32 (&type32), 897 GNUNET_SQ_query_param_uint32 (&type32),
1005 GNUNET_SQ_query_param_uint32 (&limit_off), 898 GNUNET_SQ_query_param_uint16 (&use_type),
1006 GNUNET_SQ_query_param_end 899 GNUNET_SQ_query_param_end
1007 }; 900 };
1008 struct GNUNET_SQ_QueryParam *count_params;
1009 sqlite3_stmt *count_stmt;
1010 struct GNUNET_SQ_QueryParam *get_params;
1011 sqlite3_stmt *get_stmt;
1012 901
1013 if (NULL == vhash) 902 if (random)
1014 { 903 {
1015 if (GNUNET_BLOCK_TYPE_ANY == type) 904 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1016 { 905 UINT64_MAX);
1017 count_params = count_params_key; 906 next_uid = 0;
1018 count_stmt = plugin->count_key;
1019 get_params = get_params_key;
1020 get_stmt = plugin->get_key;
1021 }
1022 else
1023 {
1024 count_params = count_params_key_type;
1025 count_stmt = plugin->count_key_type;
1026 get_params = get_params_key_type;
1027 get_stmt = plugin->get_key_type;
1028 }
1029 } 907 }
1030 else 908 else
1031 { 909 rvalue = 0;
1032 if (GNUNET_BLOCK_TYPE_ANY == type) 910
1033 {
1034 count_params = count_params_key_vhash;
1035 count_stmt = plugin->count_key_vhash;
1036 get_params = get_params_key_vhash;
1037 get_stmt = plugin->get_key_vhash;
1038 }
1039 else
1040 {
1041 count_params = count_params_key_vhash_type;
1042 count_stmt = plugin->count_key_vhash_type;
1043 get_params = get_params_key_vhash_type;
1044 get_stmt = plugin->get_key_vhash_type;
1045 }
1046 }
1047 if (GNUNET_OK !=
1048 GNUNET_SQ_bind (count_stmt,
1049 count_params))
1050 {
1051 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1052 return;
1053 }
1054 ret = sqlite3_step (count_stmt);
1055 if (ret != SQLITE_ROW)
1056 {
1057 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1058 "sqlite_step");
1059 GNUNET_SQ_reset (plugin->dbh,
1060 count_stmt);
1061 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1062 return;
1063 }
1064 total = sqlite3_column_int (count_stmt,
1065 0);
1066 GNUNET_SQ_reset (plugin->dbh,
1067 count_stmt);
1068 if (0 == total)
1069 {
1070 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1071 return;
1072 }
1073 limit_off = (uint32_t) (offset % total);
1074 if (GNUNET_OK != 911 if (GNUNET_OK !=
1075 GNUNET_SQ_bind (get_stmt, 912 GNUNET_SQ_bind (plugin->get,
1076 get_params)) 913 params))
1077 { 914 {
1078 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 915 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1079 return; 916 return;
1080 } 917 }
1081 execute_get (plugin, 918 execute_get (plugin,
1082 get_stmt, 919 plugin->get,
1083 proc, 920 proc,
1084 proc_cls); 921 proc_cls);
1085 GNUNET_SQ_reset (plugin->dbh,
1086 get_stmt);
1087} 922}
1088 923
1089 924