aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-11-23 19:18:00 +0100
committerMartin Schanzenbach <schanzen@gnunet.org>2023-11-23 19:18:00 +0100
commitd51ba6435b62772ccf2a20d13e99c164898bdc9d (patch)
tree349100514a23faf9a084fadd8dd55fca94bb8d7e
parent12ab12595f5021427c4d09623f0d7bb9aac21710 (diff)
downloadgnunet-d51ba6435b62772ccf2a20d13e99c164898bdc9d.tar.gz
gnunet-d51ba6435b62772ccf2a20d13e99c164898bdc9d.zip
PEERSTORE: Major API overhault to fix a variety of race conditions.
-rw-r--r--src/include/gnunet_protocols.h6
-rw-r--r--src/service/meson.build2
-rw-r--r--src/service/peerstore/Makefile.am8
-rw-r--r--src/service/peerstore/gnunet-service-peerstore.c133
-rw-r--r--src/service/peerstore/meson.build55
-rw-r--r--src/service/peerstore/peerstore.h33
-rw-r--r--src/service/peerstore/peerstore_api.c419
-rw-r--r--src/service/peerstore/peerstore_common.c17
-rw-r--r--src/service/peerstore/peerstore_common.h4
-rw-r--r--src/service/peerstore/perf_peerstore_store.c32
-rw-r--r--src/service/peerstore/test_peerstore_api_iterate.c84
-rw-r--r--src/service/peerstore/test_peerstore_api_store.c16
-rw-r--r--src/service/peerstore/test_peerstore_api_sync.c252
-rw-r--r--src/service/peerstore/test_peerstore_api_watch.c77
14 files changed, 549 insertions, 589 deletions
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 0daa37bed..a998344b9 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2628,6 +2628,12 @@ extern "C" {
2628 */ 2628 */
2629#define GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_CANCEL 826 2629#define GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_CANCEL 826
2630 2630
2631/**
2632 * Store result message
2633 */
2634#define GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT 827
2635
2636
2631/******************************************************************************* 2637/*******************************************************************************
2632 * SOCIAL message types 2638 * SOCIAL message types
2633 ******************************************************************************/ 2639 ******************************************************************************/
diff --git a/src/service/meson.build b/src/service/meson.build
index b5c4bc1ae..fcd3f7520 100644
--- a/src/service/meson.build
+++ b/src/service/meson.build
@@ -7,8 +7,8 @@ endif
7subdir('util') 7subdir('util')
8subdir('statistics') 8subdir('statistics')
9subdir('arm') 9subdir('arm')
10subdir('peerstore')
11subdir('testing') 10subdir('testing')
11subdir('peerstore')
12subdir('nat') 12subdir('nat')
13subdir('nat-auto') 13subdir('nat-auto')
14subdir('transport') 14subdir('transport')
diff --git a/src/service/peerstore/Makefile.am b/src/service/peerstore/Makefile.am
index 6ca8e7925..a12e8ff8b 100644
--- a/src/service/peerstore/Makefile.am
+++ b/src/service/peerstore/Makefile.am
@@ -44,7 +44,6 @@ check_PROGRAMS = \
44 test_peerstore_api_store \ 44 test_peerstore_api_store \
45 test_peerstore_api_iterate \ 45 test_peerstore_api_iterate \
46 test_peerstore_api_watch \ 46 test_peerstore_api_watch \
47 test_peerstore_api_sync \
48 perf_peerstore_store 47 perf_peerstore_store
49 48
50EXTRA_DIST = \ 49EXTRA_DIST = \
@@ -76,13 +75,6 @@ test_peerstore_api_watch_LDADD = \
76 $(top_builddir)/src/service/testing/libgnunettesting.la \ 75 $(top_builddir)/src/service/testing/libgnunettesting.la \
77 $(top_builddir)/src/lib/util/libgnunetutil.la 76 $(top_builddir)/src/lib/util/libgnunetutil.la
78 77
79test_peerstore_api_sync_SOURCES = \
80 test_peerstore_api_sync.c
81test_peerstore_api_sync_LDADD = \
82 libgnunetpeerstore.la \
83 $(top_builddir)/src/service/testing/libgnunettesting.la \
84 $(top_builddir)/src/lib/util/libgnunetutil.la
85
86perf_peerstore_store_SOURCES = \ 78perf_peerstore_store_SOURCES = \
87 perf_peerstore_store.c 79 perf_peerstore_store.c
88perf_peerstore_store_LDADD = \ 80perf_peerstore_store_LDADD = \
diff --git a/src/service/peerstore/gnunet-service-peerstore.c b/src/service/peerstore/gnunet-service-peerstore.c
index 364900674..77523aa2e 100644
--- a/src/service/peerstore/gnunet-service-peerstore.c
+++ b/src/service/peerstore/gnunet-service-peerstore.c
@@ -100,6 +100,39 @@ do_shutdown ()
100} 100}
101 101
102 102
103struct IterationContext
104{
105 /**
106 * The record that was stored.
107 */
108 struct GNUNET_PEERSTORE_Record *record;
109
110 /**
111 * The request ID
112 */
113 uint32_t rid;
114
115};
116
117struct StoreRecordContext
118{
119 /**
120 * The record that was stored.
121 */
122 struct GNUNET_PEERSTORE_Record *record;
123
124 /**
125 * The request ID
126 */
127 uint32_t rid;
128
129 /**
130 * The client
131 */
132 struct GNUNET_SERVICE_Client *client;
133};
134
135
103/** 136/**
104 * Task run during shutdown. 137 * Task run during shutdown.
105 * 138 *
@@ -245,31 +278,37 @@ record_iterator (void *cls,
245 const struct GNUNET_PEERSTORE_Record *record, 278 const struct GNUNET_PEERSTORE_Record *record,
246 const char *emsg) 279 const char *emsg)
247{ 280{
248 struct GNUNET_PEERSTORE_Record *cls_record = cls; 281 struct IterationContext *ic = cls;
249 struct GNUNET_MQ_Envelope *env; 282 struct GNUNET_MQ_Envelope *env;
250 283
251 if (NULL == record) 284 if (NULL == record)
252 { 285 {
253 /* No more records */ 286 /* No more records */
254 struct GNUNET_MessageHeader *endmsg; 287 struct PeerstoreResultMessage *endmsg;
255 288
256 env = GNUNET_MQ_msg (endmsg, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END); 289 env = GNUNET_MQ_msg (endmsg, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END);
257 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cls_record->client), env); 290 endmsg->rid = ic->rid;
258 if (NULL == emsg) 291 if (NULL == emsg)
259 { 292 {
260 GNUNET_SERVICE_client_continue (cls_record->client); 293 endmsg->result = htonl (GNUNET_OK);
294 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (ic->record->client), env);
295 GNUNET_SERVICE_client_continue (ic->record->client);
261 } 296 }
262 else 297 else
263 { 298 {
299 endmsg->result = htonl (GNUNET_SYSERR);
300 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (ic->record->client), env);
264 GNUNET_break (0); 301 GNUNET_break (0);
265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate: %s\n", emsg); 302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate: %s\n", emsg);
266 GNUNET_SERVICE_client_drop (cls_record->client); 303 GNUNET_SERVICE_client_drop (ic->record->client);
267 } 304 }
268 PEERSTORE_destroy_record (cls_record); 305 PEERSTORE_destroy_record (ic->record);
306 GNUNET_free (ic);
269 return; 307 return;
270 } 308 }
271 309
272 env = PEERSTORE_create_record_mq_envelope ( 310 env = PEERSTORE_create_record_mq_envelope (
311 ic->rid,
273 record->sub_system, 312 record->sub_system,
274 &record->peer, 313 &record->peer,
275 record->key, 314 record->key,
@@ -278,7 +317,7 @@ record_iterator (void *cls,
278 record->expiry, 317 record->expiry,
279 0, 318 0,
280 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_RECORD); 319 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_RECORD);
281 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cls_record->client), env); 320 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (ic->record->client), env);
282} 321}
283 322
284 323
@@ -300,6 +339,7 @@ watch_notifier_it (void *cls, const struct GNUNET_HashCode *key, void *value)
300 339
301 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found a watcher to update.\n"); 340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found a watcher to update.\n");
302 env = PEERSTORE_create_record_mq_envelope ( 341 env = PEERSTORE_create_record_mq_envelope (
342 0,
303 record->sub_system, 343 record->sub_system,
304 &record->peer, 344 &record->peer,
305 record->key, 345 record->key,
@@ -415,27 +455,28 @@ check_iterate (void *cls, const struct StoreRecordMessage *srm)
415static void 455static void
416handle_iterate (void *cls, const struct StoreRecordMessage *srm) 456handle_iterate (void *cls, const struct StoreRecordMessage *srm)
417{ 457{
418 struct GNUNET_SERVICE_Client *client = cls; 458 struct IterationContext *ic = GNUNET_new (struct IterationContext);
419 struct GNUNET_PEERSTORE_Record *record;
420 459
421 record = PEERSTORE_parse_record_message (srm); 460 ic->record = PEERSTORE_parse_record_message (srm);
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "Iterate request: ss `%s', peer `%s', key `%s'\n", 462 "Iterate request: ss `%s', peer `%s', key `%s'\n",
424 record->sub_system, 463 ic->record->sub_system,
425 GNUNET_i2s (&record->peer), 464 GNUNET_i2s (&ic->record->peer),
426 (NULL == record->key) ? "NULL" : record->key); 465 (NULL == ic->record->key) ? "NULL" : ic->record->key);
427 record->client = client; 466 ic->record->client = cls;
467 ic->rid = srm->rid;
428 if (GNUNET_OK != 468 if (GNUNET_OK !=
429 db->iterate_records (db->cls, 469 db->iterate_records (db->cls,
430 record->sub_system, 470 ic->record->sub_system,
431 (ntohs (srm->peer_set)) ? &record->peer : NULL, 471 (ntohs (srm->peer_set)) ? &ic->record->peer : NULL,
432 record->key, 472 ic->record->key,
433 &record_iterator, 473 &record_iterator,
434 record)) 474 ic))
435 { 475 {
436 GNUNET_break (0); 476 GNUNET_break (0);
437 GNUNET_SERVICE_client_drop (client); 477 GNUNET_SERVICE_client_drop (ic->record->client);
438 PEERSTORE_destroy_record (record); 478 PEERSTORE_destroy_record (ic->record);
479 GNUNET_free (ic);
439 } 480 }
440} 481}
441 482
@@ -449,19 +490,28 @@ handle_iterate (void *cls, const struct StoreRecordMessage *srm)
449static void 490static void
450store_record_continuation (void *cls, int success) 491store_record_continuation (void *cls, int success)
451{ 492{
452 struct GNUNET_PEERSTORE_Record *record = cls; 493 struct StoreRecordContext *src = cls;
494 struct PeerstoreResultMessage *msg;
495 struct GNUNET_MQ_Envelope *env;
453 496
454 if (GNUNET_OK == success) 497 if (GNUNET_OK == success)
455 { 498 {
456 watch_notifier (record); 499
457 GNUNET_SERVICE_client_continue (record->client); 500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found a watcher to update.\n");
501 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT);
502 msg->rid = src->rid;
503 msg->result = htonl (success);
504 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (src->client), env);
505 watch_notifier (src->record);
506 GNUNET_SERVICE_client_continue (src->client);
458 } 507 }
459 else 508 else
460 { 509 {
461 GNUNET_break (0); 510 GNUNET_break (0);
462 GNUNET_SERVICE_client_drop (record->client); 511 GNUNET_SERVICE_client_drop (src->record->client);
463 } 512 }
464 PEERSTORE_destroy_record (record); 513 PEERSTORE_destroy_record (src->record);
514 GNUNET_free (src);
465} 515}
466 516
467 517
@@ -504,35 +554,38 @@ static void
504handle_store (void *cls, const struct StoreRecordMessage *srm) 554handle_store (void *cls, const struct StoreRecordMessage *srm)
505{ 555{
506 struct GNUNET_SERVICE_Client *client = cls; 556 struct GNUNET_SERVICE_Client *client = cls;
507 struct GNUNET_PEERSTORE_Record *record; 557 struct StoreRecordContext *src = GNUNET_new (struct StoreRecordContext);
508 558 src->record = PEERSTORE_parse_record_message (srm);
509 record = PEERSTORE_parse_record_message (srm);
510 GNUNET_log ( 559 GNUNET_log (
511 GNUNET_ERROR_TYPE_DEBUG, 560 GNUNET_ERROR_TYPE_DEBUG,
512 "Received a store request. Sub system `%s' Peer `%s Key `%s' Options: %u.\n", 561 "Received a store request. Sub system `%s' Peer `%s Key `%s' Options: %u.\n",
513 record->sub_system, 562 src->record->sub_system,
514 GNUNET_i2s (&record->peer), 563 GNUNET_i2s (&src->record->peer),
515 record->key, 564 src->record->key,
516 (uint32_t) ntohl (srm->options)); 565 (uint32_t) ntohl (srm->options));
517 record->client = client; 566 src->record->client = client;
567 src->rid = srm->rid;
568 src->client = client;
518 if (GNUNET_OK != db->store_record (db->cls, 569 if (GNUNET_OK != db->store_record (db->cls,
519 record->sub_system, 570 src->record->sub_system,
520 &record->peer, 571 &src->record->peer,
521 record->key, 572 src->record->key,
522 record->value, 573 src->record->value,
523 record->value_size, 574 src->record->value_size,
524 record->expiry, 575 src->record->expiry,
525 ntohl (srm->options), 576 ntohl (srm->options),
526 &store_record_continuation, 577 &store_record_continuation,
527 record)) 578 src))
528 { 579 {
529 GNUNET_break (0); 580 GNUNET_break (0);
530 PEERSTORE_destroy_record (record); 581 PEERSTORE_destroy_record (src->record);
582 GNUNET_free (src);
531 GNUNET_SERVICE_client_drop (client); 583 GNUNET_SERVICE_client_drop (client);
532 return; 584 return;
533 } 585 }
534} 586}
535 587
588
536static void 589static void
537store_hello_continuation (void *cls, int success) 590store_hello_continuation (void *cls, int success)
538{ 591{
diff --git a/src/service/peerstore/meson.build b/src/service/peerstore/meson.build
index db70b0b9e..2c6f7eba8 100644
--- a/src/service/peerstore/meson.build
+++ b/src/service/peerstore/meson.build
@@ -37,3 +37,58 @@ executable ('gnunet-service-peerstore',
37 install: true, 37 install: true,
38 install_dir: get_option('libdir') / 'gnunet' / 'libexec') 38 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
39 39
40testpeerstore_api_iterate = executable ('test_peerstore_api_iterate',
41 ['test_peerstore_api_iterate.c'],
42 dependencies: [
43 libgnunetpeerstore_dep,
44 libgnunettesting_dep,
45 libgnunetutil_dep
46 ],
47 include_directories: [incdir, configuration_inc],
48 install: false)
49
50testpeerstore_api_store = executable ('test_peerstore_api_store',
51 ['test_peerstore_api_store.c'],
52 dependencies: [
53 libgnunetpeerstore_dep,
54 libgnunetutil_dep,
55 libgnunettesting_dep,
56 ],
57 include_directories: [incdir, configuration_inc],
58 install: false)
59
60testpeerstore_api_watch = executable ('test_peerstore_api_watch',
61 ['test_peerstore_api_watch.c'],
62 dependencies: [
63 libgnunetpeerstore_dep,
64 libgnunetutil_dep,
65 libgnunettesting_dep,
66 ],
67 include_directories: [incdir, configuration_inc],
68 install: false)
69testpeerstore_api_perf = executable ('perf_peerstore_store',
70 ['perf_peerstore_store.c'],
71 dependencies: [
72 libgnunetpeerstore_dep,
73 libgnunetutil_dep,
74 libgnunettesting_dep,
75 ],
76 include_directories: [incdir, configuration_inc],
77 install: false)
78
79configure_file(input : 'test_peerstore_api_data.conf',
80 output : 'test_peerstore_api_data.conf',
81 copy: true)
82
83test('test_peerstore_api_store', testpeerstore_api_store,
84 suite: 'peerstore', workdir: meson.current_build_dir())
85test('test_peerstore_api_watch', testpeerstore_api_watch,
86 suite: 'peerstore', workdir: meson.current_build_dir())
87test('test_peerstore_api_iterate', testpeerstore_api_iterate,
88 suite: 'peerstore', workdir: meson.current_build_dir())
89test('perf_peerstore_store', testpeerstore_api_perf,
90 suite: 'peerstore', workdir: meson.current_build_dir())
91
92
93
94
diff --git a/src/service/peerstore/peerstore.h b/src/service/peerstore/peerstore.h
index 0dec03443..26c656f00 100644
--- a/src/service/peerstore/peerstore.h
+++ b/src/service/peerstore/peerstore.h
@@ -30,6 +30,7 @@
30 30
31 31
32GNUNET_NETWORK_STRUCT_BEGIN 32GNUNET_NETWORK_STRUCT_BEGIN
33
33/** 34/**
34 * Message carrying a PEERSTORE record message 35 * Message carrying a PEERSTORE record message
35 */ 36 */
@@ -74,6 +75,11 @@ struct StoreRecordMessage
74 uint16_t value_size GNUNET_PACKED; 75 uint16_t value_size GNUNET_PACKED;
75 76
76 /** 77 /**
78 * Request id.
79 */
80 uint32_t rid GNUNET_PACKED;
81
82 /**
77 * Options, needed only in case of a 83 * Options, needed only in case of a
78 * store operation 84 * store operation
79 */ 85 */
@@ -82,6 +88,28 @@ struct StoreRecordMessage
82 /* Followed by key and value */ 88 /* Followed by key and value */
83}; 89};
84 90
91/**
92 * Message carrying a PEERSTORE result message
93 */
94struct PeerstoreResultMessage
95{
96 /**
97 * GNUnet message header
98 */
99 struct GNUNET_MessageHeader header;
100
101 /**
102 * Request id.
103 */
104 uint32_t rid GNUNET_PACKED;
105
106 /**
107 * Options, needed only in case of a
108 * store operation
109 */
110 uint32_t result GNUNET_PACKED;
111
112};
85 113
86/** 114/**
87 * Message carrying record key hash 115 * Message carrying record key hash
@@ -94,14 +122,15 @@ struct StoreKeyHashMessage
94 struct GNUNET_MessageHeader header; 122 struct GNUNET_MessageHeader header;
95 123
96 /** 124 /**
97 * Always 0, for alignment. 125 * Request id.
98 */ 126 */
99 uint32_t reserved GNUNET_PACKED; 127 uint32_t rid GNUNET_PACKED;
100 128
101 /** 129 /**
102 * Hash of a record key 130 * Hash of a record key
103 */ 131 */
104 struct GNUNET_HashCode keyhash; 132 struct GNUNET_HashCode keyhash;
133
105}; 134};
106 135
107GNUNET_NETWORK_STRUCT_END 136GNUNET_NETWORK_STRUCT_END
diff --git a/src/service/peerstore/peerstore_api.c b/src/service/peerstore/peerstore_api.c
index 3dec7e01b..394f64378 100644
--- a/src/service/peerstore/peerstore_api.c
+++ b/src/service/peerstore/peerstore_api.c
@@ -23,6 +23,7 @@
23 * @author Omar Tarabai 23 * @author Omar Tarabai
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#include "gnunet_common.h"
26#include "platform.h" 27#include "platform.h"
27#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
28#include "gnunet_hello_uri_lib.h" 29#include "gnunet_hello_uri_lib.h"
@@ -86,6 +87,11 @@ struct GNUNET_PEERSTORE_Handle
86 */ 87 */
87 struct GNUNET_TIME_Relative reconnect_delay; 88 struct GNUNET_TIME_Relative reconnect_delay;
88 89
90 /**
91 *
92 */
93 uint32_t last_op_id;
94
89}; 95};
90 96
91/** 97/**
@@ -114,6 +120,11 @@ struct GNUNET_PEERSTORE_StoreContext
114 GNUNET_PEERSTORE_Continuation cont; 120 GNUNET_PEERSTORE_Continuation cont;
115 121
116 /** 122 /**
123 * Request ID
124 */
125 uint32_t rid;
126
127 /**
117 * Closure for @e cont 128 * Closure for @e cont
118 */ 129 */
119 void *cont_cls; 130 void *cont_cls;
@@ -216,9 +227,10 @@ struct GNUNET_PEERSTORE_IterateContext
216 void *callback_cls; 227 void *callback_cls;
217 228
218 /** 229 /**
219 * #GNUNET_YES if we are currently processing records. 230 * Request ID
220 */ 231 */
221 int iterating; 232 uint32_t rid;
233
222}; 234};
223 235
224/** 236/**
@@ -275,6 +287,12 @@ struct GNUNET_PEERSTORE_WatchContext
275 * The sub system requested the watch. 287 * The sub system requested the watch.
276 */ 288 */
277 const char *sub_system; 289 const char *sub_system;
290
291 /**
292 * Request ID
293 */
294 uint32_t rid;
295
278}; 296};
279 297
280/** 298/**
@@ -306,6 +324,12 @@ struct GNUNET_PEERSTORE_NotifyContext
306 * Is this request canceled. 324 * Is this request canceled.
307 */ 325 */
308 unsigned int canceled; 326 unsigned int canceled;
327
328 /**
329 * Request ID
330 */
331 uint32_t rid;
332
309}; 333};
310 334
311/******************************************************************************/ 335/******************************************************************************/
@@ -320,6 +344,18 @@ struct GNUNET_PEERSTORE_NotifyContext
320static void 344static void
321reconnect (void *cls); 345reconnect (void *cls);
322 346
347/**
348 * Get a fresh operation id to distinguish between namestore requests
349 *
350 * @param h the namestore handle
351 * @return next operation id to use
352 */
353static uint32_t
354get_op_id (struct GNUNET_PEERSTORE_Handle *h)
355{
356 return h->last_op_id++;
357}
358
323 359
324/** 360/**
325 * Disconnect from the peerstore service. 361 * Disconnect from the peerstore service.
@@ -329,25 +365,13 @@ reconnect (void *cls);
329static void 365static void
330disconnect (struct GNUNET_PEERSTORE_Handle *h) 366disconnect (struct GNUNET_PEERSTORE_Handle *h)
331{ 367{
332 struct GNUNET_PEERSTORE_IterateContext *next; 368 if (NULL != h->watches)
333
334 for (struct GNUNET_PEERSTORE_IterateContext *ic = h->iterate_head; NULL != ic;
335 ic = next)
336 { 369 {
337 next = ic->next; 370 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (h->watches));
338 if (GNUNET_YES == ic->iterating) 371 GNUNET_CONTAINER_multihashmap_destroy (h->watches);
339 {
340 GNUNET_PEERSTORE_Processor icb;
341 void *icb_cls;
342
343 icb = ic->callback;
344 icb_cls = ic->callback_cls;
345 GNUNET_PEERSTORE_iterate_cancel (ic);
346 if (NULL != icb)
347 icb (icb_cls, NULL, "Iteration canceled due to reconnection");
348 }
349 } 372 }
350 373 GNUNET_assert (NULL == h->iterate_head);
374 GNUNET_assert (NULL == h->store_head);
351 if (NULL != h->mq) 375 if (NULL != h->mq)
352 { 376 {
353 GNUNET_MQ_destroy (h->mq); 377 GNUNET_MQ_destroy (h->mq);
@@ -376,29 +400,6 @@ disconnect_and_schedule_reconnect (struct GNUNET_PEERSTORE_Handle *h)
376} 400}
377 401
378 402
379/**
380 * Callback after MQ envelope is sent
381 *
382 * @param cls a `struct GNUNET_PEERSTORE_StoreContext *`
383 */
384static void
385store_request_sent (void *cls)
386{
387 struct GNUNET_PEERSTORE_StoreContext *sc = cls;
388 GNUNET_PEERSTORE_Continuation cont;
389 void *cont_cls;
390
391 if (NULL != sc)
392 {
393 cont = sc->cont;
394 cont_cls = sc->cont_cls;
395 GNUNET_PEERSTORE_store_cancel (sc);
396 if (NULL != cont)
397 cont (cont_cls, GNUNET_OK);
398 }
399}
400
401
402/******************************************************************************/ 403/******************************************************************************/
403/******************* CONNECTION FUNCTIONS *********************/ 404/******************* CONNECTION FUNCTIONS *********************/
404/******************************************************************************/ 405/******************************************************************************/
@@ -437,30 +438,13 @@ rewatch_it (void *cls, const struct GNUNET_HashCode *key, void *value)
437 438
438 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH); 439 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH);
439 hm->keyhash = wc->keyhash; 440 hm->keyhash = wc->keyhash;
441 hm->rid = get_op_id (h);
440 GNUNET_MQ_send (h->mq, ev); 442 GNUNET_MQ_send (h->mq, ev);
441 return GNUNET_YES; 443 return GNUNET_YES;
442} 444}
443 445
444 446
445/** 447/**
446 * Iterator over watch requests to cancel them.
447 *
448 * @param cls unused
449 * @param key key to the watch request
450 * @param value watch context
451 * @return #GNUNET_YES to continue iteration
452 */
453static int
454destroy_watch (void *cls, const struct GNUNET_HashCode *key, void *value)
455{
456 struct GNUNET_PEERSTORE_WatchContext *wc = value;
457
458 GNUNET_PEERSTORE_watch_cancel (wc);
459 return GNUNET_YES;
460}
461
462
463/**
464 * Connect to the PEERSTORE service. 448 * Connect to the PEERSTORE service.
465 * 449 *
466 * @param cfg configuration to use 450 * @param cfg configuration to use
@@ -493,26 +477,7 @@ GNUNET_PEERSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
493void 477void
494GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h) 478GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h)
495{ 479{
496 struct GNUNET_PEERSTORE_IterateContext *ic; 480 LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnect initiated from client.\n");
497 struct GNUNET_PEERSTORE_StoreContext *sc;
498
499 LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting.\n");
500 if (NULL != h->watches)
501 {
502 GNUNET_CONTAINER_multihashmap_iterate (h->watches, &destroy_watch, NULL);
503 GNUNET_CONTAINER_multihashmap_destroy (h->watches);
504 h->watches = NULL;
505 }
506 while (NULL != (ic = h->iterate_head))
507 {
508 GNUNET_break (0);
509 GNUNET_PEERSTORE_iterate_cancel (ic);
510 }
511 while (NULL != (sc = h->store_head))
512 {
513 GNUNET_break (0);
514 GNUNET_PEERSTORE_store_cancel (sc);
515 }
516 disconnect (h); 481 disconnect (h);
517} 482}
518 483
@@ -530,17 +495,17 @@ GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h)
530void 495void
531GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc) 496GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc)
532{ 497{
533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 498 LOG (GNUNET_ERROR_TYPE_DEBUG,
534 "store cancel with sc %p \n", 499 "store cancel with sc %p \n",
535 sc); 500 sc);
536 GNUNET_CONTAINER_DLL_remove (sc->h->store_head, sc->h->store_tail, sc); 501 GNUNET_CONTAINER_DLL_remove (sc->h->store_head, sc->h->store_tail, sc);
537 GNUNET_free (sc->sub_system); 502 GNUNET_free (sc->sub_system);
538 GNUNET_free (sc->value); 503 GNUNET_free (sc->value);
539 GNUNET_free (sc->key); 504 GNUNET_free (sc->key);
540 GNUNET_free (sc); 505 GNUNET_free (sc);
541 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 506 LOG (GNUNET_ERROR_TYPE_DEBUG,
542 "store cancel with sc %p is null\n", 507 "store cancel with sc %p is null\n",
543 sc); 508 sc);
544} 509}
545 510
546 511
@@ -581,17 +546,8 @@ GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
581 sub_system, 546 sub_system,
582 GNUNET_i2s (peer), 547 GNUNET_i2s (peer),
583 key); 548 key);
584 ev =
585 PEERSTORE_create_record_mq_envelope (sub_system,
586 peer,
587 key,
588 value,
589 size,
590 expiry,
591 options,
592 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
593 sc = GNUNET_new (struct GNUNET_PEERSTORE_StoreContext); 549 sc = GNUNET_new (struct GNUNET_PEERSTORE_StoreContext);
594 550 sc->rid = get_op_id (h);
595 sc->sub_system = GNUNET_strdup (sub_system); 551 sc->sub_system = GNUNET_strdup (sub_system);
596 sc->peer = *peer; 552 sc->peer = *peer;
597 sc->key = GNUNET_strdup (key); 553 sc->key = GNUNET_strdup (key);
@@ -602,14 +558,54 @@ GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
602 sc->cont = cont; 558 sc->cont = cont;
603 sc->cont_cls = cont_cls; 559 sc->cont_cls = cont_cls;
604 sc->h = h; 560 sc->h = h;
561 ev =
562 PEERSTORE_create_record_mq_envelope (sc->rid,
563 sub_system,
564 peer,
565 key,
566 value,
567 size,
568 expiry,
569 options,
570 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
605 571
606 GNUNET_CONTAINER_DLL_insert_tail (h->store_head, h->store_tail, sc); 572 GNUNET_CONTAINER_DLL_insert_tail (h->store_head, h->store_tail, sc);
607 GNUNET_MQ_notify_sent (ev, &store_request_sent, sc);
608 GNUNET_MQ_send (h->mq, ev); 573 GNUNET_MQ_send (h->mq, ev);
609 return sc; 574 return sc;
610} 575}
611 576
612 577
578/**
579 * When a response for store request is received
580 *
581 * @param cls a `struct GNUNET_PEERSTORE_Handle *`
582 * @param msg message received
583 */
584static void
585handle_store_result (void *cls, const struct PeerstoreResultMessage *msg)
586{
587 struct GNUNET_PEERSTORE_Handle *h = cls;
588 struct GNUNET_PEERSTORE_StoreContext *sc = h->store_head;
589
590 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got PeerstoreResultMessage\n");
591 for (sc = h->store_head; NULL != sc; sc = sc->next)
592 {
593 LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying %u ?= %u\n", sc->rid, msg->rid);
594 if (sc->rid == msg->rid)
595 break;
596 }
597 if (NULL == sc)
598 {
599 LOG (GNUNET_ERROR_TYPE_WARNING,
600 _("Unexpected store response.\n"));
601 return;
602 }
603 if (NULL != sc->cont)
604 sc->cont (sc->cont_cls, ntohl (msg->result));
605 GNUNET_CONTAINER_DLL_remove (h->store_head, h->store_tail, sc);
606}
607
608
613/******************************************************************************/ 609/******************************************************************************/
614/******************* ITERATE FUNCTIONS *********************/ 610/******************* ITERATE FUNCTIONS *********************/
615/******************************************************************************/ 611/******************************************************************************/
@@ -622,29 +618,24 @@ GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
622 * @param msg message received 618 * @param msg message received
623 */ 619 */
624static void 620static void
625handle_iterate_end (void *cls, const struct GNUNET_MessageHeader *msg) 621handle_iterate_end (void *cls, const struct PeerstoreResultMessage *msg)
626{ 622{
627 struct GNUNET_PEERSTORE_Handle *h = cls; 623 struct GNUNET_PEERSTORE_Handle *h = cls;
628 struct GNUNET_PEERSTORE_IterateContext *ic; 624 struct GNUNET_PEERSTORE_IterateContext *ic = h->iterate_head;
629 GNUNET_PEERSTORE_Processor callback;
630 void *callback_cls;
631 625
632 ic = h->iterate_head; 626 for (ic = h->iterate_head; NULL != ic; ic = ic->next)
627 if (ic->rid == msg->rid)
628 break;
633 if (NULL == ic) 629 if (NULL == ic)
634 { 630 {
635 LOG (GNUNET_ERROR_TYPE_ERROR, 631 LOG (GNUNET_ERROR_TYPE_WARNING,
636 _ ("Unexpected iteration response, this should not happen.\n")); 632 _ ("Unexpected iteration response.\n"));
637 disconnect_and_schedule_reconnect (h);
638 return; 633 return;
639 } 634 }
640 callback = ic->callback; 635 if (NULL != ic->callback)
641 callback_cls = ic->callback_cls; 636 ic->callback (ic->callback_cls, NULL, NULL);
642 ic->iterating = GNUNET_NO; 637 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up iteration with rid %u\n", ic->rid);
643 GNUNET_PEERSTORE_iterate_cancel (ic); 638 GNUNET_CONTAINER_DLL_remove (h->iterate_head, h->iterate_tail, ic);
644 /* NOTE: set this here and not after callback because callback may free h */
645 h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
646 if (NULL != callback)
647 callback (callback_cls, NULL, NULL);
648} 639}
649 640
650 641
@@ -674,11 +665,12 @@ handle_iterate_result (void *cls, const struct StoreRecordMessage *msg)
674{ 665{
675 struct GNUNET_PEERSTORE_Handle *h = cls; 666 struct GNUNET_PEERSTORE_Handle *h = cls;
676 struct GNUNET_PEERSTORE_IterateContext *ic; 667 struct GNUNET_PEERSTORE_IterateContext *ic;
677 GNUNET_PEERSTORE_Processor callback;
678 void *callback_cls;
679 struct GNUNET_PEERSTORE_Record *record; 668 struct GNUNET_PEERSTORE_Record *record;
680 669
681 ic = h->iterate_head; 670 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received StoreRecordMessage\n");
671 for (ic = h->iterate_head; NULL != ic; ic = ic->next)
672 if (ic->rid == msg->rid)
673 break;
682 if (NULL == ic) 674 if (NULL == ic)
683 { 675 {
684 LOG (GNUNET_ERROR_TYPE_ERROR, 676 LOG (GNUNET_ERROR_TYPE_ERROR,
@@ -686,21 +678,18 @@ handle_iterate_result (void *cls, const struct StoreRecordMessage *msg)
686 disconnect_and_schedule_reconnect (h); 678 disconnect_and_schedule_reconnect (h);
687 return; 679 return;
688 } 680 }
689 ic->iterating = GNUNET_YES; 681 if (NULL == ic->callback)
690 callback = ic->callback;
691 callback_cls = ic->callback_cls;
692 if (NULL == callback)
693 return; 682 return;
694 record = PEERSTORE_parse_record_message (msg); 683 record = PEERSTORE_parse_record_message (msg);
695 if (NULL == record) 684 if (NULL == record)
696 { 685 {
697 callback (callback_cls, 686 ic->callback (ic->callback_cls,
698 NULL, 687 NULL,
699 _ ("Received a malformed response from service.")); 688 _ ("Received a malformed response from service."));
700 } 689 }
701 else 690 else
702 { 691 {
703 callback (callback_cls, record, NULL); 692 ic->callback (ic->callback_cls, record, NULL);
704 PEERSTORE_destroy_record (record); 693 PEERSTORE_destroy_record (record);
705 } 694 }
706} 695}
@@ -715,11 +704,6 @@ handle_iterate_result (void *cls, const struct StoreRecordMessage *msg)
715void 704void
716GNUNET_PEERSTORE_iterate_cancel (struct GNUNET_PEERSTORE_IterateContext *ic) 705GNUNET_PEERSTORE_iterate_cancel (struct GNUNET_PEERSTORE_IterateContext *ic)
717{ 706{
718 if (GNUNET_YES == ic->iterating)
719 {
720 if (NULL != ic->callback)
721 ic->callback (ic->callback_cls, NULL, "Iteration canceled due to reconnection");
722 }
723 GNUNET_CONTAINER_DLL_remove (ic->h->iterate_head, ic->h->iterate_tail, ic); 707 GNUNET_CONTAINER_DLL_remove (ic->h->iterate_head, ic->h->iterate_tail, ic);
724 GNUNET_free (ic->sub_system); 708 GNUNET_free (ic->sub_system);
725 GNUNET_free (ic->key); 709 GNUNET_free (ic->key);
@@ -738,8 +722,11 @@ GNUNET_PEERSTORE_iterate (struct GNUNET_PEERSTORE_Handle *h,
738 struct GNUNET_MQ_Envelope *ev; 722 struct GNUNET_MQ_Envelope *ev;
739 struct GNUNET_PEERSTORE_IterateContext *ic; 723 struct GNUNET_PEERSTORE_IterateContext *ic;
740 724
725 ic = GNUNET_new (struct GNUNET_PEERSTORE_IterateContext);
726 ic->rid = get_op_id (h);
741 ev = 727 ev =
742 PEERSTORE_create_record_mq_envelope (sub_system, 728 PEERSTORE_create_record_mq_envelope (ic->rid,
729 sub_system,
743 peer, 730 peer,
744 key, 731 key,
745 NULL, 732 NULL,
@@ -747,7 +734,6 @@ GNUNET_PEERSTORE_iterate (struct GNUNET_PEERSTORE_Handle *h,
747 GNUNET_TIME_UNIT_FOREVER_ABS, 734 GNUNET_TIME_UNIT_FOREVER_ABS,
748 0, 735 0,
749 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE); 736 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE);
750 ic = GNUNET_new (struct GNUNET_PEERSTORE_IterateContext);
751 ic->callback = callback; 737 ic->callback = callback;
752 ic->callback_cls = callback_cls; 738 ic->callback_cls = callback_cls;
753 ic->h = h; 739 ic->h = h;
@@ -831,10 +817,14 @@ static void
831reconnect (void *cls) 817reconnect (void *cls)
832{ 818{
833 struct GNUNET_PEERSTORE_Handle *h = cls; 819 struct GNUNET_PEERSTORE_Handle *h = cls;
834 struct GNUNET_MQ_MessageHandler mq_handlers[] = 820 struct GNUNET_MQ_MessageHandler mq_handlers[] = {
835 { GNUNET_MQ_hd_fixed_size (iterate_end, 821 GNUNET_MQ_hd_fixed_size (iterate_end,
836 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END, 822 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END,
837 struct GNUNET_MessageHeader, 823 struct PeerstoreResultMessage,
824 h),
825 GNUNET_MQ_hd_fixed_size (store_result,
826 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT,
827 struct PeerstoreResultMessage,
838 h), 828 h),
839 GNUNET_MQ_hd_var_size (iterate_result, 829 GNUNET_MQ_hd_var_size (iterate_result,
840 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_RECORD, 830 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_RECORD,
@@ -844,7 +834,8 @@ reconnect (void *cls)
844 GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_RECORD, 834 GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_RECORD,
845 struct StoreRecordMessage, 835 struct StoreRecordMessage,
846 h), 836 h),
847 GNUNET_MQ_handler_end () }; 837 GNUNET_MQ_handler_end ()
838 };
848 struct GNUNET_MQ_Envelope *ev; 839 struct GNUNET_MQ_Envelope *ev;
849 840
850 h->reconnect_task = NULL; 841 h->reconnect_task = NULL;
@@ -868,8 +859,10 @@ reconnect (void *cls)
868 for (struct GNUNET_PEERSTORE_IterateContext *ic = h->iterate_head; NULL != ic; 859 for (struct GNUNET_PEERSTORE_IterateContext *ic = h->iterate_head; NULL != ic;
869 ic = ic->next) 860 ic = ic->next)
870 { 861 {
862 ic->rid = get_op_id(h);
871 ev = 863 ev =
872 PEERSTORE_create_record_mq_envelope (ic->sub_system, 864 PEERSTORE_create_record_mq_envelope (ic->rid,
865 ic->sub_system,
873 &ic->peer, 866 &ic->peer,
874 ic->key, 867 ic->key,
875 NULL, 868 NULL,
@@ -882,8 +875,10 @@ reconnect (void *cls)
882 for (struct GNUNET_PEERSTORE_StoreContext *sc = h->store_head; NULL != sc; 875 for (struct GNUNET_PEERSTORE_StoreContext *sc = h->store_head; NULL != sc;
883 sc = sc->next) 876 sc = sc->next)
884 { 877 {
878 sc->rid = get_op_id(h);
885 ev = 879 ev =
886 PEERSTORE_create_record_mq_envelope (sc->sub_system, 880 PEERSTORE_create_record_mq_envelope (sc->rid,
881 sc->sub_system,
887 &sc->peer, 882 &sc->peer,
888 sc->key, 883 sc->key,
889 sc->value, 884 sc->value,
@@ -891,7 +886,6 @@ reconnect (void *cls)
891 sc->expiry, 886 sc->expiry,
892 sc->options, 887 sc->options,
893 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE); 888 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
894 GNUNET_MQ_notify_sent (ev, &store_request_sent, sc);
895 GNUNET_MQ_send (h->mq, ev); 889 GNUNET_MQ_send (h->mq, ev);
896 } 890 }
897} 891}
@@ -909,7 +903,7 @@ GNUNET_PEERSTORE_watch_cancel (struct GNUNET_PEERSTORE_WatchContext *wc)
909 struct GNUNET_MQ_Envelope *ev; 903 struct GNUNET_MQ_Envelope *ev;
910 struct StoreKeyHashMessage *hm; 904 struct StoreKeyHashMessage *hm;
911 905
912 LOG (GNUNET_ERROR_TYPE_DEBUG, "Canceling watch.\n"); 906 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cancelling watch.\n");
913 if (NULL != wc->ic) 907 if (NULL != wc->ic)
914 { 908 {
915 GNUNET_PEERSTORE_iterate_cancel (wc->ic); 909 GNUNET_PEERSTORE_iterate_cancel (wc->ic);
@@ -919,6 +913,7 @@ GNUNET_PEERSTORE_watch_cancel (struct GNUNET_PEERSTORE_WatchContext *wc)
919 913
920 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_CANCEL); 914 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_CANCEL);
921 hm->keyhash = wc->keyhash; 915 hm->keyhash = wc->keyhash;
916 hm->rid = get_op_id (h);
922 GNUNET_MQ_send (h->mq, ev); 917 GNUNET_MQ_send (h->mq, ev);
923 GNUNET_assert ( 918 GNUNET_assert (
924 GNUNET_YES == 919 GNUNET_YES ==
@@ -935,53 +930,55 @@ watch_iterate (void *cls,
935 struct GNUNET_PEERSTORE_WatchContext *wc = cls; 930 struct GNUNET_PEERSTORE_WatchContext *wc = cls;
936 struct GNUNET_PEERSTORE_Handle *h = wc->h; 931 struct GNUNET_PEERSTORE_Handle *h = wc->h;
937 struct StoreKeyHashMessage *hm; 932 struct StoreKeyHashMessage *hm;
933 struct GNUNET_MQ_Envelope *ev;
934 const struct GNUNET_PeerIdentity *peer;
938 935
939 if (NULL != emsg) 936 if (NULL != emsg)
940 { 937 {
941 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 938 LOG (GNUNET_ERROR_TYPE_WARNING,
942 "Got failure from PEERSTORE: %s\n", 939 "Got failure from PEERSTORE: %s\n",
943 emsg); 940 emsg);
944 wc->callback (wc->callback_cls, NULL, emsg); 941 wc->callback (wc->callback_cls, NULL, emsg);
945 return; 942 return;
946 } 943 }
947 if (NULL == record) 944 if ((NULL != record) &&
945 (NULL != wc->callback))
948 { 946 {
949 struct GNUNET_MQ_Envelope *ev; 947 wc->callback (wc->callback_cls, record, NULL);
950 const struct GNUNET_PeerIdentity *peer;
951
952 if (NULL == wc->peer)
953 peer = GNUNET_new (struct GNUNET_PeerIdentity);
954 else
955 peer = wc->peer;
956 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH);
957 PEERSTORE_hash_key (wc->sub_system, peer, wc->key, &hm->keyhash);
958 LOG (GNUNET_ERROR_TYPE_DEBUG,
959 "Hash key we watch for %s\n",
960 GNUNET_h2s_full (&hm->keyhash));
961 wc->keyhash = hm->keyhash;
962 if (NULL == h->watches)
963 h->watches = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
964 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
965 h->watches,
966 &wc->keyhash,
967 wc,
968 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
969 LOG (GNUNET_ERROR_TYPE_DEBUG,
970 "Sending a watch request for subsystem `%s', peer `%s', key `%s'.\n",
971 wc->sub_system,
972 GNUNET_i2s (peer),
973 wc->key);
974 GNUNET_MQ_send (h->mq, ev);
975 wc->ic = NULL;
976 if (NULL != wc->callback)
977 wc->callback (wc->callback_cls, record, NULL);
978 if (NULL == wc->peer)
979 GNUNET_free_nz ((void *) peer);
980 return; 948 return;
981 } 949 }
982 950
951 if (NULL == wc->peer)
952 peer = GNUNET_new (struct GNUNET_PeerIdentity);
953 else
954 peer = wc->peer;
955 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH);
956 PEERSTORE_hash_key (wc->sub_system, peer, wc->key, &hm->keyhash);
957 hm->rid = get_op_id (h);
958 LOG (GNUNET_ERROR_TYPE_DEBUG,
959 "Hash key we watch for %s\n",
960 GNUNET_h2s_full (&hm->keyhash));
961 wc->keyhash = hm->keyhash;
962 if (NULL == h->watches)
963 h->watches = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
964 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
965 h->watches,
966 &wc->keyhash,
967 wc,
968 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
969 LOG (GNUNET_ERROR_TYPE_DEBUG,
970 "Sending a watch request for subsystem `%s', peer `%s', key `%s'.\n",
971 wc->sub_system,
972 GNUNET_i2s (peer),
973 wc->key);
974 GNUNET_MQ_send (h->mq, ev);
975 wc->ic = NULL;
983 if (NULL != wc->callback) 976 if (NULL != wc->callback)
984 wc->callback (wc->callback_cls, record, NULL); 977 wc->callback (wc->callback_cls, record, NULL);
978 if (NULL == wc->peer)
979 GNUNET_free_nz ((void *) peer);
980 return;
981
985} 982}
986 983
987 984
@@ -1040,32 +1037,32 @@ hello_updated (void *cls,
1040 struct GNUNET_PEERSTORE_NotifyContext *nc = cls; 1037 struct GNUNET_PEERSTORE_NotifyContext *nc = cls;
1041 const struct GNUNET_MessageHeader *hello; 1038 const struct GNUNET_MessageHeader *hello;
1042 1039
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1040 LOG (GNUNET_ERROR_TYPE_DEBUG,
1044 "hello_updated\n"); 1041 "hello_updated\n");
1045 if (NULL != emsg) 1042 if (NULL != emsg)
1046 { 1043 {
1047 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1044 LOG (GNUNET_ERROR_TYPE_WARNING,
1048 "Got failure from PEERSTORE: %s\n", 1045 "Got failure from PEERSTORE: %s\n",
1049 emsg); 1046 emsg);
1050 nc->callback (nc->callback_cls, NULL, NULL, emsg); 1047 nc->callback (nc->callback_cls, NULL, NULL, emsg);
1051 return; 1048 return;
1052 } 1049 }
1053 if (NULL == record) 1050 if (NULL == record)
1054 return; 1051 return;
1055 hello = record->value; 1052 hello = record->value;
1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1053 LOG (GNUNET_ERROR_TYPE_DEBUG,
1057 "hello_updated with expired %s and size %u for peer %s\n", 1054 "hello_updated with expired %s and size %u for peer %s\n",
1058 GNUNET_STRINGS_absolute_time_to_string ( 1055 GNUNET_STRINGS_absolute_time_to_string (
1059 GNUNET_HELLO_builder_get_expiration_time (hello)), 1056 GNUNET_HELLO_builder_get_expiration_time (hello)),
1060 ntohs (hello->size), 1057 ntohs (hello->size),
1061 GNUNET_i2s (&record->peer)); 1058 GNUNET_i2s (&record->peer));
1062 if ((0 == record->value_size)) 1059 if ((0 == record->value_size))
1063 { 1060 {
1064 GNUNET_break (0); 1061 GNUNET_break (0);
1065 return; 1062 return;
1066 } 1063 }
1067 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1064 LOG (GNUNET_ERROR_TYPE_DEBUG,
1068 "hello_updated call callback\n"); 1065 "hello_updated call callback\n");
1069 nc->callback (nc->callback_cls, &record->peer, hello, NULL); 1066 nc->callback (nc->callback_cls, &record->peer, hello, NULL);
1070} 1067}
1071 1068
@@ -1119,13 +1116,13 @@ merge_success (void *cls, int success)
1119 1116
1120 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_remove (huc->store_context_map, 1117 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_remove (huc->store_context_map,
1121 huc->pid, shu_cls->sc)) 1118 huc->pid, shu_cls->sc))
1122 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1119 LOG (GNUNET_ERROR_TYPE_WARNING,
1123 "There was no store context to be removed after storing hello for peer %s\n", 1120 "There was no store context to be removed after storing hello for peer %s\n",
1124 GNUNET_i2s (huc->pid)); 1121 GNUNET_i2s (huc->pid));
1125 if (GNUNET_OK != success) 1122 if (GNUNET_OK != success)
1126 { 1123 {
1127 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1124 LOG (GNUNET_ERROR_TYPE_WARNING,
1128 "Storing hello uri failed\n"); 1125 "Storing hello uri failed\n");
1129 huc->cont (huc->cont_cls, success); 1126 huc->cont (huc->cont_cls, success);
1130 GNUNET_free (huc->hello); 1127 GNUNET_free (huc->hello);
1131 GNUNET_free (huc->pid); 1128 GNUNET_free (huc->pid);
@@ -1139,18 +1136,18 @@ merge_success (void *cls, int success)
1139 huc->wc = NULL; 1136 huc->wc = NULL;
1140 huc->cont (huc->cont_cls, GNUNET_OK); 1137 huc->cont (huc->cont_cls, GNUNET_OK);
1141 huc->success = GNUNET_OK; 1138 huc->success = GNUNET_OK;
1142 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1139 LOG (GNUNET_ERROR_TYPE_DEBUG,
1143 "Storing hello uri succeeded for peer %s!\n", 1140 "Storing hello uri succeeded for peer %s!\n",
1144 GNUNET_i2s (huc->pid)); 1141 GNUNET_i2s (huc->pid));
1145 GNUNET_free (huc->hello); 1142 GNUNET_free (huc->hello);
1146 GNUNET_free (huc->pid); 1143 GNUNET_free (huc->pid);
1147 GNUNET_free (huc); 1144 GNUNET_free (huc);
1148 GNUNET_free (shu_cls); 1145 GNUNET_free (shu_cls);
1149 return; 1146 return;
1150 } 1147 }
1151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1148 LOG (GNUNET_ERROR_TYPE_DEBUG,
1152 "Got notified during storing hello uri for peer %s!\n", 1149 "Got notified during storing hello uri for peer %s!\n",
1153 GNUNET_i2s (huc->pid)); 1150 GNUNET_i2s (huc->pid));
1154 GNUNET_free (shu_cls); 1151 GNUNET_free (shu_cls);
1155} 1152}
1156 1153
@@ -1176,9 +1173,9 @@ store_hello (struct GNUNET_PEERSTORE_StoreHelloContext *huc,
1176 GNUNET_PEERSTORE_STOREOPTION_REPLACE, 1173 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
1177 merge_success, 1174 merge_success,
1178 shu_cls); 1175 shu_cls);
1179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1176 LOG (GNUNET_ERROR_TYPE_DEBUG,
1180 "store_hello with expiration %s\n", 1177 "store_hello with expiration %s\n",
1181 GNUNET_STRINGS_absolute_time_to_string (hello_exp)); 1178 GNUNET_STRINGS_absolute_time_to_string (hello_exp));
1182 GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_put ( 1179 GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_put (
1183 huc->store_context_map, 1180 huc->store_context_map,
1184 huc->pid, 1181 huc->pid,
@@ -1202,27 +1199,27 @@ merge_uri (void *cls,
1202 1199
1203 if (NULL != emsg) 1200 if (NULL != emsg)
1204 { 1201 {
1205 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1202 LOG (GNUNET_ERROR_TYPE_WARNING,
1206 "Got failure from PEERSTORE: %s\n", 1203 "Got failure from PEERSTORE: %s\n",
1207 emsg); 1204 emsg);
1208 return; 1205 return;
1209 } 1206 }
1210 1207
1211 if (NULL == record && GNUNET_NO == huc->success) 1208 if (NULL == record && GNUNET_NO == huc->success)
1212 { 1209 {
1213 huc_hello_exp_time = GNUNET_HELLO_builder_get_expiration_time (huc->hello); 1210 huc_hello_exp_time = GNUNET_HELLO_builder_get_expiration_time (huc->hello);
1214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1211 LOG (GNUNET_ERROR_TYPE_DEBUG,
1215 "merge_uri just store for peer %s with expiration %s\n", 1212 "merge_uri just store for peer %s with expiration %s\n",
1216 GNUNET_i2s (huc->pid), 1213 GNUNET_i2s (huc->pid),
1217 GNUNET_STRINGS_absolute_time_to_string (huc_hello_exp_time)); 1214 GNUNET_STRINGS_absolute_time_to_string (huc_hello_exp_time));
1218 store_hello (huc, huc->hello); 1215 store_hello (huc, huc->hello);
1219 } 1216 }
1220 else if (GNUNET_NO == huc->success && 0 == GNUNET_memcmp (huc->pid, 1217 else if (GNUNET_NO == huc->success && 0 == GNUNET_memcmp (huc->pid,
1221 &record->peer)) 1218 &record->peer))
1222 { 1219 {
1223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1220 LOG (GNUNET_ERROR_TYPE_DEBUG,
1224 "merge_uri record for peer %s\n", 1221 "merge_uri record for peer %s\n",
1225 GNUNET_i2s (&record->peer)); 1222 GNUNET_i2s (&record->peer));
1226 hello = record->value; 1223 hello = record->value;
1227 if ((0 == record->value_size)) 1224 if ((0 == record->value_size))
1228 { 1225 {
diff --git a/src/service/peerstore/peerstore_common.c b/src/service/peerstore/peerstore_common.c
index e3bb77d86..5d4d06c0c 100644
--- a/src/service/peerstore/peerstore_common.c
+++ b/src/service/peerstore/peerstore_common.c
@@ -59,21 +59,9 @@ PEERSTORE_hash_key (const char *sub_system,
59} 59}
60 60
61 61
62/**
63 * Creates a MQ envelope for a single record
64 *
65 * @param sub_system sub system string
66 * @param peer Peer identity (can be NULL)
67 * @param key record key string (can be NULL)
68 * @param value record value BLOB (can be NULL)
69 * @param value_size record value size in bytes (set to 0 if value is NULL)
70 * @param expiry time after which the record expires
71 * @param options options specific to the storage operation
72 * @param msg_type message type to be set in header
73 * @return pointer to record message struct
74 */
75struct GNUNET_MQ_Envelope * 62struct GNUNET_MQ_Envelope *
76PEERSTORE_create_record_mq_envelope (const char *sub_system, 63PEERSTORE_create_record_mq_envelope (uint32_t rid,
64 const char *sub_system,
77 const struct GNUNET_PeerIdentity *peer, 65 const struct GNUNET_PeerIdentity *peer,
78 const char *key, 66 const char *key,
79 const void *value, 67 const void *value,
@@ -106,6 +94,7 @@ PEERSTORE_create_record_mq_envelope (const char *sub_system,
106 srm->peer_set = htons (GNUNET_YES); 94 srm->peer_set = htons (GNUNET_YES);
107 srm->peer = *peer; 95 srm->peer = *peer;
108 } 96 }
97 srm->rid = rid;
109 srm->sub_system_size = htons (ss_size); 98 srm->sub_system_size = htons (ss_size);
110 srm->value_size = htons (value_size); 99 srm->value_size = htons (value_size);
111 srm->options = htonl (options); 100 srm->options = htonl (options);
diff --git a/src/service/peerstore/peerstore_common.h b/src/service/peerstore/peerstore_common.h
index f5352f5a5..56f1f8b8b 100644
--- a/src/service/peerstore/peerstore_common.h
+++ b/src/service/peerstore/peerstore_common.h
@@ -40,6 +40,7 @@ PEERSTORE_hash_key (const char *sub_system,
40/** 40/**
41 * Creates a MQ envelope for a single record 41 * Creates a MQ envelope for a single record
42 * 42 *
43 * @param rid request ID
43 * @param sub_system sub system string 44 * @param sub_system sub system string
44 * @param peer Peer identity (can be NULL) 45 * @param peer Peer identity (can be NULL)
45 * @param key record key string (can be NULL) 46 * @param key record key string (can be NULL)
@@ -51,7 +52,8 @@ PEERSTORE_hash_key (const char *sub_system,
51 * @return pointer to record message struct 52 * @return pointer to record message struct
52 */ 53 */
53struct GNUNET_MQ_Envelope * 54struct GNUNET_MQ_Envelope *
54PEERSTORE_create_record_mq_envelope (const char *sub_system, 55PEERSTORE_create_record_mq_envelope (uint32_t rid,
56 const char *sub_system,
55 const struct GNUNET_PeerIdentity *peer, 57 const struct GNUNET_PeerIdentity *peer,
56 const char *key, 58 const char *key,
57 const void *value, 59 const void *value,
diff --git a/src/service/peerstore/perf_peerstore_store.c b/src/service/peerstore/perf_peerstore_store.c
index e59af61e5..e328be93e 100644
--- a/src/service/peerstore/perf_peerstore_store.c
+++ b/src/service/peerstore/perf_peerstore_store.c
@@ -32,16 +32,20 @@ static int ok = 1;
32 32
33static struct GNUNET_PEERSTORE_Handle *h; 33static struct GNUNET_PEERSTORE_Handle *h;
34 34
35static struct GNUNET_PEERSTORE_WatchContext *wc;
36
35static char *ss = "test_peerstore_stress"; 37static char *ss = "test_peerstore_stress";
36static struct GNUNET_PeerIdentity p; 38static struct GNUNET_PeerIdentity p;
37static char *k = "test_peerstore_stress_key"; 39static char *k = "test_peerstore_stress_key";
38static char *v = "test_peerstore_stress_val"; 40static char *v = "test_peerstore_stress_val";
39 41
40static int count = 0; 42static int count = 0;
43static int count_fin = 0;
41 44
42static void 45static void
43disconnect () 46disconnect (void *cls)
44{ 47{
48 GNUNET_PEERSTORE_watch_cancel (wc);
45 if (NULL != h) 49 if (NULL != h)
46 GNUNET_PEERSTORE_disconnect (h); 50 GNUNET_PEERSTORE_disconnect (h);
47 GNUNET_SCHEDULER_shutdown (); 51 GNUNET_SCHEDULER_shutdown ();
@@ -49,14 +53,27 @@ disconnect ()
49 53
50 54
51static void 55static void
56store_cont (void *cls, int ret)
57{
58 count_fin++;
59 if (count_fin == count)
60 {
61 ok = 0;
62 GNUNET_SCHEDULER_add_now (&disconnect, NULL);
63 }
64}
65
66
67static void
52store () 68store ()
53{ 69{
70 count++;
54 GNUNET_PEERSTORE_store (h, ss, &p, k, v, strlen (v) + 1, 71 GNUNET_PEERSTORE_store (h, ss, &p, k, v, strlen (v) + 1,
55 GNUNET_TIME_UNIT_FOREVER_ABS, 72 GNUNET_TIME_UNIT_FOREVER_ABS,
56 (count == 73 (count ==
57 0) ? GNUNET_PEERSTORE_STOREOPTION_REPLACE : 74 0) ? GNUNET_PEERSTORE_STOREOPTION_REPLACE :
58 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, NULL, NULL); 75 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, store_cont,
59 count++; 76 NULL);
60} 77}
61 78
62 79
@@ -65,12 +82,7 @@ watch_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record,
65 const char *emsg) 82 const char *emsg)
66{ 83{
67 GNUNET_assert (NULL == emsg); 84 GNUNET_assert (NULL == emsg);
68 if (STORES == count) 85 if (STORES > count)
69 {
70 ok = 0;
71 disconnect ();
72 }
73 else
74 store (); 86 store ();
75} 87}
76 88
@@ -82,7 +94,7 @@ run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
82 memset (&p, 5, sizeof(p)); 94 memset (&p, 5, sizeof(p));
83 h = GNUNET_PEERSTORE_connect (cfg); 95 h = GNUNET_PEERSTORE_connect (cfg);
84 GNUNET_assert (NULL != h); 96 GNUNET_assert (NULL != h);
85 GNUNET_PEERSTORE_watch (h, ss, &p, k, &watch_cb, NULL); 97 wc = GNUNET_PEERSTORE_watch (h, ss, &p, k, &watch_cb, NULL);
86 store (); 98 store ();
87} 99}
88 100
diff --git a/src/service/peerstore/test_peerstore_api_iterate.c b/src/service/peerstore/test_peerstore_api_iterate.c
index 59367a110..0fa58f3fd 100644
--- a/src/service/peerstore/test_peerstore_api_iterate.c
+++ b/src/service/peerstore/test_peerstore_api_iterate.c
@@ -21,6 +21,7 @@
21 * @file peerstore/test_peerstore_api_iterate.c 21 * @file peerstore/test_peerstore_api_iterate.c
22 * @brief testcase for peerstore iteration operation 22 * @brief testcase for peerstore iteration operation
23 */ 23 */
24#include "gnunet_common.h"
24#include "platform.h" 25#include "platform.h"
25#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
26#include "gnunet_testing_lib.h" 27#include "gnunet_testing_lib.h"
@@ -40,6 +41,13 @@ static char *k3 = "test_peerstore_api_iterate_key3";
40static char *val = "test_peerstore_api_iterate_val"; 41static char *val = "test_peerstore_api_iterate_val";
41static int count = 0; 42static int count = 0;
42 43
44static void
45finish (void *cls)
46{
47 GNUNET_PEERSTORE_disconnect (h);
48 GNUNET_SCHEDULER_shutdown ();
49}
50
43 51
44static void 52static void
45iter3_cb (void *cls, 53iter3_cb (void *cls,
@@ -58,8 +66,7 @@ iter3_cb (void *cls,
58 } 66 }
59 GNUNET_assert (count == 3); 67 GNUNET_assert (count == 3);
60 ok = 0; 68 ok = 0;
61 GNUNET_PEERSTORE_disconnect (h); 69 GNUNET_SCHEDULER_add_now (&finish, NULL);
62 GNUNET_SCHEDULER_shutdown ();
63} 70}
64 71
65 72
@@ -104,6 +111,7 @@ iter1_cb (void *cls,
104 count++; 111 count++;
105 return; 112 return;
106 } 113 }
114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u is count\n", count);
107 GNUNET_assert (count == 1); 115 GNUNET_assert (count == 1);
108 count = 0; 116 count = 0;
109 ic = GNUNET_PEERSTORE_iterate (h, 117 ic = GNUNET_PEERSTORE_iterate (h,
@@ -116,6 +124,50 @@ iter1_cb (void *cls,
116 124
117 125
118static void 126static void
127store_cont (void *cls, int success)
128{
129 GNUNET_assert (GNUNET_OK == success);
130 if (0 == count)
131 {
132 GNUNET_PEERSTORE_store (h,
133 ss,
134 &p1,
135 k2,
136 val,
137 strlen (val) + 1,
138 GNUNET_TIME_UNIT_FOREVER_ABS,
139 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
140 &store_cont,
141 NULL);
142 }
143 else if (1 == count)
144 {
145 GNUNET_PEERSTORE_store (h,
146 ss,
147 &p2,
148 k3,
149 val,
150 strlen (val) + 1,
151 GNUNET_TIME_UNIT_FOREVER_ABS,
152 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
153 &store_cont,
154 NULL);
155 }
156 else
157 {
158 count = 0;
159 ic = GNUNET_PEERSTORE_iterate (h,
160 ss,
161 &p1,
162 k1,
163 &iter1_cb, NULL);
164 return;
165 }
166 count++;
167}
168
169
170static void
119run (void *cls, 171run (void *cls,
120 const struct GNUNET_CONFIGURATION_Handle *cfg, 172 const struct GNUNET_CONFIGURATION_Handle *cfg,
121 struct GNUNET_TESTING_Peer *peer) 173 struct GNUNET_TESTING_Peer *peer)
@@ -124,6 +176,7 @@ run (void *cls,
124 GNUNET_assert (NULL != h); 176 GNUNET_assert (NULL != h);
125 memset (&p1, 1, sizeof(p1)); 177 memset (&p1, 1, sizeof(p1));
126 memset (&p2, 2, sizeof(p2)); 178 memset (&p2, 2, sizeof(p2));
179 count = 0;
127 GNUNET_PEERSTORE_store (h, 180 GNUNET_PEERSTORE_store (h,
128 ss, 181 ss,
129 &p1, 182 &p1,
@@ -132,33 +185,8 @@ run (void *cls,
132 strlen (val) + 1, 185 strlen (val) + 1,
133 GNUNET_TIME_UNIT_FOREVER_ABS, 186 GNUNET_TIME_UNIT_FOREVER_ABS,
134 GNUNET_PEERSTORE_STOREOPTION_REPLACE, 187 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
135 NULL, 188 &store_cont,
136 NULL);
137 GNUNET_PEERSTORE_store (h,
138 ss,
139 &p1,
140 k2,
141 val,
142 strlen (val) + 1,
143 GNUNET_TIME_UNIT_FOREVER_ABS,
144 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
145 NULL,
146 NULL); 189 NULL);
147 GNUNET_PEERSTORE_store (h,
148 ss,
149 &p2,
150 k3,
151 val,
152 strlen (val) + 1,
153 GNUNET_TIME_UNIT_FOREVER_ABS,
154 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
155 NULL,
156 NULL);
157 ic = GNUNET_PEERSTORE_iterate (h,
158 ss,
159 &p1,
160 k1,
161 &iter1_cb, NULL);
162} 190}
163 191
164 192
diff --git a/src/service/peerstore/test_peerstore_api_store.c b/src/service/peerstore/test_peerstore_api_store.c
index 77e8a17c1..8cf0e60a7 100644
--- a/src/service/peerstore/test_peerstore_api_store.c
+++ b/src/service/peerstore/test_peerstore_api_store.c
@@ -21,6 +21,7 @@
21 * @file peerstore/test_peerstore_api_store.c 21 * @file peerstore/test_peerstore_api_store.c
22 * @brief testcase for peerstore store operation 22 * @brief testcase for peerstore store operation
23 */ 23 */
24#include "gnunet_common.h"
24#include "platform.h" 25#include "platform.h"
25#include "gnunet_peerstore_service.h" 26#include "gnunet_peerstore_service.h"
26#include "gnunet_testing_lib.h" 27#include "gnunet_testing_lib.h"
@@ -41,6 +42,13 @@ static int count = 0;
41 42
42 43
43static void 44static void
45finish (void *cls)
46{
47 GNUNET_PEERSTORE_disconnect (h);
48 GNUNET_SCHEDULER_shutdown ();
49}
50
51static void
44test3_cont2 (void *cls, 52test3_cont2 (void *cls,
45 const struct GNUNET_PEERSTORE_Record *record, 53 const struct GNUNET_PEERSTORE_Record *record,
46 const char *emsg) 54 const char *emsg)
@@ -57,8 +65,7 @@ test3_cont2 (void *cls,
57 } 65 }
58 GNUNET_assert (count == 1); 66 GNUNET_assert (count == 1);
59 ok = 0; 67 ok = 0;
60 GNUNET_PEERSTORE_disconnect (h, GNUNET_YES); 68 GNUNET_SCHEDULER_add_now (&finish, NULL);
61 GNUNET_SCHEDULER_shutdown ();
62} 69}
63 70
64 71
@@ -158,7 +165,10 @@ test1_cont2 (void *cls,
158 const char *emsg) 165 const char *emsg)
159{ 166{
160 if (NULL != emsg) 167 if (NULL != emsg)
168 {
169 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error received: %s\n", emsg);
161 return; 170 return;
171 }
162 if (NULL != record) 172 if (NULL != record)
163 { 173 {
164 GNUNET_assert ((strlen (val1) + 1) == record->value_size); 174 GNUNET_assert ((strlen (val1) + 1) == record->value_size);
@@ -175,6 +185,7 @@ test1_cont2 (void *cls,
175static void 185static void
176test1_cont (void *cls, int success) 186test1_cont (void *cls, int success)
177{ 187{
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store done, ret=%d...\n", success);
178 if (GNUNET_YES != success) 189 if (GNUNET_YES != success)
179 return; 190 return;
180 count = 0; 191 count = 0;
@@ -193,6 +204,7 @@ test1_cont (void *cls, int success)
193static void 204static void
194test1 () 205test1 ()
195{ 206{
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test1 start\n");
196 GNUNET_PEERSTORE_store (h, 208 GNUNET_PEERSTORE_store (h,
197 subsystem, 209 subsystem,
198 &pid, 210 &pid,
diff --git a/src/service/peerstore/test_peerstore_api_sync.c b/src/service/peerstore/test_peerstore_api_sync.c
deleted file mode 100644
index 4e16afae8..000000000
--- a/src/service/peerstore/test_peerstore_api_sync.c
+++ /dev/null
@@ -1,252 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2015 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 peerstore/test_peerstore_api_sync.c
22 * @brief testcase for peerstore sync-on-disconnect feature. Stores
23 * a value just before disconnecting, and then checks that
24 * this value is actually stored.
25 * @author Omar Tarabai
26 * @author Christian Grothoff (minor fix, comments)
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_peerstore_service.h"
32
33/**
34 * Overall result, 0 for success.
35 */
36static int ok = 404;
37
38/**
39 * Configuration we use.
40 */
41static const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43/**
44 * handle to talk to the peerstore.
45 */
46static struct GNUNET_PEERSTORE_Handle *h;
47
48/**
49 * Subsystem we store the value for.
50 */
51static const char *subsystem = "test_peerstore_api_sync";
52
53/**
54 * Fake PID under which we store the value.
55 */
56static struct GNUNET_PeerIdentity pid;
57
58/**
59 * Test key we're storing the test value under.
60 */
61static const char *key = "test_peerstore_api_store_key";
62
63/**
64 * Test value we are storing.
65 */
66static const char *val = "test_peerstore_api_store_val";
67
68
69/**
70 * Timeout
71 */
72#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
73
74/**
75 * Timeout task
76 */
77static struct GNUNET_SCHEDULER_Task *to;
78
79/**
80 * Iterate handle
81 */
82static struct GNUNET_PEERSTORE_IterateContext *it;
83
84static void
85test_cont (void *cls);
86
87/**
88 * Function that should be called with the result of the
89 * lookup, and finally once with NULL to signal the end
90 * of the iteration.
91 *
92 * Upon the first call, we set "ok" to success. On the
93 * second call (end of iteration) we terminate the test.
94 *
95 * @param cls NULL
96 * @param record the information stored in the peerstore
97 * @param emsg any error message
98 * @return #GNUNET_YES (all good, continue)
99 */
100static void
101iterate_cb (void *cls,
102 const struct GNUNET_PEERSTORE_Record *record,
103 const char *emsg)
104{
105 const char *rec_val;
106
107 GNUNET_break (NULL == emsg);
108 if (NULL == record)
109 {
110 it = NULL;
111 if (0 == ok)
112 {
113 GNUNET_PEERSTORE_disconnect (h);
114 if (NULL != to)
115 {
116 GNUNET_SCHEDULER_cancel (to);
117 to = NULL;
118 }
119 GNUNET_SCHEDULER_shutdown ();
120 return;
121 }
122 /**
123 * Try again
124 */
125 GNUNET_SCHEDULER_add_now (&test_cont,
126 NULL);
127 return;
128 }
129 rec_val = record->value;
130 GNUNET_break (0 == strcmp (rec_val, val));
131 ok = 0;
132}
133
134
135static void
136timeout_task (void *cls)
137{
138 to = NULL;
139 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
140 "Timeout reached\n");
141 if (NULL != it)
142 GNUNET_PEERSTORE_iterate_cancel (it);
143 it = NULL;
144 GNUNET_PEERSTORE_disconnect (h,
145 GNUNET_NO);
146 GNUNET_SCHEDULER_shutdown ();
147 return;
148}
149
150
151/**
152 * Run the 2nd stage of the test where we fetch the
153 * data that should have been stored.
154 *
155 * @param cls NULL
156 */
157static void
158test_cont (void *cls)
159{
160 it = GNUNET_PEERSTORE_iterate (h,
161 subsystem,
162 &pid, key,
163 &iterate_cb,
164 NULL);
165}
166
167
168static void
169disc_cont (void *cls)
170{
171 GNUNET_PEERSTORE_disconnect (h, GNUNET_YES);
172 h = GNUNET_PEERSTORE_connect (cfg);
173 GNUNET_SCHEDULER_add_now (&test_cont,
174 NULL);
175}
176
177
178static void
179store_cont (void *cls, int success)
180{
181 ok = success;
182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
183 "Success: %s\n",
184 (GNUNET_SYSERR == ok) ? "no" : "yes");
185 /* We need to wait a little bit to give the disconnect
186 a chance to actually finish the operation; otherwise,
187 the test may fail non-deterministically if the new
188 connection is faster than the cleanup routine of the
189 old one. */
190 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
191 &disc_cont,
192 NULL);
193}
194
195
196/**
197 * Actually run the test.
198 */
199static void
200test1 ()
201{
202 h = GNUNET_PEERSTORE_connect (cfg);
203 GNUNET_PEERSTORE_store (h,
204 subsystem,
205 &pid,
206 key,
207 val, strlen (val) + 1,
208 GNUNET_TIME_UNIT_FOREVER_ABS,
209 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
210 &store_cont, NULL);
211}
212
213
214/**
215 * Initialize globals and launch the test.
216 *
217 * @param cls NULL
218 * @param c configuration to use
219 * @param peer handle to our peer (unused)
220 */
221static void
222run (void *cls,
223 const struct GNUNET_CONFIGURATION_Handle *c,
224 struct GNUNET_TESTING_Peer *peer)
225{
226 cfg = c;
227 memset (&pid, 1, sizeof(pid));
228 to = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
229 &timeout_task,
230 NULL);
231 GNUNET_SCHEDULER_add_now (&test1, NULL);
232}
233
234
235int
236main (int argc, char *argv[])
237{
238 if (0 !=
239 GNUNET_TESTING_service_run ("test-gnunet-peerstore-sync",
240 "peerstore",
241 "peerstore.conf",
242 &run, NULL))
243 return 1;
244 if (0 != ok)
245 fprintf (stderr,
246 "Test failed: %d\n",
247 ok);
248 return ok;
249}
250
251
252/* end of test_peerstore_api_sync.c */
diff --git a/src/service/peerstore/test_peerstore_api_watch.c b/src/service/peerstore/test_peerstore_api_watch.c
index 126b321df..63b0e896b 100644
--- a/src/service/peerstore/test_peerstore_api_watch.c
+++ b/src/service/peerstore/test_peerstore_api_watch.c
@@ -21,6 +21,8 @@
21 * @file peerstore/test_peerstore_api_watch.c 21 * @file peerstore/test_peerstore_api_watch.c
22 * @brief testcase for peerstore watch functionality 22 * @brief testcase for peerstore watch functionality
23 */ 23 */
24#include "gnunet_common.h"
25#include "gnunet_time_lib.h"
24#include "platform.h" 26#include "platform.h"
25#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
26#include "gnunet_testing_lib.h" 28#include "gnunet_testing_lib.h"
@@ -31,12 +33,42 @@ static int ok = 1;
31 33
32static struct GNUNET_PEERSTORE_Handle *h; 34static struct GNUNET_PEERSTORE_Handle *h;
33 35
36static struct GNUNET_PEERSTORE_WatchContext *wc;
37
34static char *ss = "test_peerstore_api_watch"; 38static char *ss = "test_peerstore_api_watch";
35 39
36static char *k = "test_peerstore_api_watch_key"; 40static char *k = "test_peerstore_api_watch_key";
37 41
38static char *val = "test_peerstore_api_watch_val"; 42static char *val = "test_peerstore_api_watch_val";
39 43
44static struct GNUNET_PeerIdentity p;
45
46static void
47finish (void *cls)
48{
49 GNUNET_PEERSTORE_watch_cancel (wc);
50 GNUNET_PEERSTORE_disconnect (h);
51 GNUNET_SCHEDULER_shutdown ();
52}
53
54
55static void
56cont (void *cls)
57{
58 GNUNET_PEERSTORE_store (h,
59 ss,
60 &p,
61 k,
62 val,
63 strlen (val) + 1,
64 GNUNET_TIME_UNIT_FOREVER_ABS,
65 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
66 NULL,
67 NULL);
68}
69
70
71static int initial_iteration = GNUNET_YES;
40 72
41static void 73static void
42watch_cb (void *cls, 74watch_cb (void *cls,
@@ -44,12 +76,28 @@ watch_cb (void *cls,
44 const char *emsg) 76 const char *emsg)
45{ 77{
46 GNUNET_assert (NULL == emsg); 78 GNUNET_assert (NULL == emsg);
79 if (GNUNET_YES == initial_iteration)
80 {
81 if (NULL != record)
82 {
83 GNUNET_break (0);
84 return; // Ignore this record, FIXME: Test unclean
85 }
86 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &cont, NULL);
87 initial_iteration = GNUNET_NO;
88 return;
89 }
90 if (NULL == record)
91 {
92 GNUNET_break (0);
93 return;
94 }
95 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received record: %s\n",
96 (char*) record->value);
47 GNUNET_assert (0 == strcmp (val, 97 GNUNET_assert (0 == strcmp (val,
48 (char *) record->value)); 98 (char *) record->value));
49 ok = 0; 99 ok = 0;
50 GNUNET_PEERSTORE_disconnect (h, 100 GNUNET_SCHEDULER_add_now (&finish, NULL);
51 GNUNET_NO);
52 GNUNET_SCHEDULER_shutdown ();
53} 101}
54 102
55 103
@@ -58,29 +106,18 @@ run (void *cls,
58 const struct GNUNET_CONFIGURATION_Handle *cfg, 106 const struct GNUNET_CONFIGURATION_Handle *cfg,
59 struct GNUNET_TESTING_Peer *peer) 107 struct GNUNET_TESTING_Peer *peer)
60{ 108{
61 struct GNUNET_PeerIdentity p;
62 109
63 h = GNUNET_PEERSTORE_connect (cfg); 110 h = GNUNET_PEERSTORE_connect (cfg);
64 GNUNET_assert (NULL != h); 111 GNUNET_assert (NULL != h);
65 memset (&p, 112 memset (&p,
66 4, 113 4,
67 sizeof(p)); 114 sizeof(p));
68 GNUNET_PEERSTORE_watch (h, 115 wc = GNUNET_PEERSTORE_watch (h,
69 ss, 116 ss,
70 &p, 117 &p,
71 k, 118 k,
72 &watch_cb, 119 &watch_cb,
73 NULL); 120 NULL);
74 GNUNET_PEERSTORE_store (h,
75 ss,
76 &p,
77 k,
78 val,
79 strlen (val) + 1,
80 GNUNET_TIME_UNIT_FOREVER_ABS,
81 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
82 NULL,
83 NULL);
84} 121}
85 122
86 123