aboutsummaryrefslogtreecommitdiff
path: root/src/peerstore/gnunet-service-peerstore.c
diff options
context:
space:
mode:
authorOmar Tarabai <tarabai@devegypt.com>2014-07-08 18:03:39 +0000
committerOmar Tarabai <tarabai@devegypt.com>2014-07-08 18:03:39 +0000
commite2c74d15bcb68c74540ed299e3d3154aef29f407 (patch)
treee2c165d132e38d9c5e5fb6f72c63036c708d8f42 /src/peerstore/gnunet-service-peerstore.c
parent3ec64bae9f3da343c812a1ace1c5457fbc47947b (diff)
downloadgnunet-e2c74d15bcb68c74540ed299e3d3154aef29f407.tar.gz
gnunet-e2c74d15bcb68c74540ed299e3d3154aef29f407.zip
peerstore doesn't shutdown when clients are connected
Diffstat (limited to 'src/peerstore/gnunet-service-peerstore.c')
-rw-r--r--src/peerstore/gnunet-service-peerstore.c171
1 files changed, 136 insertions, 35 deletions
diff --git a/src/peerstore/gnunet-service-peerstore.c b/src/peerstore/gnunet-service-peerstore.c
index 3635b1dfe..b7128dda5 100644
--- a/src/peerstore/gnunet-service-peerstore.c
+++ b/src/peerstore/gnunet-service-peerstore.c
@@ -30,6 +30,27 @@
30#include "peerstore_common.h" 30#include "peerstore_common.h"
31 31
32/** 32/**
33 * Connected client entry
34 */
35struct ClientEntry
36{
37 /**
38 * DLL.
39 */
40 struct ClientEntry *next;
41
42 /**
43 * DLL.
44 */
45 struct ClientEntry *prev;
46
47 /**
48 * Corresponding server handle.
49 */
50 struct GNUNET_SERVER_Client *client;
51};
52
53/**
33 * Interval for expired records cleanup (in seconds) 54 * Interval for expired records cleanup (in seconds)
34 */ 55 */
35#define EXPIRED_RECORDS_CLEANUP_INTERVAL 300 /* 5mins */ 56#define EXPIRED_RECORDS_CLEANUP_INTERVAL 300 /* 5mins */
@@ -60,14 +81,24 @@ static struct GNUNET_CONTAINER_MultiHashMap *watchers;
60static struct GNUNET_SERVER_NotificationContext *nc; 81static struct GNUNET_SERVER_NotificationContext *nc;
61 82
62/** 83/**
63 * Task run during shutdown. 84 * Head of linked list of connected clients
64 *
65 * @param cls unused
66 * @param tc unused
67 */ 85 */
68static void 86static struct ClientEntry *client_head;
69shutdown_task (void *cls, 87
70 const struct GNUNET_SCHEDULER_TaskContext *tc) 88/**
89 * Tail of linked list of connected clients
90 */
91static struct ClientEntry *client_tail;
92
93/**
94 * Are we in the process of shutting down the service? #GNUNET_YES / #GNUNET_NO
95 */
96int in_shutdown;
97
98/**
99 * Perform the actual shutdown operations
100 */
101void do_shutdown ()
71{ 102{
72 if(NULL != db_lib_name) 103 if(NULL != db_lib_name)
73 { 104 {
@@ -89,6 +120,21 @@ shutdown_task (void *cls,
89} 120}
90 121
91/** 122/**
123 * Task run during shutdown.
124 *
125 * @param cls unused
126 * @param tc unused
127 */
128static void
129shutdown_task (void *cls,
130 const struct GNUNET_SCHEDULER_TaskContext *tc)
131{
132 in_shutdown = GNUNET_YES;
133 if (NULL == client_head) /* Only when no connected clients. */
134 do_shutdown ();
135}
136
137/**
92 * Deletes any expired records from storage 138 * Deletes any expired records from storage
93 */ 139 */
94static void 140static void
@@ -116,7 +162,7 @@ cleanup_expired_records(void *cls,
116 * @param value the watcher client, a 'struct GNUNET_SERVER_Client *' 162 * @param value the watcher client, a 'struct GNUNET_SERVER_Client *'
117 * @return #GNUNET_OK to continue iterating 163 * @return #GNUNET_OK to continue iterating
118 */ 164 */
119int client_disconnect_it(void *cls, 165static int client_disconnect_it(void *cls,
120 const struct GNUNET_HashCode *key, 166 const struct GNUNET_HashCode *key,
121 void *value) 167 void *value)
122{ 168{
@@ -136,10 +182,25 @@ handle_client_disconnect (void *cls,
136 struct GNUNET_SERVER_Client 182 struct GNUNET_SERVER_Client
137 * client) 183 * client)
138{ 184{
139 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A client was disconnected, cleaning up.\n"); 185 struct ClientEntry *ce;
186
187 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A client disconnected, cleaning up.\n");
140 if(NULL != watchers) 188 if(NULL != watchers)
141 GNUNET_CONTAINER_multihashmap_iterate(watchers, 189 GNUNET_CONTAINER_multihashmap_iterate(watchers,
142 &client_disconnect_it, client); 190 &client_disconnect_it, client);
191 ce = client_head;
192 while (ce != NULL)
193 {
194 if (ce->client == client)
195 {
196 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce);
197 GNUNET_free (ce);
198 break;
199 }
200 ce = ce->next;
201 }
202 if (NULL == client_head && in_shutdown)
203 do_shutdown ();
143} 204}
144 205
145/** 206/**
@@ -151,7 +212,7 @@ handle_client_disconnect (void *cls,
151 * @param value stored value 212 * @param value stored value
152 * @param size size of stored value 213 * @param size size of stored value
153 */ 214 */
154int record_iterator(void *cls, 215static int record_iterator(void *cls,
155 struct GNUNET_PEERSTORE_Record *record, 216 struct GNUNET_PEERSTORE_Record *record,
156 char *emsg) 217 char *emsg)
157{ 218{
@@ -179,7 +240,7 @@ int record_iterator(void *cls,
179 * @param value the watcher client, a 'struct GNUNET_SERVER_Client *' 240 * @param value the watcher client, a 'struct GNUNET_SERVER_Client *'
180 * @return #GNUNET_YES to continue iterating 241 * @return #GNUNET_YES to continue iterating
181 */ 242 */
182int watch_notifier_it(void *cls, 243static int watch_notifier_it(void *cls,
183 const struct GNUNET_HashCode *key, 244 const struct GNUNET_HashCode *key,
184 void *value) 245 void *value)
185{ 246{
@@ -206,7 +267,7 @@ int watch_notifier_it(void *cls,
206 * 267 *
207 * @param record changed record to update watchers with 268 * @param record changed record to update watchers with
208 */ 269 */
209void watch_notifier (struct GNUNET_PEERSTORE_Record *record) 270static void watch_notifier (struct GNUNET_PEERSTORE_Record *record)
210{ 271{
211 struct GNUNET_HashCode keyhash; 272 struct GNUNET_HashCode keyhash;
212 273
@@ -224,13 +285,13 @@ void watch_notifier (struct GNUNET_PEERSTORE_Record *record)
224 * @param client identification of the client 285 * @param client identification of the client
225 * @param message the actual message 286 * @param message the actual message
226 */ 287 */
227void handle_watch_cancel (void *cls, 288static void handle_watch_cancel (void *cls,
228 struct GNUNET_SERVER_Client *client, 289 struct GNUNET_SERVER_Client *client,
229 const struct GNUNET_MessageHeader *message) 290 const struct GNUNET_MessageHeader *message)
230{ 291{
231 struct StoreKeyHashMessage *hm; 292 struct StoreKeyHashMessage *hm;
232 293
233 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch cancel request from client.\n"); 294 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch cancel request.\n");
234 hm = (struct StoreKeyHashMessage *) message; 295 hm = (struct StoreKeyHashMessage *) message;
235 GNUNET_CONTAINER_multihashmap_remove(watchers, &hm->keyhash, client); 296 GNUNET_CONTAINER_multihashmap_remove(watchers, &hm->keyhash, client);
236 GNUNET_SERVER_receive_done(client, GNUNET_OK); 297 GNUNET_SERVER_receive_done(client, GNUNET_OK);
@@ -243,13 +304,13 @@ void handle_watch_cancel (void *cls,
243 * @param client identification of the client 304 * @param client identification of the client
244 * @param message the actual message 305 * @param message the actual message
245 */ 306 */
246void handle_watch (void *cls, 307static void handle_watch (void *cls,
247 struct GNUNET_SERVER_Client *client, 308 struct GNUNET_SERVER_Client *client,
248 const struct GNUNET_MessageHeader *message) 309 const struct GNUNET_MessageHeader *message)
249{ 310{
250 struct StoreKeyHashMessage *hm; 311 struct StoreKeyHashMessage *hm;
251 312
252 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch request from client.\n"); 313 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch request.\n");
253 hm = (struct StoreKeyHashMessage *) message; 314 hm = (struct StoreKeyHashMessage *) message;
254 GNUNET_SERVER_client_mark_monitor(client); 315 GNUNET_SERVER_client_mark_monitor(client);
255 GNUNET_SERVER_notification_context_add(nc, client); 316 GNUNET_SERVER_notification_context_add(nc, client);
@@ -265,24 +326,25 @@ void handle_watch (void *cls,
265 * @param client identification of the client 326 * @param client identification of the client
266 * @param message the actual message 327 * @param message the actual message
267 */ 328 */
268void handle_iterate (void *cls, 329static void handle_iterate (void *cls,
269 struct GNUNET_SERVER_Client *client, 330 struct GNUNET_SERVER_Client *client,
270 const struct GNUNET_MessageHeader *message) 331 const struct GNUNET_MessageHeader *message)
271{ 332{
272 struct GNUNET_PEERSTORE_Record *record; 333 struct GNUNET_PEERSTORE_Record *record;
273 struct GNUNET_MessageHeader *endmsg; 334 struct GNUNET_MessageHeader *endmsg;
274 335
275 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received an iterate request from client.\n"); 336 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received an iterate request.\n");
276 record = PEERSTORE_parse_record_message(message); 337 record = PEERSTORE_parse_record_message(message);
277 if(NULL == record) 338 if(NULL == record)
278 { 339 {
279 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Malformed iterate request from client\n")); 340 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Malformed iterate request.\n"));
280 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); 341 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
281 return; 342 return;
282 } 343 }
283 if(NULL == record->sub_system) 344 if(NULL == record->sub_system)
284 { 345 {
285 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Sub system not supplied in client iterate request\n")); 346 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
347 _("Sub system not supplied in client iterate request.\n"));
286 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); 348 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
287 return; 349 return;
288 } 350 }
@@ -319,7 +381,7 @@ void handle_iterate (void *cls,
319 * @param client identification of the client 381 * @param client identification of the client
320 * @param message the actual message 382 * @param message the actual message
321 */ 383 */
322void handle_store (void *cls, 384static void handle_store (void *cls,
323 struct GNUNET_SERVER_Client *client, 385 struct GNUNET_SERVER_Client *client,
324 const struct GNUNET_MessageHeader *message) 386 const struct GNUNET_MessageHeader *message)
325{ 387{
@@ -368,6 +430,48 @@ void handle_store (void *cls,
368} 430}
369 431
370/** 432/**
433 * Creates an entry for a new client or returns it if it already exists.
434 *
435 * @param client Client handle
436 * @return Client entry struct
437 */
438static struct ClientEntry *
439make_client_entry (struct GNUNET_SERVER_Client *client)
440{
441 struct ClientEntry *ce;
442
443 ce = client_head;
444 while (NULL != ce)
445 {
446 if (ce->client == client)
447 return ce;
448 ce = ce->next;
449 }
450 if (GNUNET_YES == in_shutdown)
451 {
452 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
453 return NULL;
454 }
455 ce = GNUNET_new (struct ClientEntry);
456 ce->client = client;
457 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ce);
458 return ce;
459}
460
461/**
462 * Callback on a new client connection
463 *
464 * @param cls closure (unused)
465 * @param client identification of the client
466 */
467static void
468handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client)
469{
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New client connection created.\n");
471 make_client_entry (client);
472}
473
474/**
371 * Peerstore service runner. 475 * Peerstore service runner.
372 * 476 *
373 * @param cls closure 477 * @param cls closure
@@ -388,6 +492,7 @@ run (void *cls,
388 }; 492 };
389 char *database; 493 char *database;
390 494
495 in_shutdown = GNUNET_NO;
391 cfg = c; 496 cfg = c;
392 if (GNUNET_OK != 497 if (GNUNET_OK !=
393 GNUNET_CONFIGURATION_get_value_string (cfg, "peerstore", "DATABASE", 498 GNUNET_CONFIGURATION_get_value_string (cfg, "peerstore", "DATABASE",
@@ -406,16 +511,12 @@ run (void *cls,
406 GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); 511 GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
407 return; 512 return;
408 } 513 }
409 else 514 nc = GNUNET_SERVER_notification_context_create (server, 16);
410 { 515 watchers = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO);
411 nc = GNUNET_SERVER_notification_context_create (server, 16); 516 GNUNET_SCHEDULER_add_now(&cleanup_expired_records, NULL);
412 watchers = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO); 517 GNUNET_SERVER_add_handlers (server, handlers);
413 GNUNET_SCHEDULER_add_now(&cleanup_expired_records, NULL); 518 GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL);
414 GNUNET_SERVER_add_handlers (server, handlers); 519 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
415 GNUNET_SERVER_disconnect_notify (server,
416 &handle_client_disconnect,
417 NULL);
418 }
419 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 520 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
420 &shutdown_task, 521 &shutdown_task,
421 NULL); 522 NULL);
@@ -434,10 +535,10 @@ main (int argc, char *const *argv)
434{ 535{
435 return (GNUNET_OK == 536 return (GNUNET_OK ==
436 GNUNET_SERVICE_run (argc, 537 GNUNET_SERVICE_run (argc,
437 argv, 538 argv,
438 "peerstore", 539 "peerstore",
439 GNUNET_SERVICE_OPTION_NONE, 540 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
440 &run, NULL)) ? 0 : 1; 541 &run, NULL)) ? 0 : 1;
441} 542}
442 543
443/* end of gnunet-service-peerstore.c */ 544/* end of gnunet-service-peerstore.c */