};
+/**
+ * Structure for matching a lock
+ */
+struct LockMatch
+{
+ /**
+ * The matched LockingRequest entry; Should be NULL if no entry is found
+ */
+ struct Lock *matched_entry;
+
+ /**
+ * The locking domain name of the lock
+ */
+ const char *domain_name;
+
+ /**
+ * The lock number
+ */
+ uint32_t lock_num;
+};
+
+
/**
* Map of lock-keys to the 'struct LockList' entry for the key.
*/
}
+/**
+ * Hashmap iterator for matching a lock
+ *
+ * @param cls the LockMatch structure
+ * @param key current key code
+ * @param value value in the hash map (struct Lock)
+ * @return GNUNET_YES if we should continue to
+ * iterate,
+ * GNUNET_NO if not.
+ */
+static int
+match_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
+{
+ struct LockMatch *match = cls;
+ struct Lock *lock = value;
+
+ if ( (match->lock_num == lock->lock_num)
+ && (0 == strcmp (match->domain_name, lock->domain_name)) )
+ {
+ match->matched_entry = lock;
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+
/**
* Function to search for a lock in the global lock hashmap
*
const uint32_t lock_num)
{
- struct Lock *matched_lock;
+ struct LockMatch match;
struct GNUNET_HashCode key;
- matched_lock = NULL;
- int match_lock (void *cls,
- const GNUNET_HashCode *key,
- void *value)
- {
- matched_lock = value;
-
- if ((lock_num == matched_lock->lock_num)
- && (0 == strcmp (domain_name, matched_lock->domain_name)))
- return GNUNET_NO;
- matched_lock = NULL;
- return GNUNET_YES;
- }
+ match.lock_num = lock_num;
+ match.domain_name = domain_name;
+ match.matched_entry = NULL;
get_key (domain_name, lock_num, &key);
GNUNET_CONTAINER_multihashmap_get_multiple (lock_map,
&key,
- &match_lock,
- NULL);
- return matched_lock;
+ &match_iterator,
+ &match);
+ return match.matched_entry;
}
/**
- * Removes a lock from the lock map
+ * Removes a lock from the lock map. The WaitList of the lock should be empty
*
- * @param the lock to remove
+ * @param lock the lock to remove
*/
static void
remove_lock (struct Lock *lock)
{
struct GNUNET_HashCode key;
-
+
+ GNUNET_assert (NULL == lock->wl_head);
get_key (lock->domain_name,
lock->lock_num,
&key);
/**
- * Delete the given client from the client list
+ * Delete the given client from the client list. The LockList should be empty
*
* @param cl_entry the client list entry to delete
*/
static void
cl_remove_client (struct ClientList *cl_entry)
{
+ GNUNET_assert (NULL == cl_entry->ll_head);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Removing a client from the client list\n");
GNUNET_SERVER_client_drop (cl_entry->client);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Giving lock to a client from wait list\n");
lock->cl_entry = wl_entry->cl_entry;
- cl_ll_add_lock (wl_entry->cl_entry, lock);
lock_wl_remove(lock, wl_entry);
send_success_msg (lock->cl_entry->client,
lock->domain_name,
{
struct ClientList *cl_entry;
struct LockList *ll_entry;
+ struct Lock *lock;
+ if (NULL == client)
+ return;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"A client has been disconnected -- freeing its locks and resources\n");
cl_entry = cl_find_client (client);
return;
while (NULL != (ll_entry = cl_entry->ll_head))
{
- process_lock_release (ll_entry->lock);
+ lock = ll_entry->lock;
cl_ll_remove_lock (cl_entry, ll_entry);
+ process_lock_release (lock);
}
cl_remove_client (cl_entry);
}
+/**
+ * Hashmap Iterator to delete lock entries in hash map
+ *
+ * @param cls NULL
+ * @param key current key code
+ * @param value value in the hash map
+ * @return GNUNET_YES if we should continue to
+ * iterate,
+ * GNUNET_NO if not.
+ */
+static int
+lock_delete_iterator (void *cls,
+ const struct GNUNET_HashCode * key,
+ void *value)
+{
+ struct Lock *lock = value;
+
+ GNUNET_assert (NULL != lock);
+ while (NULL != lock->wl_head)
+ {
+ lock_wl_remove (lock, lock->wl_head);
+ }
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove(lock_map,
+ key,
+ lock));
+ GNUNET_free (lock->domain_name);
+ GNUNET_free (lock);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Task to clean up and shutdown nicely
+ *
+ * @param cls NULL
+ * @param tc the TaskContext from scheduler
+ */
+static void
+shutdown_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Shutting down lock manager\n");
+ /* Clean the global ClientList */
+ while (NULL != cl_head)
+ {
+ while (NULL != cl_head->ll_head) /* Clear the LockList */
+ {
+ cl_ll_remove_lock (cl_head, cl_head->ll_head);
+ }
+ cl_remove_client (cl_head);
+ }
+ /* Clean the global hash table */
+ GNUNET_CONTAINER_multihashmap_iterate (lock_map,
+ &lock_delete_iterator,
+ NULL);
+ GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (lock_map));
+ GNUNET_CONTAINER_multihashmap_destroy (lock_map);
+}
+
+
/**
* Lock manager setup
*
&client_disconnect_cb,
NULL);
lock_map = GNUNET_CONTAINER_multihashmap_create (30);
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+ &shutdown_task,
+ NULL);
}