resctl, client: emulate sucessful resource allocation if Murphy is down.
authorKrisztian Litkey <krisztian.litkey@intel.com>
Wed, 4 Jun 2014 17:07:33 +0000 (20:07 +0300)
committerKrisztian Litkey <krisztian.litkey@intel.com>
Thu, 5 Jun 2014 14:16:38 +0000 (17:16 +0300)
With this patch in place, the server will now try to emulate resource
allocation (acquire/release) handling whenever the resource connection
(IOW connection to Murphy) is down.

This is the first shot at such an emulation. Hence, there are probably
bugs lingering in there... At least there are a few known issues with
handling the corner cases of the murphy-down -> murphy-up transition
with active grants. When murphy comes up we ask for the handed out
resources on behalf of the clients. However at the moment we can't
filter out the resulting focus change events even if there's no change
from the clients point of view. I suspect there might be a few more
serious issues hiding in there as well... more testing required.

As a final note, it might be a good idea to make this configurable at
least that much that those who want can completely turn off emulated
resource acquisition and opt for always failing when the connection
is down.

src/daemon/client.c
src/daemon/resctl.c
src/daemon/resctl.h

index af58925..1c11828 100644 (file)
@@ -51,7 +51,7 @@ void client_reset_resources(srs_context_t *srs)
 
     mrp_list_foreach(&srs->clients, p, n) {
         c = mrp_list_entry(p, typeof(*c), hook);
-        c->rset = NULL;
+        srs_resctl_offline(c->rset);
     }
 }
 
