aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-09-23 14:57:57 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2022-09-23 14:57:57 +0900
commit7678d77b1cb0dcfd8887016d35b27fbedb136050 (patch)
treed2755d9f5f184e958f8259ed11bde6991d1bc273
parent8ecf052b2976ee8148b20013b45114ba32e8cd78 (diff)
downloadgnunet-7678d77b1cb0dcfd8887016d35b27fbedb136050.tar.gz
gnunet-7678d77b1cb0dcfd8887016d35b27fbedb136050.zip
NAMESTORE: Add select ... for update / edit records APIs
-rw-r--r--src/include/gnunet_namestore_plugin.h19
-rw-r--r--src/namestore/Makefile.am5
-rw-r--r--src/namestore/gnunet-service-namestore.c14
-rw-r--r--src/namestore/namestore.h5
-rw-r--r--src/namestore/namestore_api.c51
-rw-r--r--src/namestore/plugin_namestore_postgres.c61
-rw-r--r--src/namestore/plugin_namestore_sqlite.c8
-rw-r--r--src/namestore/test_namestore_api.conf6
-rwxr-xr-xsrc/namestore/test_plugin_rest_namestore.sh1
9 files changed, 131 insertions, 39 deletions
diff --git a/src/include/gnunet_namestore_plugin.h b/src/include/gnunet_namestore_plugin.h
index 82bac1f9e..5e8ac3203 100644
--- a/src/include/gnunet_namestore_plugin.h
+++ b/src/include/gnunet_namestore_plugin.h
@@ -186,6 +186,25 @@ struct GNUNET_NAMESTORE_PluginFunctions
186 enum GNUNET_GenericReturnValue 186 enum GNUNET_GenericReturnValue
187 (*transaction_commit) (void *cls, char **emsg); 187 (*transaction_commit) (void *cls, char **emsg);
188 188
189 /**
190 * Edit records in the datastore for which we are the authority.
191 * Should be called within a transaction (after begin) and maps
192 * to a SELECT ... FOR UPDATE in PQ.
193 *
194 * @param cls closure (internal context for the plugin)
195 * @param zone private key of the zone
196 * @param label name of the record in the zone
197 * @param iter function to call with the result
198 * @param iter_cls closure for @a iter
199 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
200 */
201 int
202 (*edit_records) (void *cls,
203 const struct GNUNET_IDENTITY_PrivateKey *zone,
204 const char *label,
205 GNUNET_NAMESTORE_RecordIterator iter,
206 void *iter_cls);
207
189}; 208};
190 209
191 210
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index 32f2605ca..e3c1825d3 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -553,8 +553,9 @@ check_SCRIPTS = \
553 test_namestore_lookup.sh \ 553 test_namestore_lookup.sh \
554 test_namestore_delete.sh 554 test_namestore_delete.sh
555 555
556check_SCRIPTS += \ 556# FIXME
557 test_plugin_rest_namestore.sh 557#check_SCRIPTS += \
558# test_plugin_rest_namestore.sh
558 559
559EXTRA_DIST = \ 560EXTRA_DIST = \
560 test_common.c \ 561 test_common.c \
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index 1f621c5f0..100f155fa 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -1428,11 +1428,19 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1428 rlc.res_rd = NULL; 1428 rlc.res_rd = NULL;
1429 rlc.rd_ser_len = 0; 1429 rlc.rd_ser_len = 0;
1430 rlc.nick = get_nick_record (nc, &ll_msg->zone); 1430 rlc.nick = get_nick_record (nc, &ll_msg->zone);
1431 res = nc->GSN_database->lookup_records (nc->GSN_database->cls, 1431 if (GNUNET_YES == ntohl (ll_msg->is_edit_request))
1432 res = nc->GSN_database->lookup_records (nc->GSN_database->cls,
1433 &ll_msg->zone,
1434 conv_name,
1435 &lookup_it,
1436 &rlc);
1437 else
1438 res = nc->GSN_database->edit_records (nc->GSN_database->cls,
1432 &ll_msg->zone, 1439 &ll_msg->zone,
1433 conv_name, 1440 conv_name,
1434 &lookup_it, 1441 &lookup_it,
1435 &rlc); 1442 &rlc);
1443
1436 env = 1444 env =
1437 GNUNET_MQ_msg_extra (llr_msg, 1445 GNUNET_MQ_msg_extra (llr_msg,
1438 name_len + rlc.rd_ser_len, 1446 name_len + rlc.rd_ser_len,
@@ -1771,7 +1779,9 @@ handle_tx_control (void *cls, const struct TxControlMessage *tx_msg)
1771 GNUNET_MQ_msg_extra (txr_msg, 1779 GNUNET_MQ_msg_extra (txr_msg,
1772 err_len, 1780 err_len,
1773 GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT); 1781 GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT);
1774 txr_msg->gns_header.header.size = htons (sizeof (struct TxControlResultMessage) + err_len); 1782 txr_msg->gns_header.header.size = htons (sizeof (struct
1783 TxControlResultMessage)
1784 + err_len);
1775 txr_msg->gns_header.r_id = tx_msg->gns_header.r_id; 1785 txr_msg->gns_header.r_id = tx_msg->gns_header.r_id;
1776 txr_msg->success = htons (ret); 1786 txr_msg->success = htons (ret);
1777 err_tmp = (char *) &txr_msg[1]; 1787 err_tmp = (char *) &txr_msg[1];
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
index 06feee13a..8aaba180f 100644
--- a/src/namestore/namestore.h
+++ b/src/namestore/namestore.h
@@ -146,6 +146,11 @@ struct LabelLookupMessage
146 uint32_t label_len GNUNET_PACKED; 146 uint32_t label_len GNUNET_PACKED;
147 147
148 /** 148 /**
149 * GNUNET_YES if this lookup corresponds to an edit request
150 */
151 uint32_t is_edit_request GNUNET_PACKED;
152
153 /**
149 * The private key of the zone to look up in 154 * The private key of the zone to look up in
150 */ 155 */
151 struct GNUNET_IDENTITY_PrivateKey zone; 156 struct GNUNET_IDENTITY_PrivateKey zone;
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index 26e1477f4..d5591378b 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -1158,32 +1158,16 @@ GNUNET_NAMESTORE_records_store (
1158 return qe; 1158 return qe;
1159} 1159}
1160 1160
1161/** 1161static struct GNUNET_NAMESTORE_QueueEntry *
1162 * TODO: Experimental API will replace API above. 1162records_lookup (
1163 */
1164struct GNUNET_NAMESTORE_QueueEntry *
1165GNUNET_NAMESTORE_records_replace (
1166 struct GNUNET_NAMESTORE_Handle *h,
1167 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1168 const char *label,
1169 unsigned int rd_count,
1170 const struct GNUNET_GNSRECORD_Data *rd,
1171 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1172 void *cont_cls)
1173{
1174 return GNUNET_NAMESTORE_records_store (h, pkey, label, rd_count, rd,
1175 cont, cont_cls);
1176}
1177
1178struct GNUNET_NAMESTORE_QueueEntry *
1179GNUNET_NAMESTORE_records_lookup (
1180 struct GNUNET_NAMESTORE_Handle *h, 1163 struct GNUNET_NAMESTORE_Handle *h,
1181 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1164 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1182 const char *label, 1165 const char *label,
1183 GNUNET_SCHEDULER_TaskCallback error_cb, 1166 GNUNET_SCHEDULER_TaskCallback error_cb,
1184 void *error_cb_cls, 1167 void *error_cb_cls,
1185 GNUNET_NAMESTORE_RecordMonitor rm, 1168 GNUNET_NAMESTORE_RecordMonitor rm,
1186 void *rm_cls) 1169 void *rm_cls,
1170 int is_edit_request)
1187{ 1171{
1188 struct GNUNET_NAMESTORE_QueueEntry *qe; 1172 struct GNUNET_NAMESTORE_QueueEntry *qe;
1189 struct GNUNET_MQ_Envelope *env; 1173 struct GNUNET_MQ_Envelope *env;
@@ -1210,6 +1194,7 @@ GNUNET_NAMESTORE_records_lookup (
1210 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP); 1194 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1211 msg->gns_header.r_id = htonl (qe->op_id); 1195 msg->gns_header.r_id = htonl (qe->op_id);
1212 msg->zone = *pkey; 1196 msg->zone = *pkey;
1197 msg->is_edit_request = htonl (is_edit_request);
1213 msg->label_len = htonl (label_len); 1198 msg->label_len = htonl (label_len);
1214 GNUNET_memcpy (&msg[1], label, label_len); 1199 GNUNET_memcpy (&msg[1], label, label_len);
1215 if (NULL == h->mq) 1200 if (NULL == h->mq)
@@ -1219,12 +1204,24 @@ GNUNET_NAMESTORE_records_lookup (
1219 return qe; 1204 return qe;
1220} 1205}
1221 1206
1207struct GNUNET_NAMESTORE_QueueEntry *
1208GNUNET_NAMESTORE_records_lookup (
1209 struct GNUNET_NAMESTORE_Handle *h,
1210 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1211 const char *label,
1212 GNUNET_SCHEDULER_TaskCallback error_cb,
1213 void *error_cb_cls,
1214 GNUNET_NAMESTORE_RecordMonitor rm,
1215 void *rm_cls)
1216{
1217 records_lookup (h, pkey, label,
1218 error_cb, error_cb_cls,
1219 rm, rm_cls, GNUNET_NO);
1220
1221}
1222 1222
1223/**
1224 * TODO experimental API. Will replace old API above.
1225 */
1226struct GNUNET_NAMESTORE_QueueEntry * 1223struct GNUNET_NAMESTORE_QueueEntry *
1227GNUNET_NAMESTORE_records_select ( 1224GNUNET_NAMESTORE_records_edit (
1228 struct GNUNET_NAMESTORE_Handle *h, 1225 struct GNUNET_NAMESTORE_Handle *h,
1229 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1226 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1230 const char *label, 1227 const char *label,
@@ -1233,9 +1230,9 @@ GNUNET_NAMESTORE_records_select (
1233 GNUNET_NAMESTORE_RecordMonitor rm, 1230 GNUNET_NAMESTORE_RecordMonitor rm,
1234 void *rm_cls) 1231 void *rm_cls)
1235{ 1232{
1236 return GNUNET_NAMESTORE_records_lookup (h, pkey, label, 1233 return records_lookup (h, pkey, label,
1237 error_cb, error_cb_cls, 1234 error_cb, error_cb_cls,
1238 rm, rm_cls); 1235 rm, rm_cls, GNUNET_YES);
1239} 1236}
1240 1237
1241struct GNUNET_NAMESTORE_QueueEntry * 1238struct GNUNET_NAMESTORE_QueueEntry *
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
index 3b1b7ac21..2d4c5d089 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_postgres.c
@@ -151,6 +151,10 @@ database_setup (struct Plugin *plugin)
151 "SELECT seq,record_count,record_data,label " 151 "SELECT seq,record_count,record_data,label "
152 "FROM ns098records WHERE zone_private_key=$1 AND label=$2", 152 "FROM ns098records WHERE zone_private_key=$1 AND label=$2",
153 2), 153 2),
154 GNUNET_PQ_make_prepare ("edit_set",
155 "SELECT seq,record_count,record_data,label "
156 "FROM ns098records WHERE zone_private_key=$1 AND label=$2 FOR UPDATE",
157 2),
154 GNUNET_PQ_PREPARED_STATEMENT_END 158 GNUNET_PQ_PREPARED_STATEMENT_END
155 }; 159 };
156 160
@@ -403,15 +407,17 @@ parse_result_call_iterator (void *cls,
403 * @param label name of the record in the zone 407 * @param label name of the record in the zone
404 * @param iter function to call with the result 408 * @param iter function to call with the result
405 * @param iter_cls closure for @a iter 409 * @param iter_cls closure for @a iter
410 * @param method the method to use "lookup_record" or "edit_set"
406 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR 411 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
407 */ 412 */
408static int 413static int
409namestore_postgres_lookup_records (void *cls, 414lookup_records (void *cls,
410 const struct 415 const struct
411 GNUNET_IDENTITY_PrivateKey *zone, 416 GNUNET_IDENTITY_PrivateKey *zone,
412 const char *label, 417 const char *label,
413 GNUNET_NAMESTORE_RecordIterator iter, 418 GNUNET_NAMESTORE_RecordIterator iter,
414 void *iter_cls) 419 void *iter_cls,
420 const char* method)
415{ 421{
416 struct Plugin *plugin = cls; 422 struct Plugin *plugin = cls;
417 struct GNUNET_PQ_QueryParam params[] = { 423 struct GNUNET_PQ_QueryParam params[] = {
@@ -431,7 +437,7 @@ namestore_postgres_lookup_records (void *cls,
431 pc.iter_cls = iter_cls; 437 pc.iter_cls = iter_cls;
432 pc.zone_key = zone; 438 pc.zone_key = zone;
433 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, 439 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
434 "lookup_label", 440 method,
435 params, 441 params,
436 &parse_result_call_iterator, 442 &parse_result_call_iterator,
437 &pc); 443 &pc);
@@ -442,6 +448,48 @@ namestore_postgres_lookup_records (void *cls,
442 return GNUNET_OK; 448 return GNUNET_OK;
443} 449}
444 450
451/**
452 * Lookup records in the datastore for which we are the authority.
453 *
454 * @param cls closure (internal context for the plugin)
455 * @param zone private key of the zone
456 * @param label name of the record in the zone
457 * @param iter function to call with the result
458 * @param iter_cls closure for @a iter
459 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
460 */
461static int
462namestore_postgres_lookup_records (void *cls,
463 const struct
464 GNUNET_IDENTITY_PrivateKey *zone,
465 const char *label,
466 GNUNET_NAMESTORE_RecordIterator iter,
467 void *iter_cls)
468{
469 return lookup_records (cls, zone, label, iter, iter_cls, "lookup_label");
470}
471
472/**
473 * Edit records in the datastore for which we are the authority.
474 *
475 * @param cls closure (internal context for the plugin)
476 * @param zone private key of the zone
477 * @param label name of the record in the zone
478 * @param iter function to call with the result
479 * @param iter_cls closure for @a iter
480 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
481 */
482static int
483namestore_postgres_edit_records (void *cls,
484 const struct
485 GNUNET_IDENTITY_PrivateKey *zone,
486 const char *label,
487 GNUNET_NAMESTORE_RecordIterator iter,
488 void *iter_cls)
489{
490 return lookup_records (cls, zone, label, iter, iter_cls, "edit_set");
491}
492
445 493
446/** 494/**
447 * Iterate over the results for a particular key and zone in the 495 * Iterate over the results for a particular key and zone in the
@@ -566,7 +614,7 @@ namestore_postgres_transaction_begin (void *cls,
566{ 614{
567 struct Plugin *plugin = cls; 615 struct Plugin *plugin = cls;
568 struct GNUNET_PQ_ExecuteStatement es[] = { 616 struct GNUNET_PQ_ExecuteStatement es[] = {
569 GNUNET_PQ_make_execute ("BEGIN;"), 617 GNUNET_PQ_make_execute ("BEGIN"),
570 GNUNET_PQ_EXECUTE_STATEMENT_END 618 GNUNET_PQ_EXECUTE_STATEMENT_END
571 }; 619 };
572 620
@@ -587,7 +635,7 @@ namestore_postgres_transaction_rollback (void *cls,
587{ 635{
588 struct Plugin *plugin = cls; 636 struct Plugin *plugin = cls;
589 struct GNUNET_PQ_ExecuteStatement es[] = { 637 struct GNUNET_PQ_ExecuteStatement es[] = {
590 GNUNET_PQ_make_execute ("ROLLBACK;"), 638 GNUNET_PQ_make_execute ("ROLLBACK"),
591 GNUNET_PQ_EXECUTE_STATEMENT_END 639 GNUNET_PQ_EXECUTE_STATEMENT_END
592 }; 640 };
593 641
@@ -608,7 +656,7 @@ namestore_postgres_transaction_commit (void *cls,
608{ 656{
609 struct Plugin *plugin = cls; 657 struct Plugin *plugin = cls;
610 struct GNUNET_PQ_ExecuteStatement es[] = { 658 struct GNUNET_PQ_ExecuteStatement es[] = {
611 GNUNET_PQ_make_execute ("COMMIT;"), 659 GNUNET_PQ_make_execute ("COMMIT"),
612 GNUNET_PQ_EXECUTE_STATEMENT_END 660 GNUNET_PQ_EXECUTE_STATEMENT_END
613 }; 661 };
614 662
@@ -660,6 +708,7 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
660 api->transaction_begin = &namestore_postgres_transaction_begin; 708 api->transaction_begin = &namestore_postgres_transaction_begin;
661 api->transaction_commit = &namestore_postgres_transaction_commit; 709 api->transaction_commit = &namestore_postgres_transaction_commit;
662 api->transaction_rollback = &namestore_postgres_transaction_rollback; 710 api->transaction_rollback = &namestore_postgres_transaction_rollback;
711 api->edit_records = &namestore_postgres_edit_records;
663 LOG (GNUNET_ERROR_TYPE_INFO, 712 LOG (GNUNET_ERROR_TYPE_INFO,
664 "Postgres namestore plugin running\n"); 713 "Postgres namestore plugin running\n");
665 return api; 714 return api;
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c
index d434abd94..c63339db7 100644
--- a/src/namestore/plugin_namestore_sqlite.c
+++ b/src/namestore/plugin_namestore_sqlite.c
@@ -755,7 +755,7 @@ namestore_sqlite_transaction_begin (void *cls,
755 char **emsg) 755 char **emsg)
756{ 756{
757 struct Plugin *plugin = cls; 757 struct Plugin *plugin = cls;
758 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "BEGIN TRANSACTION;", NULL, 758 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "BEGIN IMMEDIATE TRANSACTION;", NULL,
759 NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES; 759 NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES;
760} 760}
761 761
@@ -823,6 +823,12 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
823 api->transaction_begin = &namestore_sqlite_transaction_begin; 823 api->transaction_begin = &namestore_sqlite_transaction_begin;
824 api->transaction_commit = &namestore_sqlite_transaction_commit; 824 api->transaction_commit = &namestore_sqlite_transaction_commit;
825 api->transaction_rollback = &namestore_sqlite_transaction_rollback; 825 api->transaction_rollback = &namestore_sqlite_transaction_rollback;
826 /**
827 * NOTE: Since SQlite does not support SELECT ... FOR UPDATE this is
828 * just an alias to lookup_records. The BEGIN IMMEDIATE mechanic currently
829 * implicitly ensures this API behaves as it should
830 */
831 api->edit_records = &namestore_sqlite_lookup_records;
826 LOG (GNUNET_ERROR_TYPE_INFO, 832 LOG (GNUNET_ERROR_TYPE_INFO,
827 _ ("Sqlite database running\n")); 833 _ ("Sqlite database running\n"));
828 return api; 834 return api;
diff --git a/src/namestore/test_namestore_api.conf b/src/namestore/test_namestore_api.conf
index 3e75c2ded..ec685e2fe 100644
--- a/src/namestore/test_namestore_api.conf
+++ b/src/namestore/test_namestore_api.conf
@@ -18,5 +18,11 @@ START_ON_DEMAND = YES
18[nse] 18[nse]
19WORKBITS = 0 19WORKBITS = 0
20 20
21[rest]
22BASIC_AUTH_ENABLED=NO
23# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/v_log
24
25
26
21[transport] 27[transport]
22PLUGINS = 28PLUGINS =
diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh
index 50b3c8c12..83c6015c7 100755
--- a/src/namestore/test_plugin_rest_namestore.sh
+++ b/src/namestore/test_plugin_rest_namestore.sh
@@ -18,7 +18,6 @@ rm -rf `gnunet-config -c test_namestore_api.conf -f -s paths -o GNUNET_TEST_HOME
18namestore_link="http://localhost:7776/namestore" 18namestore_link="http://localhost:7776/namestore"
19wrong_link="http://localhost:7776/namestoreandmore" 19wrong_link="http://localhost:7776/namestoreandmore"
20 20
21
22curl_get () { 21curl_get () {
23 #$1 is link 22 #$1 is link
24 #$2 is grep 23 #$2 is grep