diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2012-05-09 08:29:17 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2012-05-09 08:29:17 +0000 |
commit | de21b0b29055c33ed2ee1ce36abecacf77836808 (patch) | |
tree | 52da4c004206505fe29add12e23e0facf23636f1 /src/lockmanager | |
parent | dfbb0d07f39a68d9e11e8956b66a979527a397a7 (diff) | |
download | gnunet-de21b0b29055c33ed2ee1ce36abecacf77836808.tar.gz gnunet-de21b0b29055c33ed2ee1ce36abecacf77836808.zip |
lock acquire and release
Diffstat (limited to 'src/lockmanager')
-rw-r--r-- | src/lockmanager/gnunet-service-lockmanager.c | 243 |
1 files changed, 208 insertions, 35 deletions
diff --git a/src/lockmanager/gnunet-service-lockmanager.c b/src/lockmanager/gnunet-service-lockmanager.c index ed85d3e3d..f959a3c5e 100644 --- a/src/lockmanager/gnunet-service-lockmanager.c +++ b/src/lockmanager/gnunet-service-lockmanager.c | |||
@@ -82,11 +82,6 @@ struct LockList | |||
82 | struct LockList *prev; | 82 | struct LockList *prev; |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * The client whizch is currently holding this lock | ||
86 | */ | ||
87 | struct GNUNET_SERVER_Client *client; | ||
88 | |||
89 | /** | ||
90 | * List head of clients waiting for this lock | 85 | * List head of clients waiting for this lock |
91 | */ | 86 | */ |
92 | struct WaitList *wait_list_head; | 87 | struct WaitList *wait_list_head; |
@@ -97,6 +92,11 @@ struct LockList | |||
97 | struct WaitList *wait_list_tail; | 92 | struct WaitList *wait_list_tail; |
98 | 93 | ||
99 | /** | 94 | /** |
95 | * The client which is currently holding this lock | ||
96 | */ | ||
97 | struct GNUNET_SERVER_Client *client; | ||
98 | |||
99 | /** | ||
100 | * The name of the locking domain this lock belongs to | 100 | * The name of the locking domain this lock belongs to |
101 | */ | 101 | */ |
102 | char *domain_name; | 102 | char *domain_name; |
@@ -151,7 +151,6 @@ static struct ClientList *cl_head; | |||
151 | static struct ClientList *cl_tail; | 151 | static struct ClientList *cl_tail; |
152 | 152 | ||
153 | 153 | ||
154 | |||
155 | /** | 154 | /** |
156 | * Function to search for a lock in lock_list matching the given domain_name and | 155 | * Function to search for a lock in lock_list matching the given domain_name and |
157 | * lock number | 156 | * lock number |
@@ -164,8 +163,8 @@ static struct ClientList *cl_tail; | |||
164 | */ | 163 | */ |
165 | static int | 164 | static int |
166 | ll_find_lock (const char *domain_name, | 165 | ll_find_lock (const char *domain_name, |
167 | const uint32_t lock_num, | 166 | const uint32_t lock_num, |
168 | struct LockList **ret) | 167 | struct LockList **ret) |
169 | { | 168 | { |
170 | struct LockList *current_lock; | 169 | struct LockList *current_lock; |
171 | 170 | ||
@@ -176,14 +175,49 @@ ll_find_lock (const char *domain_name, | |||
176 | if ( (0 == strcmp (domain_name, current_lock->domain_name)) | 175 | if ( (0 == strcmp (domain_name, current_lock->domain_name)) |
177 | && (lock_num == current_lock->lock_num)) | 176 | && (lock_num == current_lock->lock_num)) |
178 | { | 177 | { |
179 | *ret = current_lock; | 178 | if (NULL != ret) |
179 | *ret = current_lock; | ||
180 | return GNUNET_YES; | 180 | return GNUNET_YES; |
181 | } | 181 | } |
182 | 182 | ||
183 | current_lock = current_lock->next; | 183 | current_lock = current_lock->next; |
184 | } | 184 | } |
185 | if (NULL != ret) | ||
186 | *ret = current_lock; | ||
187 | return GNUNET_NO; | ||
188 | } | ||
189 | |||
190 | |||
191 | /** | ||
192 | * Function to search for a lock in lock_list matching the given domain_name and | ||
193 | * lock number | ||
194 | * | ||
195 | * @param client the client owning this lock currently | ||
196 | * @param ret this will be the pointer to the corresponding Lock if found; else | ||
197 | * it will be the last element in the locks list | ||
198 | * @return GNUNET_YES if a matching lock is present in lock_list; GNUNET_NO if not | ||
199 | */ | ||
200 | static int | ||
201 | ll_find_lock_by_owner (const struct GNUNET_SERVER_Client *client, | ||
202 | struct LockList **ret) | ||
203 | { | ||
204 | struct LockList *current_lock; | ||
205 | |||
206 | current_lock = ll_head; | ||
185 | 207 | ||
186 | *ret = current_lock; | 208 | while (NULL != current_lock) |
209 | { | ||
210 | if (client == current_lock->client) | ||
211 | { | ||
212 | if (NULL != ret) | ||
213 | *ret = current_lock; | ||
214 | return GNUNET_YES; | ||
215 | } | ||
216 | |||
217 | current_lock = current_lock->next; | ||
218 | } | ||
219 | if (NULL != ret) | ||
220 | *ret = current_lock; | ||
187 | return GNUNET_NO; | 221 | return GNUNET_NO; |
188 | } | 222 | } |
189 | 223 | ||
@@ -191,22 +225,29 @@ ll_find_lock (const char *domain_name, | |||
191 | /** | 225 | /** |
192 | * Function to append a lock to the global lock list | 226 | * Function to append a lock to the global lock list |
193 | * | 227 | * |
228 | * @param client the client which currently owns this lock | ||
194 | * @param domain_name the name of the locking domain | 229 | * @param domain_name the name of the locking domain |
195 | * @param domain_name_len the length of the domain name | ||
196 | * @param lock_num the number of the lock | 230 | * @param lock_num the number of the lock |
197 | * @param tail the pointer to the tail of the global lock list | 231 | * @param tail the pointer to the tail of the global lock list |
198 | */ | 232 | */ |
199 | static void | 233 | static void |
200 | ll_add_lock (const char *domain_name, | 234 | ll_add_lock (struct GNUNET_SERVER_Client *client, |
201 | size_t domain_name_len, | 235 | const char *domain_name, |
202 | const uint32_t lock_num) | 236 | const uint32_t lock_num) |
203 | { | 237 | { |
204 | struct LockList *lock; | 238 | struct LockList *lock; |
239 | size_t domain_name_len; | ||
240 | |||
241 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
242 | "Adding a lock with num: %u and domain: %s to lock list\n", | ||
243 | lock_num, domain_name); | ||
205 | 244 | ||
206 | lock = GNUNET_malloc (sizeof (struct LockList)); | 245 | lock = GNUNET_malloc (sizeof (struct LockList)); |
246 | domain_name_len = strlen (domain_name) + 1; | ||
207 | lock->domain_name = GNUNET_malloc (domain_name_len); | 247 | lock->domain_name = GNUNET_malloc (domain_name_len); |
208 | strncpy (lock->domain_name, domain_name, domain_name_len); | 248 | strncpy (lock->domain_name, domain_name, domain_name_len); |
209 | lock->lock_num = lock_num; | 249 | lock->lock_num = lock_num; |
250 | lock->client = client; | ||
210 | 251 | ||
211 | GNUNET_CONTAINER_DLL_insert_tail (ll_head, | 252 | GNUNET_CONTAINER_DLL_insert_tail (ll_head, |
212 | ll_tail, | 253 | ll_tail, |
@@ -222,6 +263,9 @@ ll_add_lock (const char *domain_name, | |||
222 | static void | 263 | static void |
223 | ll_remove_lock (struct LockList *lock) | 264 | ll_remove_lock (struct LockList *lock) |
224 | { | 265 | { |
266 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
267 | "Removing lock with num: %u, domain: %s\n", | ||
268 | lock->lock_num, lock->domain_name); | ||
225 | GNUNET_assert (NULL != ll_head); | 269 | GNUNET_assert (NULL != ll_head); |
226 | GNUNET_CONTAINER_DLL_remove (ll_head, | 270 | GNUNET_CONTAINER_DLL_remove (ll_head, |
227 | ll_tail, | 271 | ll_tail, |
@@ -252,18 +296,20 @@ ll_wl_find_client (struct LockList *lock, | |||
252 | { | 296 | { |
253 | if (client == current_wl_entry->client) | 297 | if (client == current_wl_entry->client) |
254 | { | 298 | { |
255 | *ret = current_wl_entry; | 299 | if (NULL != ret) |
300 | *ret = current_wl_entry; | ||
256 | return GNUNET_YES; | 301 | return GNUNET_YES; |
257 | } | 302 | } |
258 | current_wl_entry = current_wl_entry->next; | 303 | current_wl_entry = current_wl_entry->next; |
259 | } | 304 | } |
260 | *ret = current_wl_entry; | 305 | if (NULL != ret) |
306 | *ret = current_wl_entry; | ||
261 | return GNUNET_NO; | 307 | return GNUNET_NO; |
262 | } | 308 | } |
263 | 309 | ||
264 | 310 | ||
265 | /** | 311 | /** |
266 | * Add a client to the wait list of a lock | 312 | * Add a client to the wait list of given lock |
267 | * | 313 | * |
268 | * @param lock the lock list entry of a lock | 314 | * @param lock the lock list entry of a lock |
269 | * @param client the client to queue for the lock's wait list | 315 | * @param client the client to queue for the lock's wait list |
@@ -274,6 +320,12 @@ ll_wl_add_client (struct LockList *lock, | |||
274 | { | 320 | { |
275 | struct WaitList *wl_entry; | 321 | struct WaitList *wl_entry; |
276 | 322 | ||
323 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
324 | "Adding a client to lock's wait list\n" | ||
325 | "\t lock num: %u, domain: %s\n", | ||
326 | lock->lock_num, | ||
327 | lock->domain_name); | ||
328 | |||
277 | wl_entry = GNUNET_malloc (sizeof (struct WaitList)); | 329 | wl_entry = GNUNET_malloc (sizeof (struct WaitList)); |
278 | wl_entry->client = client; | 330 | wl_entry->client = client; |
279 | GNUNET_CONTAINER_DLL_insert_tail (lock->wait_list_head, | 331 | GNUNET_CONTAINER_DLL_insert_tail (lock->wait_list_head, |
@@ -282,6 +334,12 @@ ll_wl_add_client (struct LockList *lock, | |||
282 | } | 334 | } |
283 | 335 | ||
284 | 336 | ||
337 | /** | ||
338 | * Remove a client from the wait list of the given lock | ||
339 | * | ||
340 | * @param lock the lock list entry of the lock | ||
341 | * @param wl_client the wait list entry to be removed | ||
342 | */ | ||
285 | static void | 343 | static void |
286 | ll_wl_remove_client (struct LockList *lock, | 344 | ll_wl_remove_client (struct LockList *lock, |
287 | struct WaitList *wl_client) | 345 | struct WaitList *wl_client) |
@@ -314,14 +372,16 @@ cl_find_client (const struct GNUNET_SERVER_Client *client, | |||
314 | { | 372 | { |
315 | if (client == current->client) | 373 | if (client == current->client) |
316 | { | 374 | { |
317 | *ret = current; | 375 | if (NULL != ret) |
376 | *ret = current; | ||
318 | return GNUNET_YES; | 377 | return GNUNET_YES; |
319 | } | 378 | } |
320 | 379 | ||
321 | current = current->next; | 380 | current = current->next; |
322 | } | 381 | } |
323 | 382 | ||
324 | *ret = current; | 383 | if (NULL != ret) |
384 | *ret = current; | ||
325 | return GNUNET_NO; | 385 | return GNUNET_NO; |
326 | } | 386 | } |
327 | 387 | ||
@@ -335,8 +395,12 @@ static void | |||
335 | cl_add_client (struct GNUNET_SERVER_Client *client) | 395 | cl_add_client (struct GNUNET_SERVER_Client *client) |
336 | { | 396 | { |
337 | struct ClientList *new_client; | 397 | struct ClientList *new_client; |
398 | |||
399 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
400 | "Adding a client to the client list\n"); | ||
338 | 401 | ||
339 | new_client = GNUNET_malloc (sizeof (struct ClientList)); | 402 | new_client = GNUNET_malloc (sizeof (struct ClientList)); |
403 | GNUNET_SERVER_client_keep (client); | ||
340 | new_client->client = client; | 404 | new_client->client = client; |
341 | GNUNET_CONTAINER_DLL_insert_tail (cl_head, | 405 | GNUNET_CONTAINER_DLL_insert_tail (cl_head, |
342 | cl_tail, | 406 | cl_tail, |
@@ -352,6 +416,9 @@ cl_add_client (struct GNUNET_SERVER_Client *client) | |||
352 | static void | 416 | static void |
353 | cl_remove_client (struct ClientList *client) | 417 | cl_remove_client (struct ClientList *client) |
354 | { | 418 | { |
419 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
420 | "Removing a client from the client list\n"); | ||
421 | GNUNET_SERVER_client_drop (client->client); | ||
355 | GNUNET_CONTAINER_DLL_remove (cl_head, | 422 | GNUNET_CONTAINER_DLL_remove (cl_head, |
356 | cl_tail, | 423 | cl_tail, |
357 | client); | 424 | client); |
@@ -389,6 +456,37 @@ transmit_notify (void *cls, size_t size, void *buf) | |||
389 | 456 | ||
390 | 457 | ||
391 | /** | 458 | /** |
459 | * Send SUCCESS message to the client | ||
460 | * | ||
461 | * @param client the client to which the message has to be sent | ||
462 | * @param domain_name the locking domain of the successfully acquried lock | ||
463 | * @param lock_num the number of the successfully acquired lock | ||
464 | */ | ||
465 | static void | ||
466 | send_success_msg (struct GNUNET_SERVER_Client *client, | ||
467 | const char *domain_name, | ||
468 | int lock_num) | ||
469 | { | ||
470 | struct GNUNET_LOCKMANAGER_Message *reply; | ||
471 | size_t domain_name_len; | ||
472 | uint16_t reply_size; | ||
473 | |||
474 | domain_name_len = strlen (domain_name) + 1; | ||
475 | reply_size = sizeof (struct GNUNET_LOCKMANAGER_Message) + domain_name_len; | ||
476 | reply = GNUNET_malloc (reply_size); | ||
477 | reply->header.size = htons (reply_size); | ||
478 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS); | ||
479 | reply->lock = htonl (lock_num); | ||
480 | strncpy ((char *) &reply[1], domain_name, domain_name_len); | ||
481 | GNUNET_SERVER_notify_transmit_ready (client, | ||
482 | reply_size, | ||
483 | TIMEOUT, | ||
484 | &transmit_notify, | ||
485 | reply); | ||
486 | } | ||
487 | |||
488 | |||
489 | /** | ||
392 | * Handler for GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE | 490 | * Handler for GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE |
393 | * | 491 | * |
394 | * @param cls NULL | 492 | * @param cls NULL |
@@ -401,26 +499,36 @@ handle_acquire (void *cls, | |||
401 | const struct GNUNET_MessageHeader *message) | 499 | const struct GNUNET_MessageHeader *message) |
402 | { | 500 | { |
403 | const struct GNUNET_LOCKMANAGER_Message *request; | 501 | const struct GNUNET_LOCKMANAGER_Message *request; |
404 | struct GNUNET_LOCKMANAGER_Message *reply; | 502 | const char *domain_name; |
405 | int16_t request_size; | 503 | struct LockList *ll_entry; |
504 | uint32_t lock_num; | ||
406 | 505 | ||
407 | 506 | ||
408 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 507 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
409 | "Received an ACQUIRE message\n"); | 508 | "Received an ACQUIRE message\n"); |
410 | |||
411 | request = (struct GNUNET_LOCKMANAGER_Message *) message; | ||
412 | 509 | ||
413 | /* FIXME: Dummy implementation; just echos success for every lock */ | ||
414 | request_size = ntohs (message->size); | ||
415 | reply = GNUNET_malloc (request_size); | ||
416 | memcpy (reply, request, request_size); | ||
417 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS); | ||
418 | GNUNET_SERVER_notify_transmit_ready (client, | ||
419 | request_size, | ||
420 | TIMEOUT, | ||
421 | &transmit_notify, | ||
422 | reply); | ||
423 | 510 | ||
511 | /* Check if the client is in client list */ | ||
512 | if (GNUNET_NO == cl_find_client (client, NULL)) | ||
513 | { | ||
514 | cl_add_client (client); | ||
515 | } | ||
516 | |||
517 | request = (struct GNUNET_LOCKMANAGER_Message *) message; | ||
518 | lock_num = ntohl (request->lock); | ||
519 | domain_name = (char *) &request[1]; | ||
520 | if (GNUNET_YES == ll_find_lock (domain_name, | ||
521 | lock_num, | ||
522 | &ll_entry)) | ||
523 | {/* Add client to the lock's wait list */ | ||
524 | ll_wl_add_client (ll_entry, client); | ||
525 | } | ||
526 | else | ||
527 | { | ||
528 | ll_add_lock (client, domain_name, lock_num); | ||
529 | send_success_msg (client, domain_name, lock_num); | ||
530 | } | ||
531 | |||
424 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 532 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
425 | } | 533 | } |
426 | 534 | ||
@@ -437,14 +545,75 @@ handle_release (void *cls, | |||
437 | struct GNUNET_SERVER_Client *client, | 545 | struct GNUNET_SERVER_Client *client, |
438 | const struct GNUNET_MessageHeader *message) | 546 | const struct GNUNET_MessageHeader *message) |
439 | { | 547 | { |
440 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 548 | const struct GNUNET_LOCKMANAGER_Message *request; |
441 | "Received a RELEASE message\n"); | 549 | const char *domain_name; |
550 | struct LockList *ll_entry; | ||
551 | uint32_t lock_num; | ||
442 | 552 | ||
553 | request = (struct GNUNET_LOCKMANAGER_Message *) message; | ||
554 | lock_num = ntohl (request->lock); | ||
555 | domain_name = (char *) &request[1]; | ||
556 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
557 | "Received a RELEASE message on lock with num: %d, domain: %s\n", | ||
558 | lock_num, domain_name); | ||
559 | if (GNUNET_YES == ll_find_lock (domain_name, lock_num, &ll_entry)) | ||
560 | { | ||
561 | if (NULL == ll_entry->wait_list_head) | ||
562 | { | ||
563 | ll_remove_lock (ll_entry); | ||
564 | } | ||
565 | else | ||
566 | { | ||
567 | /* Do furthur processing on lock's wait list here */ | ||
568 | } | ||
569 | } | ||
570 | else | ||
571 | { | ||
572 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
573 | "\t give lock doesn't exist\n"); | ||
574 | } | ||
575 | |||
576 | |||
443 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 577 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
444 | } | 578 | } |
445 | 579 | ||
446 | 580 | ||
447 | /** | 581 | /** |
582 | * Callback for client disconnect | ||
583 | * | ||
584 | * @param cls NULL | ||
585 | * @param client the client which has disconnected | ||
586 | */ | ||
587 | static void | ||
588 | client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) | ||
589 | { | ||
590 | struct ClientList *cl_entry; | ||
591 | |||
592 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
593 | "A client has been disconnected -- freeing its locks and resources\n"); | ||
594 | |||
595 | if (GNUNET_YES == cl_find_client (client, &cl_entry)) | ||
596 | { | ||
597 | struct LockList *lock; | ||
598 | |||
599 | cl_remove_client (cl_entry); | ||
600 | while (GNUNET_YES == ll_find_lock_by_owner (client, &lock)) | ||
601 | { | ||
602 | if (NULL == lock->wait_list_head) | ||
603 | { | ||
604 | ll_remove_lock (lock); | ||
605 | } | ||
606 | else | ||
607 | { | ||
608 | /* Do furthur processing on lock's wait list here */ | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | else GNUNET_break (0); | ||
613 | } | ||
614 | |||
615 | |||
616 | /** | ||
448 | * Lock manager setup | 617 | * Lock manager setup |
449 | * | 618 | * |
450 | * @param cls closure | 619 | * @param cls closure |
@@ -466,6 +635,10 @@ lockmanager_run (void *cls, | |||
466 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting lockmanager\n"); | 635 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting lockmanager\n"); |
467 | GNUNET_SERVER_add_handlers (server, | 636 | GNUNET_SERVER_add_handlers (server, |
468 | message_handlers); | 637 | message_handlers); |
638 | GNUNET_SERVER_disconnect_notify (server, | ||
639 | &client_disconnect_cb, | ||
640 | NULL); | ||
641 | |||
469 | 642 | ||
470 | } | 643 | } |
471 | 644 | ||