aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-03-16 18:53:22 +0100
committerMartin Schanzenbach <schanzen@gnunet.org>2022-03-16 18:53:22 +0100
commit68ac68b70cf7fac5367421badade9febbaea7bf2 (patch)
treef6987aedad35faf7ef7e951bfa802511f270f70e /src
parenta3343861db6a9e55707c1a55f7c5d2a4738f4ea0 (diff)
downloadgnunet-68ac68b70cf7fac5367421badade9febbaea7bf2.tar.gz
gnunet-68ac68b70cf7fac5367421badade9febbaea7bf2.zip
NAMESTORE: Add record set blocking API
New API that allows the caller to reserve the mofification of a record set under a label. The record set cannot be modified by other clients until released.
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_namestore_service.h55
-rw-r--r--src/namestore/Makefile.am11
-rw-r--r--src/namestore/gnunet-service-namestore.c141
-rw-r--r--src/namestore/namestore.h12
-rw-r--r--src/namestore/namestore_api.c108
5 files changed, 285 insertions, 42 deletions
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h
index 7db5e9d9e..619b81aed 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -212,6 +212,61 @@ 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/**
215 * Look for an existing PKEY delegation record for a given public key. 270 * Look for an existing PKEY delegation record for a given public key.
216 * Returns at most one result to the processor. 271 * Returns at most one result to the processor.
217 * 272 *
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index 51708dd67..2441b864a 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -39,6 +39,7 @@ 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 \
42 test_namestore_api_store_update_sqlite \ 43 test_namestore_api_store_update_sqlite \
43 test_namestore_api_zone_iteration_sqlite \ 44 test_namestore_api_zone_iteration_sqlite \
44 test_namestore_api_remove_sqlite \ 45 test_namestore_api_remove_sqlite \
@@ -249,6 +250,16 @@ test_namestore_api_store_sqlite_LDADD = \
249 $(top_builddir)/src/identity/libgnunetidentity.la \ 250 $(top_builddir)/src/identity/libgnunetidentity.la \
250 libgnunetnamestore.la 251 libgnunetnamestore.la
251 252
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
252test_namestore_api_store_postgres_SOURCES = \ 263test_namestore_api_store_postgres_SOURCES = \
253 test_namestore_api_store.c 264 test_namestore_api_store.c
254test_namestore_api_store_postgres_LDADD = \ 265test_namestore_api_store_postgres_LDADD = \
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index 2a3a006e8..3f679cacd 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -121,6 +121,23 @@ struct ZoneIteration
121 int send_end; 121 int send_end;
122}; 122};
123 123
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};
124 141
125/** 142/**
126 * A namestore client 143 * A namestore client
@@ -394,6 +411,16 @@ static struct StoreActivity *sa_head;
394static struct StoreActivity *sa_tail; 411static struct StoreActivity *sa_tail;
395 412
396/** 413/**
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/**
397 * Notification context shared by all monitors. 424 * Notification context shared by all monitors.
398 */ 425 */
399static struct GNUNET_NotificationContext *monitor_nc; 426static struct GNUNET_NotificationContext *monitor_nc;
@@ -420,6 +447,7 @@ static void
420cleanup_task (void *cls) 447cleanup_task (void *cls)
421{ 448{
422 struct CacheOperation *cop; 449 struct CacheOperation *cop;
450 struct RecordsLock *lock;
423 451
424 (void) cls; 452 (void) cls;
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); 453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
@@ -431,6 +459,14 @@ cleanup_task (void *cls)
431 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); 459 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
432 GNUNET_free (cop); 460 GNUNET_free (cop);
433 } 461 }
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
434 if (NULL != namecache) 470 if (NULL != namecache)
435 { 471 {
436 GNUNET_NAMECACHE_disconnect (namecache); 472 GNUNET_NAMECACHE_disconnect (namecache);
@@ -1118,6 +1154,7 @@ client_disconnect_cb (void *cls,
1118 struct NamestoreClient *nc = app_ctx; 1154 struct NamestoreClient *nc = app_ctx;
1119 struct ZoneIteration *no; 1155 struct ZoneIteration *no;
1120 struct CacheOperation *cop; 1156 struct CacheOperation *cop;
1157 struct RecordsLock *lock;
1121 1158
1122 (void) cls; 1159 (void) cls;
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); 1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
@@ -1168,6 +1205,15 @@ client_disconnect_cb (void *cls,
1168 for (cop = cop_head; NULL != cop; cop = cop->next) 1205 for (cop = cop_head; NULL != cop; cop = cop->next)
1169 if (nc == cop->nc) 1206 if (nc == cop->nc)
1170 cop->nc = NULL; 1207 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 }
1171 GNUNET_free (nc); 1217 GNUNET_free (nc);
1172} 1218}
1173 1219
@@ -1361,6 +1407,7 @@ check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1361 return GNUNET_OK; 1407 return GNUNET_OK;
1362} 1408}
1363 1409
1410
1364/** 1411/**
1365 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message 1412 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1366 * 1413 *
@@ -1374,13 +1421,14 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1374 struct GNUNET_MQ_Envelope *env; 1421 struct GNUNET_MQ_Envelope *env;
1375 struct LabelLookupResponseMessage *llr_msg; 1422 struct LabelLookupResponseMessage *llr_msg;
1376 struct RecordLookupContext rlc; 1423 struct RecordLookupContext rlc;
1424 struct RecordsLock *lock;
1425 struct GNUNET_HashCode label_hash;
1377 const char *name_tmp; 1426 const char *name_tmp;
1378 char *res_name; 1427 char *res_name;
1379 char *conv_name; 1428 char *conv_name;
1380 uint32_t name_len; 1429 uint32_t name_len;
1381 int res; 1430 int res;
1382 1431
1383 name_len = ntohl (ll_msg->label_len);
1384 name_tmp = (const char *) &ll_msg[1]; 1432 name_tmp = (const char *) &ll_msg[1];
1385 GNUNET_SERVICE_client_continue (nc->client); 1433 GNUNET_SERVICE_client_continue (nc->client);
1386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1396,6 +1444,52 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1396 GNUNET_SERVICE_client_drop (nc->client); 1444 GNUNET_SERVICE_client_drop (nc->client);
1397 return; 1445 return;
1398 } 1446 }
1447 name_len = strlen (conv_name) + 1;
1448 if (GNUNET_YES == ntohl (ll_msg->locking))
1449 {
1450 GNUNET_CRYPTO_hash (conv_name, strlen (conv_name), &label_hash);
1451 for (lock = locks_head; NULL != lock; lock = lock->next)
1452 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1453 break;
1454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1455 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1456 if (NULL != lock)
1457 {
1458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1459 "Client holds lock: %s\n", (lock->client != nc) ? "No" : "Yes");
1460
1461 if (lock->client != nc)
1462 {
1463 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1464 "Lock is held by other client on `%s'\n", conv_name);
1465 env =
1466 GNUNET_MQ_msg_extra (llr_msg,
1467 name_len,
1468 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1469 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1470 llr_msg->private_key = ll_msg->zone;
1471 llr_msg->name_len = htons (name_len);
1472 llr_msg->rd_count = htons (0);
1473 llr_msg->rd_len = htons (0);
1474 llr_msg->found = htons (GNUNET_SYSERR);
1475 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1476 GNUNET_MQ_send (nc->mq, env);
1477 GNUNET_free (conv_name);
1478 return;
1479 }
1480 }
1481 else
1482 {
1483 lock = GNUNET_new (struct RecordsLock);
1484 lock->client = nc;
1485 GNUNET_CRYPTO_hash (conv_name,
1486 strlen (conv_name),
1487 &lock->label_hash);
1488 GNUNET_CONTAINER_DLL_insert (locks_head,
1489 locks_tail,
1490 lock);
1491 }
1492 }
1399 rlc.label = conv_name; 1493 rlc.label = conv_name;
1400 rlc.found = GNUNET_NO; 1494 rlc.found = GNUNET_NO;
1401 rlc.res_rd_count = 0; 1495 rlc.res_rd_count = 0;
@@ -1407,7 +1501,6 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1407 conv_name, 1501 conv_name,
1408 &lookup_it, 1502 &lookup_it,
1409 &rlc); 1503 &rlc);
1410 GNUNET_free (conv_name);
1411 env = 1504 env =
1412 GNUNET_MQ_msg_extra (llr_msg, 1505 GNUNET_MQ_msg_extra (llr_msg,
1413 name_len + rlc.rd_ser_len, 1506 name_len + rlc.rd_ser_len,
@@ -1419,16 +1512,18 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1419 llr_msg->rd_len = htons (rlc.rd_ser_len); 1512 llr_msg->rd_len = htons (rlc.rd_ser_len);
1420 res_name = (char *) &llr_msg[1]; 1513 res_name = (char *) &llr_msg[1];
1421 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) 1514 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1422 llr_msg->found = ntohs (GNUNET_YES); 1515 llr_msg->found = htons (GNUNET_YES);
1423 else 1516 else
1424 llr_msg->found = ntohs (GNUNET_NO); 1517 llr_msg->found = htons (GNUNET_NO);
1425 GNUNET_memcpy (&llr_msg[1], name_tmp, name_len); 1518 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1426 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len); 1519 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1427 GNUNET_MQ_send (nc->mq, env); 1520 GNUNET_MQ_send (nc->mq, env);
1428 GNUNET_free (rlc.res_rd); 1521 GNUNET_free (rlc.res_rd);
1522 GNUNET_free (conv_name);
1429} 1523}
1430 1524
1431 1525
1526
1432/** 1527/**
1433 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message 1528 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1434 * 1529 *
@@ -1528,6 +1623,8 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1528 unsigned int rd_count; 1623 unsigned int rd_count;
1529 int res; 1624 int res;
1530 struct StoreActivity *sa; 1625 struct StoreActivity *sa;
1626 struct RecordsLock *lock;
1627 struct GNUNET_HashCode label_hash;
1531 struct GNUNET_TIME_Absolute existing_block_exp; 1628 struct GNUNET_TIME_Absolute existing_block_exp;
1532 struct GNUNET_TIME_Absolute new_block_exp; 1629 struct GNUNET_TIME_Absolute new_block_exp;
1533 1630
@@ -1552,7 +1649,8 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1552 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1649 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1553 "Error normalizing name `%s'\n", 1650 "Error normalizing name `%s'\n",
1554 name_tmp); 1651 name_tmp);
1555 send_store_response (nc, GNUNET_SYSERR, _("Error normalizing name."), rid); 1652 send_store_response (nc, GNUNET_SYSERR, _ ("Error normalizing name."),
1653 rid);
1556 GNUNET_SERVICE_client_continue (nc->client); 1654 GNUNET_SERVICE_client_continue (nc->client);
1557 return; 1655 return;
1558 } 1656 }
@@ -1574,11 +1672,28 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1574 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)) 1672 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1575 { 1673 {
1576 send_store_response (nc, GNUNET_SYSERR, 1674 send_store_response (nc, GNUNET_SYSERR,
1577 _("Error deserializing records."), rid); 1675 _ ("Error deserializing records."), rid);
1578 GNUNET_free (conv_name); 1676 GNUNET_free (conv_name);
1579 GNUNET_SERVICE_client_continue (nc->client); 1677 GNUNET_SERVICE_client_continue (nc->client);
1580 return; 1678 return;
1581 } 1679 }
1680 if (GNUNET_YES == ntohl (rp_msg->locking))
1681 {
1682 GNUNET_CRYPTO_hash (conv_name, strlen (conv_name), &label_hash);
1683 for (lock = locks_head; NULL != lock; lock = lock->next)
1684 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1685 break;
1686 if ((NULL == lock) ||
1687 (lock->client != nc))
1688 {
1689 send_store_response (nc, res, _ ("Record set locked."), rid);
1690 GNUNET_SERVICE_client_continue (nc->client);
1691 GNUNET_free (conv_name);
1692 return;
1693 }
1694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695 "Client has lock on `%s', continuing.\n", conv_name);
1696 }
1582 1697
1583 GNUNET_STATISTICS_update (statistics, 1698 GNUNET_STATISTICS_update (statistics,
1584 "Well-formed store requests received", 1699 "Well-formed store requests received",
@@ -1683,11 +1798,21 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1683 if (GNUNET_OK != res) 1798 if (GNUNET_OK != res)
1684 { 1799 {
1685 /* store not successful, no need to tell monitors */ 1800 /* store not successful, no need to tell monitors */
1686 send_store_response (nc, res, _("Store failed"), rid); 1801 send_store_response (nc, res, _ ("Store failed"), rid);
1687 GNUNET_SERVICE_client_continue (nc->client); 1802 GNUNET_SERVICE_client_continue (nc->client);
1688 GNUNET_free (conv_name); 1803 GNUNET_free (conv_name);
1689 return; 1804 return;
1690 } 1805 }
1806 if (GNUNET_YES == ntohl (rp_msg->locking))
1807 {
1808 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1809 "Releasing lock on `%s'\n", conv_name);
1810 GNUNET_assert (NULL != lock);
1811 GNUNET_CONTAINER_DLL_remove (locks_head,
1812 locks_tail,
1813 lock);
1814 GNUNET_free (lock);
1815 }
1691 1816
1692 sa = GNUNET_malloc (sizeof(struct StoreActivity) 1817 sa = GNUNET_malloc (sizeof(struct StoreActivity)
1693 + ntohs (rp_msg->gns_header.header.size)); 1818 + ntohs (rp_msg->gns_header.header.size));
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
index 8391d9d74..0f3ffa837 100644
--- a/src/namestore/namestore.h
+++ b/src/namestore/namestore.h
@@ -68,6 +68,11 @@ 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 /**
71 * Name length 76 * Name length
72 */ 77 */
73 uint16_t name_len GNUNET_PACKED; 78 uint16_t name_len GNUNET_PACKED;
@@ -146,6 +151,11 @@ struct LabelLookupMessage
146 uint32_t label_len GNUNET_PACKED; 151 uint32_t label_len GNUNET_PACKED;
147 152
148 /** 153 /**
154 * Lock the label with this lookup
155 */
156 uint32_t locking GNUNET_PACKED;
157
158 /**
149 * The private key of the zone to look up in 159 * The private key of the zone to look up in
150 */ 160 */
151 struct GNUNET_IDENTITY_PrivateKey zone; 161 struct GNUNET_IDENTITY_PrivateKey zone;
@@ -185,7 +195,7 @@ struct LabelLookupResponseMessage
185 * Was the label found in the database?? 195 * Was the label found in the database??
186 * #GNUNET_YES or #GNUNET_NO 196 * #GNUNET_YES or #GNUNET_NO
187 */ 197 */
188 uint16_t found GNUNET_PACKED; 198 int16_t found GNUNET_PACKED;
189 199
190 /** 200 /**
191 * The private key of the authority. 201 * The private key of the authority.
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index 3c8caf961..a7380bbde 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -479,8 +479,10 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
479 size_t name_len; 479 size_t name_len;
480 size_t rd_len; 480 size_t rd_len;
481 unsigned int rd_count; 481 unsigned int rd_count;
482 int16_t found = (int16_t) ntohs (msg->found);
482 483
483 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT\n"); 484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n",
485 found);
484 qe = find_qe (h, ntohl (msg->gns_header.r_id)); 486 qe = find_qe (h, ntohl (msg->gns_header.r_id));
485 if (NULL == qe) 487 if (NULL == qe)
486 return; 488 return;
@@ -488,7 +490,7 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
488 rd_count = ntohs (msg->rd_count); 490 rd_count = ntohs (msg->rd_count);
489 name_len = ntohs (msg->name_len); 491 name_len = ntohs (msg->name_len);
490 name = (const char *) &msg[1]; 492 name = (const char *) &msg[1];
491 if (GNUNET_NO == ntohs (msg->found)) 493 if (GNUNET_NO == found)
492 { 494 {
493 /* label was not in namestore */ 495 /* label was not in namestore */
494 if (NULL != qe->proc) 496 if (NULL != qe->proc)
@@ -496,6 +498,13 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
496 free_qe (qe); 498 free_qe (qe);
497 return; 499 return;
498 } 500 }
501 if (GNUNET_SYSERR == found)
502 {
503 if (NULL != qe->error_cb)
504 qe->error_cb (qe->error_cb_cls);
505 free_qe (qe);
506 return;
507 }
499 508
500 rd_tmp = &name[name_len]; 509 rd_tmp = &name[name_len];
501 { 510 {
@@ -1005,14 +1014,15 @@ warn_delay (void *cls)
1005} 1014}
1006 1015
1007struct GNUNET_NAMESTORE_QueueEntry * 1016struct GNUNET_NAMESTORE_QueueEntry *
1008GNUNET_NAMESTORE_records_store ( 1017records_store_ (
1009 struct GNUNET_NAMESTORE_Handle *h, 1018 struct GNUNET_NAMESTORE_Handle *h,
1010 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1019 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1011 const char *label, 1020 const char *label,
1012 unsigned int rd_count, 1021 unsigned int rd_count,
1013 const struct GNUNET_GNSRECORD_Data *rd, 1022 const struct GNUNET_GNSRECORD_Data *rd,
1014 GNUNET_NAMESTORE_ContinuationWithStatus cont, 1023 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1015 void *cont_cls) 1024 void *cont_cls,
1025 int locking)
1016{ 1026{
1017 struct GNUNET_NAMESTORE_QueueEntry *qe; 1027 struct GNUNET_NAMESTORE_QueueEntry *qe;
1018 struct GNUNET_MQ_Envelope *env; 1028 struct GNUNET_MQ_Envelope *env;
@@ -1059,6 +1069,7 @@ GNUNET_NAMESTORE_records_store (
1059 msg->rd_len = htons (rd_ser_len); 1069 msg->rd_len = htons (rd_ser_len);
1060 msg->reserved = ntohs(0); 1070 msg->reserved = ntohs(0);
1061 msg->private_key = *pkey; 1071 msg->private_key = *pkey;
1072 msg->locking = htonl (locking);
1062 1073
1063 name_tmp = (char *) &msg[1]; 1074 name_tmp = (char *) &msg[1];
1064 GNUNET_memcpy (name_tmp, label, name_len); 1075 GNUNET_memcpy (name_tmp, label, name_len);
@@ -1090,27 +1101,45 @@ GNUNET_NAMESTORE_records_store (
1090 return qe; 1101 return qe;
1091} 1102}
1092 1103
1093/**
1094 * Lookup an item in the namestore.
1095 *
1096 * @param h handle to the namestore
1097 * @param pkey private key of the zone
1098 * @param label name that is being mapped (at most 255 characters long)
1099 * @param error_cb function to call on error (i.e. disconnect)
1100 * @param error_cb_cls closure for @a error_cb
1101 * @param rm function to call with the result (with 0 records if we don't have that label)
1102 * @param rm_cls closure for @a rm
1103 * @return handle to abort the request
1104 */
1105struct GNUNET_NAMESTORE_QueueEntry * 1104struct GNUNET_NAMESTORE_QueueEntry *
1106GNUNET_NAMESTORE_records_lookup ( 1105GNUNET_NAMESTORE_records_store (
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,
1121 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1122 const char *label,
1123 unsigned int rd_count,
1124 const struct GNUNET_GNSRECORD_Data *rd,
1125 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1126 void *cont_cls)
1127{
1128 return records_store_ (h, pkey, label,
1129 rd_count, rd, cont, cont_cls, GNUNET_YES);
1130}
1131
1132
1133struct GNUNET_NAMESTORE_QueueEntry *
1134records_lookup_ (
1107 struct GNUNET_NAMESTORE_Handle *h, 1135 struct GNUNET_NAMESTORE_Handle *h,
1108 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1136 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1109 const char *label, 1137 const char *label,
1110 GNUNET_SCHEDULER_TaskCallback error_cb, 1138 GNUNET_SCHEDULER_TaskCallback error_cb,
1111 void *error_cb_cls, 1139 void *error_cb_cls,
1112 GNUNET_NAMESTORE_RecordMonitor rm, 1140 GNUNET_NAMESTORE_RecordMonitor rm,
1113 void *rm_cls) 1141 void *rm_cls,
1142 int locking)
1114{ 1143{
1115 struct GNUNET_NAMESTORE_QueueEntry *qe; 1144 struct GNUNET_NAMESTORE_QueueEntry *qe;
1116 struct GNUNET_MQ_Envelope *env; 1145 struct GNUNET_MQ_Envelope *env;
@@ -1138,6 +1167,7 @@ GNUNET_NAMESTORE_records_lookup (
1138 msg->gns_header.r_id = htonl (qe->op_id); 1167 msg->gns_header.r_id = htonl (qe->op_id);
1139 msg->zone = *pkey; 1168 msg->zone = *pkey;
1140 msg->label_len = htonl (label_len); 1169 msg->label_len = htonl (label_len);
1170 msg->locking = htonl (locking);
1141 GNUNET_memcpy (&msg[1], label, label_len); 1171 GNUNET_memcpy (&msg[1], label, label_len);
1142 if (NULL == h->mq) 1172 if (NULL == h->mq)
1143 qe->env = env; 1173 qe->env = env;
@@ -1146,22 +1176,34 @@ GNUNET_NAMESTORE_records_lookup (
1146 return qe; 1176 return qe;
1147} 1177}
1148 1178
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
1193struct GNUNET_NAMESTORE_QueueEntry *
1194GNUNET_NAMESTORE_records_open (
1195 struct GNUNET_NAMESTORE_Handle *h,
1196 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1197 const char *label,
1198 GNUNET_SCHEDULER_TaskCallback error_cb,
1199 void *error_cb_cls,
1200 GNUNET_NAMESTORE_RecordMonitor rm,
1201 void *rm_cls)
1202{
1203 return records_lookup_ (h, pkey, label,
1204 error_cb, error_cb_cls, rm, rm_cls, GNUNET_YES);
1205}
1149 1206
1150/**
1151 * Look for an existing PKEY delegation record for a given public key.
1152 * Returns at most one result to the processor.
1153 *
1154 * @param h handle to the namestore
1155 * @param zone public key of the zone to look up in, never NULL
1156 * @param value_zone public key of the target zone (value), never NULL
1157 * @param error_cb function to call on error (i.e. disconnect)
1158 * @param error_cb_cls closure for @a error_cb
1159 * @param proc function to call on the matching records, or with
1160 * NULL (rd_count == 0) if there are no matching records
1161 * @param proc_cls closure for @a proc
1162 * @return a handle that can be used to
1163 * cancel
1164 */
1165struct GNUNET_NAMESTORE_QueueEntry * 1207struct GNUNET_NAMESTORE_QueueEntry *
1166GNUNET_NAMESTORE_zone_to_name ( 1208GNUNET_NAMESTORE_zone_to_name (
1167 struct GNUNET_NAMESTORE_Handle *h, 1209 struct GNUNET_NAMESTORE_Handle *h,