aboutsummaryrefslogtreecommitdiff
path: root/src/datastore/plugin_datastore_mysql.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_mysql.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_mysql.c')
-rw-r--r--src/datastore/plugin_datastore_mysql.c201
1 files changed, 52 insertions, 149 deletions
diff --git a/src/datastore/plugin_datastore_mysql.c b/src/datastore/plugin_datastore_mysql.c
index 1067064aa..5ae4485cb 100644
--- a/src/datastore/plugin_datastore_mysql.c
+++ b/src/datastore/plugin_datastore_mysql.c
@@ -150,28 +150,19 @@ struct Plugin
150#define DELETE_ENTRY_BY_UID "DELETE FROM gn090 WHERE uid=?" 150#define DELETE_ENTRY_BY_UID "DELETE FROM gn090 WHERE uid=?"
151 struct GNUNET_MYSQL_StatementHandle *delete_entry_by_uid; 151 struct GNUNET_MYSQL_StatementHandle *delete_entry_by_uid;
152 152
153#define COUNT_ENTRY_BY_HASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash) WHERE hash=?" 153#define SELECT_ENTRY "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 WHERE uid >= ? AND (rvalue >= ? OR 0 = ?) ORDER BY uid LIMIT 1"
154 struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash; 154 struct GNUNET_MYSQL_StatementHandle *select_entry;
155 155
156#define SELECT_ENTRY_BY_HASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash) WHERE hash=? ORDER BY uid LIMIT 1 OFFSET ?" 156#define SELECT_ENTRY_BY_HASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash) WHERE hash=? AND uid >= ? AND (rvalue >= ? OR 0 = ?) ORDER BY uid LIMIT 1"
157 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash; 157 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash;
158 158
159#define COUNT_ENTRY_BY_HASH_AND_VHASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=?" 159#define SELECT_ENTRY_BY_HASH_AND_VHASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND uid >= ? AND (rvalue >= ? OR 0 = ?) ORDER BY uid LIMIT 1"
160 struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_and_vhash;
161
162#define SELECT_ENTRY_BY_HASH_AND_VHASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? ORDER BY uid LIMIT 1 OFFSET ?"
163 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_vhash; 160 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_vhash;
164 161
165#define COUNT_ENTRY_BY_HASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=?" 162#define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=? AND uid >= ? AND (rvalue >= ? OR 0 = ?) ORDER BY uid LIMIT 1"
166 struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_and_type;
167
168#define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=? ORDER BY uid LIMIT 1 OFFSET ?"
169 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_type; 163 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_type;
170 164
171#define COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=?" 165#define SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=? AND uid >= ? AND (rvalue >= ? OR 0 = ?) ORDER BY uid LIMIT 1"
172 struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_vhash_and_type;
173
174#define SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=? ORDER BY uid ASC LIMIT 1 OFFSET ?"
175 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_vhash_and_type; 166 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_vhash_and_type;
176 167
177#define UPDATE_ENTRY "UPDATE gn090 SET prio=prio+?,expire=IF(expire>=?,expire,?) WHERE uid=?" 168#define UPDATE_ENTRY "UPDATE gn090 SET prio=prio+?,expire=IF(expire>=?,expire,?) WHERE uid=?"
@@ -185,10 +176,8 @@ struct Plugin
185 176
186#define SELECT_IT_NON_ANONYMOUS "SELECT type,prio,anonLevel,expire,hash,value,uid "\ 177#define SELECT_IT_NON_ANONYMOUS "SELECT type,prio,anonLevel,expire,hash,value,uid "\
187 "FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) "\ 178 "FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) "\
188 "WHERE anonLevel=0 AND type=? AND "\ 179 "WHERE anonLevel=0 AND type=? AND uid >= ? "\
189 "(rvalue >= ? OR"\ 180 "ORDER BY uid LIMIT 1"
190 " NOT EXISTS (SELECT 1 FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) WHERE anonLevel=0 AND type=? AND rvalue>=?)) "\
191 "ORDER BY rvalue ASC LIMIT 1"
192 struct GNUNET_MYSQL_StatementHandle *zero_iter; 181 struct GNUNET_MYSQL_StatementHandle *zero_iter;
193 182
194#define SELECT_IT_EXPIRATION "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_expire) WHERE expire < ? ORDER BY expire ASC LIMIT 1" 183#define SELECT_IT_EXPIRATION "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_expire) WHERE expire < ? ORDER BY expire ASC LIMIT 1"
@@ -541,8 +530,8 @@ execute_select (struct Plugin *plugin,
541 * Get one of the results for a particular key in the datastore. 530 * Get one of the results for a particular key in the datastore.
542 * 531 *
543 * @param cls closure 532 * @param cls closure
544 * @param offset offset of the result (modulo num-results); 533 * @param next_uid return the result with lowest uid >= next_uid
545 * specific ordering does not matter for the offset 534 * @param random if true, return a random result instead of using next_uid
546 * @param key key to match, never NULL 535 * @param key key to match, never NULL
547 * @param vhash hash of the value, maybe NULL (to 536 * @param vhash hash of the value, maybe NULL (to
548 * match all values that have the right key). 537 * match all values that have the right key).
@@ -557,7 +546,8 @@ execute_select (struct Plugin *plugin,
557 */ 546 */
558static void 547static void
559mysql_plugin_get_key (void *cls, 548mysql_plugin_get_key (void *cls,
560 uint64_t offset, 549 uint64_t next_uid,
550 bool random,
561 const struct GNUNET_HashCode *key, 551 const struct GNUNET_HashCode *key,
562 const struct GNUNET_HashCode *vhash, 552 const struct GNUNET_HashCode *vhash,
563 enum GNUNET_BLOCK_Type type, 553 enum GNUNET_BLOCK_Type type,
@@ -565,121 +555,33 @@ mysql_plugin_get_key (void *cls,
565 void *proc_cls) 555 void *proc_cls)
566{ 556{
567 struct Plugin *plugin = cls; 557 struct Plugin *plugin = cls;
568 int ret; 558 uint64_t rvalue;
569 uint64_t total;
570 struct GNUNET_MY_ResultSpec results_get[] = {
571 GNUNET_MY_result_spec_uint64 (&total),
572 GNUNET_MY_result_spec_end
573 };
574 559
575 total = UINT64_MAX; 560 if (random)
576 if (0 != type)
577 { 561 {
578 if (NULL != vhash) 562 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
579 { 563 UINT64_MAX);
580 struct GNUNET_MY_QueryParam params_get[] = { 564 next_uid = 0;
581 GNUNET_MY_query_param_auto_from_type (key),
582 GNUNET_MY_query_param_auto_from_type (vhash),
583 GNUNET_MY_query_param_uint32 (&type),
584 GNUNET_MY_query_param_end
585 };
586
587 ret =
588 GNUNET_MY_exec_prepared (plugin->mc,
589 plugin->count_entry_by_hash_vhash_and_type,
590 params_get);
591 GNUNET_break (GNUNET_OK == ret);
592 if (GNUNET_OK == ret)
593 ret =
594 GNUNET_MY_extract_result (plugin->count_entry_by_hash_vhash_and_type,
595 results_get);
596 if (GNUNET_OK == ret)
597 GNUNET_break (GNUNET_NO ==
598 GNUNET_MY_extract_result (plugin->count_entry_by_hash_vhash_and_type,
599 NULL));
600 }
601 else
602 {
603 struct GNUNET_MY_QueryParam params_get[] = {
604 GNUNET_MY_query_param_auto_from_type (key),
605 GNUNET_MY_query_param_uint32 (&type),
606 GNUNET_MY_query_param_end
607 };
608
609 ret =
610 GNUNET_MY_exec_prepared (plugin->mc,
611 plugin->count_entry_by_hash_and_type,
612 params_get);
613 GNUNET_break (GNUNET_OK == ret);
614 if (GNUNET_OK == ret)
615 ret =
616 GNUNET_MY_extract_result (plugin->count_entry_by_hash_and_type,
617 results_get);
618 if (GNUNET_OK == ret)
619 GNUNET_break (GNUNET_NO ==
620 GNUNET_MY_extract_result (plugin->count_entry_by_hash_and_type,
621 NULL));
622 }
623 } 565 }
624 else 566 else
625 { 567 rvalue = 0;
626 if (NULL != vhash)
627 {
628 struct GNUNET_MY_QueryParam params_get[] = {
629 GNUNET_MY_query_param_auto_from_type (key),
630 GNUNET_MY_query_param_auto_from_type (vhash),
631 GNUNET_MY_query_param_end
632 };
633 568
634 ret = 569 if (NULL == key)
635 GNUNET_MY_exec_prepared (plugin->mc,
636 plugin->count_entry_by_hash_and_vhash,
637 params_get);
638 GNUNET_break (GNUNET_OK == ret);
639 if (GNUNET_OK == ret)
640 ret =
641 GNUNET_MY_extract_result (plugin->count_entry_by_hash_and_vhash,
642 results_get);
643 if (GNUNET_OK == ret)
644 GNUNET_break (GNUNET_NO ==
645 GNUNET_MY_extract_result (plugin->count_entry_by_hash_and_vhash,
646 NULL));
647 }
648 else
649 {
650 struct GNUNET_MY_QueryParam params_get[] = {
651 GNUNET_MY_query_param_auto_from_type (key),
652 GNUNET_MY_query_param_end
653 };
654
655 ret =
656 GNUNET_MY_exec_prepared (plugin->mc,
657 plugin->count_entry_by_hash,
658 params_get);
659 GNUNET_break (GNUNET_OK == ret);
660 if (GNUNET_OK == ret)
661 ret =
662 GNUNET_MY_extract_result (plugin->count_entry_by_hash,
663 results_get);
664 if (GNUNET_OK == ret)
665 GNUNET_break (GNUNET_NO ==
666 GNUNET_MY_extract_result (plugin->count_entry_by_hash,
667 NULL));
668 }
669 }
670 if ( (GNUNET_OK != ret) ||
671 (0 >= total) )
672 { 570 {
673 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 571 struct GNUNET_MY_QueryParam params_select[] = {
674 return; 572 GNUNET_MY_query_param_uint64 (&next_uid),
573 GNUNET_MY_query_param_uint64 (&rvalue),
574 GNUNET_MY_query_param_uint64 (&rvalue),
575 GNUNET_MY_query_param_end
576 };
577
578 execute_select (plugin,
579 plugin->select_entry,
580 proc,
581 proc_cls,
582 params_select);
675 } 583 }
676 offset = offset % total; 584 else if (type != GNUNET_BLOCK_TYPE_ANY)
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
678 "Obtaining %llu/%lld result for GET `%s'\n",
679 (unsigned long long) offset,
680 (unsigned long long) total,
681 GNUNET_h2s (key));
682 if (type != GNUNET_BLOCK_TYPE_ANY)
683 { 585 {
684 if (NULL != vhash) 586 if (NULL != vhash)
685 { 587 {
@@ -687,7 +589,9 @@ mysql_plugin_get_key (void *cls,
687 GNUNET_MY_query_param_auto_from_type (key), 589 GNUNET_MY_query_param_auto_from_type (key),
688 GNUNET_MY_query_param_auto_from_type (vhash), 590 GNUNET_MY_query_param_auto_from_type (vhash),
689 GNUNET_MY_query_param_uint32 (&type), 591 GNUNET_MY_query_param_uint32 (&type),
690 GNUNET_MY_query_param_uint64 (&offset), 592 GNUNET_MY_query_param_uint64 (&next_uid),
593 GNUNET_MY_query_param_uint64 (&rvalue),
594 GNUNET_MY_query_param_uint64 (&rvalue),
691 GNUNET_MY_query_param_end 595 GNUNET_MY_query_param_end
692 }; 596 };
693 597
@@ -702,7 +606,9 @@ mysql_plugin_get_key (void *cls,
702 struct GNUNET_MY_QueryParam params_select[] = { 606 struct GNUNET_MY_QueryParam params_select[] = {
703 GNUNET_MY_query_param_auto_from_type (key), 607 GNUNET_MY_query_param_auto_from_type (key),
704 GNUNET_MY_query_param_uint32 (&type), 608 GNUNET_MY_query_param_uint32 (&type),
705 GNUNET_MY_query_param_uint64 (&offset), 609 GNUNET_MY_query_param_uint64 (&next_uid),
610 GNUNET_MY_query_param_uint64 (&rvalue),
611 GNUNET_MY_query_param_uint64 (&rvalue),
706 GNUNET_MY_query_param_end 612 GNUNET_MY_query_param_end
707 }; 613 };
708 614
@@ -720,7 +626,9 @@ mysql_plugin_get_key (void *cls,
720 struct GNUNET_MY_QueryParam params_select[] = { 626 struct GNUNET_MY_QueryParam params_select[] = {
721 GNUNET_MY_query_param_auto_from_type (key), 627 GNUNET_MY_query_param_auto_from_type (key),
722 GNUNET_MY_query_param_auto_from_type (vhash), 628 GNUNET_MY_query_param_auto_from_type (vhash),
723 GNUNET_MY_query_param_uint64 (&offset), 629 GNUNET_MY_query_param_uint64 (&next_uid),
630 GNUNET_MY_query_param_uint64 (&rvalue),
631 GNUNET_MY_query_param_uint64 (&rvalue),
724 GNUNET_MY_query_param_end 632 GNUNET_MY_query_param_end
725 }; 633 };
726 634
@@ -734,7 +642,9 @@ mysql_plugin_get_key (void *cls,
734 { 642 {
735 struct GNUNET_MY_QueryParam params_select[] = { 643 struct GNUNET_MY_QueryParam params_select[] = {
736 GNUNET_MY_query_param_auto_from_type (key), 644 GNUNET_MY_query_param_auto_from_type (key),
737 GNUNET_MY_query_param_uint64 (&offset), 645 GNUNET_MY_query_param_uint64 (&next_uid),
646 GNUNET_MY_query_param_uint64 (&rvalue),
647 GNUNET_MY_query_param_uint64 (&rvalue),
738 GNUNET_MY_query_param_end 648 GNUNET_MY_query_param_end
739 }; 649 };
740 650
@@ -753,28 +663,26 @@ mysql_plugin_get_key (void *cls,
753 * Get a zero-anonymity datum from the datastore. 663 * Get a zero-anonymity datum from the datastore.
754 * 664 *
755 * @param cls our `struct Plugin *` 665 * @param cls our `struct Plugin *`
756 * @param offset offset of the result 666 * @param next_uid return the result with lowest uid >= next_uid
757 * @param type entries of which type should be considered? 667 * @param type entries of which type should be considered?
758 * Use 0 for any type. 668 * Must not be zero (ANY).
759 * @param proc function to call on a matching value or NULL 669 * @param proc function to call on a matching value;
670 * will be called with NULL if no value matches
760 * @param proc_cls closure for @a proc 671 * @param proc_cls closure for @a proc
761 */ 672 */
762static void 673static void
763mysql_plugin_get_zero_anonymity (void *cls, 674mysql_plugin_get_zero_anonymity (void *cls,
764 uint64_t offset, 675 uint64_t next_uid,
765 enum GNUNET_BLOCK_Type type, 676 enum GNUNET_BLOCK_Type type,
766 PluginDatumProcessor proc, 677 PluginDatumProcessor proc,
767 void *proc_cls) 678 void *proc_cls)
768{ 679{
769 struct Plugin *plugin = cls; 680 struct Plugin *plugin = cls;
770 uint32_t typei = (uint32_t) type; 681 uint32_t typei = (uint32_t) type;
771 uint64_t rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, 682
772 UINT64_MAX);
773 struct GNUNET_MY_QueryParam params_zero_iter[] = { 683 struct GNUNET_MY_QueryParam params_zero_iter[] = {
774 GNUNET_MY_query_param_uint32 (&typei), 684 GNUNET_MY_query_param_uint32 (&typei),
775 GNUNET_MY_query_param_uint64 (&rvalue), 685 GNUNET_MY_query_param_uint64 (&next_uid),
776 GNUNET_MY_query_param_uint32 (&typei),
777 GNUNET_MY_query_param_uint64 (&rvalue),
778 GNUNET_MY_query_param_end 686 GNUNET_MY_query_param_end
779 }; 687 };
780 688
@@ -1209,6 +1117,7 @@ libgnunet_plugin_datastore_mysql_init (void *cls)
1209 ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1") || 1117 ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1") ||
1210 PINIT (plugin->insert_entry, INSERT_ENTRY) || 1118 PINIT (plugin->insert_entry, INSERT_ENTRY) ||
1211 PINIT (plugin->delete_entry_by_uid, DELETE_ENTRY_BY_UID) || 1119 PINIT (plugin->delete_entry_by_uid, DELETE_ENTRY_BY_UID) ||
1120 PINIT (plugin->select_entry, SELECT_ENTRY) ||
1212 PINIT (plugin->select_entry_by_hash, SELECT_ENTRY_BY_HASH) || 1121 PINIT (plugin->select_entry_by_hash, SELECT_ENTRY_BY_HASH) ||
1213 PINIT (plugin->select_entry_by_hash_and_vhash, 1122 PINIT (plugin->select_entry_by_hash_and_vhash,
1214 SELECT_ENTRY_BY_HASH_AND_VHASH) || 1123 SELECT_ENTRY_BY_HASH_AND_VHASH) ||
@@ -1216,13 +1125,7 @@ libgnunet_plugin_datastore_mysql_init (void *cls)
1216 SELECT_ENTRY_BY_HASH_AND_TYPE) || 1125 SELECT_ENTRY_BY_HASH_AND_TYPE) ||
1217 PINIT (plugin->select_entry_by_hash_vhash_and_type, 1126 PINIT (plugin->select_entry_by_hash_vhash_and_type,
1218 SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE) || 1127 SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE) ||
1219 PINIT (plugin->count_entry_by_hash, COUNT_ENTRY_BY_HASH) ||
1220 PINIT (plugin->get_size, SELECT_SIZE) || 1128 PINIT (plugin->get_size, SELECT_SIZE) ||
1221 PINIT (plugin->count_entry_by_hash_and_vhash,
1222 COUNT_ENTRY_BY_HASH_AND_VHASH) ||
1223 PINIT (plugin->count_entry_by_hash_and_type, COUNT_ENTRY_BY_HASH_AND_TYPE)
1224 || PINIT (plugin->count_entry_by_hash_vhash_and_type,
1225 COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE) ||
1226 PINIT (plugin->update_entry, UPDATE_ENTRY) || 1129 PINIT (plugin->update_entry, UPDATE_ENTRY) ||
1227 PINIT (plugin->dec_repl, DEC_REPL) || 1130 PINIT (plugin->dec_repl, DEC_REPL) ||
1228 PINIT (plugin->zero_iter, SELECT_IT_NON_ANONYMOUS) || 1131 PINIT (plugin->zero_iter, SELECT_IT_NON_ANONYMOUS) ||