session: start to manage concurrency
authorJosé Bollo <jose.bollo@iot.bzh>
Fri, 5 May 2017 10:04:25 +0000 (12:04 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Fri, 5 May 2017 10:12:05 +0000 (12:12 +0200)
Change-Id: I5895fa14fcb496e71fba600994e7e454cf1d110b
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
bindings/samples/DemoContext.c
src/afb-context.c
src/afb-context.h
src/afb-session.c
src/afb-session.h

index 66dc6cc..2667794 100644 (file)
@@ -67,6 +67,10 @@ static void myAction (struct afb_req request)
 {
     MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request);
 
+    if (!ctx) {
+       afb_req_fail(request, "invalid-state", "Can't perform action");
+       return;
+    }
     // store something in our plugin private client context
     ctx->count++;
     afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Check=[%d]\n", ctx->abcd, ctx->count);
@@ -80,6 +84,10 @@ static void myClose (struct afb_req request)
 {
     MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request);
 
+    if (!ctx) {
+        afb_req_success(request, NULL, NULL);
+       return;
+    }
     // store something in our plugin private client context
     ctx->count++;
     afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Close=[%d]\n", ctx->abcd, ctx->count);
index 9f5ddd3..83ce573 100644 (file)
@@ -109,6 +109,12 @@ const char *afb_context_sent_uuid(struct afb_context *context)
        return afb_session_uuid(context->session);
 }
 
+void *afb_context_data(struct afb_context *context, void *(*make_value)(void), void (*free_value)(void*))
+{
+       assert(context->session != NULL);
+       return afb_session_cookie(context->session, context->api_key, make_value, free_value);
+}
+
 void *afb_context_get(struct afb_context *context)
 {
        assert(context->session != NULL);
index ceda5d2..5560585 100644 (file)
@@ -47,6 +47,7 @@ extern const char *afb_context_sent_uuid(struct afb_context *context);
 
 extern void *afb_context_get(struct afb_context *context);
 extern void afb_context_set(struct afb_context *context, void *value, void (*free_value)(void*));
+extern void *afb_context_data(struct afb_context *context, void *(*make_value)(void), void (*free_value)(void*));
 
 extern void afb_context_close(struct afb_context *context);
 extern void afb_context_refresh(struct afb_context *context);
index 17fddd5..523cbf0 100644 (file)
@@ -50,6 +50,7 @@ struct afb_session
        int timeout;
        time_t expiration;    // expiration time of the token
        time_t access;
+       pthread_mutex_t mutex;
        char uuid[37];        // long term authentication of remote client
        char token[37];       // short term authentication of remote client
        struct cookie *cookies[COOKEYCOUNT];
@@ -85,6 +86,16 @@ static void new_uuid(char uuid[37])
        uuid_unparse_lower(newuuid, uuid);
 }
 
