*/
struct LockList *prev;
- /**
- * The client whizch is currently holding this lock
- */
- struct GNUNET_SERVER_Client *client;
-
/**
* List head of clients waiting for this lock
*/
*/
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
*/
static struct ClientList *cl_tail;
-
/**
* Function to search for a lock in lock_list matching the given domain_name and
* lock number
*/
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;
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;
}
/**
* 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,
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,
{
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
{
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,
}
+/**
+ * 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)
{
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;
}
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,
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);
}
+/**
+ * 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
*
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);
}
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
*
LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting lockmanager\n");
GNUNET_SERVER_add_handlers (server,
message_handlers);
+ GNUNET_SERVER_disconnect_notify (server,
+ &client_disconnect_cb,
+ NULL);
+
}