aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_sqlite.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-04-25 16:18:31 +0200
committerChristian Grothoff <christian@grothoff.org>2018-04-25 16:18:31 +0200
commit4dc79497d7f745996068e62e973e34d220580323 (patch)
treee6d429d3cf2240ec3459f1d4533201dc40b27015 /src/namestore/plugin_namestore_sqlite.c
parentbdbb7c684f2c9711989d2543ecc08a95be23e6c4 (diff)
downloadgnunet-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.c185
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 */
533static int 534static int
534get_record_and_call_iterator (struct Plugin *plugin, 535get_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 */
678static int 694static int
679namestore_sqlite_iterate_records (void *cls, 695namestore_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 {