+static inline void lock(struct afb_session *session)
+{
+       pthread_mutex_lock(&session->mutex);
+}
+
+static inline void unlock(struct afb_session *session)
+{
+       pthread_mutex_unlock(&session->mutex);
+}
+
 // Free context [XXXX Should be protected again memory abort XXXX]
 static void free_data (struct afb_session *session)
 {
@@ -110,6 +121,7 @@ void afb_session_init (int max_session_count, int timeout, const char *initok)
 {
        // let's create as store as hashtable does not have any
        sessions.store = calloc (1 + (unsigned)max_session_count, sizeof(struct afb_session));
+       pthread_mutex_init(&sessions.mutex, NULL);
        sessions.max = max_session_count;
        sessions.timeout = timeout;
        if (initok == NULL)
@@ -224,11 +236,12 @@ static struct afb_session *make_session (const char *uuid, int timeout, time_t n
        struct afb_session *session;
 
        /* allocates a new one */
-       session = calloc(1, sizeof(struct afb_session));
+       session = calloc(1, sizeof *session);
        if (session == NULL) {
                errno = ENOMEM;
                goto error;
        }
+       pthread_mutex_init(&session->mutex, NULL);
 
        /* generate the uuid */
        if (uuid == NULL) {
@@ -322,6 +335,7 @@ void afb_session_unref(struct afb_session *session)
                --session->refcount;
                if (session->refcount == 0 && session->uuid[0] == 0) {
                        destroy (session);
+                       pthread_mutex_destroy(&session->mutex);
                        free(session);
                }
        }
@@ -382,52 +396,87 @@ const char *afb_session_token (struct afb_session *session)
        return session->token;
 }
 
-void *afb_session_get_cookie(struct afb_session *session, const void *key)
+static struct cookie *cookie_search(struct afb_session *session, const void *key, int *idx)
 {
        struct cookie *cookie;
-       int idx;
 
-       idx = cookeyidx(key);
-       cookie = session->cookies[idx];
-       while(cookie != NULL) {
-               if (cookie->key == key)
-                       return cookie->value;
+       cookie = session->cookies[*idx = cookeyidx(key)];
+       while(cookie != NULL && cookie->key != key)
                cookie = cookie->next;
-       }
-       return NULL;
+       return cookie;
 }
 
-int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*))
+static struct cookie *cookie_add(struct afb_session *session, int idx, const void *key, void *value, void (*freecb)(void*))
 {
        struct cookie *cookie;
+
+       cookie = malloc(sizeof *cookie);
+       if (!cookie)
+               errno = ENOMEM;
+       else {
+               cookie->key = key;
+               cookie->value = value;
+               cookie->freecb = freecb;
+               cookie->next = session->cookies[idx];
+               session->cookies[idx] = cookie;
+       }
+       return cookie;
+}
+
+void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void), void (*freecb)(void*))
+{
        int idx;
+       void *value;
+       struct cookie *cookie;
 
-       /* search for a replacement */
-       idx = cookeyidx(key);
-       cookie = session->cookies[idx];
-       while(cookie != NULL) {
-               if (cookie->key == key) {
-                       if (cookie->value != value && cookie->freecb)
-                               cookie->freecb(cookie->value);
-                       cookie->value = value;
-                       cookie->freecb = freecb;
-                       return 0;
+       lock(session);
+       cookie = cookie_search(session, key, &idx);
+       if (cookie)
+               value = cookie->value;
+       else {
+               value = makecb ? makecb() : NULL;
+               if (makecb || freecb) {
+                       cookie = cookie_add(session, idx, key, value, freecb);
+                       if (!cookie) {
+                               if (makecb && freecb)
+                                       free(value);
+                               value = NULL;
+                       }
                }
-               cookie = cookie->next;
        }
+       unlock(session);
+       return value;
+}
 
-       /* allocates */
-       cookie = malloc(sizeof *cookie);
-       if (cookie == NULL) {
-               errno = ENOMEM;
-               return -1;
-       }
+void *afb_session_get_cookie(struct afb_session *session, const void *key)
+{
+       int idx;
+       void *value;
+       struct cookie *cookie;
+
+       lock(session);
+       cookie = cookie_search(session, key, &idx);
+       value = cookie ? cookie->value : NULL;
+       unlock(session);
+       return value;
+}
+
+int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*))
+{
+       int idx;
+       struct cookie *cookie;
 
-       cookie->key = key;
-       cookie->value = value;
-       cookie->freecb = freecb;
-       cookie->next = session->cookies[idx];
-       session->cookies[idx] = cookie;
-       return 0;
+       lock(session);
+       cookie = cookie_search(session, key, &idx);
+       if (!cookie)
+               cookie = cookie_add(session, idx, key, value, freecb);
+       else {
+               if (cookie->value != value && cookie->freecb)
+                       cookie->freecb(cookie->value);
+               cookie->value = value;
+               cookie->freecb = freecb;
+       }
+       unlock(session);
+       return -!cookie;
 }
 
index afff671..e79d037 100644 (file)
@@ -35,5 +35,6 @@ extern void afb_session_new_token(struct afb_session *session);
 extern const char *afb_session_token(struct afb_session *session);
 
 extern void *afb_session_get_cookie(struct afb_session *session, const void *key);
+extern void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void), void (*freecb)(void*));
 extern int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*));