@@ -64,7 +64,12 @@ void client_create_resources(srs_context_t *srs)
 
     mrp_list_foreach(&srs->clients, p, n) {
         c = mrp_list_entry(p, typeof(*c), hook);
-        c->rset = srs_resctl_create(srs, c->appclass, resource_event, c);
+
+        if (c->rset == NULL)
+            c->rset = srs_resctl_create(srs, c->appclass, resource_event, c);
+        else
+            srs_resctl_online(srs, c->rset);
+
         if (c->rset != NULL) {
             f = c->requested;
             c->requested = SRS_VOICE_FOCUS_NONE;
@@ -201,8 +206,7 @@ srs_client_t *client_create(srs_context_t *srs, srs_client_type_t type,
         return NULL;
     }
 
-    if (srs->rctx != NULL)
-        c->rset = srs_resctl_create(srs, c->appclass, resource_event, c);
+    c->rset = srs_resctl_create(srs, c->appclass, resource_event, c);
 
     mrp_list_append(&srs->clients, &c->hook);
 
@@ -345,7 +349,7 @@ void client_notify_command(srs_client_t *c, int index,
     if (!c->enabled)
         return;
 
-    if (!(c->granted & SRS_RESCTL_MASK_SREC))
+    if (c->rset != NULL && !(c->granted & SRS_RESCTL_MASK_SREC))
         return;
 
     if (0 <= index && index < c->ncommand) {
index 9358130..aab2fd7 100644 (file)
@@ -50,6 +50,7 @@ struct srs_resset_s {
     void                   *user_data;   /* opaque notification data */
     char                   *appclass;    /* application class */
     int                     shared : 1;  /* whether currently shared */
+    mrp_deferred_t         *emul;        /* deferred cb for emulation */
 };
 
 
@@ -61,6 +62,8 @@ static void stop_connect(srs_resctx_t *ctx);
 static void notify_connect(srs_resctx_t *ctx);
 static void notify_disconnect(srs_resctx_t *ctx, int requested);
 
+static int emul_acquire(srs_resset_t *set, int shared);
+static int emul_release(srs_resset_t *set);
 
 #define CONFIG_SREC  "resource.recognition"
 #define DEFAULT_SREC "speech_recognition"
@@ -217,14 +220,12 @@ static void notify_disconnect(srs_resctx_t *ctx, int requested)
     }
 
     e.type = SRS_RESCTL_EVENT_DESTROYED;
+
     mrp_list_foreach(&ctx->sets, p, n) {
         set = mrp_list_entry(p, typeof(*set), hook);
 
         if (set->cb != NULL)
             set->cb(&e, set->user_data);
-
-        mrp_list_delete(&set->hook);
-        mrp_free(set);
     }
 }
 
@@ -236,9 +237,6 @@ srs_resset_t *srs_resctl_create(srs_context_t *srs, char *appclass,
     srs_resset_t *set;
     int           shared;
 
-    if (ctx == NULL)
-        return NULL;
-
     set = mrp_allocz(sizeof(*set));
 
     if (set == NULL)
@@ -251,24 +249,13 @@ srs_resset_t *srs_resctl_create(srs_context_t *srs, char *appclass,
     set->shared    = shared = TRUE;
     set->appclass  = mrp_strdup(appclass);
 
-    set->set = mrp_res_create_resource_set(ctx->ctx, appclass, set_event, set);
-
-    if (set->set == NULL)
-        goto fail;
-
-    if (name_srec == NULL || name_ssyn == NULL)
-        get_resource_names(srs->settings);
-
-    if (!mrp_res_create_resource(ctx->ctx, set->set, name_srec, TRUE, shared) ||
-        !mrp_res_create_resource(ctx->ctx, set->set, name_ssyn, TRUE, shared))
-        goto fail;
-
-    mrp_list_append(&ctx->sets, &set->hook);
-
-    return set;
+    if (ctx == NULL || ctx->ctx == NULL || srs_resctl_online(srs, set)) {
+        mrp_list_append(&ctx->sets, &set->hook);
+        return set;
+    }
 
  fail:
-    if (set != NULL) {
+    if (ctx != NULL) {
         if (set->set != NULL)
             mrp_res_delete_resource_set(ctx->ctx, set->set);
 
@@ -285,6 +272,11 @@ void srs_resctl_destroy(srs_resset_t *set)
     srs_resctx_t *ctx = set ? set->ctx : NULL;
 
     if (set != NULL) {
+        if (set->emul != NULL) {
+            mrp_del_deferred(set->emul);
+            set->emul = NULL;
+        }
+
         if (ctx != NULL)
             mrp_res_delete_resource_set(ctx->ctx, set->set);
 
@@ -295,13 +287,57 @@ void srs_resctl_destroy(srs_resset_t *set)
 }
 
 
+int srs_resctl_online(srs_context_t *srs, srs_resset_t *set)
+{
+    srs_resctx_t *ctx    = srs->rctx;
+    int           shared = set->shared;
+
+    if (set == NULL)
+        return FALSE;
+
+    if (set->emul != NULL) {
+        mrp_del_deferred(set->emul);
+        set->emul = NULL;
+    }
+
+    set->ctx = ctx;
+    set->set = mrp_res_create_resource_set(ctx->ctx, set->appclass,
+                                           set_event, set);
+
+    if (set->set == NULL)
+        return FALSE;
+
+    if (name_srec == NULL || name_ssyn == NULL)
+        get_resource_names(srs->settings);
+
+    if (mrp_res_create_resource(ctx->ctx, set->set, name_srec, TRUE, shared) &&
+        mrp_res_create_resource(ctx->ctx, set->set, name_ssyn, TRUE, shared))
+        return TRUE;
+
+    mrp_res_delete_resource_set(ctx->ctx, set->set);
+    set->set = NULL;
+
+    return FALSE;
+}
+
+
+void srs_resctl_offline(srs_resset_t *set)
+{
+    if (set != NULL)
+        set->set = NULL;
+}
+
+
 int srs_resctl_acquire(srs_resset_t *set, int shared)
 {
     srs_resctx_t *ctx = set ? set->ctx : NULL;
 
-    if (ctx == NULL || ctx->ctx == NULL || set == NULL || set->set == NULL)
+    if (ctx == NULL)
         return FALSE;
 
+    if (ctx->ctx == NULL || set->set == NULL)
+        return emul_acquire(set, shared);
+
     if (!!shared != !!set->shared) {
         mrp_res_delete_resource_set(ctx->ctx, set->set);
         set->shared = !!shared;
@@ -339,9 +375,12 @@ int srs_resctl_release(srs_resset_t *set)
 {
     srs_resctx_t *ctx = set ? set->ctx : NULL;
 
-    if (ctx == NULL || ctx->ctx == NULL || set == NULL || set->set == NULL)
+    if (ctx == NULL)
         return FALSE;
 
+    if (ctx->ctx == NULL || set->set == NULL)
+        return emul_release(set);
+
     if (mrp_res_release_resource_set(ctx->ctx, set->set) >= 0)
         return TRUE;
     else
@@ -377,3 +416,77 @@ static void set_event(mrp_res_context_t *rctx,
 
     set->cb(&e, set->user_data);
 }
+
+
+static void emul_acquire_cb(mrp_deferred_t *d, void *user_data)
+{
+    srs_resset_t       *set = (srs_resset_t *)user_data;
+    srs_resctl_event_t  e;
+
+    mrp_del_deferred(d);
+
+    if (set->emul == d)
+        set->emul = NULL;
+
+    e.resource.type    = SRS_RESCTL_EVENT_RESOURCE;
+    e.resource.granted = SRS_RESCTL_MASK_SREC | SRS_RESCTL_MASK_SYNT;
+
+    set->cb(&e, set->user_data);
+}
+
+
+static int emul_acquire(srs_resset_t *set, int shared)
+{
+    srs_resctx_t *ctx = set ? set->ctx : NULL;
+
+    MRP_UNUSED(shared);
+
+    if (ctx == NULL)
+        return FALSE;
+
+    if (set->emul != NULL)
+        return FALSE;
+
+    set->emul = mrp_add_deferred(ctx->srs->ml, emul_acquire_cb, set);
+
+    if (set->emul != NULL)
+        return TRUE;
+    else
+        return FALSE;
+}
+
+
+static void emul_release_cb(mrp_deferred_t *d, void *user_data)
+{
+    srs_resset_t       *set = (srs_resset_t *)user_data;
+    srs_resctl_event_t  e;
+
+    mrp_del_deferred(d);
+
+    if (set->emul == d)
+        set->emul = NULL;
+
+    e.resource.type    = SRS_RESCTL_EVENT_RESOURCE;
+    e.resource.granted = 0;
+
+    set->cb(&e, set->user_data);
+}
+
+
+static int emul_release(srs_resset_t *set)
+{
+    srs_resctx_t *ctx = set ? set->ctx : NULL;
+
+    if (ctx == NULL)
+        return FALSE;
+
+    if (set->emul != NULL)
+        return FALSE;
+
+    set->emul = mrp_add_deferred(set->ctx->srs->ml, emul_release_cb, set);
+
+    if (set->emul != NULL)
+        return TRUE;
+    else
+        return FALSE;
+}
index 7dfd205..54e3687 100644 (file)
@@ -74,6 +74,9 @@ srs_resset_t *srs_resctl_create(srs_context_t *srs, char *appclass,
                                 srs_resctl_event_cb_t cb, void *user_data);
 void srs_resctl_destroy(srs_resset_t *set);
 
+int srs_resctl_online(srs_context_t *srs, srs_resset_t *set);
+void srs_resctl_offline(srs_resset_t *set);
+
 int srs_resctl_acquire(srs_resset_t *set, int shared);
 int srs_resctl_release(srs_resset_t *set);