From c1c0db0e9591de979b6572eb41bdd99f3cb6613d Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Thu, 26 Apr 2012 20:49:58 +0000 Subject: [PATCH] -extended lockmanager api --- src/lockmanager/lockmanager_api.c | 237 +++++++++++++++++++++++++++++- 1 file changed, 235 insertions(+), 2 deletions(-) diff --git a/src/lockmanager/lockmanager_api.c b/src/lockmanager/lockmanager_api.c index e8d18666b..311f43b0f 100644 --- a/src/lockmanager/lockmanager_api.c +++ b/src/lockmanager/lockmanager_api.c @@ -28,11 +28,17 @@ #include "gnunet_common.h" #include "gnunet_protocols.h" #include "gnunet_client_lib.h" +#include "gnunet_lockmanager_service.h" #include "lockmanager.h" #define LOG(kind,...) \ - GNUNET_log_from (kind, "gnunet-service-lockmanager",__VA_ARGS__) + GNUNET_log_from (kind, "lockmanager-api",__VA_ARGS__) + +#define TIME_REL_MINS(min) \ + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, min) + +#define TIMEOUT TIME_REL_MINS(3) /** * Handler for the lockmanager service @@ -46,6 +52,121 @@ struct GNUNET_LOCKMANAGER_Handle }; +/** + * Structure for Locking Request + */ +struct GNUNET_LOCKMANAGER_LockingRequest +{ + /** + * The handle associated with this request + */ + struct GNUNET_LOCKMANAGER_Handle *handle; + + /** + * The status callback + */ + GNUNET_LOCKMANAGER_StatusCallback status_cb; + + /** + * Closure for the status callback + */ + void *status_cb_cls; + + /** + * The pending transmit handle for the ACQUIRE message + */ + struct GNUNET_CLIENT_TransmitHandle *transmit_handle; + + /** + * The locking domain of this request + */ + char *domain; + + /** + * The lock + */ + uint32_t lock; + + /** + * The status of the lock + */ + enum GNUNET_LOCKMANAGER_Status status; + + /** + * The length of the locking domain string including the trailing NULL + */ + uint16_t domain_name_length; +}; + + +/** + * Message handler for SUCCESS messages + * + * @param cls the LOCKMANAGER_Handle + * @param msg message received, NULL on timeout or fatal error + */ +static void +handle_success (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + if (NULL == msg) + return; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received SUCCESS message\n"); +} + + +/** + * We wait for DUMMY message which will never be sent by the server. However, + * in case the server shuts-down/crashes/restarts we are notified by this call + * back with a NULL for msg. + * + * @param cls closure + * @param msg message received, NULL on timeout or fatal error + */ +static void +handle_server_crash (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Lockmanger service went down\n"); + +} + + +/** + * Transmit notify for sending message to server + * + * @param cls the message to send + * @param size number of bytes available in buf + * @param buf where the callee should write the message + * @return number of bytes written to buf + */ +static size_t +transmit_notify (void *cls, size_t size, void *buf) +{ + struct GNUNET_LOCKMANAGER_Message *msg = cls; + uint16_t msg_size; + + if ((0 == size) || (NULL == buf)) + { + /* FIXME: Timed out -- requeue? */ + return 0; + } + msg_size = ntohs (msg->header.size); + GNUNET_assert (size >= msg_size); + memcpy (buf, msg, msg_size); + GNUNET_free (msg); + return msg_size; +} + + + +/*******************/ +/* API Definitions */ +/*******************/ + /** * Connect to the lockmanager service * @@ -65,9 +186,20 @@ GNUNET_LOCKMANAGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) GNUNET_free (h); return NULL; } - return NULL; + + GNUNET_CLIENT_receive (h->conn, + &handle_server_crash, + NULL, + GNUNET_TIME_UNIT_FOREVER_REL); + + GNUNET_CLIENT_receive (h->conn, + &handle_success, + h, + GNUNET_TIME_UNIT_FOREVER_REL); + return h; } + /** * Disconnect from the lockmanager service * @@ -76,5 +208,106 @@ GNUNET_LOCKMANAGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) void GNUNET_LOCKMANAGER_disconnect (struct GNUNET_LOCKMANAGER_Handle *handle) { + GNUNET_CLIENT_disconnect (handle->conn); + GNUNET_free (handle); +} + + +/** + * Tries to acquire the given lock(even if the lock has been lost) until the + * request is called. If the lock is available the status_cb will be + * called. If the lock is busy then the request is queued and status_cb + * will be called when the lock has been made available and acquired by us. + * + * @param handle the handle to the lockmanager service + * + * @param domain_name name of the locking domain. Clients who want to share + * locks must use the same name for the locking domain. Also the + * domain_name should be selected with the prefix + * "GNUNET__" to avoid domain name collisions. + * + * + * @param lock which lock to lock + * + * @param status_cb the callback for signalling when the lock is acquired and + * when it is lost + * + * @param status_cb_cls the closure to the above callback + * + * @return the locking request handle for this request. It will be invalidated + * when status_cb is called. + */ +struct GNUNET_LOCKMANAGER_LockingRequest * +GNUNET_LOCKMANAGER_acquire_lock (struct GNUNET_LOCKMANAGER_Handle *handle, + const char *domain_name, + uint32_t lock, + GNUNET_LOCKMANAGER_StatusCallback + status_cb, + void *status_cb_cls) +{ + struct GNUNET_LOCKMANAGER_LockingRequest *r; + struct GNUNET_LOCKMANAGER_Message *msg; + uint16_t msg_size; + + + r = GNUNET_malloc (sizeof (struct GNUNET_LOCKMANAGER_LockingRequest)); + r->domain_name_length = strlen (domain_name) + 1; + r->handle = handle; + r->lock = lock; + r->domain = GNUNET_malloc (r->domain_name_length); + memcpy (r->domain, domain_name, r->domain_name_length); + msg_size = sizeof (struct GNUNET_LOCKMANAGER_Message) + r->domain_name_length; + msg = GNUNET_malloc (msg_size); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE); + msg->header.size = htons (msg_size); + msg->lock = htonl (lock); + memcpy (&msg[1], r->domain, r->domain_name_length); + + r->transmit_handle = + GNUNET_CLIENT_notify_transmit_ready (r->handle->conn, + msg_size, + TIMEOUT, + GNUNET_NO, + *transmit_notify, + msg); + return r; +} + + + +/** + * Function to cancel the locking request generated by + * GNUNET_LOCKMANAGER_acquire_lock. If the lock is acquired us then the lock is + * released. GNUNET_LOCKMANAGER_StatusCallback will not be called upon any + * status changes resulting due to this call. + * + * @param request the LockingRequest to cancel + */ +void +GNUNET_LOCKMANAGER_cancel_request (struct GNUNET_LOCKMANAGER_LockingRequest + *request) +{ + /* FIXME: Stop ACQUIRE retransmissions */ + if (GNUNET_LOCKMANAGER_SUCCESS == request->status) + { + struct GNUNET_LOCKMANAGER_Message *msg; + uint16_t msg_size; + + msg_size = sizeof (struct GNUNET_LOCKMANAGER_Message) + + request->domain_name_length; + msg = GNUNET_malloc (msg_size); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_RELEASE); + msg->header.size = htons (msg_size); + msg->lock = htonl (request->lock); + memcpy (&msg[1], request->domain, request->domain_name_length); + + GNUNET_CLIENT_notify_transmit_ready (request->handle->conn, + msg_size, + TIMEOUT, /* What if this fails */ + GNUNET_NO, + &transmit_notify, + msg); + } + GNUNET_free (request); } -- 2.25.1