diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-04-25 16:18:31 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-04-25 16:18:31 +0200 |
commit | 4dc79497d7f745996068e62e973e34d220580323 (patch) | |
tree | e6d429d3cf2240ec3459f1d4533201dc40b27015 /src/namestore/plugin_namestore_sqlite.c | |
parent | bdbb7c684f2c9711989d2543ecc08a95be23e6c4 (diff) | |
download | gnunet-4dc79497d7f745996068e62e973e34d220580323.tar.gz gnunet-4dc79497d7f745996068e62e973e34d220580323.zip |
extend namestore API to enable faster iterations by returning more than one result at a time
Diffstat (limited to 'src/namestore/plugin_namestore_sqlite.c')
-rw-r--r-- | src/namestore/plugin_namestore_sqlite.c | 185 |
1 files changed, 104 insertions, 81 deletions
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c index 5ad84688c..f905787b5 100644 --- a/src/namestore/plugin_namestore_sqlite.c +++ b/src/namestore/plugin_namestore_sqlite.c | |||
@@ -302,12 +302,12 @@ database_setup (struct Plugin *plugin) | |||
302 | sq_prepare (plugin->dbh, | 302 | sq_prepare (plugin->dbh, |
303 | "SELECT record_count,record_data,label" | 303 | "SELECT record_count,record_data,label" |
304 | " FROM ns097records WHERE zone_private_key=?" | 304 | " FROM ns097records WHERE zone_private_key=?" |
305 | " ORDER BY rvalue LIMIT 1 OFFSET ?", | 305 | " ORDER BY rvalue LIMIT ? OFFSET ?", |
306 | &plugin->iterate_zone)) || | 306 | &plugin->iterate_zone)) || |
307 | (SQLITE_OK != | 307 | (SQLITE_OK != |
308 | sq_prepare (plugin->dbh, | 308 | sq_prepare (plugin->dbh, |
309 | "SELECT record_count,record_data,label,zone_private_key" | 309 | "SELECT record_count,record_data,label,zone_private_key" |
310 | " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET ?", | 310 | " FROM ns097records ORDER BY rvalue LIMIT ? OFFSET ?", |
311 | &plugin->iterate_all_zones)) || | 311 | &plugin->iterate_all_zones)) || |
312 | (SQLITE_OK != | 312 | (SQLITE_OK != |
313 | sq_prepare (plugin->dbh, | 313 | sq_prepare (plugin->dbh, |
@@ -526,16 +526,18 @@ namestore_sqlite_store_records (void *cls, | |||
526 | * @param plugin plugin context | 526 | * @param plugin plugin context |
527 | * @param stmt to run (and then clean up) | 527 | * @param stmt to run (and then clean up) |
528 | * @param zone_key private key of the zone | 528 | * @param zone_key private key of the zone |
529 | * @param limit maximum number of results to fetch | ||
529 | * @param iter iterator to call with the result | 530 | * @param iter iterator to call with the result |
530 | * @param iter_cls closure for @a iter | 531 | * @param iter_cls closure for @a iter |
531 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | 532 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error |
532 | */ | 533 | */ |
533 | static int | 534 | static int |
534 | get_record_and_call_iterator (struct Plugin *plugin, | 535 | get_records_and_call_iterator (struct Plugin *plugin, |
535 | sqlite3_stmt *stmt, | 536 | sqlite3_stmt *stmt, |
536 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, | 537 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, |
537 | GNUNET_NAMESTORE_RecordIterator iter, | 538 | uint64_t limit, |
538 | void *iter_cls) | 539 | GNUNET_NAMESTORE_RecordIterator iter, |
540 | void *iter_cls) | ||
539 | { | 541 | { |
540 | uint32_t record_count; | 542 | uint32_t record_count; |
541 | size_t data_size; | 543 | size_t data_size; |
@@ -545,74 +547,86 @@ get_record_and_call_iterator (struct Plugin *plugin, | |||
545 | int ret; | 547 | int ret; |
546 | int sret; | 548 | int sret; |
547 | 549 | ||
548 | ret = GNUNET_NO; | 550 | ret = GNUNET_OK; |
549 | if (SQLITE_ROW == (sret = sqlite3_step (stmt))) | 551 | for (uint64_t i = 0;i<limit ; i++) |
550 | { | 552 | { |
551 | struct GNUNET_SQ_ResultSpec rs[] = { | 553 | if (SQLITE_ROW == (sret = sqlite3_step (stmt))) |
552 | GNUNET_SQ_result_spec_uint32 (&record_count), | ||
553 | GNUNET_SQ_result_spec_variable_size (&data, &data_size), | ||
554 | GNUNET_SQ_result_spec_string (&label), | ||
555 | GNUNET_SQ_result_spec_end | ||
556 | }; | ||
557 | struct GNUNET_SQ_ResultSpec rsx[] = { | ||
558 | GNUNET_SQ_result_spec_uint32 (&record_count), | ||
559 | GNUNET_SQ_result_spec_variable_size (&data, &data_size), | ||
560 | GNUNET_SQ_result_spec_string (&label), | ||
561 | GNUNET_SQ_result_spec_auto_from_type (&zk), | ||
562 | GNUNET_SQ_result_spec_end | ||
563 | }; | ||
564 | |||
565 | if (NULL == zone_key) | ||
566 | { | ||
567 | zone_key = &zk; | ||
568 | ret = GNUNET_SQ_extract_result (stmt, | ||
569 | rsx); | ||
570 | } | ||
571 | else | ||
572 | { | ||
573 | ret = GNUNET_SQ_extract_result (stmt, | ||
574 | rs); | ||
575 | } | ||
576 | if ( (GNUNET_OK != ret) || | ||
577 | (record_count > 64 * 1024) ) | ||
578 | { | 554 | { |
579 | /* sanity check, don't stack allocate far too much just | 555 | struct GNUNET_SQ_ResultSpec rs[] = { |
580 | because database might contain a large value here */ | 556 | GNUNET_SQ_result_spec_uint32 (&record_count), |
581 | GNUNET_break (0); | 557 | GNUNET_SQ_result_spec_variable_size (&data, &data_size), |
582 | ret = GNUNET_SYSERR; | 558 | GNUNET_SQ_result_spec_string (&label), |
559 | GNUNET_SQ_result_spec_end | ||
560 | }; | ||
561 | struct GNUNET_SQ_ResultSpec rsx[] = { | ||
562 | GNUNET_SQ_result_spec_uint32 (&record_count), | ||
563 | GNUNET_SQ_result_spec_variable_size (&data, &data_size), | ||
564 | GNUNET_SQ_result_spec_string (&label), | ||
565 | GNUNET_SQ_result_spec_auto_from_type (&zk), | ||
566 | GNUNET_SQ_result_spec_end | ||
567 | }; | ||
568 | |||
569 | if (NULL == zone_key) | ||
570 | { | ||
571 | zone_key = &zk; | ||
572 | ret = GNUNET_SQ_extract_result (stmt, | ||
573 | rsx); | ||
574 | } | ||
575 | else | ||
576 | { | ||
577 | ret = GNUNET_SQ_extract_result (stmt, | ||
578 | rs); | ||
579 | } | ||
580 | if ( (GNUNET_OK != ret) || | ||
581 | (record_count > 64 * 1024) ) | ||
582 | { | ||
583 | /* sanity check, don't stack allocate far too much just | ||
584 | because database might contain a large value here */ | ||
585 | GNUNET_break (0); | ||
586 | ret = GNUNET_SYSERR; | ||
587 | break; | ||
588 | } | ||
589 | else | ||
590 | { | ||
591 | struct GNUNET_GNSRECORD_Data rd[record_count]; | ||
592 | |||
593 | if (GNUNET_OK != | ||
594 | GNUNET_GNSRECORD_records_deserialize (data_size, | ||
595 | data, | ||
596 | record_count, | ||
597 | rd)) | ||
598 | { | ||
599 | GNUNET_break (0); | ||
600 | ret = GNUNET_SYSERR; | ||
601 | break; | ||
602 | } | ||
603 | else | ||
604 | { | ||
605 | if (NULL != iter) | ||
606 | iter (iter_cls, | ||
607 | zone_key, | ||
608 | label, | ||
609 | record_count, | ||
610 | rd); | ||
611 | } | ||
612 | } | ||
613 | GNUNET_SQ_cleanup_result (rs); | ||
583 | } | 614 | } |
584 | else | 615 | else |
585 | { | 616 | { |
586 | struct GNUNET_GNSRECORD_Data rd[record_count]; | 617 | if (SQLITE_DONE != sret) |
587 | |||
588 | if (GNUNET_OK != | ||
589 | GNUNET_GNSRECORD_records_deserialize (data_size, | ||
590 | data, | ||
591 | record_count, | ||
592 | rd)) | ||
593 | { | 618 | { |
594 | GNUNET_break (0); | 619 | LOG_SQLITE (plugin, |
595 | ret = GNUNET_SYSERR; | 620 | GNUNET_ERROR_TYPE_ERROR, |
621 | "sqlite_step"); | ||
622 | ret = GNUNET_SYSERR; | ||
596 | } | 623 | } |
597 | else | 624 | else |
598 | { | 625 | { |
599 | if (NULL != iter) | 626 | ret = GNUNET_NO; |
600 | iter (iter_cls, | ||
601 | zone_key, | ||
602 | label, | ||
603 | record_count, | ||
604 | rd); | ||
605 | ret = GNUNET_YES; | ||
606 | } | 627 | } |
628 | break; | ||
607 | } | 629 | } |
608 | GNUNET_SQ_cleanup_result (rs); | ||
609 | } | ||
610 | else | ||
611 | { | ||
612 | if (SQLITE_DONE != sret) | ||
613 | LOG_SQLITE (plugin, | ||
614 | GNUNET_ERROR_TYPE_ERROR, | ||
615 | "sqlite_step"); | ||
616 | } | 630 | } |
617 | GNUNET_SQ_reset (plugin->dbh, | 631 | GNUNET_SQ_reset (plugin->dbh, |
618 | stmt); | 632 | stmt); |
@@ -656,11 +670,12 @@ namestore_sqlite_lookup_records (void *cls, | |||
656 | plugin->lookup_label); | 670 | plugin->lookup_label); |
657 | return GNUNET_SYSERR; | 671 | return GNUNET_SYSERR; |
658 | } | 672 | } |
659 | return get_record_and_call_iterator (plugin, | 673 | return get_records_and_call_iterator (plugin, |
660 | plugin->lookup_label, | 674 | plugin->lookup_label, |
661 | zone, | 675 | zone, |
662 | iter, | 676 | 1, |
663 | iter_cls); | 677 | iter, |
678 | iter_cls); | ||
664 | } | 679 | } |
665 | 680 | ||
666 | 681 | ||
@@ -671,14 +686,16 @@ namestore_sqlite_lookup_records (void *cls, | |||
671 | * @param cls closure (internal context for the plugin) | 686 | * @param cls closure (internal context for the plugin) |
672 | * @param zone hash of public key of the zone, NULL to iterate over all zones | 687 | * @param zone hash of public key of the zone, NULL to iterate over all zones |
673 | * @param offset offset in the list of all matching records | 688 | * @param offset offset in the list of all matching records |
689 | * @param limit maximum number of results to return | ||
674 | * @param iter function to call with the result | 690 | * @param iter function to call with the result |
675 | * @param iter_cls closure for @a iter | 691 | * @param iter_cls closure for @a iter |
676 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | 692 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error |
677 | */ | 693 | */ |
678 | static int | 694 | static int |
679 | namestore_sqlite_iterate_records (void *cls, | 695 | namestore_sqlite_iterate_records (void *cls, |
680 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 696 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, |
681 | uint64_t offset, | 697 | uint64_t offset, |
698 | uint64_t limit, | ||
682 | GNUNET_NAMESTORE_RecordIterator iter, | 699 | GNUNET_NAMESTORE_RecordIterator iter, |
683 | void *iter_cls) | 700 | void *iter_cls) |
684 | { | 701 | { |
@@ -689,6 +706,7 @@ namestore_sqlite_iterate_records (void *cls, | |||
689 | if (NULL == zone) | 706 | if (NULL == zone) |
690 | { | 707 | { |
691 | struct GNUNET_SQ_QueryParam params[] = { | 708 | struct GNUNET_SQ_QueryParam params[] = { |
709 | GNUNET_SQ_query_param_uint64 (&limit), | ||
692 | GNUNET_SQ_query_param_uint64 (&offset), | 710 | GNUNET_SQ_query_param_uint64 (&offset), |
693 | GNUNET_SQ_query_param_end | 711 | GNUNET_SQ_query_param_end |
694 | }; | 712 | }; |
@@ -701,6 +719,7 @@ namestore_sqlite_iterate_records (void *cls, | |||
701 | { | 719 | { |
702 | struct GNUNET_SQ_QueryParam params[] = { | 720 | struct GNUNET_SQ_QueryParam params[] = { |
703 | GNUNET_SQ_query_param_auto_from_type (zone), | 721 | GNUNET_SQ_query_param_auto_from_type (zone), |
722 | GNUNET_SQ_query_param_uint64 (&limit), | ||
704 | GNUNET_SQ_query_param_uint64 (&offset), | 723 | GNUNET_SQ_query_param_uint64 (&offset), |
705 | GNUNET_SQ_query_param_end | 724 | GNUNET_SQ_query_param_end |
706 | }; | 725 | }; |
@@ -718,11 +737,12 @@ namestore_sqlite_iterate_records (void *cls, | |||
718 | stmt); | 737 | stmt); |
719 | return GNUNET_SYSERR; | 738 | return GNUNET_SYSERR; |
720 | } | 739 | } |
721 | return get_record_and_call_iterator (plugin, | 740 | return get_records_and_call_iterator (plugin, |
722 | stmt, | 741 | stmt, |
723 | zone, | 742 | zone, |
724 | iter, | 743 | limit, |
725 | iter_cls); | 744 | iter, |
745 | iter_cls); | ||
726 | } | 746 | } |
727 | 747 | ||
728 | 748 | ||
@@ -764,11 +784,12 @@ namestore_sqlite_zone_to_name (void *cls, | |||
764 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 784 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
765 | "Performing reverse lookup for `%s'\n", | 785 | "Performing reverse lookup for `%s'\n", |
766 | GNUNET_GNSRECORD_z2s (value_zone)); | 786 | GNUNET_GNSRECORD_z2s (value_zone)); |
767 | return get_record_and_call_iterator (plugin, | 787 | return get_records_and_call_iterator (plugin, |
768 | plugin->zone_to_name, | 788 | plugin->zone_to_name, |
769 | zone, | 789 | zone, |
770 | iter, | 790 | 1, |
771 | iter_cls); | 791 | iter, |
792 | iter_cls); | ||
772 | } | 793 | } |
773 | 794 | ||
774 | 795 | ||
@@ -787,7 +808,9 @@ libgnunet_plugin_namestore_sqlite_init (void *cls) | |||
787 | 808 | ||
788 | if (NULL != plugin.cfg) | 809 | if (NULL != plugin.cfg) |
789 | return NULL; /* can only initialize once! */ | 810 | return NULL; /* can only initialize once! */ |
790 | memset (&plugin, 0, sizeof (struct Plugin)); | 811 | memset (&plugin, |
812 | 0, | ||
813 | sizeof (struct Plugin)); | ||
791 | plugin.cfg = cfg; | 814 | plugin.cfg = cfg; |
792 | if (GNUNET_OK != database_setup (&plugin)) | 815 | if (GNUNET_OK != database_setup (&plugin)) |
793 | { | 816 | { |