From de21b0b29055c33ed2ee1ce36abecacf77836808 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Wed, 9 May 2012 08:29:17 +0000 Subject: [PATCH] lock acquire and release --- src/lockmanager/gnunet-service-lockmanager.c | 243 ++++++++++++++++--- 1 file 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 @@ -81,11 +81,6 @@ struct LockList */ struct LockList *prev; - /** - * The client whizch is currently holding this lock - */ - struct GNUNET_SERVER_Client *client; - /** * List head of clients waiting for this lock */ @@ -96,6 +91,11 @@ struct LockList */ struct WaitList *wait_list_tail; + /** + * The client which is currently holding this lock + */ + struct GNUNET_SERVER_Client *client; + /** * The name of the locking domain this lock belongs to */ @@ -151,7 +151,6 @@ static struct ClientList *cl_head; static struct ClientList *cl_tail; - /** * Function to search for a lock in lock_list matching the given domain_name and * lock number @@ -164,8 +163,8 @@ static struct ClientList *cl_tail; */ static int ll_find_lock (const char *domain_name, - const uint32_t lock_num, - struct LockList **ret) + const uint32_t lock_num, + struct LockList **ret) { struct LockList *current_lock; @@ -176,14 +175,49 @@ ll_find_lock (const char *domain_name, if ( (0 == strcmp (domain_name, current_lock->domain_name)) && (lock_num == current_lock->lock_num)) { - *ret = current_lock; + if (NULL != ret) + *ret = current_lock; return GNUNET_YES; } current_lock = current_lock->next; } + if (NULL != ret) + *ret = current_lock; + return GNUNET_NO; +} + + +/** + * Function to search for a lock in lock_list matching the given domain_name and + * lock number + * + * @param client the client owning this lock currently + * @param ret this will be the pointer to the corresponding Lock if found; else + * it will be the last element in the locks list + * @return GNUNET_YES if a matching lock is present in lock_list; GNUNET_NO if not + */ +static int +ll_find_lock_by_owner (const struct GNUNET_SERVER_Client *client, + struct LockList **ret) +{ + struct LockList *current_lock; + + current_lock = ll_head; - *ret = current_lock; + while (NULL != current_lock) + { + if (client == current_lock->client) + { + if (NULL != ret) + *ret = current_lock; + return GNUNET_YES; + } + + current_lock = current_lock->next; + } + if (NULL != ret) + *ret = current_lock; return GNUNET_NO; } @@ -191,22 +225,29 @@ ll_find_lock (const char *domain_name, /** * Function to append a lock to the global lock list * + * @param client the client which currently owns this lock * @param domain_name the name of the locking domain - * @param domain_name_len the length of the domain name * @param lock_num the number of the lock * @param tail the pointer to the tail of the global lock list */ static void -ll_add_lock (const char *domain_name, - size_t domain_name_len, - const uint32_t lock_num) +ll_add_lock (struct GNUNET_SERVER_Client *client, + const char *domain_name, + const uint32_t lock_num) { struct LockList *lock; + size_t domain_name_len; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Adding a lock with num: %u and domain: %s to lock list\n", + lock_num, domain_name); lock = GNUNET_malloc (sizeof (struct LockList)); + domain_name_len = strlen (domain_name) + 1; lock->domain_name = GNUNET_malloc (domain_name_len); strncpy (lock->domain_name, domain_name, domain_name_len); lock->lock_num = lock_num; + lock->client = client; GNUNET_CONTAINER_DLL_insert_tail (ll_head, ll_tail, @@ -222,6 +263,9 @@ ll_add_lock (const char *domain_name, static void ll_remove_lock (struct LockList *lock) { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Removing lock with num: %u, domain: %s\n", + lock->lock_num, lock->domain_name); GNUNET_assert (NULL != ll_head); GNUNET_CONTAINER_DLL_remove (ll_head, ll_tail, @@ -252,18 +296,20 @@ ll_wl_find_client (struct LockList *lock, { if (client == current_wl_entry->client) { - *ret = current_wl_entry; + if (NULL != ret) + *ret = current_wl_entry; return GNUNET_YES; } current_wl_entry = current_wl_entry->next; } - *ret = current_wl_entry; + if (NULL != ret) + *ret = current_wl_entry; return GNUNET_NO; } /** - * Add a client to the wait list of a lock + * Add a client to the wait list of given lock * * @param lock the lock list entry of a lock * @param client the client to queue for the lock's wait list @@ -274,6 +320,12 @@ ll_wl_add_client (struct LockList *lock, { struct WaitList *wl_entry; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Adding a client to lock's wait list\n" + "\t lock num: %u, domain: %s\n", + lock->lock_num, + lock->domain_name); + wl_entry = GNUNET_malloc (sizeof (struct WaitList)); wl_entry->client = client; GNUNET_CONTAINER_DLL_insert_tail (lock->wait_list_head, @@ -282,6 +334,12 @@ ll_wl_add_client (struct LockList *lock, } +/** + * Remove a client from the wait list of the given lock + * + * @param lock the lock list entry of the lock + * @param wl_client the wait list entry to be removed + */ static void ll_wl_remove_client (struct LockList *lock, struct WaitList *wl_client) @@ -314,14 +372,16 @@ cl_find_client (const struct GNUNET_SERVER_Client *client, { if (client == current->client) { - *ret = current; + if (NULL != ret) + *ret = current; return GNUNET_YES; } current = current->next; } - *ret = current; + if (NULL != ret) + *ret = current; return GNUNET_NO; } @@ -335,8 +395,12 @@ static void cl_add_client (struct GNUNET_SERVER_Client *client) { struct ClientList *new_client; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Adding a client to the client list\n"); new_client = GNUNET_malloc (sizeof (struct ClientList)); + GNUNET_SERVER_client_keep (client); new_client->client = client; GNUNET_CONTAINER_DLL_insert_tail (cl_head, cl_tail, @@ -352,6 +416,9 @@ cl_add_client (struct GNUNET_SERVER_Client *client) static void cl_remove_client (struct ClientList *client) { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Removing a client from the client list\n"); + GNUNET_SERVER_client_drop (client->client); GNUNET_CONTAINER_DLL_remove (cl_head, cl_tail, client); @@ -388,6 +455,37 @@ transmit_notify (void *cls, size_t size, void *buf) } +/** + * Send SUCCESS message to the client + * + * @param client the client to which the message has to be sent + * @param domain_name the locking domain of the successfully acquried lock + * @param lock_num the number of the successfully acquired lock + */ +static void +send_success_msg (struct GNUNET_SERVER_Client *client, + const char *domain_name, + int lock_num) +{ + struct GNUNET_LOCKMANAGER_Message *reply; + size_t domain_name_len; + uint16_t reply_size; + + domain_name_len = strlen (domain_name) + 1; + reply_size = sizeof (struct GNUNET_LOCKMANAGER_Message) + domain_name_len; + reply = GNUNET_malloc (reply_size); + reply->header.size = htons (reply_size); + reply->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS); + reply->lock = htonl (lock_num); + strncpy ((char *) &reply[1], domain_name, domain_name_len); + GNUNET_SERVER_notify_transmit_ready (client, + reply_size, + TIMEOUT, + &transmit_notify, + reply); +} + + /** * Handler for GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE * @@ -401,26 +499,36 @@ handle_acquire (void *cls, const struct GNUNET_MessageHeader *message) { const struct GNUNET_LOCKMANAGER_Message *request; - struct GNUNET_LOCKMANAGER_Message *reply; - int16_t request_size; + const char *domain_name; + struct LockList *ll_entry; + uint32_t lock_num; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received an ACQUIRE message\n"); - - request = (struct GNUNET_LOCKMANAGER_Message *) message; - /* FIXME: Dummy implementation; just echos success for every lock */ - request_size = ntohs (message->size); - reply = GNUNET_malloc (request_size); - memcpy (reply, request, request_size); - reply->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS); - GNUNET_SERVER_notify_transmit_ready (client, - request_size, - TIMEOUT, - &transmit_notify, - reply); + /* Check if the client is in client list */ + if (GNUNET_NO == cl_find_client (client, NULL)) + { + cl_add_client (client); + } + + request = (struct GNUNET_LOCKMANAGER_Message *) message; + lock_num = ntohl (request->lock); + domain_name = (char *) &request[1]; + if (GNUNET_YES == ll_find_lock (domain_name, + lock_num, + &ll_entry)) + {/* Add client to the lock's wait list */ + ll_wl_add_client (ll_entry, client); + } + else + { + ll_add_lock (client, domain_name, lock_num); + send_success_msg (client, domain_name, lock_num); + } + GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -437,13 +545,74 @@ handle_release (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received a RELEASE message\n"); + const struct GNUNET_LOCKMANAGER_Message *request; + const char *domain_name; + struct LockList *ll_entry; + uint32_t lock_num; + request = (struct GNUNET_LOCKMANAGER_Message *) message; + lock_num = ntohl (request->lock); + domain_name = (char *) &request[1]; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received a RELEASE message on lock with num: %d, domain: %s\n", + lock_num, domain_name); + if (GNUNET_YES == ll_find_lock (domain_name, lock_num, &ll_entry)) + { + if (NULL == ll_entry->wait_list_head) + { + ll_remove_lock (ll_entry); + } + else + { + /* Do furthur processing on lock's wait list here */ + } + } + else + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "\t give lock doesn't exist\n"); + } + + GNUNET_SERVER_receive_done (client, GNUNET_OK); } +/** + * Callback for client disconnect + * + * @param cls NULL + * @param client the client which has disconnected + */ +static void +client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) +{ + struct ClientList *cl_entry; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "A client has been disconnected -- freeing its locks and resources\n"); + + if (GNUNET_YES == cl_find_client (client, &cl_entry)) + { + struct LockList *lock; + + cl_remove_client (cl_entry); + while (GNUNET_YES == ll_find_lock_by_owner (client, &lock)) + { + if (NULL == lock->wait_list_head) + { + ll_remove_lock (lock); + } + else + { + /* Do furthur processing on lock's wait list here */ + } + } + } + else GNUNET_break (0); +} + + /** * Lock manager setup * @@ -466,6 +635,10 @@ lockmanager_run (void *cls, LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting lockmanager\n"); GNUNET_SERVER_add_handlers (server, message_handlers); + GNUNET_SERVER_disconnect_notify (server, + &client_disconnect_cb, + NULL); + } -- 2.25.1