aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-03-21 13:54:28 +0100
committerMartin Schanzenbach <schanzen@gnunet.org>2022-03-21 13:54:28 +0100
commit4e95b59a6f3cd35c9c1b5dcdc6320f0e0dfef79b (patch)
tree22f87fcea0ea417a7a3ca8b900c3e6c891c28088 /src
parentec8a825b0e56c692c4879db10c6b25cd26bb42e4 (diff)
downloadgnunet-4e95b59a6f3cd35c9c1b5dcdc6320f0e0dfef79b.tar.gz
gnunet-4e95b59a6f3cd35c9c1b5dcdc6320f0e0dfef79b.zip
NAMESTORE: Towards new transaction-based API
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_namestore_service.h156
-rw-r--r--src/namestore/Makefile.am11
-rw-r--r--src/namestore/gnunet-service-namestore.c183
-rw-r--r--src/namestore/namestore.h10
-rw-r--r--src/namestore/namestore_api.c115
-rw-r--r--src/namestore/test_namestore_api_store_locking.c283
6 files changed, 168 insertions, 590 deletions
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h
index 619b81aed..86572803f 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -212,61 +212,6 @@ GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h,
212 212
213 213
214/** 214/**
215 * Open a record set for editing.
216 * Retrieves an exclusive lock on this set.
217 * Must be commited using @a GNUNET_NAMESTORE_records_commit
218 *
219 * @param h handle to the namestore
220 * @param pkey private key of the zone
221 * @param label name that is being mapped
222 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
223 * the handle is afterwards invalid
224 * @param error_cb_cls closure for @a error_cb
225 * @param rm function to call with the result (with 0 records if we don't have that label)
226 * @param rm_cls closure for @a rm
227 * @return handle to abort the request
228 */
229struct GNUNET_NAMESTORE_QueueEntry *
230GNUNET_NAMESTORE_records_open (struct GNUNET_NAMESTORE_Handle *h,
231 const struct
232 GNUNET_IDENTITY_PrivateKey *pkey,
233 const char *label,
234 GNUNET_SCHEDULER_TaskCallback error_cb,
235 void *error_cb_cls,
236 GNUNET_NAMESTORE_RecordMonitor rm,
237 void *rm_cls);
238
239/**
240 * Commit the record set to the namestore.
241 * Releases the lock on the record set.
242 * Use an empty array to
243 * remove all records under the given name.
244 *
245 * The continuation is called after the value has been stored in the
246 * database. Monitors may be notified asynchronously (basically with
247 * a buffer). However, if any monitor is consistently too slow to
248 * keep up with the changes, calling @a cont will be delayed until the
249 * monitors do keep up.
250 *
251 * @param h handle to the namestore
252 * @param pkey private key of the zone
253 * @param label name that is being mapped
254 * @param rd_count number of records in the 'rd' array
255 * @param rd array of records with data to store
256 * @param cont continuation to call when done
257 * @param cont_cls closure for @a cont
258 * @return handle to abort the request
259 */
260struct GNUNET_NAMESTORE_QueueEntry *
261GNUNET_NAMESTORE_records_commit (struct GNUNET_NAMESTORE_Handle *h,
262 const struct GNUNET_IDENTITY_PrivateKey *pkey,
263 const char *label,
264 unsigned int rd_count,
265 const struct GNUNET_GNSRECORD_Data *rd,
266 GNUNET_NAMESTORE_ContinuationWithStatus cont,
267 void *cont_cls);
268
269/**
270 * Look for an existing PKEY delegation record for a given public key. 215 * Look for an existing PKEY delegation record for a given public key.
271 * Returns at most one result to the processor. 216 * Returns at most one result to the processor.
272 * 217 *
@@ -448,6 +393,107 @@ void
448GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm); 393GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
449 394
450 395
396/**
397 * New API draft. Experimental
398 */
399
400/**
401 * Begin a namestore transaction.
402 *
403 * @param h handle to the namestore
404 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
405 * the handle is afterwards invalid
406 * @param error_cb_cls closure for @a error_cb
407 * @return handle to abort the request
408 */
409struct GNUNET_NAMESTORE_QueueEntry *
410GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
411 GNUNET_SCHEDULER_TaskCallback error_cb,
412 void *error_cb_cls);
413
414/**
415 * Begin rollback all actions in a transaction.
416 * Reverts all actions performed since #GNUNET_NAMESTORE_transaction_begin
417 *
418 * @param h handle to the namestore
419 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
420 * the handle is afterwards invalid
421 * @param error_cb_cls closure for @a error_cb
422 * @return handle to abort the request
423 */
424struct GNUNET_NAMESTORE_QueueEntry *
425GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h,
426 GNUNET_SCHEDULER_TaskCallback error_cb,
427 void *error_cb_cls);
428/**
429 * Commit a namestore transaction.
430 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
431 *
432 * @param h handle to the namestore
433 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
434 * the handle is afterwards invalid
435 * @param error_cb_cls closure for @a error_cb
436 * @return handle to abort the request
437 */
438struct GNUNET_NAMESTORE_QueueEntry *
439GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
440 GNUNET_SCHEDULER_TaskCallback error_cb,
441 void *error_cb_cls);
442
443/**
444 * Lookup an item in the namestore.
445 *
446 * @param h handle to the namestore
447 * @param pkey private key of the zone
448 * @param label name that is being mapped
449 * @param error_cb function to call on error (i.e. disconnect)
450 * the handle is afterwards invalid
451 * @param error_cb_cls closure for @a error_cb
452 * @param rm function to call with the result (with 0 records if we don't have that label);
453 * the handle is afterwards invalid
454 * @param rm_cls closure for @a rm
455 * @return handle to abort the request
456 */
457struct GNUNET_NAMESTORE_QueueEntry *
458GNUNET_NAMESTORE_records_select (struct GNUNET_NAMESTORE_Handle *h,
459 const struct
460 GNUNET_IDENTITY_PrivateKey *pkey,
461 const char *label,
462 GNUNET_SCHEDULER_TaskCallback error_cb,
463 void *error_cb_cls,
464 GNUNET_NAMESTORE_RecordMonitor rm,
465 void *rm_cls);
466
467
468/**
469 * Creates, deletes or updates an item in the namestore.
470 * If the item is already present, it is replaced with the new record set.
471 * Use an empty array to remove all records under the given name.
472 *
473 * The continuation is called after the value has been stored in the
474 * database. Monitors may be notified asynchronously (basically with
475 * a buffer). However, if any monitor is consistently too slow to
476 * keep up with the changes, calling @a cont will be delayed until the
477 * monitors do keep up.
478 *
479 * @param h handle to the namestore
480 * @param pkey private key of the zone
481 * @param label name that is being mapped
482 * @param rd_count number of records in the 'rd' array
483 * @param rd array of records with data to store
484 * @param cont continuation to call when done
485 * @param cont_cls closure for @a cont
486 * @return handle to abort the request
487 */
488struct GNUNET_NAMESTORE_QueueEntry *
489GNUNET_NAMESTORE_records_replace (struct GNUNET_NAMESTORE_Handle *h,
490 const struct GNUNET_IDENTITY_PrivateKey *pkey,
491 const char *label,
492 unsigned int rd_count,
493 const struct GNUNET_GNSRECORD_Data *rd,
494 GNUNET_NAMESTORE_ContinuationWithStatus cont,
495 void *cont_cls);
496
451#if 0 /* keep Emacsens' auto-indent happy */ 497#if 0 /* keep Emacsens' auto-indent happy */
452{ 498{
453#endif 499#endif
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index 2441b864a..51708dd67 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -39,7 +39,6 @@ if HAVE_SQLITE
39SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la 39SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la
40SQLITE_TESTS = test_plugin_namestore_sqlite \ 40SQLITE_TESTS = test_plugin_namestore_sqlite \
41 test_namestore_api_store_sqlite \ 41 test_namestore_api_store_sqlite \
42 test_namestore_api_store_locking_sqlite \
43 test_namestore_api_store_update_sqlite \ 42 test_namestore_api_store_update_sqlite \
44 test_namestore_api_zone_iteration_sqlite \ 43 test_namestore_api_zone_iteration_sqlite \
45 test_namestore_api_remove_sqlite \ 44 test_namestore_api_remove_sqlite \
@@ -250,16 +249,6 @@ test_namestore_api_store_sqlite_LDADD = \
250 $(top_builddir)/src/identity/libgnunetidentity.la \ 249 $(top_builddir)/src/identity/libgnunetidentity.la \
251 libgnunetnamestore.la 250 libgnunetnamestore.la
252 251
253test_namestore_api_store_locking_sqlite_SOURCES = \
254 test_namestore_api_store_locking.c
255test_namestore_api_store_locking_sqlite_LDADD = \
256 $(top_builddir)/src/testing/libgnunettesting.la \
257 $(top_builddir)/src/util/libgnunetutil.la \
258 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
259 $(top_builddir)/src/identity/libgnunetidentity.la \
260 libgnunetnamestore.la
261
262
263test_namestore_api_store_postgres_SOURCES = \ 252test_namestore_api_store_postgres_SOURCES = \
264 test_namestore_api_store.c 253 test_namestore_api_store.c
265test_namestore_api_store_postgres_LDADD = \ 254test_namestore_api_store_postgres_LDADD = \
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index d735822fb..95260ff9c 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -122,24 +122,6 @@ struct ZoneIteration
122}; 122};
123 123
124/** 124/**
125 * Lock on a record set
126 */
127struct RecordsLock
128{
129 /* DLL */
130 struct RecordsLock *prev;
131
132 /* DLL */
133 struct RecordsLock *next;
134
135 /* Hash of the locked label */
136 struct GNUNET_HashCode label_hash;
137
138 /* Client locking the zone */
139 struct NamestoreClient *client;
140};
141
142/**
143 * A namestore client 125 * A namestore client
144 */ 126 */
145struct NamestoreClient 127struct NamestoreClient
@@ -411,16 +393,6 @@ static struct StoreActivity *sa_head;
411static struct StoreActivity *sa_tail; 393static struct StoreActivity *sa_tail;
412 394
413/** 395/**
414 * Head of the DLL of record set locks
415 */
416static struct RecordsLock *locks_head;
417
418/**
419 * Tail of the DLL of record set locks
420 */
421static struct RecordsLock *locks_tail;
422
423/**
424 * Notification context shared by all monitors. 396 * Notification context shared by all monitors.
425 */ 397 */
426static struct GNUNET_NotificationContext *monitor_nc; 398static struct GNUNET_NotificationContext *monitor_nc;
@@ -447,7 +419,6 @@ static void
447cleanup_task (void *cls) 419cleanup_task (void *cls)
448{ 420{
449 struct CacheOperation *cop; 421 struct CacheOperation *cop;
450 struct RecordsLock *lock;
451 422
452 (void) cls; 423 (void) cls;
453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); 424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
@@ -459,13 +430,6 @@ cleanup_task (void *cls)
459 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); 430 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
460 GNUNET_free (cop); 431 GNUNET_free (cop);
461 } 432 }
462 while (NULL != (lock = locks_head))
463 {
464 GNUNET_CONTAINER_DLL_remove (locks_head,
465 locks_tail,
466 lock);
467 GNUNET_free (lock);
468 }
469 433
470 if (NULL != namecache) 434 if (NULL != namecache)
471 { 435 {
@@ -1154,7 +1118,6 @@ client_disconnect_cb (void *cls,
1154 struct NamestoreClient *nc = app_ctx; 1118 struct NamestoreClient *nc = app_ctx;
1155 struct ZoneIteration *no; 1119 struct ZoneIteration *no;
1156 struct CacheOperation *cop; 1120 struct CacheOperation *cop;
1157 struct RecordsLock *lock;
1158 1121
1159 (void) cls; 1122 (void) cls;
1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); 1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
@@ -1205,15 +1168,6 @@ client_disconnect_cb (void *cls,
1205 for (cop = cop_head; NULL != cop; cop = cop->next) 1168 for (cop = cop_head; NULL != cop; cop = cop->next)
1206 if (nc == cop->nc) 1169 if (nc == cop->nc)
1207 cop->nc = NULL; 1170 cop->nc = NULL;
1208 for (lock = locks_head; NULL != lock; lock = lock->next)
1209 {
1210 if (nc != lock->client)
1211 continue;
1212 GNUNET_CONTAINER_DLL_remove (locks_head,
1213 locks_tail,
1214 lock);
1215 GNUNET_free (lock);
1216 }
1217 GNUNET_free (nc); 1171 GNUNET_free (nc);
1218} 1172}
1219 1173
@@ -1407,105 +1361,6 @@ check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1407 return GNUNET_OK; 1361 return GNUNET_OK;
1408} 1362}
1409 1363
1410static void
1411calculate_lock_hash (const char *label,
1412 const struct GNUNET_IDENTITY_PrivateKey *zone,
1413 struct GNUNET_HashCode *result)
1414{
1415 struct GNUNET_HashContext *hctx;
1416
1417 hctx = GNUNET_CRYPTO_hash_context_start ();
1418 GNUNET_CRYPTO_hash_context_read (hctx, label, strlen (label));
1419 GNUNET_CRYPTO_hash_context_read (hctx, zone,
1420 sizeof (*zone));
1421 GNUNET_CRYPTO_hash_context_finish (hctx, result);
1422}
1423
1424/**
1425 * Release a lock on a record set.
1426 * Does nothing if lock not held.
1427 *
1428 * @param label the label of the record set
1429 * @param zone the zone
1430 * @param nc the client releasing the lock
1431 */
1432static void
1433NST_label_lock_release (const char *label,
1434 const struct GNUNET_IDENTITY_PrivateKey *zone,
1435 const struct NamestoreClient *nc)
1436{
1437 struct GNUNET_HashCode label_hash;
1438 struct RecordsLock *lock;
1439
1440 calculate_lock_hash (label, zone, &label_hash);
1441 for (lock = locks_head; NULL != lock; lock = lock->next)
1442 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1443 break;
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1445 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1446 if (NULL == lock)
1447 return;
1448 if (lock->client != nc)
1449 {
1450 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1451 "Lock is held by other client on `%s'\n", label);
1452 return;
1453 }
1454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1455 "Unocking %s\n", GNUNET_h2s (&label_hash));
1456 GNUNET_CONTAINER_DLL_remove (locks_head,
1457 locks_tail,
1458 lock);
1459 GNUNET_free (lock);
1460}
1461
1462/**
1463 * Get/set a lock on a record set.
1464 * May be called multiple times but will
1465 * not aquire additional locks.
1466 *
1467 * @param the label of the record set
1468 * @param the zone
1469 * @param the client doing the locking
1470 * @return GNUNET_YES if lock retrieved or set already.
1471 */
1472static enum GNUNET_GenericReturnValue
1473NST_label_lock (const char *label,
1474 const struct GNUNET_IDENTITY_PrivateKey *zone,
1475 struct NamestoreClient *nc)
1476{
1477 struct GNUNET_HashCode label_hash;
1478 struct RecordsLock *lock;
1479
1480 calculate_lock_hash (label, zone, &label_hash);
1481 for (lock = locks_head; NULL != lock; lock = lock->next)
1482 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1483 break;
1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1486 if (NULL != lock)
1487 {
1488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1489 "Client holds lock: %s\n", (lock->client != nc) ? "No" : "Yes");
1490 if (lock->client != nc)
1491 {
1492 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1493 "Lock is held by other client on `%s'\n", label);
1494 return GNUNET_NO;
1495 }
1496 return GNUNET_YES;
1497 }
1498 lock = GNUNET_new (struct RecordsLock);
1499 lock->client = nc;
1500 memcpy (&lock->label_hash, &label_hash, sizeof (label_hash));
1501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1502 "Locking %s\n", GNUNET_h2s (&label_hash));
1503 GNUNET_CONTAINER_DLL_insert (locks_head,
1504 locks_tail,
1505 lock);
1506 return GNUNET_YES;
1507}
1508
1509 1364
1510/** 1365/**
1511 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message 1366 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
@@ -1520,7 +1375,6 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1520 struct GNUNET_MQ_Envelope *env; 1375 struct GNUNET_MQ_Envelope *env;
1521 struct LabelLookupResponseMessage *llr_msg; 1376 struct LabelLookupResponseMessage *llr_msg;
1522 struct RecordLookupContext rlc; 1377 struct RecordLookupContext rlc;
1523 struct RecordsLock *lock;
1524 struct GNUNET_HashCode label_hash; 1378 struct GNUNET_HashCode label_hash;
1525 const char *name_tmp; 1379 const char *name_tmp;
1526 char *res_name; 1380 char *res_name;
@@ -1544,28 +1398,6 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1544 return; 1398 return;
1545 } 1399 }
1546 name_len = strlen (conv_name) + 1; 1400 name_len = strlen (conv_name) + 1;
1547 if (GNUNET_YES == ntohl (ll_msg->locking))
1548 {
1549 if (GNUNET_NO == NST_label_lock (conv_name, &ll_msg->zone, nc))
1550 {
1551 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1552 "Lock is held by other client on `%s'\n", conv_name);
1553 env =
1554 GNUNET_MQ_msg_extra (llr_msg,
1555 name_len,
1556 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1557 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1558 llr_msg->private_key = ll_msg->zone;
1559 llr_msg->name_len = htons (name_len);
1560 llr_msg->rd_count = htons (0);
1561 llr_msg->rd_len = htons (0);
1562 llr_msg->found = htons (GNUNET_SYSERR);
1563 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1564 GNUNET_MQ_send (nc->mq, env);
1565 GNUNET_free (conv_name);
1566 return;
1567 }
1568 }
1569 rlc.label = conv_name; 1401 rlc.label = conv_name;
1570 rlc.found = GNUNET_NO; 1402 rlc.found = GNUNET_NO;
1571 rlc.res_rd_count = 0; 1403 rlc.res_rd_count = 0;
@@ -1699,7 +1531,6 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1699 unsigned int rd_count; 1531 unsigned int rd_count;
1700 int res; 1532 int res;
1701 struct StoreActivity *sa; 1533 struct StoreActivity *sa;
1702 struct RecordsLock *lock;
1703 struct GNUNET_HashCode label_hash; 1534 struct GNUNET_HashCode label_hash;
1704 struct GNUNET_TIME_Absolute existing_block_exp; 1535 struct GNUNET_TIME_Absolute existing_block_exp;
1705 struct GNUNET_TIME_Absolute new_block_exp; 1536 struct GNUNET_TIME_Absolute new_block_exp;
@@ -1753,20 +1584,6 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1753 GNUNET_SERVICE_client_continue (nc->client); 1584 GNUNET_SERVICE_client_continue (nc->client);
1754 return; 1585 return;
1755 } 1586 }
1756 if (GNUNET_YES == ntohl (rp_msg->locking))
1757 {
1758 if (GNUNET_NO == NST_label_lock (conv_name, &rp_msg->private_key, nc))
1759 {
1760 send_store_response (nc, GNUNET_SYSERR, _ ("Record set locked."), rid);
1761 GNUNET_SERVICE_client_continue (nc->client);
1762 GNUNET_free (conv_name);
1763 return;
1764 }
1765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1766 "Client has lock on `%s', continuing.\n", conv_name);
1767 if (GNUNET_YES == ntohl (rp_msg->locking))
1768 NST_label_lock_release (conv_name, &rp_msg->private_key, nc);
1769 }
1770 1587
1771 GNUNET_STATISTICS_update (statistics, 1588 GNUNET_STATISTICS_update (statistics,
1772 "Well-formed store requests received", 1589 "Well-formed store requests received",
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
index 0f3ffa837..583ec1e68 100644
--- a/src/namestore/namestore.h
+++ b/src/namestore/namestore.h
@@ -68,11 +68,6 @@ struct RecordStoreMessage
68 struct GNUNET_TIME_AbsoluteNBO expire; 68 struct GNUNET_TIME_AbsoluteNBO expire;
69 69
70 /** 70 /**
71 * Unock the label with this request.
72 */
73 uint32_t locking GNUNET_PACKED;
74
75 /**
76 * Name length 71 * Name length
77 */ 72 */
78 uint16_t name_len GNUNET_PACKED; 73 uint16_t name_len GNUNET_PACKED;
@@ -151,11 +146,6 @@ struct LabelLookupMessage
151 uint32_t label_len GNUNET_PACKED; 146 uint32_t label_len GNUNET_PACKED;
152 147
153 /** 148 /**
154 * Lock the label with this lookup
155 */
156 uint32_t locking GNUNET_PACKED;
157
158 /**
159 * The private key of the zone to look up in 149 * The private key of the zone to look up in
160 */ 150 */
161 struct GNUNET_IDENTITY_PrivateKey zone; 151 struct GNUNET_IDENTITY_PrivateKey zone;
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index a7380bbde..73f985803 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -411,7 +411,7 @@ handle_record_store_response (void *cls,
411 return; 411 return;
412 if (NULL != qe->cont) 412 if (NULL != qe->cont)
413 qe->cont (qe->cont_cls, res, 413 qe->cont (qe->cont_cls, res,
414 (GNUNET_OK == res) ? NULL : emsg); 414 (GNUNET_OK == res) ? NULL : emsg);
415 free_qe (qe); 415 free_qe (qe);
416} 416}
417 417
@@ -482,7 +482,7 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
482 int16_t found = (int16_t) ntohs (msg->found); 482 int16_t found = (int16_t) ntohs (msg->found);
483 483
484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n", 484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n",
485 found); 485 found);
486 qe = find_qe (h, ntohl (msg->gns_header.r_id)); 486 qe = find_qe (h, ntohl (msg->gns_header.r_id));
487 if (NULL == qe) 487 if (NULL == qe)
488 return; 488 return;
@@ -820,9 +820,9 @@ reconnect (struct GNUNET_NAMESTORE_Handle *h)
820{ 820{
821 struct GNUNET_MQ_MessageHandler handlers[] = 821 struct GNUNET_MQ_MessageHandler handlers[] =
822 { GNUNET_MQ_hd_var_size (record_store_response, 822 { GNUNET_MQ_hd_var_size (record_store_response,
823 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE, 823 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
824 struct RecordStoreResponseMessage, 824 struct RecordStoreResponseMessage,
825 h), 825 h),
826 GNUNET_MQ_hd_var_size (zone_to_name_response, 826 GNUNET_MQ_hd_var_size (zone_to_name_response,
827 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE, 827 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE,
828 struct ZoneToNameResponseMessage, 828 struct ZoneToNameResponseMessage,
@@ -1013,16 +1013,16 @@ warn_delay (void *cls)
1013 GNUNET_NAMESTORE_cancel (qe); 1013 GNUNET_NAMESTORE_cancel (qe);
1014} 1014}
1015 1015
1016
1016struct GNUNET_NAMESTORE_QueueEntry * 1017struct GNUNET_NAMESTORE_QueueEntry *
1017records_store_ ( 1018GNUNET_NAMESTORE_records_store (
1018 struct GNUNET_NAMESTORE_Handle *h, 1019 struct GNUNET_NAMESTORE_Handle *h,
1019 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1020 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1020 const char *label, 1021 const char *label,
1021 unsigned int rd_count, 1022 unsigned int rd_count,
1022 const struct GNUNET_GNSRECORD_Data *rd, 1023 const struct GNUNET_GNSRECORD_Data *rd,
1023 GNUNET_NAMESTORE_ContinuationWithStatus cont, 1024 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1024 void *cont_cls, 1025 void *cont_cls)
1025 int locking)
1026{ 1026{
1027 struct GNUNET_NAMESTORE_QueueEntry *qe; 1027 struct GNUNET_NAMESTORE_QueueEntry *qe;
1028 struct GNUNET_MQ_Envelope *env; 1028 struct GNUNET_MQ_Envelope *env;
@@ -1067,9 +1067,8 @@ records_store_ (
1067 msg->name_len = htons (name_len); 1067 msg->name_len = htons (name_len);
1068 msg->rd_count = htons (rd_count); 1068 msg->rd_count = htons (rd_count);
1069 msg->rd_len = htons (rd_ser_len); 1069 msg->rd_len = htons (rd_ser_len);
1070 msg->reserved = ntohs(0); 1070 msg->reserved = ntohs (0);
1071 msg->private_key = *pkey; 1071 msg->private_key = *pkey;
1072 msg->locking = htonl (locking);
1073 1072
1074 name_tmp = (char *) &msg[1]; 1073 name_tmp = (char *) &msg[1];
1075 GNUNET_memcpy (name_tmp, label, name_len); 1074 GNUNET_memcpy (name_tmp, label, name_len);
@@ -1101,22 +1100,11 @@ records_store_ (
1101 return qe; 1100 return qe;
1102} 1101}
1103 1102
1103/**
1104 * TODO: Experimental API will replace API above.
1105 */
1104struct GNUNET_NAMESTORE_QueueEntry * 1106struct GNUNET_NAMESTORE_QueueEntry *
1105GNUNET_NAMESTORE_records_store ( 1107GNUNET_NAMESTORE_records_replace (
1106 struct GNUNET_NAMESTORE_Handle *h,
1107 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1108 const char *label,
1109 unsigned int rd_count,
1110 const struct GNUNET_GNSRECORD_Data *rd,
1111 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1112 void *cont_cls)
1113{
1114 return records_store_ (h, pkey, label,
1115 rd_count, rd, cont, cont_cls, GNUNET_NO);
1116}
1117
1118struct GNUNET_NAMESTORE_QueueEntry *
1119GNUNET_NAMESTORE_records_commit (
1120 struct GNUNET_NAMESTORE_Handle *h, 1108 struct GNUNET_NAMESTORE_Handle *h,
1121 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1109 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1122 const char *label, 1110 const char *label,
@@ -1125,21 +1113,19 @@ GNUNET_NAMESTORE_records_commit (
1125 GNUNET_NAMESTORE_ContinuationWithStatus cont, 1113 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1126 void *cont_cls) 1114 void *cont_cls)
1127{ 1115{
1128 return records_store_ (h, pkey, label, 1116 return GNUNET_NAMESTORE_records_store (h, pkey, label, rd_count, rd,
1129 rd_count, rd, cont, cont_cls, GNUNET_YES); 1117 cont, cont_cls);
1130} 1118}
1131 1119
1132
1133struct GNUNET_NAMESTORE_QueueEntry * 1120struct GNUNET_NAMESTORE_QueueEntry *
1134records_lookup_ ( 1121GNUNET_NAMESTORE_records_lookup (
1135 struct GNUNET_NAMESTORE_Handle *h, 1122 struct GNUNET_NAMESTORE_Handle *h,
1136 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1123 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1137 const char *label, 1124 const char *label,
1138 GNUNET_SCHEDULER_TaskCallback error_cb, 1125 GNUNET_SCHEDULER_TaskCallback error_cb,
1139 void *error_cb_cls, 1126 void *error_cb_cls,
1140 GNUNET_NAMESTORE_RecordMonitor rm, 1127 GNUNET_NAMESTORE_RecordMonitor rm,
1141 void *rm_cls, 1128 void *rm_cls)
1142 int locking)
1143{ 1129{
1144 struct GNUNET_NAMESTORE_QueueEntry *qe; 1130 struct GNUNET_NAMESTORE_QueueEntry *qe;
1145 struct GNUNET_MQ_Envelope *env; 1131 struct GNUNET_MQ_Envelope *env;
@@ -1167,7 +1153,6 @@ records_lookup_ (
1167 msg->gns_header.r_id = htonl (qe->op_id); 1153 msg->gns_header.r_id = htonl (qe->op_id);
1168 msg->zone = *pkey; 1154 msg->zone = *pkey;
1169 msg->label_len = htonl (label_len); 1155 msg->label_len = htonl (label_len);
1170 msg->locking = htonl (locking);
1171 GNUNET_memcpy (&msg[1], label, label_len); 1156 GNUNET_memcpy (&msg[1], label, label_len);
1172 if (NULL == h->mq) 1157 if (NULL == h->mq)
1173 qe->env = env; 1158 qe->env = env;
@@ -1176,22 +1161,12 @@ records_lookup_ (
1176 return qe; 1161 return qe;
1177} 1162}
1178 1163
1179struct GNUNET_NAMESTORE_QueueEntry *
1180GNUNET_NAMESTORE_records_lookup (
1181 struct GNUNET_NAMESTORE_Handle *h,
1182 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1183 const char *label,
1184 GNUNET_SCHEDULER_TaskCallback error_cb,
1185 void *error_cb_cls,
1186 GNUNET_NAMESTORE_RecordMonitor rm,
1187 void *rm_cls)
1188{
1189 return records_lookup_ (h, pkey, label,
1190 error_cb, error_cb_cls, rm, rm_cls, GNUNET_NO);
1191}
1192 1164
1165/**
1166 * TODO experimental API. Will replace old API above.
1167 */
1193struct GNUNET_NAMESTORE_QueueEntry * 1168struct GNUNET_NAMESTORE_QueueEntry *
1194GNUNET_NAMESTORE_records_open ( 1169GNUNET_NAMESTORE_records_select (
1195 struct GNUNET_NAMESTORE_Handle *h, 1170 struct GNUNET_NAMESTORE_Handle *h,
1196 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1171 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1197 const char *label, 1172 const char *label,
@@ -1200,8 +1175,9 @@ GNUNET_NAMESTORE_records_open (
1200 GNUNET_NAMESTORE_RecordMonitor rm, 1175 GNUNET_NAMESTORE_RecordMonitor rm,
1201 void *rm_cls) 1176 void *rm_cls)
1202{ 1177{
1203 return records_lookup_ (h, pkey, label, 1178 return GNUNET_NAMESTORE_records_lookup (h, pkey, label,
1204 error_cb, error_cb_cls, rm, rm_cls, GNUNET_YES); 1179 error_cb, error_cb_cls,
1180 rm, rm_cls);
1205} 1181}
1206 1182
1207struct GNUNET_NAMESTORE_QueueEntry * 1183struct GNUNET_NAMESTORE_QueueEntry *
@@ -1364,5 +1340,48 @@ GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1364 free_qe (qe); 1340 free_qe (qe);
1365} 1341}
1366 1342
1343/**
1344 * New API draft. Experimental
1345 */
1346
1347struct GNUNET_NAMESTORE_QueueEntry *
1348GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
1349 GNUNET_SCHEDULER_TaskCallback error_cb,
1350 void *error_cb_cls)
1351{
1352 GNUNET_break (0);
1353 return NULL;
1354}
1355
1356
1357struct GNUNET_NAMESTORE_QueueEntry *
1358GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h,
1359 GNUNET_SCHEDULER_TaskCallback error_cb,
1360 void *error_cb_cls)
1361{
1362 GNUNET_break (0);
1363 return NULL;
1364}
1365
1366
1367/**
1368 * Commit a namestore transaction.
1369 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
1370 *
1371 * @param h handle to the namestore
1372 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
1373 * the handle is afterwards invalid
1374 * @param error_cb_cls closure for @a error_cb
1375 * @return handle to abort the request
1376 */
1377struct GNUNET_NAMESTORE_QueueEntry *
1378GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
1379 GNUNET_SCHEDULER_TaskCallback error_cb,
1380 void *error_cb_cls)
1381{
1382 GNUNET_break (0);
1383 return NULL;
1384}
1385
1367 1386
1368/* end of namestore_api.c */ 1387/* end of namestore_api.c */
diff --git a/src/namestore/test_namestore_api_store_locking.c b/src/namestore/test_namestore_api_store_locking.c
deleted file mode 100644
index a80cad523..000000000
--- a/src/namestore/test_namestore_api_store_locking.c
+++ /dev/null
@@ -1,283 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file namestore/test_namestore_api_store_locking.c
22 * @brief testcase for namestore_api.c: store a record, locking
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_testing_lib.h"
27#include "gnunet_dnsparser_lib.h"
28
29#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
30
31#define TEST_RECORD_DATALEN 123
32
33#define TEST_RECORD_DATA 'a'
34
35#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
36
37
38static struct GNUNET_NAMESTORE_Handle *nsh;
39
40static struct GNUNET_NAMESTORE_Handle *nsh_alt;
41
42static struct GNUNET_SCHEDULER_Task *endbadly_task;
43
44static struct GNUNET_IDENTITY_PrivateKey privkey;
45
46static struct GNUNET_IDENTITY_PublicKey pubkey;
47
48static int res;
49
50static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
51
52static struct GNUNET_NAMESTORE_QueueEntry *nsqe_alt;
53
54
55static void
56cleanup ()
57{
58 if (NULL != nsh)
59 {
60 GNUNET_NAMESTORE_disconnect (nsh);
61 nsh = NULL;
62 }
63 if (NULL != nsh_alt)
64 {
65 GNUNET_NAMESTORE_disconnect (nsh_alt);
66 nsh_alt = NULL;
67 }
68 GNUNET_SCHEDULER_shutdown ();
69}
70
71
72/**
73 * Re-establish the connection to the service.
74 *
75 * @param cls handle to use to re-connect.
76 */
77static void
78endbadly (void *cls)
79{
80 if (NULL != nsqe)
81 {
82 GNUNET_NAMESTORE_cancel (nsqe);
83 nsqe = NULL;
84 }
85 cleanup ();
86 res = 1;
87}
88
89
90static void
91end (void *cls)
92{
93 cleanup ();
94 res = 0;
95}
96
97
98static void
99open_alt_second_failed (void *cls)
100{
101 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
102 "Got did not get lock when I should...\n");
103 nsqe_alt = NULL;
104 GNUNET_SCHEDULER_cancel (endbadly_task);
105 endbadly_task = NULL;
106 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
107}
108
109
110void
111open_alt_second_cont (void *cls,
112 const struct
113 GNUNET_IDENTITY_PrivateKey *zone,
114 const char *label,
115 unsigned int rd_count,
116 const struct GNUNET_GNSRECORD_Data *rd)
117{
118 nsqe_alt = NULL;
119 GNUNET_SCHEDULER_cancel (endbadly_task);
120 endbadly_task = NULL;
121 GNUNET_SCHEDULER_add_now (&end, NULL);
122}
123
124
125static void
126put_cont (void *cls, int32_t success, const char *emsg)
127{
128 const char *name = cls;
129
130 nsqe = NULL;
131 GNUNET_assert (NULL != cls);
132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
133 "Name store added record for `%s': %s\n",
134 name,
135 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
136 /* This should not work */
137 nsqe_alt = GNUNET_NAMESTORE_records_open (nsh_alt,
138 &privkey,
139 name,
140 &open_alt_second_failed,
141 NULL,
142 &open_alt_second_cont,
143 NULL);
144}
145
146static void
147open_alt_failed (void *cls)
148{
149 struct GNUNET_GNSRECORD_Data rd;
150 const char *name = "dummy";
151
152 nsqe_alt = NULL;
153 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us;
154 rd.record_type = TEST_RECORD_TYPE;
155 rd.data_size = TEST_RECORD_DATALEN;
156 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
157 rd.flags = 0;
158 memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN);
159
160 nsqe = GNUNET_NAMESTORE_records_commit (nsh,
161 &privkey,
162 name,
163 1,
164 &rd,
165 &put_cont,
166 (void *) name);
167
168 GNUNET_free_nz ((void *) rd.data);
169
170}
171
172
173void
174open_alt_cont (void *cls,
175 const struct
176 GNUNET_IDENTITY_PrivateKey *zone,
177 const char *label,
178 unsigned int rd_count,
179 const struct GNUNET_GNSRECORD_Data *rd)
180{
181 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
182 "Got lock when I should not...\n");
183 nsqe_alt = NULL;
184 GNUNET_SCHEDULER_cancel (endbadly_task);
185 endbadly_task = NULL;
186 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
187}
188
189void
190open_cont (void *cls,
191 const struct
192 GNUNET_IDENTITY_PrivateKey *zone,
193 const char *label,
194 unsigned int rd_count,
195 const struct GNUNET_GNSRECORD_Data *rd)
196{
197 const char *name = "dummy";
198 /* Record set does not exist */
199 GNUNET_assert (NULL == rd);
200 nsqe = NULL;
201 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
202 &endbadly, NULL);
203
204 /* This should not work */
205 nsqe_alt = GNUNET_NAMESTORE_records_open (nsh_alt,
206 &privkey,
207 name,
208 &open_alt_failed,
209 NULL,
210 &open_alt_cont,
211 NULL);
212
213}
214
215
216static void
217open_cont_failed (void *cls)
218{
219 nsqe = NULL;
220 GNUNET_SCHEDULER_cancel (endbadly_task);
221 endbadly_task = NULL;
222 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
223}
224
225
226static void
227run (void *cls,
228 const struct GNUNET_CONFIGURATION_Handle *cfg,
229 struct GNUNET_TESTING_Peer *peer)
230{
231 const char *name = "dummy";
232 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
233 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
234 GNUNET_IDENTITY_key_get_public (&privkey, &pubkey);
235
236
237 nsh = GNUNET_NAMESTORE_connect (cfg);
238 GNUNET_break (NULL != nsh);
239 nsh_alt = GNUNET_NAMESTORE_connect (cfg);
240 GNUNET_break (NULL != nsh_alt);
241
242 nsqe = GNUNET_NAMESTORE_records_open (nsh,
243 &privkey,
244 name,
245 &open_cont_failed,
246 NULL,
247 &open_cont,
248 NULL);
249 if (NULL == nsqe)
250 {
251 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
252 _ ("Namestore cannot store no block\n"));
253 }
254}
255
256
257#include "test_common.c"
258
259
260int
261main (int argc, char *argv[])
262{
263 const char *plugin_name;
264 char *cfg_name;
265
266 SETUP_CFG (plugin_name, cfg_name);
267 res = 1;
268 if (0 !=
269 GNUNET_TESTING_peer_run ("test-namestore-api",
270 cfg_name,
271 &run,
272 NULL))
273 {
274 res = 1;
275 }
276 GNUNET_DISK_purge_cfg_dir (cfg_name,
277 "GNUNET_TEST_HOME");
278 GNUNET_free (cfg_name);
279 return res;
280}
281
282
283/* end of test_namestore_api_store.c */