aboutsummaryrefslogtreecommitdiff
path: root/src/lockmanager/gnunet-service-lockmanager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockmanager/gnunet-service-lockmanager.c')
-rw-r--r--src/lockmanager/gnunet-service-lockmanager.c847
1 files changed, 0 insertions, 847 deletions
diff --git a/src/lockmanager/gnunet-service-lockmanager.c b/src/lockmanager/gnunet-service-lockmanager.c
deleted file mode 100644
index fde32ed60..000000000
--- a/src/lockmanager/gnunet-service-lockmanager.c
+++ /dev/null
@@ -1,847 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file lockmanager/gnunet-service-lockmanager.c
23 * @brief implementation of the LOCKMANAGER service
24 * @author Sree Harsha Totakura
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_protocols.h"
30
31#include "lockmanager.h"
32
33
34#define LOG(kind,...) \
35 GNUNET_log (kind, __VA_ARGS__)
36
37#define TIME_REL_MINS(min) \
38 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, min)
39
40#define TIMEOUT TIME_REL_MINS(3)
41
42
43/**
44 * Doubly linked list of clients having connections to us
45 */
46struct ClientList;
47
48
49/**
50 * Doubly linked list of clients waiting for a lock
51 */
52struct WaitList
53{
54 /**
55 * The next client structure
56 */
57 struct WaitList *next;
58
59 /**
60 * The prev client structure
61 */
62 struct WaitList *prev;
63
64 /**
65 * Pointer to the client
66 */
67 struct ClientList *cl_entry;
68};
69
70
71/**
72 * Structure representing a Lock
73 */
74struct Lock
75{
76 /**
77 * List head of clients waiting for this lock
78 */
79 struct WaitList *wl_head;
80
81 /**
82 * List tail of clients waiting for this lock
83 */
84 struct WaitList *wl_tail;
85
86 /**
87 * The client which is currently holding this lock
88 */
89 struct ClientList *cl_entry;
90
91 /**
92 * The name of the locking domain this lock belongs to
93 */
94 char *domain_name;
95
96 /**
97 * The number of this lock
98 */
99 uint32_t lock_num;
100};
101
102
103/**
104 * A Lock element for a doubly linked list
105 */
106struct LockList
107{
108 /**
109 * The next element pointer
110 */
111 struct LockList *next;
112
113 /**
114 * Pointer to the previous element
115 */
116 struct LockList *prev;
117
118 /**
119 * Pointer to the Lock
120 */
121 struct Lock *lock;
122};
123
124
125/**
126 * Doubly linked list of clients having connections to us
127 */
128struct ClientList
129{
130
131 /**
132 * The next client structure
133 */
134 struct ClientList *next;
135
136 /**
137 * The previous client structure
138 */
139 struct ClientList *prev;
140
141 /**
142 * Head of the doubly linked list of the currently held locks by this client
143 */
144 struct LockList *ll_head;
145
146 /**
147 * Tail of the doubly linked list of the currently held locks by this client
148 */
149 struct LockList *ll_tail;
150
151 /**
152 * Pointer to the client
153 */
154 struct GNUNET_SERVER_Client *client;
155};
156
157
158/**
159 * Structure for matching a lock
160 */
161struct LockMatch
162{
163 /**
164 * The matched LockingRequest entry; Should be NULL if no entry is found
165 */
166 struct Lock *matched_entry;
167
168 /**
169 * The locking domain name of the lock
170 */
171 const char *domain_name;
172
173 /**
174 * The lock number
175 */
176 uint32_t lock_num;
177};
178
179
180/**
181 * Map of lock-keys to the 'struct LockList' entry for the key.
182 */
183static struct GNUNET_CONTAINER_MultiHashMap *lock_map;
184
185/**
186 * Head of the doubly linked list of clients currently connected
187 */
188static struct ClientList *cl_head;
189
190/**
191 * Tail of the doubly linked list of clients currently connected
192 */
193static struct ClientList *cl_tail;
194
195
196/**
197 * Get the key for the given lock in the 'lock_map'.
198 *
199 * @param domain_name
200 * @param lock_number
201 * @param key set to the key
202 */
203static void
204get_key (const char *domain_name, uint32_t lock_number,
205 struct GNUNET_HashCode *key)
206{
207 uint32_t *last_32;
208
209 GNUNET_CRYPTO_hash (domain_name, strlen (domain_name), key);
210 last_32 = (uint32_t *) key;
211 *last_32 ^= lock_number;
212}
213
214
215/**
216 * Hashmap iterator for matching a lock
217 *
218 * @param cls the LockMatch structure
219 * @param key current key code
220 * @param value value in the hash map (struct Lock)
221 * @return GNUNET_YES if we should continue to
222 * iterate,
223 * GNUNET_NO if not.
224 */
225static int
226match_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
227{
228 struct LockMatch *match = cls;
229 struct Lock *lock = value;
230
231 if ((match->lock_num == lock->lock_num) &&
232 (0 == strcmp (match->domain_name, lock->domain_name)))
233 {
234 match->matched_entry = lock;
235 return GNUNET_NO;
236 }
237 return GNUNET_YES;
238}
239
240
241/**
242 * Function to search for a lock in the global lock hashmap
243 *
244 * @param domain_name the name of the locking domain
245 * @param lock_num the number of the lock
246 * @return the lock if found; NULL if not
247 */
248static struct Lock *
249find_lock (const char *domain_name, const uint32_t lock_num)
250{
251 struct LockMatch match;
252 struct GNUNET_HashCode key;
253
254 match.lock_num = lock_num;
255 match.domain_name = domain_name;
256 match.matched_entry = NULL;
257 get_key (domain_name, lock_num, &key);
258 GNUNET_CONTAINER_multihashmap_get_multiple (lock_map, &key, &match_iterator,
259 &match);
260 return match.matched_entry;
261}
262
263
264/**
265 * Adds a lock to the global lock hashmap
266 *
267 * @param domain_name the name of the lock's locking domain
268 * @param lock_num the lock number
269 * @return pointer to the lock structure which is added to lock map
270 */
271static struct Lock *
272add_lock (const char *domain_name, uint32_t lock_num)
273{
274 struct Lock *lock;
275 struct GNUNET_HashCode key;
276 size_t domain_name_len;
277
278 lock = GNUNET_malloc (sizeof (struct Lock));
279 domain_name_len = strlen (domain_name) + 1;
280 lock->domain_name = GNUNET_malloc (domain_name_len);
281 strncpy (lock->domain_name, domain_name, domain_name_len);
282 lock->lock_num = lock_num;
283 get_key (domain_name, lock_num, &key);
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Adding a lock with num: %d and domain: %s to the lock map\n",
286 lock->lock_num, lock->domain_name);
287 GNUNET_CONTAINER_multihashmap_put (lock_map, &key, lock,
288 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
289 return lock;
290}
291
292
293/**
294 * Removes a lock from the lock map. The WaitList of the lock should be empty
295 *
296 * @param lock the lock to remove
297 */
298static void
299remove_lock (struct Lock *lock)
300{
301 struct GNUNET_HashCode key;
302
303 GNUNET_assert (NULL == lock->wl_head);
304 get_key (lock->domain_name, lock->lock_num, &key);
305 LOG (GNUNET_ERROR_TYPE_DEBUG,
306 "Removing lock with num: %u, domain: %s from lock map\n", lock->lock_num,
307 lock->domain_name);
308 GNUNET_assert (GNUNET_YES ==
309 GNUNET_CONTAINER_multihashmap_remove (lock_map, &key, lock));
310 GNUNET_free (lock->domain_name);
311 GNUNET_free (lock);
312}
313
314
315/**
316 * Find the LockList entry corresponding to the given Lock in a ClientList
317 * entry
318 *
319 * @param cl_entry the ClientList entry whose lock list has to be searched
320 * @param lock the lock which has to be matched
321 * @return the matching LockList entry; NULL if no match is found
322 */
323static struct LockList *
324cl_ll_find_lock (struct ClientList *cl_entry, const struct Lock *lock)
325{
326 struct LockList *ll_entry;
327
328 for (ll_entry = cl_entry->ll_head; NULL != ll_entry;
329 ll_entry = ll_entry->next)
330 {
331 if (lock == ll_entry->lock)
332 return ll_entry;
333 }
334 return NULL;
335}
336
337
338/**
339 * Function to append a lock to the lock list of a ClientList entry
340 *
341 * @param cl_entry the client which currently owns this lock
342 * @param lock the lock to be added to the cl_entry's lock list
343 */
344static void
345cl_ll_add_lock (struct ClientList *cl_entry, struct Lock *lock)
346{
347 struct LockList *ll_entry;
348
349 ll_entry = GNUNET_malloc (sizeof (struct LockList));
350 ll_entry->lock = lock;
351 LOG (GNUNET_ERROR_TYPE_DEBUG,
352 "Adding a lock with num: %u and domain: %s to lock list\n",
353 lock->lock_num, lock->domain_name);
354 GNUNET_CONTAINER_DLL_insert_tail (cl_entry->ll_head, cl_entry->ll_tail,
355 ll_entry);
356}
357
358
359/**
360 * Function to delete a lock from the lock list of the given ClientList entry
361 *
362 * @param cl_entry the ClientList entry
363 * @param ll_entry the LockList entry to be deleted
364 */
365static void
366cl_ll_remove_lock (struct ClientList *cl_entry, struct LockList *ll_entry)
367{
368 LOG (GNUNET_ERROR_TYPE_DEBUG,
369 "Removing lock with num: %u, domain: %s from lock list of a client\n",
370 ll_entry->lock->lock_num, ll_entry->lock->domain_name);
371 GNUNET_assert (NULL != cl_entry->ll_head);
372 GNUNET_CONTAINER_DLL_remove (cl_entry->ll_head, cl_entry->ll_tail, ll_entry);
373 GNUNET_free (ll_entry);
374}
375
376
377/**
378 * Find a WaitList entry in the waiting list of a lock
379 *
380 * @param lock the lock whose wait list has to be searched
381 * @param cl_entry the ClientList entry to be searched
382 * @return the WaitList entry matching the given cl_entry; NULL if not match
383 * was found
384 */
385static struct WaitList *
386lock_wl_find (const struct Lock *lock, const struct ClientList *cl_entry)
387{
388 struct WaitList *wl_entry;
389
390 for (wl_entry = lock->wl_head; NULL != wl_entry; wl_entry = wl_entry->next)
391 {
392 if (cl_entry == wl_entry->cl_entry)
393 return wl_entry;
394 }
395 return NULL;
396}
397
398
399/**
400 * Add a client to the wait list of given lock
401 *
402 * @param lock the lock list entry of a lock
403 * @param cl_entry the client to queue for the lock's wait list
404 */
405static void
406lock_wl_add_client (struct Lock *lock, struct ClientList *cl_entry)
407{
408 struct WaitList *wl_entry;
409
410 LOG (GNUNET_ERROR_TYPE_DEBUG,
411 "Adding a client to lock's wait list (lock num: %u, domain: %s)\n",
412 lock->lock_num, lock->domain_name);
413 wl_entry = GNUNET_malloc (sizeof (struct WaitList));
414 wl_entry->cl_entry = cl_entry;
415 GNUNET_CONTAINER_DLL_insert_tail (lock->wl_head, lock->wl_tail, wl_entry);
416}
417
418
419/**
420 * Remove an entry from the wait list of the given lock
421 *
422 * @param lock the lock
423 * @param wl_entry the wait list entry to be removed
424 */
425static void
426lock_wl_remove (struct Lock *lock, struct WaitList *wl_entry)
427{
428 LOG (GNUNET_ERROR_TYPE_DEBUG,
429 "Removing client from wait list of lock with num: %u, domain: %s\n",
430 lock->lock_num, lock->domain_name);
431 GNUNET_CONTAINER_DLL_remove (lock->wl_head, lock->wl_tail, wl_entry);
432 GNUNET_free (wl_entry);
433}
434
435
436/**
437 * Search for a client in the client list
438 *
439 * @param client the client to be searched for
440 * @return the ClientList entry; NULL if the client is not found
441 */
442static struct ClientList *
443cl_find_client (const struct GNUNET_SERVER_Client *client)
444{
445 struct ClientList *current;
446
447 for (current = cl_head; NULL != current; current = current->next)
448 if (client == current->client)
449 return current;
450 return NULL;
451}
452
453
454/**
455 * Append a client to the client list
456 *
457 * @param client the client to be appended to the list
458 * @return the client list entry which is added to the client list
459 */
460static struct ClientList *
461cl_add_client (struct GNUNET_SERVER_Client *client)
462{
463 struct ClientList *new_client;
464
465 LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding a client to the client list\n");
466 new_client = GNUNET_malloc (sizeof (struct ClientList));
467 GNUNET_SERVER_client_keep (client);
468 new_client->client = client;
469 GNUNET_CONTAINER_DLL_insert_tail (cl_head, cl_tail, new_client);
470 return new_client;
471}
472
473
474/**
475 * Delete the given client from the client list. The LockList should be empty
476 *
477 * @param cl_entry the client list entry to delete
478 */
479static void
480cl_remove_client (struct ClientList *cl_entry)
481{
482 GNUNET_assert (NULL == cl_entry->ll_head);
483 LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing a client from the client list\n");
484 GNUNET_SERVER_client_drop (cl_entry->client);
485 GNUNET_CONTAINER_DLL_remove (cl_head, cl_tail, cl_entry);
486 GNUNET_free (cl_entry);
487}
488
489
490/**
491 * Transmit notify for sending message to client
492 *
493 * @param cls the message to send
494 * @param size number of bytes available in buf
495 * @param buf where the callee should write the message
496 * @return number of bytes written to buf
497 */
498static size_t
499transmit_notify (void *cls, size_t size, void *buf)
500{
501 struct GNUNET_LOCKMANAGER_Message *msg = cls;
502 uint16_t msg_size;
503
504 if ((0 == size) || (NULL == buf))
505 {
506 /* FIXME: Timed out -- requeue? */
507 return 0;
508 }
509 msg_size = ntohs (msg->header.size);
510 GNUNET_assert (size >= msg_size);
511 memcpy (buf, msg, msg_size);
512 GNUNET_free (msg);
513 LOG (GNUNET_ERROR_TYPE_DEBUG, "Message of size %u sent\n", msg_size);
514 return msg_size;
515}
516
517
518/**
519 * Send SUCCESS message to the client
520 *
521 * @param client the client to which the message has to be sent
522 * @param domain_name the locking domain of the successfully acquried lock
523 * @param lock_num the number of the successfully acquired lock
524 */
525static void
526send_success_msg (struct GNUNET_SERVER_Client *client, const char *domain_name,
527 int lock_num)
528{
529 struct GNUNET_LOCKMANAGER_Message *reply;
530 size_t domain_name_len;
531 uint16_t reply_size;
532
533 domain_name_len = strlen (domain_name) + 1;
534 reply_size = sizeof (struct GNUNET_LOCKMANAGER_Message) + domain_name_len;
535 reply = GNUNET_malloc (reply_size);
536 reply->header.size = htons (reply_size);
537 reply->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS);
538 reply->lock = htonl (lock_num);
539 strncpy ((char *) &reply[1], domain_name, domain_name_len);
540 LOG (GNUNET_ERROR_TYPE_DEBUG,
541 "Sending SUCCESS message for lock with num: %u, domain: %s\n", lock_num,
542 domain_name);
543 GNUNET_SERVER_notify_transmit_ready (client, reply_size, TIMEOUT,
544 &transmit_notify, reply);
545}
546
547
548/**
549 * Handler for GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE
550 *
551 * @param cls NULL
552 * @param client the client sending this message
553 * @param message GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE message
554 */
555static void
556handle_acquire (void *cls, struct GNUNET_SERVER_Client *client,
557 const struct GNUNET_MessageHeader *message)
558{
559 const struct GNUNET_LOCKMANAGER_Message *request;
560 const char *domain_name;
561 struct Lock *lock;
562 struct ClientList *cl_entry;
563 uint32_t lock_num;
564 uint16_t msize;
565
566 msize = htons (message->size);
567 if (msize <= sizeof (struct GNUNET_LOCKMANAGER_Message))
568 {
569 GNUNET_break (0);
570 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
571 return;
572 }
573 request = (struct GNUNET_LOCKMANAGER_Message *) message;
574 domain_name = (const char *) &request[1];
575 msize -= sizeof (struct GNUNET_LOCKMANAGER_Message);
576 if ('\0' != domain_name[msize - 1])
577 {
578 LOG (GNUNET_ERROR_TYPE_DEBUG,
579 "Bad domain `%.*s' - byte with index %u is %X, not 0.\n", msize,
580 domain_name, msize - 1, (unsigned int) domain_name[msize - 1]);
581 GNUNET_break (0);
582 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
583 return;
584 }
585 lock_num = ntohl (request->lock);
586 LOG (GNUNET_ERROR_TYPE_DEBUG,
587 "Received an ACQUIRE message for lock num: %u domain: %s\n", lock_num,
588 domain_name);
589 if (NULL == (cl_entry = cl_find_client (client)))
590 cl_entry = cl_add_client (client); /* Add client if not in client list */
591 if (NULL != (lock = find_lock (domain_name, lock_num)))
592 {
593 if (lock->cl_entry == cl_entry)
594 { /* Client is requesting a lock it already owns */
595 GNUNET_break_op (0);
596 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
597 return;
598 }
599 lock_wl_add_client (lock, cl_entry);
600 cl_ll_add_lock (cl_entry, lock);
601 }
602 else /* Lock not present */
603 {
604 lock = add_lock (domain_name, lock_num);
605 lock->cl_entry = cl_entry;
606 cl_ll_add_lock (cl_entry, lock);
607 send_success_msg (cl_entry->client, domain_name, lock_num);
608 }
609 GNUNET_SERVER_receive_done (client, GNUNET_OK);
610}
611
612
613/**
614 * This function gives the lock to the first client in the wait list of the
615 * lock. If no clients are currently waiting for this lock, the lock is then
616 * destroyed.
617 *
618 * @param lock the lock which has to be processed for release
619 */
620static void
621process_lock_release (struct Lock *lock)
622{
623 struct WaitList *wl_entry;
624
625 LOG (GNUNET_ERROR_TYPE_DEBUG,
626 "Processing lock release for lock with num: %u, domain: %s\n",
627 lock->lock_num, lock->domain_name);
628 wl_entry = lock->wl_head;
629 if (NULL == wl_entry)
630 {
631 remove_lock (lock); /* No clients waiting for this lock - delete */
632 return;
633 }
634 LOG (GNUNET_ERROR_TYPE_DEBUG, "Giving lock to a client from wait list\n");
635 lock->cl_entry = wl_entry->cl_entry;
636 lock_wl_remove (lock, wl_entry);
637 send_success_msg (lock->cl_entry->client, lock->domain_name, lock->lock_num);
638}
639
640
641/**
642 * Handle for GNUNET_MESSAGE_TYPE_LOCKMANAGER_RELEASE
643 *
644 * @param cls NULL
645 * @param client the client sending this message
646 * @param message the LOCKMANAGER_RELEASE message
647 */
648static void
649handle_release (void *cls, struct GNUNET_SERVER_Client *client,
650 const struct GNUNET_MessageHeader *message)
651{
652 const struct GNUNET_LOCKMANAGER_Message *request;
653 struct ClientList *cl_entry;
654 struct WaitList *wl_entry;
655 struct LockList *ll_entry;
656 const char *domain_name;
657 struct Lock *lock;
658 uint32_t lock_num;
659 uint16_t msize;
660
661 msize = ntohs (message->size);
662 if (msize <= sizeof (struct GNUNET_LOCKMANAGER_Message))
663 {
664 GNUNET_break (0);
665 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
666 return;
667 }
668 request = (const struct GNUNET_LOCKMANAGER_Message *) message;
669 domain_name = (const char *) &request[1];
670 msize -= sizeof (struct GNUNET_LOCKMANAGER_Message);
671 if ('\0' != domain_name[msize - 1])
672 {
673 GNUNET_break (0);
674 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
675 return;
676
677
678 }
679 lock_num = ntohl (request->lock);
680 LOG (GNUNET_ERROR_TYPE_DEBUG,
681 "Received RELEASE message for lock with num: %d, domain: %s\n", lock_num,
682 domain_name);
683 if (NULL == (cl_entry = cl_find_client (client)))
684 {
685 GNUNET_break (0);
686 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
687 return;
688 }
689 lock = find_lock (domain_name, lock_num);
690 if (NULL == lock)
691 {
692 GNUNET_break (0);
693 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
694 return;
695 }
696 if (NULL == (ll_entry = cl_ll_find_lock (cl_entry, lock)))
697 {
698 GNUNET_break (0);
699 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
700 return;
701 }
702 cl_ll_remove_lock (cl_entry, ll_entry);
703 if (cl_entry == lock->cl_entry)
704 {
705 process_lock_release (lock);
706 GNUNET_SERVER_receive_done (client, GNUNET_OK);
707 return;
708 }
709 /* remove 'client' from wait list (check that it is not there...) */
710 if (NULL != (wl_entry = lock_wl_find (lock, cl_entry)))
711 {
712 lock_wl_remove (lock, wl_entry);
713 }
714 GNUNET_SERVER_receive_done (client, GNUNET_OK);
715}
716
717
718/**
719 * Callback for client disconnect
720 *
721 * @param cls NULL
722 * @param client the client which has disconnected
723 */
724static void
725client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
726{
727 struct ClientList *cl_entry;
728 struct LockList *ll_entry;
729 struct Lock *lock;
730 struct WaitList *wl_entry;
731
732 if (NULL == client)
733 return;
734 LOG (GNUNET_ERROR_TYPE_DEBUG,
735 "A client has been disconnected -- freeing its locks and resources\n");
736 cl_entry = cl_find_client (client);
737 if (NULL == cl_entry)
738 return;
739 while (NULL != (ll_entry = cl_entry->ll_head))
740 {
741 lock = ll_entry->lock;
742 cl_ll_remove_lock (cl_entry, ll_entry);
743 if (lock->cl_entry == cl_entry)
744 process_lock_release (lock);
745 else
746 {
747 wl_entry = lock_wl_find (lock, cl_entry);
748 GNUNET_assert (NULL != wl_entry);
749 lock_wl_remove (lock, wl_entry);
750 }
751 }
752 cl_remove_client (cl_entry);
753}
754
755
756/**
757 * Hashmap Iterator to delete lock entries in hash map
758 *
759 * @param cls NULL
760 * @param key current key code
761 * @param value value in the hash map
762 * @return GNUNET_YES if we should continue to
763 * iterate,
764 * GNUNET_NO if not.
765 */
766static int
767lock_delete_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
768{
769 struct Lock *lock = value;
770
771 GNUNET_assert (NULL != lock);
772 while (NULL != lock->wl_head)
773 {
774 lock_wl_remove (lock, lock->wl_head);
775 }
776 GNUNET_assert (GNUNET_YES ==
777 GNUNET_CONTAINER_multihashmap_remove (lock_map, key, lock));
778 GNUNET_free (lock->domain_name);
779 GNUNET_free (lock);
780 return GNUNET_YES;
781}
782
783
784/**
785 * Task to clean up and shutdown nicely
786 *
787 * @param cls NULL
788 * @param tc the TaskContext from scheduler
789 */
790static void
791shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
792{
793 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down lock manager\n");
794 /* Clean the global ClientList */
795 while (NULL != cl_head)
796 {
797 while (NULL != cl_head->ll_head) /* Clear the LockList */
798 {
799 cl_ll_remove_lock (cl_head, cl_head->ll_head);
800 }
801 cl_remove_client (cl_head);
802 }
803 /* Clean the global hash table */
804 GNUNET_CONTAINER_multihashmap_iterate (lock_map, &lock_delete_iterator, NULL);
805 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (lock_map));
806 GNUNET_CONTAINER_multihashmap_destroy (lock_map);
807 lock_map = NULL;
808}
809
810
811/**
812 * Lock manager setup
813 *
814 * @param cls closure
815 * @param server the initialized server
816 * @param cfg configuration to use
817 */
818static void
819lockmanager_run (void *cls, struct GNUNET_SERVER_Handle *server,
820 const struct GNUNET_CONFIGURATION_Handle *cfg)
821{
822 static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
823 {&handle_acquire, NULL, GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE, 0},
824 {&handle_release, NULL, GNUNET_MESSAGE_TYPE_LOCKMANAGER_RELEASE, 0},
825 {NULL}
826 };
827 GNUNET_SERVER_add_handlers (server, message_handlers);
828 GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
829 lock_map = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
830 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
831 NULL);
832}
833
834
835/**
836 * The starting point of execution
837 */
838int
839main (int argc, char *const *argv)
840{
841 return (GNUNET_OK ==
842 GNUNET_SERVICE_run (argc, argv, "lockmanager",
843 GNUNET_SERVICE_OPTION_NONE, &lockmanager_run,
844 NULL)) ? 0 : 1;
845}
846
847/* end of gnunet-service-lockmanager.c */