aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_namestore_plugin.h22
-rw-r--r--src/include/gnunet_namestore_service.h2
-rw-r--r--src/plugin/namestore/plugin_namestore_postgres.c58
-rw-r--r--src/plugin/namestore/plugin_namestore_sqlite.c108
-rw-r--r--src/service/namestore/gnunet-service-namestore.c123
-rw-r--r--src/service/namestore/namestore_api.c9
-rw-r--r--src/service/namestore/test_namestore_api_edit_records.c22
7 files changed, 318 insertions, 26 deletions
diff --git a/src/include/gnunet_namestore_plugin.h b/src/include/gnunet_namestore_plugin.h
index c31926a49..b7bcc4eb6 100644
--- a/src/include/gnunet_namestore_plugin.h
+++ b/src/include/gnunet_namestore_plugin.h
@@ -181,6 +181,28 @@ struct GNUNET_NAMESTORE_PluginFunctions
181 void *iter_cls); 181 void *iter_cls);
182 182
183 /** 183 /**
184 * This clears the editor hint, unless it does not match the
185 * given editor hint, in which case this is a NOP.
186 * If a replacement hint is given, it hint is not cleared, but
187 * set to the replacement.
188 *
189 * @param cls closure (internal context for the plugin)
190 * @param zone private key of the zone
191 * @param editor_hint the new value for the advisory lock field
192 * @param editor_hint_replacement an optional value to use instead of a clear
193 * @param label name of the record in the zone
194 * @param iter function to call with the result
195 * @param iter_cls closure for @a iter
196 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
197 */
198 enum GNUNET_GenericReturnValue
199 (*clear_editor_hint)(void *cls,
200 const char *editor_hint,
201 const char *editor_hint_replacement,
202 const struct GNUNET_CRYPTO_PrivateKey *zone,
203 const char *label);
204
205 /**
184 * Setup the database. 206 * Setup the database.
185 * 207 *
186 * @param cls closure (internal context for the plugin) 208 * @param cls closure (internal context for the plugin)
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h
index 5d79ebd13..0f9be8b10 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -662,7 +662,7 @@ GNUNET_NAMESTORE_record_set_edit_cancel (struct GNUNET_NAMESTORE_Handle *h,
662 const char *label, 662 const char *label,
663 const char *editor_hint, 663 const char *editor_hint,
664 const char *editor_hint_replacement, 664 const char *editor_hint_replacement,
665 GNUNET_SCHEDULER_TaskCallback 665 GNUNET_NAMESTORE_ContinuationWithStatus
666 finished_cb, 666 finished_cb,
667 void *finished_cls); 667 void *finished_cls);
668 668
diff --git a/src/plugin/namestore/plugin_namestore_postgres.c b/src/plugin/namestore/plugin_namestore_postgres.c
index e4c350a3e..0bc98a98a 100644
--- a/src/plugin/namestore/plugin_namestore_postgres.c
+++ b/src/plugin/namestore/plugin_namestore_postgres.c
@@ -144,9 +144,15 @@ database_prepare (struct Plugin *plugin)
144 "FROM namestore.ns098records WHERE zone_private_key=$1 AND label=$2"), 144 "FROM namestore.ns098records WHERE zone_private_key=$1 AND label=$2"),
145 GNUNET_PQ_make_prepare ("edit_set", 145 GNUNET_PQ_make_prepare ("edit_set",
146 "UPDATE namestore.ns098records" 146 "UPDATE namestore.ns098records"
147 "SET editor_hint=$3" 147 " SET editor_hint=$3"
148 "WHERE zone_private_key=$1 AND label=$2" 148 " FROM ns098records AS old_ns098records"
149 "RETURNING seq,record_count,record_data,label,editor_hint "), 149 " WHERE ns098records.zone_private_key=$1 AND ns098records.label=$2"
150 " RETURNING ns098records.seq,ns098records.record_count,ns098records.record_data,ns098records.label,old_ns098records.editor_hint "),
151 GNUNET_PQ_make_prepare ("clear_editor_hint",
152 "UPDATE namestore.ns098records"
153 " SET editor_hint=$4"
154 " FROM namestore.ns098records"
155 " WHERE zone_private_key=$1 AND label=$2 AND editor_hint=$3"),
150 GNUNET_PQ_PREPARED_STATEMENT_END 156 GNUNET_PQ_PREPARED_STATEMENT_END
151 }; 157 };
152 158
@@ -521,6 +527,51 @@ namestore_postgres_lookup_records (void *cls,
521 527
522 528
523/** 529/**
530 *
531 * @param cls closure (internal context for the plugin)
532 * @param zone private key of the zone
533 * @param label name of the record in the zone
534 * @param iter function to call with the result
535 * @param iter_cls closure for @a iter
536 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
537 */
538static int
539namestore_postgres_clear_editor_hint (void *cls,
540 const char *editor_hint,
541 const char *editor_hint_replacement,
542 const struct
543 GNUNET_CRYPTO_PrivateKey *zone,
544 const char *label)
545{
546
547 struct Plugin *plugin = cls;
548 struct GNUNET_CRYPTO_PublicKey pkey;
549
550 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
551 memset (&pkey,
552 0,
553 sizeof(pkey));
554 {
555 struct GNUNET_PQ_QueryParam params[] = {
556 GNUNET_PQ_query_param_auto_from_type (zone),
557 GNUNET_PQ_query_param_string (label),
558 GNUNET_PQ_query_param_string (editor_hint),
559 GNUNET_PQ_query_param_string (editor_hint_replacement),
560 GNUNET_PQ_query_param_end
561 };
562 enum GNUNET_DB_QueryStatus res;
563
564 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
565 "clear_editor_hint",
566 params);
567 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res)
568 return GNUNET_SYSERR;
569 }
570 return GNUNET_OK;
571}
572
573
574/**
524 * Edit records in the datastore for which we are the authority. 575 * Edit records in the datastore for which we are the authority.
525 * 576 *
526 * @param cls closure (internal context for the plugin) 577 * @param cls closure (internal context for the plugin)
@@ -701,6 +752,7 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
701 api->zone_to_name = &namestore_postgres_zone_to_name; 752 api->zone_to_name = &namestore_postgres_zone_to_name;
702 api->lookup_records = &namestore_postgres_lookup_records; 753 api->lookup_records = &namestore_postgres_lookup_records;
703 api->edit_records = &namestore_postgres_edit_records; 754 api->edit_records = &namestore_postgres_edit_records;
755 api->clear_editor_hint = &namestore_postgres_clear_editor_hint;
704 LOG (GNUNET_ERROR_TYPE_INFO, 756 LOG (GNUNET_ERROR_TYPE_INFO,
705 "Postgres namestore plugin running\n"); 757 "Postgres namestore plugin running\n");
706 return api; 758 return api;
diff --git a/src/plugin/namestore/plugin_namestore_sqlite.c b/src/plugin/namestore/plugin_namestore_sqlite.c
index c38e9e08f..50c2f5728 100644
--- a/src/plugin/namestore/plugin_namestore_sqlite.c
+++ b/src/plugin/namestore/plugin_namestore_sqlite.c
@@ -112,6 +112,11 @@ struct Plugin
112 * Precompiled SQL to lookup records based on label. 112 * Precompiled SQL to lookup records based on label.
113 */ 113 */
114 sqlite3_stmt *lookup_label; 114 sqlite3_stmt *lookup_label;
115
116 /**
117 * Precompiled SQL to clear editor hint.
118 */
119 sqlite3_stmt *editor_hint_clear;
115}; 120};
116 121
117 122
@@ -148,16 +153,18 @@ database_prepare (struct Plugin *plugin)
148 GNUNET_SQ_make_prepare ("DELETE FROM ns098records " 153 GNUNET_SQ_make_prepare ("DELETE FROM ns098records "
149 "WHERE zone_private_key=? AND label=?", 154 "WHERE zone_private_key=? AND label=?",
150 &plugin->delete_records), 155 &plugin->delete_records),
151 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label,editor_hint" 156 GNUNET_SQ_make_prepare (
152 " FROM ns098records" 157 "SELECT uid,record_count,record_data,label,editor_hint"
153 " WHERE zone_private_key=? AND pkey=?", 158 " FROM ns098records"
154 &plugin->zone_to_name), 159 " WHERE zone_private_key=? AND pkey=?",
155 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label,editor_hint" 160 &plugin->zone_to_name),
156 " FROM ns098records" 161 GNUNET_SQ_make_prepare (
157 " WHERE zone_private_key=? AND uid > ?" 162 "SELECT uid,record_count,record_data,label,editor_hint"
158 " ORDER BY uid ASC" 163 " FROM ns098records"
159 " LIMIT ?", 164 " WHERE zone_private_key=? AND uid > ?"
160 &plugin->iterate_zone), 165 " ORDER BY uid ASC"
166 " LIMIT ?",
167 &plugin->iterate_zone),
161 GNUNET_SQ_make_prepare ( 168 GNUNET_SQ_make_prepare (
162 "SELECT uid,record_count,record_data,label,editor_hint,zone_private_key" 169 "SELECT uid,record_count,record_data,label,editor_hint,zone_private_key"
163 " FROM ns098records" 170 " FROM ns098records"
@@ -171,6 +178,11 @@ database_prepare (struct Plugin *plugin)
171 " WHERE ns098records.zone_private_key=? AND ns098records.label=?" 178 " WHERE ns098records.zone_private_key=? AND ns098records.label=?"
172 " RETURNING ns098records.uid,ns098records.record_count,ns098records.record_data,ns098records.label,editor_hint ", 179 " RETURNING ns098records.uid,ns098records.record_count,ns098records.record_data,ns098records.label,editor_hint ",
173 &plugin->lookup_label), 180 &plugin->lookup_label),
181 GNUNET_SQ_make_prepare ("UPDATE ns098records"
182 " SET editor_hint=?"
183 " FROM ns098records AS old_ns098records"
184 " WHERE ns098records.zone_private_key=? AND ns098records.label=? AND ns098records.editor_hint=?",
185 &plugin->editor_hint_clear),
174 GNUNET_SQ_PREPARE_END 186 GNUNET_SQ_PREPARE_END
175 }; 187 };
176 188
@@ -221,6 +233,8 @@ database_shutdown (struct Plugin *plugin)
221 sqlite3_finalize (plugin->zone_to_name); 233 sqlite3_finalize (plugin->zone_to_name);
222 if (NULL != plugin->lookup_label) 234 if (NULL != plugin->lookup_label)
223 sqlite3_finalize (plugin->lookup_label); 235 sqlite3_finalize (plugin->lookup_label);
236 if (NULL != plugin->editor_hint_clear)
237 sqlite3_finalize (plugin->editor_hint_clear);
224 result = sqlite3_close (plugin->dbh); 238 result = sqlite3_close (plugin->dbh);
225 if (result == SQLITE_BUSY) 239 if (result == SQLITE_BUSY)
226 { 240 {
@@ -610,6 +624,79 @@ namestore_sqlite_lookup_records (void *cls,
610 624
611 625
612/** 626/**
627 * Clear editor hint.
628 *
629 * @param cls closure (internal context for the plugin)
630 * @param zone private key of the zone
631 * @param label name of the record in the zone
632 * @param editor_hint editor hint to clear
633 * @param editor_hint_repl editor hint to replace the old with (optional)
634 * @param iter function to call with the result
635 * @param iter_cls closure for @a iter
636 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
637 */
638static enum GNUNET_GenericReturnValue
639namestore_sqlite_editor_hint_clear (void *cls,
640 const char *editor_hint,
641 const char *editor_hint_replacement,
642 const struct
643 GNUNET_CRYPTO_PrivateKey *zone,
644 const char *label)
645{
646 struct Plugin *plugin = cls;
647 int n;
648 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
649 struct GNUNET_SQ_QueryParam params[] = {
650 GNUNET_SQ_query_param_string ((NULL == editor_hint_replacement) ? "":
651 editor_hint_replacement),
652 GNUNET_SQ_query_param_auto_from_type (zone),
653 GNUNET_SQ_query_param_string (label),
654 GNUNET_SQ_query_param_string (editor_hint),
655 GNUNET_SQ_query_param_end
656 };
657
658 if (NULL == zone)
659 {
660 GNUNET_break (0);
661 return GNUNET_SYSERR;
662 }
663 if (GNUNET_OK !=
664 GNUNET_SQ_bind (plugin->editor_hint_clear,
665 params))
666 {
667 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
668 "sqlite3_bind_XXXX");
669 GNUNET_SQ_reset (plugin->dbh,
670 plugin->editor_hint_clear);
671 return GNUNET_SYSERR;
672 }
673 n = sqlite3_step (plugin->editor_hint_clear);
674 GNUNET_SQ_reset (plugin->dbh,
675 plugin->store_records);
676 switch (n)
677 {
678 case SQLITE_DONE:
679 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
680 "sqlite",
681 "Editor hint cleared\n");
682 return GNUNET_OK;
683
684 case SQLITE_BUSY:
685 LOG_SQLITE (plugin,
686 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
687 "sqlite3_step");
688 return GNUNET_NO;
689
690 default:
691 LOG_SQLITE (plugin,
692 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
693 "sqlite3_step");
694 return GNUNET_SYSERR;
695 }
696}
697
698
699/**
613 * Lookup records in the datastore for which we are the authority. 700 * Lookup records in the datastore for which we are the authority.
614 * 701 *
615 * @param cls closure (internal context for the plugin) 702 * @param cls closure (internal context for the plugin)
@@ -911,6 +998,7 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
911 api->create_tables = &namestore_sqlite_create_tables; 998 api->create_tables = &namestore_sqlite_create_tables;
912 api->drop_tables = &namestore_sqlite_drop_tables; 999 api->drop_tables = &namestore_sqlite_drop_tables;
913 api->edit_records = &namestore_sqlite_edit_records; 1000 api->edit_records = &namestore_sqlite_edit_records;
1001 api->clear_editor_hint = &namestore_sqlite_editor_hint_clear;
914 LOG (GNUNET_ERROR_TYPE_DEBUG, 1002 LOG (GNUNET_ERROR_TYPE_DEBUG,
915 _ ("SQlite database running\n")); 1003 _ ("SQlite database running\n"));
916 return api; 1004 return api;
diff --git a/src/service/namestore/gnunet-service-namestore.c b/src/service/namestore/gnunet-service-namestore.c
index 230583936..f375828dc 100644
--- a/src/service/namestore/gnunet-service-namestore.c
+++ b/src/service/namestore/gnunet-service-namestore.c
@@ -1275,7 +1275,7 @@ check_edit_record_set (void *cls, const struct EditRecordSetMessage *er_msg)
1275 key_len = ntohs (er_msg->key_len); 1275 key_len = ntohs (er_msg->key_len);
1276 src_size = ntohs (er_msg->gns_header.header.size); 1276 src_size = ntohs (er_msg->gns_header.header.size);
1277 if (name_len + editor_hint_len + key_len != src_size - sizeof(struct 1277 if (name_len + editor_hint_len + key_len != src_size - sizeof(struct
1278 LabelLookupMessage)) 1278 EditRecordSetMessage))
1279 { 1279 {
1280 GNUNET_break (0); 1280 GNUNET_break (0);
1281 return GNUNET_SYSERR; 1281 return GNUNET_SYSERR;
@@ -1285,10 +1285,10 @@ check_edit_record_set (void *cls, const struct EditRecordSetMessage *er_msg)
1285 1285
1286 1286
1287/** 1287/**
1288 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message 1288 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_SET_EDIT message
1289 * 1289 *
1290 * @param cls client sending the message 1290 * @param cls client sending the message
1291 * @param ll_msg message of type `struct LabelLookupMessage` 1291 * @param ll_msg message of type `struct EditRecordSetMessage`
1292 */ 1292 */
1293static void 1293static void
1294handle_edit_record_set (void *cls, const struct EditRecordSetMessage *er_msg) 1294handle_edit_record_set (void *cls, const struct EditRecordSetMessage *er_msg)
@@ -1381,6 +1381,119 @@ handle_edit_record_set (void *cls, const struct EditRecordSetMessage *er_msg)
1381 1381
1382 1382
1383/** 1383/**
1384 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_SET_EDIT_CANCEL message
1385 *
1386 * @param cls client sending the message
1387 * @param er_msg message of type `struct EditRecordSetMessage`
1388 * @return #GNUNET_OK if @a er_msg is well-formed
1389 */
1390static int
1391check_edit_record_set_cancel (void *cls, const struct
1392 EditRecordSetCancelMessage *er_msg)
1393{
1394 uint16_t name_len;
1395 uint16_t editor_hint_len;
1396 uint16_t editor_hint_repl_len;
1397 size_t src_size;
1398 size_t key_len;
1399
1400 (void) cls;
1401 name_len = ntohs (er_msg->label_len);
1402 editor_hint_len = ntohs (er_msg->editor_hint_len);
1403 editor_hint_repl_len = ntohs (er_msg->editor_hint_len);
1404 key_len = ntohs (er_msg->key_len);
1405 src_size = ntohs (er_msg->gns_header.header.size);
1406 if (name_len + editor_hint_len + editor_hint_repl_len + key_len != src_size
1407 - sizeof(struct
1408 EditRecordSetCancelMessage))
1409 {
1410 GNUNET_break (0);
1411 return GNUNET_SYSERR;
1412 }
1413 return GNUNET_OK;
1414}
1415
1416
1417/**
1418 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_SET_EDIT_CANCEL message
1419 *
1420 * @param cls client sending the message
1421 * @param ll_msg message of type `struct EditRecordSetCancelMessage`
1422 */
1423static void
1424handle_edit_record_set_cancel (void *cls, const struct
1425 EditRecordSetCancelMessage *er_msg)
1426{
1427 struct GNUNET_CRYPTO_PrivateKey zone;
1428 struct NamestoreClient *nc = cls;
1429 struct GNUNET_MQ_Envelope *env;
1430 struct NamestoreResponseMessage *rer_msg;
1431 const char *name_tmp;
1432 const char *editor_hint;
1433 const char *editor_hint_repl;
1434 char *conv_name;
1435 uint16_t name_len;
1436 uint16_t editor_hint_len;
1437 int res;
1438 size_t key_len;
1439 size_t kb_read;
1440
1441 key_len = ntohs (er_msg->key_len);
1442 name_len = ntohs (er_msg->label_len);
1443 editor_hint_len = ntohs (er_msg->editor_hint_len);
1444 if ((GNUNET_SYSERR ==
1445 GNUNET_CRYPTO_read_private_key_from_buffer (&er_msg[1],
1446 key_len,
1447 &zone,
1448 &kb_read)) ||
1449 (kb_read != key_len))
1450 {
1451 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1452 "Error reading private key\n");
1453 GNUNET_SERVICE_client_drop (nc->client);
1454 return;
1455 }
1456 name_tmp = (const char *) &er_msg[1] + key_len;
1457 editor_hint = (const char *) name_tmp + name_len;
1458 editor_hint_repl = (const char *) name_tmp + name_len + editor_hint_len;
1459 GNUNET_SERVICE_client_continue (nc->client);
1460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1461 "Received NAMESTORE_RECORD_SET_EDIT message for name `%s'\n",
1462 name_tmp);
1463
1464 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1465 if (NULL == conv_name)
1466 {
1467 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1468 "Error converting name `%s'\n",
1469 name_tmp);
1470 GNUNET_SERVICE_client_drop (nc->client);
1471 return;
1472 }
1473 name_len = strlen (conv_name) + 1;
1474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1475 "Clearing editor hint\n");
1476 res = nc->GSN_database->clear_editor_hint (nc->GSN_database->cls,
1477 editor_hint,
1478 editor_hint_repl,
1479 &zone,
1480 conv_name);
1481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1482 "Clearing editor hint %s\n", (GNUNET_SYSERR == res) ? "failed." :
1483 "successful.");
1484
1485 env =
1486 GNUNET_MQ_msg (rer_msg,
1487 GNUNET_MESSAGE_TYPE_NAMESTORE_GENERIC_RESPONSE);
1488 rer_msg->gns_header.r_id = er_msg->gns_header.r_id;
1489 rer_msg->ec = htons ((GNUNET_OK == res) ? GNUNET_EC_NONE :
1490 GNUNET_EC_NAMESTORE_BACKEND_FAILED);
1491 GNUNET_MQ_send (nc->mq, env);
1492 GNUNET_free (conv_name);
1493}
1494
1495
1496/**
1384 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message 1497 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1385 * 1498 *
1386 * @param cls client sending the message 1499 * @param cls client sending the message
@@ -2674,6 +2787,10 @@ GNUNET_SERVICE_MAIN (
2674 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_SET_EDIT, 2787 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_SET_EDIT,
2675 struct EditRecordSetMessage, 2788 struct EditRecordSetMessage,
2676 NULL), 2789 NULL),
2790 GNUNET_MQ_hd_var_size (edit_record_set_cancel,
2791 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_SET_EDIT_CANCEL,
2792 struct EditRecordSetCancelMessage,
2793 NULL),
2677 GNUNET_MQ_hd_var_size (record_lookup, 2794 GNUNET_MQ_hd_var_size (record_lookup,
2678 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP, 2795 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2679 struct LabelLookupMessage, 2796 struct LabelLookupMessage,
diff --git a/src/service/namestore/namestore_api.c b/src/service/namestore/namestore_api.c
index 435c1622d..45a15c39a 100644
--- a/src/service/namestore/namestore_api.c
+++ b/src/service/namestore/namestore_api.c
@@ -375,8 +375,8 @@ handle_generic_response (void *cls,
375 qe = find_qe (h, ntohl (msg->gns_header.r_id)); 375 qe = find_qe (h, ntohl (msg->gns_header.r_id));
376 res = ntohl (msg->ec); 376 res = ntohl (msg->ec);
377 LOG (GNUNET_ERROR_TYPE_DEBUG, 377 LOG (GNUNET_ERROR_TYPE_DEBUG,
378 "Received RECORD_STORE_RESPONSE with result %d\n", 378 "Received GENERIC_RESPONSE with result %s\n",
379 res); 379 GNUNET_ErrorCode_get_hint(res));
380 if (NULL == qe) 380 if (NULL == qe)
381 return; 381 return;
382 if (NULL != qe->cont) 382 if (NULL != qe->cont)
@@ -1617,8 +1617,7 @@ GNUNET_NAMESTORE_record_set_edit_cancel (struct GNUNET_NAMESTORE_Handle *h,
1617 const char *label, 1617 const char *label,
1618 const char *editor_hint, 1618 const char *editor_hint,
1619 const char *editor_hint_replacement, 1619 const char *editor_hint_replacement,
1620 GNUNET_SCHEDULER_TaskCallback 1620 GNUNET_NAMESTORE_ContinuationWithStatus finished_cb,
1621 finished_cb,
1622 void *finished_cls) 1621 void *finished_cls)
1623{ 1622{
1624 struct GNUNET_NAMESTORE_QueueEntry *qe; 1623 struct GNUNET_NAMESTORE_QueueEntry *qe;
@@ -1641,6 +1640,8 @@ GNUNET_NAMESTORE_record_set_edit_cancel (struct GNUNET_NAMESTORE_Handle *h,
1641 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); 1640 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1642 qe->h = h; 1641 qe->h = h;
1643 qe->op_id = get_op_id (h); 1642 qe->op_id = get_op_id (h);
1643 qe->cont = finished_cb;
1644 qe->cont_cls = finished_cls;
1644 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); 1645 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1645 1646
1646 key_len = GNUNET_CRYPTO_private_key_get_length (pkey); 1647 key_len = GNUNET_CRYPTO_private_key_get_length (pkey);
diff --git a/src/service/namestore/test_namestore_api_edit_records.c b/src/service/namestore/test_namestore_api_edit_records.c
index 9dce13e33..02e821377 100644
--- a/src/service/namestore/test_namestore_api_edit_records.c
+++ b/src/service/namestore/test_namestore_api_edit_records.c
@@ -21,7 +21,9 @@
21 * @file namestore/test_namestore_api_edit_records.c 21 * @file namestore/test_namestore_api_edit_records.c
22 * @brief testcase for namestore_api.c: Multiple clients work with record set. 22 * @brief testcase for namestore_api.c: Multiple clients work with record set.
23 */ 23 */
24#include "gnunet_error_codes.h"
24#include "gnunet_namestore_service.h" 25#include "gnunet_namestore_service.h"
26#include "gnunet_scheduler_lib.h"
25#include "gnunet_testing_lib.h" 27#include "gnunet_testing_lib.h"
26 28
27#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT 29#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
@@ -91,6 +93,15 @@ end (void *cls)
91 GNUNET_SCHEDULER_cancel (endbadly_task); 93 GNUNET_SCHEDULER_cancel (endbadly_task);
92 cleanup (); 94 cleanup ();
93 res = 0; 95 res = 0;
96 GNUNET_SCHEDULER_shutdown ();
97}
98
99
100static void
101cancel_done (void *cls, enum GNUNET_ErrorCode ec)
102{
103 GNUNET_assert (GNUNET_EC_NONE == ec);
104 GNUNET_SCHEDULER_add_now (&end, NULL);
94} 105}
95 106
96 107
@@ -102,11 +113,12 @@ begin_cont_b (void *cls,
102 GNUNET_GNSRECORD_Data *rd, 113 GNUNET_GNSRECORD_Data *rd,
103 const char *editor_hint) 114 const char *editor_hint)
104{ 115{
105 const char *name = cls; 116 char *name = cls;
106 117
107 GNUNET_assert (GNUNET_EC_NONE == ec); 118 GNUNET_assert (GNUNET_EC_NONE == ec);
108 GNUNET_assert (0 != strcmp (editor_hint, "B")); 119 GNUNET_assert (0 != strcmp (editor_hint, "B"));
109 GNUNET_SCHEDULER_add_now (&end, NULL); 120 nsqe = GNUNET_NAMESTORE_record_set_edit_cancel (nsh2, &privkey, name, "A",
121 "B", &cancel_done, name);
110} 122}
111 123
112 124
@@ -118,7 +130,7 @@ begin_cont (void *cls,
118 GNUNET_GNSRECORD_Data *rd, 130 GNUNET_GNSRECORD_Data *rd,
119 const char *editor_hint) 131 const char *editor_hint)
120{ 132{
121 const char *name = cls; 133 char *name = cls;
122 134
123 GNUNET_assert (GNUNET_EC_NONE == ec); 135 GNUNET_assert (GNUNET_EC_NONE == ec);
124 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 136 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -135,7 +147,7 @@ static void
135preload_cont (void *cls, 147preload_cont (void *cls,
136 enum GNUNET_ErrorCode ec) 148 enum GNUNET_ErrorCode ec)
137{ 149{
138 const char *name = cls; 150 char *name = cls;
139 151
140 GNUNET_assert (NULL != cls); 152 GNUNET_assert (NULL != cls);
141 nsqe = NULL; 153 nsqe = NULL;
@@ -168,7 +180,7 @@ run (void *cls,
168 struct GNUNET_TESTING_Peer *peer) 180 struct GNUNET_TESTING_Peer *peer)
169{ 181{
170 struct GNUNET_GNSRECORD_Data rd; 182 struct GNUNET_GNSRECORD_Data rd;
171 const char *name = "dummy"; 183 char *name = "dummy";
172 184
173 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 185 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
174 &endbadly, 186 &endbadly,