aboutsummaryrefslogtreecommitdiff
path: root/src/datastore
diff options
context:
space:
mode:
authorDavid Barksdale <amatus@amat.us>2017-04-16 20:46:21 -0500
committerDavid Barksdale <amatus@amat.us>2017-04-16 20:49:27 -0500
commita58d36b8da7afa42410bac54f57d5f3b6b6c4391 (patch)
tree87b00f07dda6a5c28a9d65ef9c05044cab2336fd /src/datastore
parent4907330f51ffd48af1f7bac6f43c7c7f78c37818 (diff)
downloadgnunet-a58d36b8da7afa42410bac54f57d5f3b6b6c4391.tar.gz
gnunet-a58d36b8da7afa42410bac54f57d5f3b6b6c4391.zip
[datastore] Create remove plugin API call
The only use of vhash in the get_key call was for removing, split that out into its own function. This simplifies the get_key call and removes the need for some indexes, speeding up insertion into the database.
Diffstat (limited to 'src/datastore')
-rw-r--r--src/datastore/gnunet-service-datastore.c80
-rw-r--r--src/datastore/plugin_datastore_heap.c202
-rw-r--r--src/datastore/plugin_datastore_mysql.c209
-rw-r--r--src/datastore/plugin_datastore_postgres.c90
-rw-r--r--src/datastore/plugin_datastore_sqlite.c110
-rw-r--r--src/datastore/plugin_datastore_template.c39
-rw-r--r--src/datastore/test_plugin_datastore.c40
7 files changed, 511 insertions, 259 deletions
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c
index d965ad8e0..53ba858e4 100644
--- a/src/datastore/gnunet-service-datastore.c
+++ b/src/datastore/gnunet-service-datastore.c
@@ -880,7 +880,6 @@ handle_get (void *cls,
880 GNUNET_ntohll (msg->next_uid), 880 GNUNET_ntohll (msg->next_uid),
881 msg->random, 881 msg->random,
882 NULL, 882 NULL,
883 NULL,
884 ntohl (msg->type), 883 ntohl (msg->type),
885 &transmit_item, 884 &transmit_item,
886 client); 885 client);
@@ -932,7 +931,6 @@ handle_get_key (void *cls,
932 GNUNET_ntohll (msg->next_uid), 931 GNUNET_ntohll (msg->next_uid),
933 msg->random, 932 msg->random,
934 &msg->key, 933 &msg->key,
935 NULL,
936 ntohl (msg->type), 934 ntohl (msg->type),
937 &transmit_item, 935 &transmit_item,
938 client); 936 client);
@@ -1001,50 +999,46 @@ handle_get_zero_anonymity (void *cls,
1001 999
1002 1000
1003/** 1001/**
1004 * Callback function that will cause the item that is passed 1002 * Remove continuation.
1005 * in to be deleted (by returning #GNUNET_NO).
1006 * 1003 *
1007 * @param cls closure 1004 * @param cls closure
1008 * @param key key for the content 1005 * @param key key for the content
1009 * @param size number of bytes in data 1006 * @param size number of bytes in data
1010 * @param data content stored 1007 * @param status #GNUNET_OK if removed, #GNUNET_NO if not found,
1011 * @param type type of the content 1008 * or #GNUNET_SYSERROR if error
1012 * @param priority priority of the content 1009 * @param msg error message on error
1013 * @param anonymity anonymity-level for the content
1014 * @param replication replication-level for the content
1015 * @param expiration expiration time for the content
1016 * @param uid unique identifier for the datum
1017 * @return #GNUNET_OK to keep the item
1018 * #GNUNET_NO to delete the item
1019 */ 1010 */
1020static int 1011static void
1021remove_callback (void *cls, 1012remove_continuation (void *cls,
1022 const struct GNUNET_HashCode *key, 1013 const struct GNUNET_HashCode *key,
1023 uint32_t size, 1014 uint32_t size,
1024 const void *data, 1015 int status,
1025 enum GNUNET_BLOCK_Type type, 1016 const char *msg)
1026 uint32_t priority,
1027 uint32_t anonymity,
1028 uint32_t replication,
1029 struct GNUNET_TIME_Absolute expiration,
1030 uint64_t uid)
1031{ 1017{
1032 struct GNUNET_SERVICE_Client *client = cls; 1018 struct GNUNET_SERVICE_Client *client = cls;
1033 1019
1034 if (NULL == key) 1020 if (GNUNET_SYSERR == status)
1021 {
1022 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1023 "REMOVE request failed: %s.\n",
1024 msg);
1025 transmit_status (client,
1026 GNUNET_NO,
1027 msg);
1028 return;
1029 }
1030 if (GNUNET_NO == status)
1035 { 1031 {
1036 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1037 "No further matches for REMOVE request.\n"); 1033 "Content not found for REMOVE request.\n");
1038 transmit_status (client, 1034 transmit_status (client,
1039 GNUNET_NO, 1035 GNUNET_NO,
1040 _("Content not found")); 1036 _("Content not found"));
1041 return GNUNET_OK; /* last item */ 1037 return;
1042 } 1038 }
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1039 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1044 "Item %llu matches REMOVE request for key `%s' and type %u.\n", 1040 "Item matches REMOVE request for key `%s'.\n",
1045 (unsigned long long) uid, 1041 GNUNET_h2s (key));
1046 GNUNET_h2s (key),
1047 type);
1048 GNUNET_STATISTICS_update (stats, 1042 GNUNET_STATISTICS_update (stats,
1049 gettext_noop ("# bytes removed (explicit request)"), 1043 gettext_noop ("# bytes removed (explicit request)"),
1050 size, 1044 size,
@@ -1054,7 +1048,6 @@ remove_callback (void *cls,
1054 transmit_status (client, 1048 transmit_status (client,
1055 GNUNET_OK, 1049 GNUNET_OK,
1056 NULL); 1050 NULL);
1057 return GNUNET_NO;
1058} 1051}
1059 1052
1060 1053
@@ -1090,26 +1083,19 @@ handle_remove (void *cls,
1090 const struct DataMessage *dm) 1083 const struct DataMessage *dm)
1091{ 1084{
1092 struct GNUNET_SERVICE_Client *client = cls; 1085 struct GNUNET_SERVICE_Client *client = cls;
1093 struct GNUNET_HashCode vhash;
1094 1086
1095 GNUNET_STATISTICS_update (stats, 1087 GNUNET_STATISTICS_update (stats,
1096 gettext_noop ("# REMOVE requests received"), 1088 gettext_noop ("# REMOVE requests received"),
1097 1, GNUNET_NO); 1089 1, GNUNET_NO);
1098 GNUNET_CRYPTO_hash (&dm[1],
1099 ntohl (dm->size),
1100 &vhash);
1101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1102 "Processing REMOVE request for `%s' of type %u\n", 1091 "Processing REMOVE request for `%s'\n",
1103 GNUNET_h2s (&dm->key), 1092 GNUNET_h2s (&dm->key));
1104 (uint32_t) ntohl (dm->type)); 1093 plugin->api->remove_key (plugin->api->cls,
1105 plugin->api->get_key (plugin->api->cls, 1094 &dm->key,
1106 0, 1095 ntohl (dm->size),
1107 false, 1096 &dm[1],
1108 &dm->key, 1097 &remove_continuation,
1109 &vhash, 1098 client);
1110 (enum GNUNET_BLOCK_Type) ntohl (dm->type),
1111 &remove_callback,
1112 client);
1113 GNUNET_SERVICE_client_continue (client); 1099 GNUNET_SERVICE_client_continue (client);
1114} 1100}
1115 1101
diff --git a/src/datastore/plugin_datastore_heap.c b/src/datastore/plugin_datastore_heap.c
index 6dbc15ebd..9950f7ab2 100644
--- a/src/datastore/plugin_datastore_heap.c
+++ b/src/datastore/plugin_datastore_heap.c
@@ -433,11 +433,6 @@ struct GetContext
433 struct Value *value; 433 struct Value *value;
434 434
435 /** 435 /**
436 * Requested value hash.
437 */
438 const struct GNUNET_HashCode *vhash;
439
440 /**
441 * Requested type. 436 * Requested type.
442 */ 437 */
443 enum GNUNET_BLOCK_Type type; 438 enum GNUNET_BLOCK_Type type;
@@ -465,17 +460,10 @@ get_iterator (void *cls,
465{ 460{
466 struct GetContext *gc = cls; 461 struct GetContext *gc = cls;
467 struct Value *value = val; 462 struct Value *value = val;
468 struct GNUNET_HashCode vh;
469 463
470 if ( (gc->type != GNUNET_BLOCK_TYPE_ANY) && 464 if ( (gc->type != GNUNET_BLOCK_TYPE_ANY) &&
471 (gc->type != value->type) ) 465 (gc->type != value->type) )
472 return GNUNET_OK; 466 return GNUNET_OK;
473 if (NULL != gc->vhash)
474 {
475 GNUNET_CRYPTO_hash (&value[1], value->size, &vh);
476 if (0 != memcmp (&vh, gc->vhash, sizeof (struct GNUNET_HashCode)))
477 return GNUNET_OK;
478 }
479 if (gc->random) 467 if (gc->random)
480 { 468 {
481 gc->value = value; 469 gc->value = value;
@@ -498,23 +486,20 @@ get_iterator (void *cls,
498 * @param next_uid return the result with lowest uid >= next_uid 486 * @param next_uid return the result with lowest uid >= next_uid
499 * @param random if true, return a random result instead of using next_uid 487 * @param random if true, return a random result instead of using next_uid
500 * @param key maybe NULL (to match all entries) 488 * @param key maybe NULL (to match all entries)
501 * @param vhash hash of the value, maybe NULL (to
502 * match all values that have the right key).
503 * Note that for DBlocks there is no difference
504 * betwen key and vhash, but for other blocks
505 * there may be!
506 * @param type entries of which type are relevant? 489 * @param type entries of which type are relevant?
507 * Use 0 for any type. 490 * Use 0 for any type.
508 * @param proc function to call on each matching value; 491 * @param proc function to call on the matching value;
509 * will be called with NULL if nothing matches 492 * will be called with NULL if nothing matches
510 * @param proc_cls closure for proc 493 * @param proc_cls closure for @a proc
511 */ 494 */
512static void 495static void
513heap_plugin_get_key (void *cls, uint64_t next_uid, bool random, 496heap_plugin_get_key (void *cls,
514 const struct GNUNET_HashCode *key, 497 uint64_t next_uid,
515 const struct GNUNET_HashCode *vhash, 498 bool random,
516 enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, 499 const struct GNUNET_HashCode *key,
517 void *proc_cls) 500 enum GNUNET_BLOCK_Type type,
501 PluginDatumProcessor proc,
502 void *proc_cls)
518{ 503{
519 struct Plugin *plugin = cls; 504 struct Plugin *plugin = cls;
520 struct GetContext gc; 505 struct GetContext gc;
@@ -522,7 +507,6 @@ heap_plugin_get_key (void *cls, uint64_t next_uid, bool random,
522 gc.value = NULL; 507 gc.value = NULL;
523 gc.next_uid = next_uid; 508 gc.next_uid = next_uid;
524 gc.random = random; 509 gc.random = random;
525 gc.vhash = vhash;
526 gc.type = type; 510 gc.type = type;
527 if (NULL == key) 511 if (NULL == key)
528 { 512 {
@@ -542,20 +526,17 @@ heap_plugin_get_key (void *cls, uint64_t next_uid, bool random,
542 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 526 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
543 return; 527 return;
544 } 528 }
545 if (GNUNET_NO == 529 GNUNET_assert (GNUNET_OK ==
546 proc (proc_cls, 530 proc (proc_cls,
547 &gc.value->key, 531 &gc.value->key,
548 gc.value->size, 532 gc.value->size,
549 &gc.value[1], 533 &gc.value[1],
550 gc.value->type, 534 gc.value->type,
551 gc.value->priority, 535 gc.value->priority,
552 gc.value->anonymity, 536 gc.value->anonymity,
553 gc.value->replication, 537 gc.value->replication,
554 gc.value->expiration, 538 gc.value->expiration,
555 (uint64_t) (intptr_t) gc.value)) 539 (uint64_t) (intptr_t) gc.value));
556 {
557 delete_value (plugin, gc.value);
558 }
559} 540}
560 541
561 542
@@ -599,18 +580,17 @@ heap_plugin_get_replication (void *cls,
599 value->replication); 580 value->replication);
600 value = GNUNET_CONTAINER_heap_walk_get_next (plugin->by_replication); 581 value = GNUNET_CONTAINER_heap_walk_get_next (plugin->by_replication);
601 } 582 }
602 if (GNUNET_NO == 583 GNUNET_assert (GNUNET_OK ==
603 proc (proc_cls, 584 proc (proc_cls,
604 &value->key, 585 &value->key,
605 value->size, 586 value->size,
606 &value[1], 587 &value[1],
607 value->type, 588 value->type,
608 value->priority, 589 value->priority,
609 value->anonymity, 590 value->anonymity,
610 value->replication, 591 value->replication,
611 value->expiration, 592 value->expiration,
612 (uint64_t) (intptr_t) value)) 593 (uint64_t) (intptr_t) value));
613 delete_value (plugin, value);
614} 594}
615 595
616 596
@@ -690,18 +670,17 @@ heap_plugin_get_zero_anonymity (void *cls, uint64_t next_uid,
690 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); 670 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
691 return; 671 return;
692 } 672 }
693 if (GNUNET_NO == 673 GNUNET_assert (GNUNET_OK ==
694 proc (proc_cls, 674 proc (proc_cls,
695 &value->key, 675 &value->key,
696 value->size, 676 value->size,
697 &value[1], 677 &value[1],
698 value->type, 678 value->type,
699 value->priority, 679 value->priority,
700 value->anonymity, 680 value->anonymity,
701 value->replication, 681 value->replication,
702 value->expiration, 682 value->expiration,
703 (uint64_t) (intptr_t) value)) 683 (uint64_t) (intptr_t) value));
704 delete_value (plugin, value);
705} 684}
706 685
707 686
@@ -779,6 +758,102 @@ heap_get_keys (void *cls,
779 758
780 759
781/** 760/**
761 * Closure for iterator called during 'remove_key'.
762 */
763struct RemoveContext
764{
765
766 /**
767 * Value found.
768 */
769 struct Value *value;
770
771 /**
772 * Size of data.
773 */
774 uint32_t size;
775
776 /**
777 * Data to remove.
778 */
779 const void *data;
780
781};
782
783
784/**
785 * Obtain the matching value with the lowest uid >= next_uid.
786 *
787 * @param cls the 'struct GetContext'
788 * @param key unused
789 * @param val the 'struct Value'
790 * @return GNUNET_YES (continue iteration), GNUNET_NO if result was found
791 */
792static int
793remove_iterator (void *cls,
794 const struct GNUNET_HashCode *key,
795 void *val)
796{
797 struct RemoveContext *rc = cls;
798 struct Value *value = val;
799
800 if (value->size != rc->size)
801 return GNUNET_YES;
802 if (0 != memcmp (value->data, rc->data, rc->size))
803 return GNUNET_YES;
804 rc->value = value;
805 return GNUNET_NO;
806}
807
808
809/**
810 * Remove a particular key in the datastore.
811 *
812 * @param cls closure
813 * @param key key for the content
814 * @param size number of bytes in data
815 * @param data content stored
816 * @param cont continuation called with success or failure status
817 * @param cont_cls continuation closure for @a cont
818 */
819static void
820heap_plugin_remove_key (void *cls,
821 const struct GNUNET_HashCode *key,
822 uint32_t size,
823 const void *data,
824 PluginRemoveCont cont,
825 void *cont_cls)
826{
827 struct Plugin *plugin = cls;
828 struct RemoveContext rc;
829
830 rc.value = NULL;
831 rc.size = size;
832 rc.data = data;
833 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->keyvalue,
834 key,
835 &remove_iterator,
836 &rc);
837 if (NULL == rc.value)
838 {
839 cont (cont_cls,
840 key,
841 size,
842 GNUNET_NO,
843 NULL);
844 return;
845 }
846 delete_value (plugin,
847 rc.value);
848 cont (cont_cls,
849 key,
850 size,
851 GNUNET_OK,
852 NULL);
853}
854
855
856/**
782 * Entry point for the plugin. 857 * Entry point for the plugin.
783 * 858 *
784 * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*" 859 * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*"
@@ -813,6 +888,7 @@ libgnunet_plugin_datastore_heap_init (void *cls)
813 api->get_zero_anonymity = &heap_plugin_get_zero_anonymity; 888 api->get_zero_anonymity = &heap_plugin_get_zero_anonymity;
814 api->drop = &heap_plugin_drop; 889 api->drop = &heap_plugin_drop;
815 api->get_keys = &heap_get_keys; 890 api->get_keys = &heap_get_keys;
891 api->remove_key = &heap_plugin_remove_key;
816 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "heap", 892 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "heap",
817 _("Heap database running\n")); 893 _("Heap database running\n"));
818 return api; 894 return api;
diff --git a/src/datastore/plugin_datastore_mysql.c b/src/datastore/plugin_datastore_mysql.c
index edc459272..708e35860 100644
--- a/src/datastore/plugin_datastore_mysql.c
+++ b/src/datastore/plugin_datastore_mysql.c
@@ -150,6 +150,12 @@ 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 DELETE_ENTRY_BY_HASH_VALUE "DELETE FROM gn090 "\
154 "WHERE hash = ? AND "\
155 "value = ? "\
156 "LIMIT 1"
157 struct GNUNET_MYSQL_StatementHandle *delete_entry_by_hash_value;
158
153#define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, uid" 159#define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, uid"
154 160
155#define SELECT_ENTRY "SELECT " RESULT_COLUMNS " FROM gn090 "\ 161#define SELECT_ENTRY "SELECT " RESULT_COLUMNS " FROM gn090 "\
@@ -159,22 +165,13 @@ struct Plugin
159 struct GNUNET_MYSQL_StatementHandle *select_entry; 165 struct GNUNET_MYSQL_StatementHandle *select_entry;
160 166
161#define SELECT_ENTRY_BY_HASH "SELECT " RESULT_COLUMNS " FROM gn090 "\ 167#define SELECT_ENTRY_BY_HASH "SELECT " RESULT_COLUMNS " FROM gn090 "\
162 "FORCE INDEX (idx_hash) "\ 168 "FORCE INDEX (idx_hash_type_uid) "\
163 "WHERE hash=? AND "\ 169 "WHERE hash=? AND "\
164 "uid >= ? AND "\ 170 "uid >= ? AND "\
165 "(rvalue >= ? OR 0 = ?) "\ 171 "(rvalue >= ? OR 0 = ?) "\
166 "ORDER BY uid LIMIT 1" 172 "ORDER BY uid LIMIT 1"
167 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash; 173 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash;
168 174
169#define SELECT_ENTRY_BY_HASH_AND_VHASH "SELECT " RESULT_COLUMNS " FROM gn090 "\
170 "FORCE INDEX (idx_hash_vhash) "\
171 "WHERE hash = ? AND "\
172 "vhash = ? AND "\
173 "uid >= ? AND "\
174 "(rvalue >= ? OR 0 = ?) "\
175 "ORDER BY uid LIMIT 1"
176 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_vhash;
177
178#define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT " RESULT_COLUMNS " FROM gn090 "\ 175#define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT " RESULT_COLUMNS " FROM gn090 "\
179 "FORCE INDEX (idx_hash_type_uid) "\ 176 "FORCE INDEX (idx_hash_type_uid) "\
180 "WHERE hash = ? AND "\ 177 "WHERE hash = ? AND "\
@@ -184,17 +181,6 @@ struct Plugin
184 "ORDER BY uid LIMIT 1" 181 "ORDER BY uid LIMIT 1"
185 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_type; 182 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_type;
186 183
187#define SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT " RESULT_COLUMNS " "\
188 "FROM gn090 "\
189 "FORCE INDEX (idx_hash_vhash) "\
190 "WHERE hash = ? AND "\
191 "vhash = ? AND "\
192 "type = ? AND "\
193 "uid >= ? AND "\
194 "(rvalue >= ? OR 0 = ?) "\
195 "ORDER BY uid LIMIT 1"
196 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_vhash_and_type;
197
198#define UPDATE_ENTRY "UPDATE gn090 SET "\ 184#define UPDATE_ENTRY "UPDATE gn090 SET "\
199 "prio = prio + ?, "\ 185 "prio = prio + ?, "\
200 "repl = repl + ?, "\ 186 "repl = repl + ?, "\
@@ -552,11 +538,6 @@ execute_select (struct Plugin *plugin,
552 * @param next_uid return the result with lowest uid >= next_uid 538 * @param next_uid return the result with lowest uid >= next_uid
553 * @param random if true, return a random result instead of using next_uid 539 * @param random if true, return a random result instead of using next_uid
554 * @param key key to match, never NULL 540 * @param key key to match, never NULL
555 * @param vhash hash of the value, maybe NULL (to
556 * match all values that have the right key).
557 * Note that for DBlocks there is no difference
558 * betwen key and vhash, but for other blocks
559 * there may be!
560 * @param type entries of which type are relevant? 541 * @param type entries of which type are relevant?
561 * Use 0 for any type. 542 * Use 0 for any type.
562 * @param proc function to call on the matching value, 543 * @param proc function to call on the matching value,
@@ -568,7 +549,6 @@ mysql_plugin_get_key (void *cls,
568 uint64_t next_uid, 549 uint64_t next_uid,
569 bool random, 550 bool random,
570 const struct GNUNET_HashCode *key, 551 const struct GNUNET_HashCode *key,
571 const struct GNUNET_HashCode *vhash,
572 enum GNUNET_BLOCK_Type type, 552 enum GNUNET_BLOCK_Type type,
573 PluginDatumProcessor proc, 553 PluginDatumProcessor proc,
574 void *proc_cls) 554 void *proc_cls)
@@ -602,79 +582,37 @@ mysql_plugin_get_key (void *cls,
602 } 582 }
603 else if (type != GNUNET_BLOCK_TYPE_ANY) 583 else if (type != GNUNET_BLOCK_TYPE_ANY)
604 { 584 {
605 if (NULL != vhash) 585 struct GNUNET_MY_QueryParam params_select[] = {
606 { 586 GNUNET_MY_query_param_auto_from_type (key),
607 struct GNUNET_MY_QueryParam params_select[] = { 587 GNUNET_MY_query_param_uint32 (&type),
608 GNUNET_MY_query_param_auto_from_type (key), 588 GNUNET_MY_query_param_uint64 (&next_uid),
609 GNUNET_MY_query_param_auto_from_type (vhash), 589 GNUNET_MY_query_param_uint64 (&rvalue),
610 GNUNET_MY_query_param_uint32 (&type), 590 GNUNET_MY_query_param_uint64 (&rvalue),
611 GNUNET_MY_query_param_uint64 (&next_uid), 591 GNUNET_MY_query_param_end
612 GNUNET_MY_query_param_uint64 (&rvalue), 592 };
613 GNUNET_MY_query_param_uint64 (&rvalue), 593
614 GNUNET_MY_query_param_end 594 execute_select (plugin,
615 }; 595 plugin->select_entry_by_hash_and_type,
616 596 proc,
617 execute_select (plugin, 597 proc_cls,
618 plugin->select_entry_by_hash_vhash_and_type, 598 params_select);
619 proc,
620 proc_cls,
621 params_select);
622 }
623 else
624 {
625 struct GNUNET_MY_QueryParam params_select[] = {
626 GNUNET_MY_query_param_auto_from_type (key),
627 GNUNET_MY_query_param_uint32 (&type),
628 GNUNET_MY_query_param_uint64 (&next_uid),
629 GNUNET_MY_query_param_uint64 (&rvalue),
630 GNUNET_MY_query_param_uint64 (&rvalue),
631 GNUNET_MY_query_param_end
632 };
633
634 execute_select (plugin,
635 plugin->select_entry_by_hash_and_type,
636 proc,
637 proc_cls,
638 params_select);
639 }
640 } 599 }
641 else 600 else
642 { 601 {
643 if (NULL != vhash) 602 struct GNUNET_MY_QueryParam params_select[] = {
644 { 603 GNUNET_MY_query_param_auto_from_type (key),
645 struct GNUNET_MY_QueryParam params_select[] = { 604 GNUNET_MY_query_param_uint64 (&next_uid),
646 GNUNET_MY_query_param_auto_from_type (key), 605 GNUNET_MY_query_param_uint64 (&rvalue),
647 GNUNET_MY_query_param_auto_from_type (vhash), 606 GNUNET_MY_query_param_uint64 (&rvalue),
648 GNUNET_MY_query_param_uint64 (&next_uid), 607 GNUNET_MY_query_param_end
649 GNUNET_MY_query_param_uint64 (&rvalue), 608 };
650 GNUNET_MY_query_param_uint64 (&rvalue),
651 GNUNET_MY_query_param_end
652 };
653
654 execute_select (plugin,
655 plugin->select_entry_by_hash_and_vhash,
656 proc,
657 proc_cls,
658 params_select);
659 }
660 else
661 {
662 struct GNUNET_MY_QueryParam params_select[] = {
663 GNUNET_MY_query_param_auto_from_type (key),
664 GNUNET_MY_query_param_uint64 (&next_uid),
665 GNUNET_MY_query_param_uint64 (&rvalue),
666 GNUNET_MY_query_param_uint64 (&rvalue),
667 GNUNET_MY_query_param_end
668 };
669
670 execute_select (plugin,
671 plugin->select_entry_by_hash,
672 proc,
673 proc_cls,
674 params_select);
675 }
676 }
677 609
610 execute_select (plugin,
611 plugin->select_entry_by_hash,
612 proc,
613 proc_cls,
614 params_select);
615 }
678} 616}
679 617
680 618
@@ -1098,6 +1036,69 @@ mysql_plugin_drop (void *cls)
1098 1036
1099 1037
1100/** 1038/**
1039 * Remove a particular key in the datastore.
1040 *
1041 * @param cls closure
1042 * @param key key for the content
1043 * @param size number of bytes in data
1044 * @param data content stored
1045 * @param cont continuation called with success or failure status
1046 * @param cont_cls continuation closure for @a cont
1047 */
1048static void
1049mysql_plugin_remove_key (void *cls,
1050 const struct GNUNET_HashCode *key,
1051 uint32_t size,
1052 const void *data,
1053 PluginRemoveCont cont,
1054 void *cont_cls)
1055{
1056 struct Plugin *plugin = cls;
1057 struct GNUNET_MY_QueryParam params_delete[] = {
1058 GNUNET_MY_query_param_auto_from_type (key),
1059 GNUNET_MY_query_param_fixed_size (data, size),
1060 GNUNET_MY_query_param_end
1061 };
1062
1063 if (GNUNET_OK !=
1064 GNUNET_MY_exec_prepared (plugin->mc,
1065 plugin->delete_entry_by_hash_value,
1066 params_delete))
1067 {
1068 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1069 "Removing key `%s' from gn090 table failed\n",
1070 GNUNET_h2s (key));
1071 cont (cont_cls,
1072 key,
1073 size,
1074 GNUNET_SYSERR,
1075 _("MySQL statement run failure"));
1076 return;
1077 }
1078
1079 MYSQL_STMT *stmt = GNUNET_MYSQL_statement_get_stmt (plugin->delete_entry_by_hash_value);
1080 my_ulonglong rows = mysql_stmt_affected_rows (stmt);
1081
1082 if (0 == rows)
1083 {
1084 cont (cont_cls,
1085 key,
1086 size,
1087 GNUNET_NO,
1088 NULL);
1089 return;
1090 }
1091 plugin->env->duc (plugin->env->cls,
1092 -size);
1093 cont (cont_cls,
1094 key,
1095 size,
1096 GNUNET_OK,
1097 NULL);
1098}
1099
1100
1101/**
1101 * Entry point for the plugin. 1102 * Entry point for the plugin.
1102 * 1103 *
1103 * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment *` 1104 * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment *`
@@ -1132,24 +1133,20 @@ libgnunet_plugin_datastore_mysql_init (void *cls)
1132 " hash BINARY(64) NOT NULL DEFAULT ''," 1133 " hash BINARY(64) NOT NULL DEFAULT '',"
1133 " vhash BINARY(64) NOT NULL DEFAULT ''," 1134 " vhash BINARY(64) NOT NULL DEFAULT '',"
1134 " value BLOB NOT NULL DEFAULT ''," " uid BIGINT NOT NULL AUTO_INCREMENT," 1135 " value BLOB NOT NULL DEFAULT ''," " uid BIGINT NOT NULL AUTO_INCREMENT,"
1135 " PRIMARY KEY (uid)," " INDEX idx_hash (hash(64))," 1136 " PRIMARY KEY (uid),"
1136 " INDEX idx_hash_uid (hash(64),uid),"
1137 " INDEX idx_hash_vhash (hash(64),vhash(64)),"
1138 " INDEX idx_hash_type_uid (hash(64),type,rvalue)," 1137 " INDEX idx_hash_type_uid (hash(64),type,rvalue),"
1139 " INDEX idx_prio (prio)," " INDEX idx_repl_rvalue (repl,rvalue)," 1138 " INDEX idx_prio (prio),"
1139 " INDEX idx_repl_rvalue (repl,rvalue),"
1140 " INDEX idx_expire (expire)," 1140 " INDEX idx_expire (expire),"
1141 " INDEX idx_anonLevel_type_rvalue (anonLevel,type,rvalue)" 1141 " INDEX idx_anonLevel_type_rvalue (anonLevel,type,rvalue)"
1142 ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1") || 1142 ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1") ||
1143 PINIT (plugin->insert_entry, INSERT_ENTRY) || 1143 PINIT (plugin->insert_entry, INSERT_ENTRY) ||
1144 PINIT (plugin->delete_entry_by_uid, DELETE_ENTRY_BY_UID) || 1144 PINIT (plugin->delete_entry_by_uid, DELETE_ENTRY_BY_UID) ||
1145 PINIT (plugin->delete_entry_by_hash_value, DELETE_ENTRY_BY_HASH_VALUE) ||
1145 PINIT (plugin->select_entry, SELECT_ENTRY) || 1146 PINIT (plugin->select_entry, SELECT_ENTRY) ||
1146 PINIT (plugin->select_entry_by_hash, SELECT_ENTRY_BY_HASH) || 1147 PINIT (plugin->select_entry_by_hash, SELECT_ENTRY_BY_HASH) ||
1147 PINIT (plugin->select_entry_by_hash_and_vhash,
1148 SELECT_ENTRY_BY_HASH_AND_VHASH) ||
1149 PINIT (plugin->select_entry_by_hash_and_type, 1148 PINIT (plugin->select_entry_by_hash_and_type,
1150 SELECT_ENTRY_BY_HASH_AND_TYPE) || 1149 SELECT_ENTRY_BY_HASH_AND_TYPE) ||
1151 PINIT (plugin->select_entry_by_hash_vhash_and_type,
1152 SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE) ||
1153 PINIT (plugin->get_size, SELECT_SIZE) || 1150 PINIT (plugin->get_size, SELECT_SIZE) ||
1154 PINIT (plugin->update_entry, UPDATE_ENTRY) || 1151 PINIT (plugin->update_entry, UPDATE_ENTRY) ||
1155 PINIT (plugin->dec_repl, DEC_REPL) || 1152 PINIT (plugin->dec_repl, DEC_REPL) ||
@@ -1158,7 +1155,8 @@ libgnunet_plugin_datastore_mysql_init (void *cls)
1158 PINIT (plugin->select_priority, SELECT_IT_PRIORITY) || 1155 PINIT (plugin->select_priority, SELECT_IT_PRIORITY) ||
1159 PINIT (plugin->max_repl, SELECT_MAX_REPL) || 1156 PINIT (plugin->max_repl, SELECT_MAX_REPL) ||
1160 PINIT (plugin->get_all_keys, GET_ALL_KEYS) || 1157 PINIT (plugin->get_all_keys, GET_ALL_KEYS) ||
1161 PINIT (plugin->select_replication, SELECT_IT_REPLICATION)) 1158 PINIT (plugin->select_replication, SELECT_IT_REPLICATION) ||
1159 false)
1162 { 1160 {
1163 GNUNET_MYSQL_context_destroy (plugin->mc); 1161 GNUNET_MYSQL_context_destroy (plugin->mc);
1164 GNUNET_free (plugin); 1162 GNUNET_free (plugin);
@@ -1177,6 +1175,7 @@ libgnunet_plugin_datastore_mysql_init (void *cls)
1177 api->get_zero_anonymity = &mysql_plugin_get_zero_anonymity; 1175 api->get_zero_anonymity = &mysql_plugin_get_zero_anonymity;
1178 api->get_keys = &mysql_plugin_get_keys; 1176 api->get_keys = &mysql_plugin_get_keys;
1179 api->drop = &mysql_plugin_drop; 1177 api->drop = &mysql_plugin_drop;
1178 api->remove_key = &mysql_plugin_remove_key;
1180 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql", 1179 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql",
1181 _("Mysql database running\n")); 1180 _("Mysql database running\n"));
1182 return api; 1181 return api;
diff --git a/src/datastore/plugin_datastore_postgres.c b/src/datastore/plugin_datastore_postgres.c
index 349848ae6..b6aeb0be6 100644
--- a/src/datastore/plugin_datastore_postgres.c
+++ b/src/datastore/plugin_datastore_postgres.c
@@ -119,9 +119,6 @@ init_connection (struct Plugin *plugin)
119 "CREATE INDEX IF NOT EXISTS idx_hash ON gn090 (hash)")) || 119 "CREATE INDEX IF NOT EXISTS idx_hash ON gn090 (hash)")) ||
120 (GNUNET_OK != 120 (GNUNET_OK !=
121 GNUNET_POSTGRES_exec (plugin->dbh, 121 GNUNET_POSTGRES_exec (plugin->dbh,
122 "CREATE INDEX IF NOT EXISTS idx_hash_vhash ON gn090 (hash,vhash)")) ||
123 (GNUNET_OK !=
124 GNUNET_POSTGRES_exec (plugin->dbh,
125 "CREATE INDEX IF NOT EXISTS idx_prio ON gn090 (prio)")) || 122 "CREATE INDEX IF NOT EXISTS idx_prio ON gn090 (prio)")) ||
126 (GNUNET_OK != 123 (GNUNET_OK !=
127 GNUNET_POSTGRES_exec (plugin->dbh, 124 GNUNET_POSTGRES_exec (plugin->dbh,
@@ -183,9 +180,8 @@ init_connection (struct Plugin *plugin)
183 "WHERE oid >= $1::bigint AND " 180 "WHERE oid >= $1::bigint AND "
184 "(rvalue >= $2 OR 0 = $3::smallint) AND " 181 "(rvalue >= $2 OR 0 = $3::smallint) AND "
185 "(hash = $4 OR 0 = $5::smallint) AND " 182 "(hash = $4 OR 0 = $5::smallint) AND "
186 "(vhash = $6 OR 0 = $7::smallint) AND " 183 "(type = $6 OR 0 = $7::smallint) "
187 "(type = $8 OR 0 = $9::smallint) " 184 "ORDER BY oid ASC LIMIT 1", 7)) ||
188 "ORDER BY oid ASC LIMIT 1", 9)) ||
189 (GNUNET_OK != 185 (GNUNET_OK !=
190 GNUNET_POSTGRES_prepare (plugin->dbh, "put", 186 GNUNET_POSTGRES_prepare (plugin->dbh, "put",
191 "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " 187 "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) "
@@ -223,6 +219,10 @@ init_connection (struct Plugin *plugin)
223 (GNUNET_OK != 219 (GNUNET_OK !=
224 GNUNET_POSTGRES_prepare (plugin->dbh, "delrow", "DELETE FROM gn090 " "WHERE oid=$1", 1)) || 220 GNUNET_POSTGRES_prepare (plugin->dbh, "delrow", "DELETE FROM gn090 " "WHERE oid=$1", 1)) ||
225 (GNUNET_OK != 221 (GNUNET_OK !=
222 GNUNET_POSTGRES_prepare (plugin->dbh, "remove", "DELETE FROM gn090 "
223 "WHERE hash = $1 AND "
224 "value = $2", 2)) ||
225 (GNUNET_OK !=
226 GNUNET_POSTGRES_prepare (plugin->dbh, "get_keys", "SELECT hash FROM gn090", 0))) 226 GNUNET_POSTGRES_prepare (plugin->dbh, "get_keys", "SELECT hash FROM gn090", 0)))
227 { 227 {
228 PQfinish (plugin->dbh); 228 PQfinish (plugin->dbh);
@@ -536,11 +536,6 @@ process_result (struct Plugin *plugin,
536 * @param next_uid return the result with lowest uid >= next_uid 536 * @param next_uid return the result with lowest uid >= next_uid
537 * @param random if true, return a random result instead of using next_uid 537 * @param random if true, return a random result instead of using next_uid
538 * @param key maybe NULL (to match all entries) 538 * @param key maybe NULL (to match all entries)
539 * @param vhash hash of the value, maybe NULL (to
540 * match all values that have the right key).
541 * Note that for DBlocks there is no difference
542 * betwen key and vhash, but for other blocks
543 * there may be!
544 * @param type entries of which type are relevant? 539 * @param type entries of which type are relevant?
545 * Use 0 for any type. 540 * Use 0 for any type.
546 * @param proc function to call on the matching value; 541 * @param proc function to call on the matching value;
@@ -552,7 +547,6 @@ postgres_plugin_get_key (void *cls,
552 uint64_t next_uid, 547 uint64_t next_uid,
553 bool random, 548 bool random,
554 const struct GNUNET_HashCode *key, 549 const struct GNUNET_HashCode *key,
555 const struct GNUNET_HashCode *vhash,
556 enum GNUNET_BLOCK_Type type, 550 enum GNUNET_BLOCK_Type type,
557 PluginDatumProcessor proc, 551 PluginDatumProcessor proc,
558 void *proc_cls) 552 void *proc_cls)
@@ -561,7 +555,6 @@ postgres_plugin_get_key (void *cls,
561 uint32_t utype = type; 555 uint32_t utype = type;
562 uint16_t use_rvalue = random; 556 uint16_t use_rvalue = random;
563 uint16_t use_key = NULL != key; 557 uint16_t use_key = NULL != key;
564 uint16_t use_vhash = NULL != vhash;
565 uint16_t use_type = GNUNET_BLOCK_TYPE_ANY != type; 558 uint16_t use_type = GNUNET_BLOCK_TYPE_ANY != type;
566 uint64_t rvalue; 559 uint64_t rvalue;
567 struct GNUNET_PQ_QueryParam params[] = { 560 struct GNUNET_PQ_QueryParam params[] = {
@@ -570,8 +563,6 @@ postgres_plugin_get_key (void *cls,
570 GNUNET_PQ_query_param_uint16 (&use_rvalue), 563 GNUNET_PQ_query_param_uint16 (&use_rvalue),
571 GNUNET_PQ_query_param_auto_from_type (key), 564 GNUNET_PQ_query_param_auto_from_type (key),
572 GNUNET_PQ_query_param_uint16 (&use_key), 565 GNUNET_PQ_query_param_uint16 (&use_key),
573 GNUNET_PQ_query_param_auto_from_type (vhash),
574 GNUNET_PQ_query_param_uint16 (&use_vhash),
575 GNUNET_PQ_query_param_uint32 (&utype), 566 GNUNET_PQ_query_param_uint32 (&utype),
576 GNUNET_PQ_query_param_uint16 (&use_type), 567 GNUNET_PQ_query_param_uint16 (&use_type),
577 GNUNET_PQ_query_param_end 568 GNUNET_PQ_query_param_end
@@ -854,6 +845,74 @@ postgres_plugin_drop (void *cls)
854 845
855 846
856/** 847/**
848 * Remove a particular key in the datastore.
849 *
850 * @param cls closure
851 * @param key key for the content
852 * @param size number of bytes in data
853 * @param data content stored
854 * @param cont continuation called with success or failure status
855 * @param cont_cls continuation closure for @a cont
856 */
857static void
858postgres_plugin_remove_key (void *cls,
859 const struct GNUNET_HashCode *key,
860 uint32_t size,
861 const void *data,
862 PluginRemoveCont cont,
863 void *cont_cls)
864{
865 struct Plugin *plugin = cls;
866 PGresult *ret;
867 struct GNUNET_PQ_QueryParam params[] = {
868 GNUNET_PQ_query_param_auto_from_type (key),
869 GNUNET_PQ_query_param_fixed_size (data, size),
870 GNUNET_PQ_query_param_end
871 };
872 ret = GNUNET_PQ_exec_prepared (plugin->dbh,
873 "remove",
874 params);
875 if (GNUNET_OK !=
876 GNUNET_POSTGRES_check_result (plugin->dbh,
877 ret,
878 PGRES_COMMAND_OK,
879 "PQexecPrepared",
880 "remove"))
881 {
882 cont (cont_cls,
883 key,
884 size,
885 GNUNET_SYSERR,
886 _("Postgress exec failure"));
887 return;
888 }
889 /* What an awful API, this function really does return a string */
890 bool affected = 0 != strcmp ("0", PQcmdTuples (ret));
891 PQclear (ret);
892 if (!affected)
893 {
894 cont (cont_cls,
895 key,
896 size,
897 GNUNET_NO,
898 NULL);
899 return;
900 }
901 plugin->env->duc (plugin->env->cls,
902 - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
903 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
904 "datastore-postgres",
905 "Deleted %u bytes from database\n",
906 (unsigned int) size);
907 cont (cont_cls,
908 key,
909 size,
910 GNUNET_OK,
911 NULL);
912}
913
914
915/**
857 * Entry point for the plugin. 916 * Entry point for the plugin.
858 * 917 *
859 * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment*` 918 * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment*`
@@ -883,6 +942,7 @@ libgnunet_plugin_datastore_postgres_init (void *cls)
883 api->get_zero_anonymity = &postgres_plugin_get_zero_anonymity; 942 api->get_zero_anonymity = &postgres_plugin_get_zero_anonymity;
884 api->get_keys = &postgres_plugin_get_keys; 943 api->get_keys = &postgres_plugin_get_keys;
885 api->drop = &postgres_plugin_drop; 944 api->drop = &postgres_plugin_drop;
945 api->remove_key = &postgres_plugin_remove_key;
886 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, 946 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
887 "datastore-postgres", 947 "datastore-postgres",
888 _("Postgres database running\n")); 948 _("Postgres database running\n"));
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c
index 469dd7717..bcaf27d99 100644
--- a/src/datastore/plugin_datastore_sqlite.c
+++ b/src/datastore/plugin_datastore_sqlite.c
@@ -88,6 +88,11 @@ struct Plugin
88 sqlite3 *dbh; 88 sqlite3 *dbh;
89 89
90 /** 90 /**
91 * Precompiled SQL for remove_key.
92 */
93 sqlite3_stmt *remove;
94
95 /**
91 * Precompiled SQL for deletion. 96 * Precompiled SQL for deletion.
92 */ 97 */
93 sqlite3_stmt *delRow; 98 sqlite3_stmt *delRow;
@@ -185,10 +190,6 @@ create_indices (sqlite3 * dbh)
185 NULL, NULL, NULL)) || 190 NULL, NULL, NULL)) ||
186 (SQLITE_OK != 191 (SQLITE_OK !=
187 sqlite3_exec (dbh, 192 sqlite3_exec (dbh,
188 "CREATE INDEX IF NOT EXISTS idx_hash_vhash ON gn090 (hash,vhash)",
189 NULL, NULL, NULL)) ||
190 (SQLITE_OK !=
191 sqlite3_exec (dbh,
192 "CREATE INDEX IF NOT EXISTS idx_expire_repl ON gn090 (expire ASC,repl DESC)", 193 "CREATE INDEX IF NOT EXISTS idx_expire_repl ON gn090 (expire ASC,repl DESC)",
193 NULL, NULL, NULL)) || 194 NULL, NULL, NULL)) ||
194 (SQLITE_OK != 195 (SQLITE_OK !=
@@ -415,15 +416,21 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
415 "WHERE _ROWID_ >= ? AND " 416 "WHERE _ROWID_ >= ? AND "
416 "(rvalue >= ? OR 0 = ?) AND " 417 "(rvalue >= ? OR 0 = ?) AND "
417 "(hash = ? OR 0 = ?) AND " 418 "(hash = ? OR 0 = ?) AND "
418 "(vhash = ? OR 0 = ?) AND "
419 "(type = ? OR 0 = ?) " 419 "(type = ? OR 0 = ?) "
420 "ORDER BY _ROWID_ ASC LIMIT 1", 420 "ORDER BY _ROWID_ ASC LIMIT 1",
421 &plugin->get)) || 421 &plugin->get)) ||
422 (SQLITE_OK != 422 (SQLITE_OK !=
423 sq_prepare (plugin->dbh, 423 sq_prepare (plugin->dbh,
424 "DELETE FROM gn090 WHERE _ROWID_ = ?", 424 "DELETE FROM gn090 WHERE _ROWID_ = ?",
425 &plugin->delRow)) 425 &plugin->delRow)) ||
426 ) 426 (SQLITE_OK !=
427 sq_prepare (plugin->dbh,
428 "DELETE FROM gn090 "
429 "WHERE hash = ? AND "
430 "value = ? "
431 "LIMIT 1",
432 &plugin->remove)) ||
433 false)
427 { 434 {
428 LOG_SQLITE (plugin, 435 LOG_SQLITE (plugin,
429 GNUNET_ERROR_TYPE_ERROR, 436 GNUNET_ERROR_TYPE_ERROR,
@@ -448,6 +455,8 @@ database_shutdown (struct Plugin *plugin)
448 sqlite3_stmt *stmt; 455 sqlite3_stmt *stmt;
449#endif 456#endif
450 457
458 if (NULL != plugin->remove)
459 sqlite3_finalize (plugin->remove);
451 if (NULL != plugin->delRow) 460 if (NULL != plugin->delRow)
452 sqlite3_finalize (plugin->delRow); 461 sqlite3_finalize (plugin->delRow);
453 if (NULL != plugin->update) 462 if (NULL != plugin->update)
@@ -845,15 +854,10 @@ sqlite_plugin_get_zero_anonymity (void *cls,
845 * @param next_uid return the result with lowest uid >= next_uid 854 * @param next_uid return the result with lowest uid >= next_uid
846 * @param random if true, return a random result instead of using next_uid 855 * @param random if true, return a random result instead of using next_uid
847 * @param key maybe NULL (to match all entries) 856 * @param key maybe NULL (to match all entries)
848 * @param vhash hash of the value, maybe NULL (to
849 * match all values that have the right key).
850 * Note that for DBlocks there is no difference
851 * betwen key and vhash, but for other blocks
852 * there may be!
853 * @param type entries of which type are relevant? 857 * @param type entries of which type are relevant?
854 * Use 0 for any type. 858 * Use 0 for any type.
855 * @param proc function to call on each matching value; 859 * @param proc function to call on the matching value;
856 * will be called once with a NULL value at the end 860 * will be called with NULL if nothing matches
857 * @param proc_cls closure for @a proc 861 * @param proc_cls closure for @a proc
858 */ 862 */
859static void 863static void
@@ -861,7 +865,6 @@ sqlite_plugin_get_key (void *cls,
861 uint64_t next_uid, 865 uint64_t next_uid,
862 bool random, 866 bool random,
863 const struct GNUNET_HashCode *key, 867 const struct GNUNET_HashCode *key,
864 const struct GNUNET_HashCode *vhash,
865 enum GNUNET_BLOCK_Type type, 868 enum GNUNET_BLOCK_Type type,
866 PluginDatumProcessor proc, 869 PluginDatumProcessor proc,
867 void *proc_cls) 870 void *proc_cls)
@@ -872,15 +875,12 @@ sqlite_plugin_get_key (void *cls,
872 uint32_t type32 = (uint32_t) type; 875 uint32_t type32 = (uint32_t) type;
873 uint16_t use_type = GNUNET_BLOCK_TYPE_ANY != type; 876 uint16_t use_type = GNUNET_BLOCK_TYPE_ANY != type;
874 uint16_t use_key = NULL != key; 877 uint16_t use_key = NULL != key;
875 uint16_t use_vhash = NULL != vhash;
876 struct GNUNET_SQ_QueryParam params[] = { 878 struct GNUNET_SQ_QueryParam params[] = {
877 GNUNET_SQ_query_param_uint64 (&next_uid), 879 GNUNET_SQ_query_param_uint64 (&next_uid),
878 GNUNET_SQ_query_param_uint64 (&rvalue), 880 GNUNET_SQ_query_param_uint64 (&rvalue),
879 GNUNET_SQ_query_param_uint16 (&use_rvalue), 881 GNUNET_SQ_query_param_uint16 (&use_rvalue),
880 GNUNET_SQ_query_param_auto_from_type (key), 882 GNUNET_SQ_query_param_auto_from_type (key),
881 GNUNET_SQ_query_param_uint16 (&use_key), 883 GNUNET_SQ_query_param_uint16 (&use_key),
882 GNUNET_SQ_query_param_auto_from_type (vhash),
883 GNUNET_SQ_query_param_uint16 (&use_vhash),
884 GNUNET_SQ_query_param_uint32 (&type32), 884 GNUNET_SQ_query_param_uint32 (&type32),
885 GNUNET_SQ_query_param_uint16 (&use_type), 885 GNUNET_SQ_query_param_uint16 (&use_type),
886 GNUNET_SQ_query_param_end 886 GNUNET_SQ_query_param_end
@@ -1186,6 +1186,79 @@ sqlite_plugin_drop (void *cls)
1186 1186
1187 1187
1188/** 1188/**
1189 * Remove a particular key in the datastore.
1190 *
1191 * @param cls closure
1192 * @param key key for the content
1193 * @param size number of bytes in data
1194 * @param data content stored
1195 * @param cont continuation called with success or failure status
1196 * @param cont_cls continuation closure for @a cont
1197 */
1198static void
1199sqlite_plugin_remove_key (void *cls,
1200 const struct GNUNET_HashCode *key,
1201 uint32_t size,
1202 const void *data,
1203 PluginRemoveCont cont,
1204 void *cont_cls)
1205{
1206 struct Plugin *plugin = cls;
1207 struct GNUNET_SQ_QueryParam params[] = {
1208 GNUNET_SQ_query_param_auto_from_type (key),
1209 GNUNET_SQ_query_param_fixed_size (data, size),
1210 GNUNET_SQ_query_param_end
1211 };
1212
1213 if (GNUNET_OK !=
1214 GNUNET_SQ_bind (plugin->remove,
1215 params))
1216 {
1217 cont (cont_cls,
1218 key,
1219 size,
1220 GNUNET_SYSERR,
1221 "bind failed");
1222 return;
1223 }
1224 if (SQLITE_DONE != sqlite3_step (plugin->remove))
1225 {
1226 LOG_SQLITE (plugin,
1227 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1228 "sqlite3_step");
1229 GNUNET_SQ_reset (plugin->dbh,
1230 plugin->remove);
1231 cont (cont_cls,
1232 key,
1233 size,
1234 GNUNET_SYSERR,
1235 "sqlite3_step failed");
1236 return;
1237 }
1238 int changes = sqlite3_changes (plugin->dbh);
1239 GNUNET_SQ_reset (plugin->dbh,
1240 plugin->remove);
1241 if (0 == changes)
1242 {
1243 cont (cont_cls,
1244 key,
1245 size,
1246 GNUNET_NO,
1247 NULL);
1248 return;
1249 }
1250 if (NULL != plugin->env->duc)
1251 plugin->env->duc (plugin->env->cls,
1252 -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
1253 cont (cont_cls,
1254 key,
1255 size,
1256 GNUNET_OK,
1257 NULL);
1258}
1259
1260
1261/**
1189 * Get an estimate of how much space the database is 1262 * Get an estimate of how much space the database is
1190 * currently using. 1263 * currently using.
1191 * 1264 *
@@ -1286,6 +1359,7 @@ libgnunet_plugin_datastore_sqlite_init (void *cls)
1286 api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity; 1359 api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity;
1287 api->get_keys = &sqlite_plugin_get_keys; 1360 api->get_keys = &sqlite_plugin_get_keys;
1288 api->drop = &sqlite_plugin_drop; 1361 api->drop = &sqlite_plugin_drop;
1362 api->remove_key = &sqlite_plugin_remove_key;
1289 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, 1363 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
1290 "sqlite", 1364 "sqlite",
1291 _("Sqlite database running\n")); 1365 _("Sqlite database running\n"));
diff --git a/src/datastore/plugin_datastore_template.c b/src/datastore/plugin_datastore_template.c
index 704d586bc..16bda45d4 100644
--- a/src/datastore/plugin_datastore_template.c
+++ b/src/datastore/plugin_datastore_template.c
@@ -99,11 +99,6 @@ template_plugin_put (void *cls,
99 * @param next_uid return the result with lowest uid >= next_uid 99 * @param next_uid return the result with lowest uid >= next_uid
100 * @param random if true, return a random result instead of using next_uid 100 * @param random if true, return a random result instead of using next_uid
101 * @param key maybe NULL (to match all entries) 101 * @param key maybe NULL (to match all entries)
102 * @param vhash hash of the value, maybe NULL (to
103 * match all values that have the right key).
104 * Note that for DBlocks there is no difference
105 * betwen key and vhash, but for other blocks
106 * there may be!
107 * @param type entries of which type are relevant? 102 * @param type entries of which type are relevant?
108 * Use 0 for any type. 103 * Use 0 for any type.
109 * @param proc function to call on each matching value; 104 * @param proc function to call on each matching value;
@@ -111,10 +106,12 @@ template_plugin_put (void *cls,
111 * @param proc_cls closure for proc 106 * @param proc_cls closure for proc
112 */ 107 */
113static void 108static void
114template_plugin_get_key (void *cls, uint64_t next_uid, bool random, 109template_plugin_get_key (void *cls,
115 const struct GNUNET_HashCode * key, 110 uint64_t next_uid,
116 const struct GNUNET_HashCode * vhash, 111 bool random,
117 enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, 112 const struct GNUNET_HashCode *key,
113 enum GNUNET_BLOCK_Type type,
114 PluginDatumProcessor proc,
118 void *proc_cls) 115 void *proc_cls)
119{ 116{
120 GNUNET_break (0); 117 GNUNET_break (0);
@@ -204,6 +201,29 @@ template_get_keys (void *cls,
204 201
205 202
206/** 203/**
204 * Remove a particular key in the datastore.
205 *
206 * @param cls closure
207 * @param key key for the content
208 * @param size number of bytes in data
209 * @param data content stored
210 * @param cont continuation called with success or failure status
211 * @param cont_cls continuation closure for @a cont
212 */
213static void
214template_plugin_remove_key (void *cls,
215 const struct GNUNET_HashCode *key,
216 uint32_t size,
217 const void *data,
218 PluginRemoveCont cont,
219 void *cont_cls)
220{
221 GNUNET_break (0);
222 cont (cont_cls, key, size, GNUNET_SYSERR, "not implemented");
223}
224
225
226/**
207 * Entry point for the plugin. 227 * Entry point for the plugin.
208 * 228 *
209 * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*" 229 * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*"
@@ -228,6 +248,7 @@ libgnunet_plugin_datastore_template_init (void *cls)
228 api->get_zero_anonymity = &template_plugin_get_zero_anonymity; 248 api->get_zero_anonymity = &template_plugin_get_zero_anonymity;
229 api->drop = &template_plugin_drop; 249 api->drop = &template_plugin_drop;
230 api->get_keys = &template_get_keys; 250 api->get_keys = &template_get_keys;
251 api->remove_key = &template_plugin_remove_key;
231 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "template", 252 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "template",
232 _("Template database running\n")); 253 _("Template database running\n"));
233 return api; 254 return api;
diff --git a/src/datastore/test_plugin_datastore.c b/src/datastore/test_plugin_datastore.c
index 0c34a5f66..d460daed7 100644
--- a/src/datastore/test_plugin_datastore.c
+++ b/src/datastore/test_plugin_datastore.c
@@ -52,6 +52,7 @@ enum RunPhase
52 RP_ITER_ZERO, 52 RP_ITER_ZERO,
53 RP_REPL_GET, 53 RP_REPL_GET,
54 RP_EXPI_GET, 54 RP_EXPI_GET,
55 RP_REMOVE,
55 RP_DROP 56 RP_DROP
56}; 57};
57 58
@@ -153,7 +154,7 @@ do_put (struct CpsRunContext *crc)
153 /* most content is 32k */ 154 /* most content is 32k */
154 size = 32 * 1024; 155 size = 32 * 1024;
155 156
156 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16) == 0) /* but some of it is less! */ 157 if (0 != i && GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16) == 0) /* but some of it is less! */
157 size = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 32 * 1024); 158 size = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 32 * 1024);
158 size = size - (size & 7); /* always multiple of 8 */ 159 size = size - (size & 7); /* always multiple of 8 */
159 160
@@ -220,6 +221,25 @@ iterate_one_shot (void *cls,
220} 221}
221 222
222 223
224static void
225remove_continuation (void *cls,
226 const struct GNUNET_HashCode *key,
227 uint32_t size,
228 int status,
229 const char *msg)
230{
231 struct CpsRunContext *crc = cls;
232
233 GNUNET_assert (NULL != key);
234 GNUNET_assert (32768 == size);
235 GNUNET_assert (GNUNET_OK == status);
236 GNUNET_assert (NULL == msg);
237 crc->phase++;
238 GNUNET_SCHEDULER_add_now (&test,
239 crc);
240}
241
242
223/** 243/**
224 * Function called when the service shuts 244 * Function called when the service shuts
225 * down. Unloads our datastore plugin. 245 * down. Unloads our datastore plugin.
@@ -303,7 +323,6 @@ test (void *cls)
303 0, 323 0,
304 false, 324 false,
305 &key, 325 &key,
306 NULL,
307 GNUNET_BLOCK_TYPE_ANY, 326 GNUNET_BLOCK_TYPE_ANY,
308 &iterate_one_shot, 327 &iterate_one_shot,
309 crc); 328 crc);
@@ -324,6 +343,23 @@ test (void *cls)
324 case RP_EXPI_GET: 343 case RP_EXPI_GET:
325 crc->api->get_expiration (crc->api->cls, &iterate_one_shot, crc); 344 crc->api->get_expiration (crc->api->cls, &iterate_one_shot, crc);
326 break; 345 break;
346 case RP_REMOVE:
347 {
348 struct GNUNET_HashCode key;
349 uint32_t size = 32768;
350 char value[size];
351
352 gen_key (0, &key);
353 memset (value, 0, size);
354 value[0] = crc->i;
355 crc->api->remove_key (crc->api->cls,
356 &key,
357 size,
358 value,
359 &remove_continuation,
360 crc);
361 break;
362 }
327 case RP_DROP: 363 case RP_DROP:
328 crc->api->drop (crc->api->cls); 364 crc->api->drop (crc->api->cls);
329 GNUNET_SCHEDULER_add_now (&cleaning_task, crc); 365 GNUNET_SCHEDULER_add_now (&cleaning_task, crc);