aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-09-23 16:39:21 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2022-09-23 16:39:21 +0900
commite0e36b6feba6cbcbbb3516d3a9de4d6fd0199825 (patch)
tree77429f5da157e6c002cdb0d31dfb44da0cc48123
parent7678d77b1cb0dcfd8887016d35b27fbedb136050 (diff)
downloadgnunet-e0e36b6feba6cbcbbb3516d3a9de4d6fd0199825.tar.gz
gnunet-e0e36b6feba6cbcbbb3516d3a9de4d6fd0199825.zip
NAMESTORE: Towards proper transactional locks
-rw-r--r--src/include/gnunet_namestore_service.h10
-rw-r--r--src/namestore/Makefile.am12
-rw-r--r--src/namestore/gnunet-service-namestore.c6
-rw-r--r--src/namestore/plugin_namestore_postgres.c26
-rw-r--r--src/namestore/test_namestore_api_edit_records.c404
-rw-r--r--src/namestore/test_namestore_api_postgres.conf2
-rw-r--r--src/namestore/test_namestore_api_tx_rollback.c268
-rw-r--r--src/pq/pq.c4
-rw-r--r--src/pq/pq_exec.c4
9 files changed, 715 insertions, 21 deletions
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h
index 68aeebef8..0788bc8b4 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -453,6 +453,16 @@ GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
453 cont, 453 cont,
454 void *cont_cls); 454 void *cont_cls);
455 455
456struct GNUNET_NAMESTORE_QueueEntry *
457GNUNET_NAMESTORE_records_edit (
458 struct GNUNET_NAMESTORE_Handle *h,
459 const struct GNUNET_IDENTITY_PrivateKey *pkey,
460 const char *label,
461 GNUNET_SCHEDULER_TaskCallback error_cb,
462 void *error_cb_cls,
463 GNUNET_NAMESTORE_RecordMonitor rm,
464 void *rm_cls);
465
456#if 0 /* keep Emacsens' auto-indent happy */ 466#if 0 /* keep Emacsens' auto-indent happy */
457{ 467{
458#endif 468#endif
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index e3c1825d3..b71896894 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -58,7 +58,8 @@ POSTGRES_TESTS = test_plugin_namestore_postgres \
58 test_namestore_api_monitoring_existing_postgres \ 58 test_namestore_api_monitoring_existing_postgres \
59 test_namestore_api_zone_to_name_postgres \ 59 test_namestore_api_zone_to_name_postgres \
60 perf_namestore_api_zone_iteration_postgres \ 60 perf_namestore_api_zone_iteration_postgres \
61 test_namestore_api_tx_rollback_postgres 61 test_namestore_api_tx_rollback_postgres \
62 test_namestore_api_edit_records_postgres
62endif 63endif
63 64
64if HAVE_SQLITE 65if HAVE_SQLITE
@@ -442,7 +443,14 @@ test_namestore_api_tx_rollback_postgres_LDADD = \
442 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 443 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
443 $(top_builddir)/src/util/libgnunetutil.la 444 $(top_builddir)/src/util/libgnunetutil.la
444 445
445 446test_namestore_api_edit_records_postgres_SOURCES = \
447 test_namestore_api_edit_records.c
448test_namestore_api_edit_records_postgres_LDADD = \
449 $(top_builddir)/src/testing/libgnunettesting.la \
450 $(top_builddir)/src/identity/libgnunetidentity.la \
451 libgnunetnamestore.la \
452 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
453 $(top_builddir)/src/util/libgnunetutil.la
446 454
447test_namestore_api_zone_iteration_sqlite_SOURCES = \ 455test_namestore_api_zone_iteration_sqlite_SOURCES = \
448 test_namestore_api_zone_iteration.c 456 test_namestore_api_zone_iteration.c
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index 100f155fa..c1d7b8753 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -1428,7 +1428,7 @@ 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 if (GNUNET_YES == ntohl (ll_msg->is_edit_request)) 1431 if (GNUNET_YES != ntohl (ll_msg->is_edit_request))
1432 res = nc->GSN_database->lookup_records (nc->GSN_database->cls, 1432 res = nc->GSN_database->lookup_records (nc->GSN_database->cls,
1433 &ll_msg->zone, 1433 &ll_msg->zone,
1434 conv_name, 1434 conv_name,
@@ -1451,7 +1451,9 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1451 llr_msg->rd_count = htons (rlc.res_rd_count); 1451 llr_msg->rd_count = htons (rlc.res_rd_count);
1452 llr_msg->rd_len = htons (rlc.rd_ser_len); 1452 llr_msg->rd_len = htons (rlc.rd_ser_len);
1453 res_name = (char *) &llr_msg[1]; 1453 res_name = (char *) &llr_msg[1];
1454 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) 1454 if (GNUNET_OK != res)
1455 llr_msg->found = htons (GNUNET_SYSERR);
1456 else if (GNUNET_YES == rlc.found)
1455 llr_msg->found = htons (GNUNET_YES); 1457 llr_msg->found = htons (GNUNET_YES);
1456 else 1458 else
1457 llr_msg->found = htons (GNUNET_NO); 1459 llr_msg->found = htons (GNUNET_NO);
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
index 2d4c5d089..510d24496 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_postgres.c
@@ -153,7 +153,7 @@ database_setup (struct Plugin *plugin)
153 2), 153 2),
154 GNUNET_PQ_make_prepare ("edit_set", 154 GNUNET_PQ_make_prepare ("edit_set",
155 "SELECT seq,record_count,record_data,label " 155 "SELECT seq,record_count,record_data,label "
156 "FROM ns098records WHERE zone_private_key=$1 AND label=$2 FOR UPDATE", 156 "FROM ns098records WHERE zone_private_key=$1 AND label=$2 FOR UPDATE NOWAIT",
157 2), 157 2),
158 GNUNET_PQ_PREPARED_STATEMENT_END 158 GNUNET_PQ_PREPARED_STATEMENT_END
159 }; 159 };
@@ -328,6 +328,8 @@ parse_result_call_iterator (void *cls,
328 328
329 if (NULL == pc->iter) 329 if (NULL == pc->iter)
330 return; /* no need to do more work */ 330 return; /* no need to do more work */
331 LOG (GNUNET_ERROR_TYPE_DEBUG,
332 "Got %d results from PQ.\n", num_results);
331 for (unsigned int i = 0; i < num_results; i++) 333 for (unsigned int i = 0; i < num_results; i++)
332 { 334 {
333 uint64_t serial; 335 uint64_t serial;
@@ -412,12 +414,12 @@ parse_result_call_iterator (void *cls,
412 */ 414 */
413static int 415static int
414lookup_records (void *cls, 416lookup_records (void *cls,
415 const struct 417 const struct
416 GNUNET_IDENTITY_PrivateKey *zone, 418 GNUNET_IDENTITY_PrivateKey *zone,
417 const char *label, 419 const char *label,
418 GNUNET_NAMESTORE_RecordIterator iter, 420 GNUNET_NAMESTORE_RecordIterator iter,
419 void *iter_cls, 421 void *iter_cls,
420 const char* method) 422 const char*method)
421{ 423{
422 struct Plugin *plugin = cls; 424 struct Plugin *plugin = cls;
423 struct GNUNET_PQ_QueryParam params[] = { 425 struct GNUNET_PQ_QueryParam params[] = {
@@ -481,11 +483,11 @@ namestore_postgres_lookup_records (void *cls,
481 */ 483 */
482static int 484static int
483namestore_postgres_edit_records (void *cls, 485namestore_postgres_edit_records (void *cls,
484 const struct 486 const struct
485 GNUNET_IDENTITY_PrivateKey *zone, 487 GNUNET_IDENTITY_PrivateKey *zone,
486 const char *label, 488 const char *label,
487 GNUNET_NAMESTORE_RecordIterator iter, 489 GNUNET_NAMESTORE_RecordIterator iter,
488 void *iter_cls) 490 void *iter_cls)
489{ 491{
490 return lookup_records (cls, zone, label, iter, iter_cls, "edit_set"); 492 return lookup_records (cls, zone, label, iter, iter_cls, "edit_set");
491} 493}
diff --git a/src/namestore/test_namestore_api_edit_records.c b/src/namestore/test_namestore_api_edit_records.c
new file mode 100644
index 000000000..c1c64ee9c
--- /dev/null
+++ b/src/namestore/test_namestore_api_edit_records.c
@@ -0,0 +1,404 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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_edit_records.c
22 * @brief testcase for namestore_api.c: Multiple clients work with record set.
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 *nsh2;
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 int removed;
51
52static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
53
54static int nonce = 0;
55
56static void
57cleanup ()
58{
59 if (NULL != nsh)
60 {
61 GNUNET_NAMESTORE_disconnect (nsh);
62 nsh = NULL;
63 }
64 GNUNET_SCHEDULER_shutdown ();
65}
66
67
68/**
69 * Re-establish the connection to the service.
70 *
71 * @param cls handle to use to re-connect.
72 */
73static void
74endbadly (void *cls)
75{
76 if (NULL != nsqe)
77 {
78 GNUNET_NAMESTORE_cancel (nsqe);
79 nsqe = NULL;
80 }
81 cleanup ();
82 res = 1;
83}
84
85
86static void
87end (void *cls)
88{
89 cleanup ();
90 res = 0;
91}
92
93static void
94lookup_it (void *cls,
95 const struct GNUNET_IDENTITY_PrivateKey *zone,
96 const char *label,
97 unsigned int rd_count,
98 const struct GNUNET_GNSRECORD_Data *rd)
99{
100 GNUNET_assert (0 == rd_count);
101 GNUNET_SCHEDULER_add_now (&end, NULL);
102}
103
104static void
105fail_cb (void *cls)
106{
107 if (endbadly_task != NULL)
108 GNUNET_SCHEDULER_cancel (endbadly_task);
109 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
110 return;
111}
112
113static void
114remove_cont (void *cls,
115 int32_t success,
116 const char *emsg)
117{
118 nsqe = NULL;
119 if (GNUNET_YES != success)
120 {
121 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
122 _ ("Unable to roll back: `%s'\n"),
123 emsg);
124 if (NULL != endbadly_task)
125 GNUNET_SCHEDULER_cancel (endbadly_task);
126 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly,
127 NULL);
128 return;
129 }
130 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
131 "Rolled back, perform lookup\n");
132 removed = GNUNET_YES;
133 if (NULL != endbadly_task)
134 GNUNET_SCHEDULER_cancel (endbadly_task);
135 GNUNET_SCHEDULER_add_now (&end, NULL);
136}
137
138static void
139fail_cb_lock (void *cls);
140
141static void
142edit_cont_b (void *cls,
143 const struct GNUNET_IDENTITY_PrivateKey *zone,
144 const char *label,
145 unsigned int rd_count,
146 const struct GNUNET_GNSRECORD_Data *rd)
147{
148 const char *name = cls;
149 /**
150 * We should probably never get here right at first.
151 * We may want to change the blocking of nsh2 so that we do get this
152 * eventually instead of the error callback above when locked.
153 */
154 if (0 == nonce)
155 {
156 if (endbadly_task != NULL)
157 GNUNET_SCHEDULER_cancel (endbadly_task);
158 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
159 return;
160
161 }
162 /* Abort transaction for B */
163 nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh2, remove_cont,
164 (void *) name);
165}
166
167
168static void
169commit_cont_a (void *cls,
170 int32_t success,
171 const char *emsg)
172{
173 const char *name = cls;
174
175 GNUNET_assert (NULL != cls);
176 nsqe = NULL;
177 if (GNUNET_SYSERR == success)
178 {
179 GNUNET_break (0);
180 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
181 "Namestore could not store record: `%s'\n",
182 emsg);
183 if (endbadly_task != NULL)
184 GNUNET_SCHEDULER_cancel (endbadly_task);
185 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
186 return;
187 }
188
189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
190 "Name store added record for `%s': %s\n",
191 name,
192 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
193 /**
194 * Try again for B
195 */
196 nsqe = GNUNET_NAMESTORE_records_edit (nsh2,
197 &privkey,
198 name,
199 &fail_cb_lock,
200 (void *) name,
201 &edit_cont_b,
202 (void *) name);
203
204 GNUNET_assert (NULL != nsqe);
205}
206
207static void
208fail_cb_lock (void *cls)
209{
210 const char *name = cls;
211 if (1 == nonce)
212 {
213 if (endbadly_task != NULL)
214 GNUNET_SCHEDULER_cancel (endbadly_task);
215 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
216 return;
217 }
218 nonce = 1;
219 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
220 "Failed to aquire additional lock\n");
221 /* Now, we stop the transaction for B */
222 nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont_a,
223 (void *) name);
224}
225
226
227static void
228begin_cont_b (void *cls,
229 int32_t success,
230 const char *emsg)
231{
232 const char *name = cls;
233
234 GNUNET_assert (success == GNUNET_YES);
235 /** Now, we expect this to "hang" let's see how this behaves in practice. */
236 nsqe = GNUNET_NAMESTORE_records_edit (nsh2,
237 &privkey,
238 name,
239 &fail_cb_lock,
240 (void *) name,
241 &edit_cont_b,
242 (void *) name);
243
244 GNUNET_assert (NULL != nsqe);
245}
246
247
248static void
249edit_cont (void *cls,
250 const struct GNUNET_IDENTITY_PrivateKey *zone,
251 const char *label,
252 unsigned int rd_count,
253 const struct GNUNET_GNSRECORD_Data *rd)
254{
255 const char *name = cls;
256
257 GNUNET_assert (1 == rd_count);
258 /* Now, we start a transaction for B */
259 nsqe = GNUNET_NAMESTORE_transaction_begin (nsh2, begin_cont_b, (void *) name);
260}
261
262
263static void
264begin_cont (void *cls,
265 int32_t success,
266 const char *emsg)
267{
268 const char *name = cls;
269
270 GNUNET_assert (success == GNUNET_YES);
271 nsqe = GNUNET_NAMESTORE_records_edit (nsh,
272 &privkey,
273 name,
274 &fail_cb,
275 (void *) name,
276 &edit_cont,
277 (void *) name);
278
279 GNUNET_assert (NULL != nsqe);
280}
281
282static void
283preload_cont (void *cls,
284 int32_t success,
285 const char *emsg)
286{
287 const char *name = cls;
288
289 GNUNET_assert (NULL != cls);
290 nsqe = NULL;
291 if (GNUNET_SYSERR == success)
292 {
293 GNUNET_break (0);
294 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
295 "Namestore could not store record: `%s'\n",
296 emsg);
297 if (endbadly_task != NULL)
298 GNUNET_SCHEDULER_cancel (endbadly_task);
299 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
300 return;
301 }
302
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304 "Name store added record for `%s': %s\n",
305 name,
306 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
307 /* We start transaction for A */
308 nsqe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, (void *) name);
309
310}
311
312
313static void
314run (void *cls,
315 const struct GNUNET_CONFIGURATION_Handle *cfg,
316 struct GNUNET_TESTING_Peer *peer)
317{
318 struct GNUNET_GNSRECORD_Data rd;
319 const char *name = "dummy";
320
321 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
322 &endbadly,
323 NULL);
324 nsh = GNUNET_NAMESTORE_connect (cfg);
325 nsh2 = GNUNET_NAMESTORE_connect (cfg);
326 GNUNET_break (NULL != nsh);
327 GNUNET_break (NULL != nsh2);
328
329 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
330 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
331 GNUNET_IDENTITY_key_get_public (&privkey,
332 &pubkey);
333
334 removed = GNUNET_NO;
335
336 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us;
337 rd.record_type = TEST_RECORD_TYPE;
338 rd.data_size = TEST_RECORD_DATALEN;
339 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
340 rd.flags = 0;
341 memset ((char *) rd.data,
342 'a',
343 TEST_RECORD_DATALEN);
344 nsqe = GNUNET_NAMESTORE_records_store (nsh,
345 &privkey,
346 name,
347 1,
348 &rd,
349 &preload_cont,
350 (void *) name);
351 GNUNET_assert (NULL != nsqe);
352 GNUNET_free_nz ((void *) rd.data);
353
354 /*nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont);
355 nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, rollback_cont); Must also happen on disconnect
356 nsqe = GNUNET_NAMESTORE_records_edit (nsh,
357 &privkey,
358 name,
359 1,
360 &rd,
361 &edit_cont,
362 (void *) name);
363 nsqe = GNUNET_NAMESTORE_records_insert_bulk (nsh,
364 count,
365 &rd,
366 &
367 nsqe = GNUNET_NAMESTORE_records_store (nsh,
368 &privkey,
369 name,
370 1,
371 &rd,
372 &put_cont,
373 (void *) name);*/
374 GNUNET_assert (NULL != nsqe);
375}
376
377
378#include "test_common.c"
379
380
381int
382main (int argc, char *argv[])
383{
384 const char *plugin_name;
385 char *cfg_name;
386
387 SETUP_CFG (plugin_name, cfg_name);
388 res = 1;
389 if (0 !=
390 GNUNET_TESTING_peer_run ("test-namestore-api-remove",
391 cfg_name,
392 &run,
393 NULL))
394 {
395 res = 1;
396 }
397 GNUNET_DISK_purge_cfg_dir (cfg_name,
398 "GNUNET_TEST_HOME");
399 GNUNET_free (cfg_name);
400 return res;
401}
402
403
404/* end of test_namestore_api_remove.c */
diff --git a/src/namestore/test_namestore_api_postgres.conf b/src/namestore/test_namestore_api_postgres.conf
index 93ef935b5..c648a6ab9 100644
--- a/src/namestore/test_namestore_api_postgres.conf
+++ b/src/namestore/test_namestore_api_postgres.conf
@@ -6,4 +6,4 @@ DATABASE = postgres
6 6
7[namestore-postgres] 7[namestore-postgres]
8CONFIG = connect_timeout=10 dbname=gnunetcheck 8CONFIG = connect_timeout=10 dbname=gnunetcheck
9TEMPORARY_TABLE = YES 9TEMPORARY_TABLE = NO
diff --git a/src/namestore/test_namestore_api_tx_rollback.c b/src/namestore/test_namestore_api_tx_rollback.c
new file mode 100644
index 000000000..ccfd8d701
--- /dev/null
+++ b/src/namestore/test_namestore_api_tx_rollback.c
@@ -0,0 +1,268 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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_tx_rollback.c
22 * @brief testcase for namestore_api_tx_rollback.c to: rollback changes in TX
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_SCHEDULER_Task *endbadly_task;
41
42static struct GNUNET_IDENTITY_PrivateKey privkey;
43
44static struct GNUNET_IDENTITY_PublicKey pubkey;
45
46static int res;
47
48static int removed;
49
50static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
51
52
53static void
54cleanup ()
55{
56 if (NULL != nsh)
57 {
58 GNUNET_NAMESTORE_disconnect (nsh);
59 nsh = NULL;
60 }
61 GNUNET_SCHEDULER_shutdown ();
62}
63
64
65/**
66 * Re-establish the connection to the service.
67 *
68 * @param cls handle to use to re-connect.
69 */
70static void
71endbadly (void *cls)
72{
73 if (NULL != nsqe)
74 {
75 GNUNET_NAMESTORE_cancel (nsqe);
76 nsqe = NULL;
77 }
78 cleanup ();
79 res = 1;
80}
81
82
83static void
84end (void *cls)
85{
86 cleanup ();
87 res = 0;
88}
89
90static void
91lookup_it (void *cls,
92 const struct GNUNET_IDENTITY_PrivateKey *zone,
93 const char *label,
94 unsigned int rd_count,
95 const struct GNUNET_GNSRECORD_Data *rd)
96{
97 GNUNET_assert (0 == rd_count);
98 GNUNET_SCHEDULER_add_now (&end, NULL);
99}
100
101static void
102fail_cb (void *cls)
103{
104 GNUNET_assert (0);
105}
106
107static void
108remove_cont (void *cls,
109 int32_t success,
110 const char *emsg)
111{
112 nsqe = NULL;
113 if (GNUNET_YES != success)
114 {
115 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
116 _ ("Unable to roll back: `%s'\n"),
117 emsg);
118 if (NULL != endbadly_task)
119 GNUNET_SCHEDULER_cancel (endbadly_task);
120 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly,
121 NULL);
122 return;
123 }
124 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
125 "Rolled back, perform lookup\n");
126 removed = GNUNET_YES;
127 if (NULL != endbadly_task)
128 GNUNET_SCHEDULER_cancel (endbadly_task);
129 /* FIXME not actually doing lookup here */
130 nsqe = GNUNET_NAMESTORE_records_lookup (nsh,
131 &privkey,
132 (char*) cls,
133 &fail_cb,
134 NULL,
135 &lookup_it,
136 NULL);
137}
138
139
140static void
141put_cont (void *cls,
142 int32_t success,
143 const char *emsg)
144{
145 const char *name = cls;
146
147 GNUNET_assert (NULL != cls);
148 nsqe = NULL;
149 if (GNUNET_SYSERR == success)
150 {
151 GNUNET_break (0);
152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
153 "Namestore could not store record: `%s'\n",
154 emsg);
155 if (endbadly_task != NULL)
156 GNUNET_SCHEDULER_cancel (endbadly_task);
157 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
158 return;
159 }
160
161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
162 "Name store added record for `%s': %s\n",
163 name,
164 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
165 nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, remove_cont,
166 (void *) name);
167}
168
169static void
170begin_cont (void *cls,
171 int32_t success,
172 const char *emsg)
173{
174 struct GNUNET_GNSRECORD_Data rd;
175 const char *name = cls;
176
177 GNUNET_assert (success == GNUNET_YES);
178 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
179 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
180 GNUNET_IDENTITY_key_get_public (&privkey,
181 &pubkey);
182
183 removed = GNUNET_NO;
184
185 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us;
186 rd.record_type = TEST_RECORD_TYPE;
187 rd.data_size = TEST_RECORD_DATALEN;
188 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
189 rd.flags = 0;
190 memset ((char *) rd.data,
191 'a',
192 TEST_RECORD_DATALEN);
193 nsqe = GNUNET_NAMESTORE_records_store (nsh,
194 &privkey,
195 name,
196 1,
197 &rd,
198 &put_cont,
199 (void *) name);
200 GNUNET_assert (NULL != nsqe);
201 GNUNET_free_nz ((void *) rd.data);
202}
203
204static void
205run (void *cls,
206 const struct GNUNET_CONFIGURATION_Handle *cfg,
207 struct GNUNET_TESTING_Peer *peer)
208{
209 struct GNUNET_GNSRECORD_Data rd;
210 const char *name = "dummy";
211
212 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
213 &endbadly,
214 NULL);
215 nsh = GNUNET_NAMESTORE_connect (cfg);
216 GNUNET_break (NULL != nsh);
217 nsqe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, (void *) name);
218 /*nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont);
219 nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, rollback_cont); Must also happen on disconnect
220 nsqe = GNUNET_NAMESTORE_records_edit (nsh,
221 &privkey,
222 name,
223 1,
224 &rd,
225 &edit_cont,
226 (void *) name);
227 nsqe = GNUNET_NAMESTORE_records_insert_bulk (nsh,
228 count,
229 &rd,
230 &
231 nsqe = GNUNET_NAMESTORE_records_store (nsh,
232 &privkey,
233 name,
234 1,
235 &rd,
236 &put_cont,
237 (void *) name);*/
238 GNUNET_assert (NULL != nsqe);
239}
240
241
242#include "test_common.c"
243
244
245int
246main (int argc, char *argv[])
247{
248 const char *plugin_name;
249 char *cfg_name;
250
251 SETUP_CFG (plugin_name, cfg_name);
252 res = 1;
253 if (0 !=
254 GNUNET_TESTING_peer_run ("test-namestore-api-remove",
255 cfg_name,
256 &run,
257 NULL))
258 {
259 res = 1;
260 }
261 GNUNET_DISK_purge_cfg_dir (cfg_name,
262 "GNUNET_TEST_HOME");
263 GNUNET_free (cfg_name);
264 return res;
265}
266
267
268/* end of test_namestore_api_remove.c */
diff --git a/src/pq/pq.c b/src/pq/pq.c
index 130ff355f..c8deb8193 100644
--- a/src/pq/pq.c
+++ b/src/pq/pq.c
@@ -97,9 +97,9 @@ GNUNET_PQ_exec_prepared (struct GNUNET_PQ_Context *db,
97 1); 97 1);
98 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 98 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
99 "pq", 99 "pq",
100 "Execution of prepared SQL statement `%s' finished (%d)\n", 100 "Execution of prepared SQL statement `%s' finished (%s)\n",
101 name, 101 name,
102 PGRES_COMMAND_OK == PQresultStatus (res)); 102 PQresStatus (PQresultStatus (res)));
103 if ( (PGRES_COMMAND_OK != PQresultStatus (res)) && 103 if ( (PGRES_COMMAND_OK != PQresultStatus (res)) &&
104 (CONNECTION_OK != (status = PQstatus (db->conn))) ) 104 (CONNECTION_OK != (status = PQstatus (db->conn))) )
105 { 105 {
diff --git a/src/pq/pq_exec.c b/src/pq/pq_exec.c
index dcde331b6..62dd577ad 100644
--- a/src/pq/pq_exec.c
+++ b/src/pq/pq_exec.c
@@ -87,10 +87,10 @@ GNUNET_PQ_exec_statements (struct GNUNET_PQ_Context *db,
87 result = PQexec (db->conn, 87 result = PQexec (db->conn,
88 es[i].sql); 88 es[i].sql);
89 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 89 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
90 "Running statement `%s' on %p finished (%d)\n", 90 "Running statement `%s' on %p finished (%s)\n",
91 es[i].sql, 91 es[i].sql,
92 db, 92 db,
93 PGRES_COMMAND_OK == PQresultStatus (result)); 93 PQresStatus (PQresultStatus (result)));
94 if ((GNUNET_NO == es[i].ignore_errors) && 94 if ((GNUNET_NO == es[i].ignore_errors) &&
95 (PGRES_COMMAND_OK != PQresultStatus (result))) 95 (PGRES_COMMAND_OK != PQresultStatus (result)))
96 { 96 {