From f72ed770bc81e51aebbf456b4c83d58bcdbbbfd0 Mon Sep 17 00:00:00 2001 From: Ismo Puustinen Date: Tue, 4 Dec 2012 13:31:36 +0200 Subject: [PATCH] resource-c: cleaning up the code. --- src/Makefile.am | 10 +- .../resource-native/libmurphy-resource/api_test.c | 244 ++- .../resource-native/libmurphy-resource/attribute.c | 311 ++++ .../resource-native/libmurphy-resource/attribute.h | 46 + .../resource-native/libmurphy-resource/message.c | 686 +++++++++ .../resource-native/libmurphy-resource/message.h | 83 + .../libmurphy-resource/resource-api.h | 295 ++-- .../libmurphy-resource/resource-private.h | 84 +- .../resource-native/libmurphy-resource/resource.c | 1629 ++------------------ .../resource-native/libmurphy-resource/rset.c | 756 +++++++++ .../resource-native/libmurphy-resource/rset.h | 59 + .../libmurphy-resource/string_array.c | 92 ++ .../libmurphy-resource/string_array.h | 35 + 13 files changed, 2616 insertions(+), 1714 deletions(-) create mode 100644 src/plugins/resource-native/libmurphy-resource/attribute.c create mode 100644 src/plugins/resource-native/libmurphy-resource/attribute.h create mode 100644 src/plugins/resource-native/libmurphy-resource/message.c create mode 100644 src/plugins/resource-native/libmurphy-resource/message.h create mode 100644 src/plugins/resource-native/libmurphy-resource/rset.c create mode 100644 src/plugins/resource-native/libmurphy-resource/rset.h create mode 100644 src/plugins/resource-native/libmurphy-resource/string_array.c create mode 100644 src/plugins/resource-native/libmurphy-resource/string_array.h diff --git a/src/Makefile.am b/src/Makefile.am index 86b5640..2d9c060 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,7 +6,7 @@ SUBDIRS = murphy-db . \ BUILT_SOURCES = AM_CFLAGS = $(WARNING_CFLAGS) -I$(top_builddir) -DLIBDIR=\"@LIBDIR@\" -MURPHY_CFLAGS = +MURPHY_CFLAGS = pkgconfigdir = ${libdir}/pkgconfig bin_PROGRAMS = @@ -853,7 +853,11 @@ libmurphy_resource_la_HEADERS = \ plugins/resource-native/libmurphy-resource/resource-private.h libmurphy_resource_la_SOURCES = \ - plugins/resource-native/libmurphy-resource/resource.c + plugins/resource-native/libmurphy-resource/resource.c \ + plugins/resource-native/libmurphy-resource/attribute.c \ + plugins/resource-native/libmurphy-resource/rset.c \ + plugins/resource-native/libmurphy-resource/string_array.c \ + plugins/resource-native/libmurphy-resource/message.c libmurphy_resource_la_CFLAGS = \ $(AM_CFLAGS) \ @@ -887,7 +891,7 @@ BUILTIN_LIBS = LINKEDIN_PLUGINS = -plugin_LTLIBRARIES = +plugin_LTLIBRARIES = plugindir = $(libdir)/murphy/plugins diff --git a/src/plugins/resource-native/libmurphy-resource/api_test.c b/src/plugins/resource-native/libmurphy-resource/api_test.c index 56bd43f..0900141f 100644 --- a/src/plugins/resource-native/libmurphy-resource/api_test.c +++ b/src/plugins/resource-native/libmurphy-resource/api_test.c @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include #include @@ -6,100 +35,118 @@ #include typedef struct my_app_data { - murphy_resource_context *cx; - murphy_resource_set *rs; + mrp_res_context_t *cx; + mrp_res_resource_set_t *rs; } my_app_data; static bool accept_input; /* state callback for murphy connection */ -static void state_callback(murphy_resource_context *cx, - murphy_resource_error, - void *ud); +static void state_callback(mrp_res_context_t *cx, + mrp_res_error_t, + void *ud); /* callback for resource set update */ -static void resource_callback(murphy_resource_context *cx, - const murphy_resource_set *rs, - void *userdata); +static void resource_callback(mrp_res_context_t *cx, + const mrp_res_resource_set_t *rs, + void *userdata); void acquire_resources(my_app_data *app_data) { - murphy_resource *resource= NULL; + mrp_res_resource_t *resource = NULL; + mrp_res_attribute_t *attr; + + /* if we already have a decent set, just re-acquire it */ + if (app_data->rs) { + mrp_res_acquire_resource_set(app_data->cx, app_data->rs); + return; + } - /* create resource set and resources */ - app_data->rs = murphy_resource_set_create(app_data->cx, - "player", - resource_callback, - (void*)app_data); + /* otherwise create resource set and resources */ + app_data->rs = mrp_res_create_resource_set(app_data->cx, + "player", + resource_callback, + (void*)app_data); if (app_data->rs == NULL) { - printf("Couldn't create resource set\n"); - return; + printf("Couldn't create resource set\n"); + return; } - resource = murphy_resource_create(app_data->cx, - app_data->rs, - "audio_playback", - true, - false); + resource = mrp_res_create_resource(app_data->cx, + app_data->rs, + "audio_playback", + true, + false); if (resource == NULL) { - printf("Couldn't create audio resource\n"); - murphy_resource_set_delete(app_data->rs); - return; + printf("Couldn't create audio resource\n"); + mrp_res_delete_resource_set(app_data->cx, app_data->rs); + return; } - resource = murphy_resource_create(app_data->cx, - app_data->rs, - "video_playback", - true, - false); + /* set a resource attribute */ + attr = mrp_res_get_attribute_by_name(app_data->cx, resource, "role"); + + if (attr) { + mrp_res_set_attribute_string(app_data->cx, attr, "call"); + } + + resource = mrp_res_create_resource(app_data->cx, + app_data->rs, + "video_playback", + true, + false); if (resource == NULL) { - printf("Couldn't create video resource\n"); - murphy_resource_set_delete(app_data->rs); - return; + printf("Couldn't create video resource\n"); + mrp_res_delete_resource_set(app_data->cx, app_data->rs); + return; } + printf("created the resource set, acquiring now!\n"); + /* acquire the resources */ - murphy_resource_set_acquire(app_data->cx, app_data->rs); + mrp_res_acquire_resource_set(app_data->cx, app_data->rs); } void giveup_resources(my_app_data *app_data) { - printf("giving up resources\n"); - /* release resources */ - murphy_resource_set_release(app_data->cx, app_data->rs); + if (app_data->rs) + mrp_res_release_resource_set(app_data->cx, app_data->rs); } -static void state_callback(murphy_resource_context *context, - murphy_resource_error err, - void *userdata) +static void state_callback(mrp_res_context_t *context, + mrp_res_error_t err, + void *userdata) { int i = 0, j = 0; - const murphy_string_array *app_classes = NULL; - const murphy_resource_set *rs; - murphy_string_array *attributes = NULL; - murphy_resource_attribute *attr; + const mrp_res_string_array_t *app_classes = NULL; + const mrp_res_resource_set_t *rs; + mrp_res_string_array_t *attributes = NULL; + mrp_res_attribute_t *attr; bool system_handles_audio = FALSE; bool system_handles_video = FALSE; + mrp_res_resource_t *resource; - my_app_data *app_data = userdata; + my_app_data *app_data = (my_app_data *) userdata; - if (err != murphy_resource_error_none) { + if (err != MRP_RES_ERROR_NONE) { printf("error message received from Murphy\n"); return; } switch (context->state) { - case murphy_connected: + case MRP_RES_CONNECTED: + printf("connected to murphy\n"); - if ((app_classes = murphy_application_class_list(context)) != NULL) { + if ((app_classes = + mrp_res_list_application_classes(context)) != NULL) { printf("listing all application classes in the system\n"); for (i = 0; i < app_classes->num_strings; i++) { @@ -107,18 +154,21 @@ static void state_callback(murphy_resource_context *context, } } - if ((rs = murphy_resource_set_list(context)) != NULL) { - murphy_string_array *resource_names; + if ((rs = mrp_res_list_resources(context)) != NULL) { + mrp_res_string_array_t *resource_names; printf("listing all resources available in the system\n"); - resource_names = murphy_resource_list_names(context, rs); + resource_names = mrp_res_list_resource_names(context, rs); - for (i = 0; i < resource_names->num_strings; i++) { + if (!resource_names) { + printf("No resources available in the system!\n"); + return; + } - murphy_resource *resource; + for (i = 0; i < resource_names->num_strings; i++) { - resource = murphy_resource_get_by_name(context, rs, + resource = mrp_res_get_resource_by_name(context, rs, resource_names->strings[i]); printf("resource %d is %s\n", i, resource->name); @@ -127,33 +177,38 @@ static void state_callback(murphy_resource_context *context, if (strcmp(resource->name, "video_playback") == 0) system_handles_video = TRUE; - attributes = murphy_attribute_list_names(context, resource); + attributes = mrp_res_list_attribute_names(context, resource); for (j = 0; j < attributes->num_strings; j++) { - attr = murphy_attribute_get_by_name(context, + attr = mrp_res_get_attribute_by_name(context, resource, attributes->strings[i]); printf("attr %s has ", attr->name); switch(attr->type) { - case murphy_string: - printf("type string and value %s\n", attr->string); + case mrp_string: + printf("type string and value %s\n", + attr->string); break; - case murphy_int32: - printf("type string and value %d\n", attr->integer); + case mrp_int32: + printf("type string and value %d\n", + attr->integer); break; - case murphy_uint32: - printf("type string and value %u\n", attr->unsignd); + case mrp_uint32: + printf("type string and value %u\n", + attr->unsignd); break; - case murphy_double: - printf("type string and value %f\n", attr->floating); + case mrp_double: + printf("type string and value %f\n", + attr->floating); break; default: printf("type unknown\n"); break; } - } + mrp_res_free_string_array(attributes); } + mrp_res_free_string_array(resource_names); } if (system_handles_audio && system_handles_video) { @@ -163,40 +218,43 @@ static void state_callback(murphy_resource_context *context, break; - case murphy_disconnected: + case MRP_RES_DISCONNECTED: printf("disconnected from murphy\n"); - murphy_resource_set_delete(app_data->rs); - murphy_destroy(app_data->cx); + mrp_res_delete_resource_set(app_data->cx, app_data->rs); + mrp_res_destroy(app_data->cx); exit(1); } } -static void resource_callback(murphy_resource_context *cx, - const murphy_resource_set *rs, - void *userdata) +static void resource_callback(mrp_res_context_t *cx, + const mrp_res_resource_set_t *rs, + void *userdata) { my_app_data *my_data = (my_app_data *) userdata; - murphy_resource *res; + mrp_res_resource_t *res; + mrp_res_attribute_t *attr; + + printf("> resource_callback\n"); - if (!murphy_resource_set_equals(rs, my_data->rs)) + if (!mrp_res_equal_resource_set(rs, my_data->rs)) return; /* here compare the resource set difference */ - res = murphy_resource_get_by_name(cx, rs, "audio_playback"); + res = mrp_res_get_resource_by_name(cx, rs, "audio_playback"); if (!res) { - printf("audio_playback not present in resource set"); + printf("audio_playback not present in resource set\n"); return; } printf("resource 0 name %s\n", res->name); printf("resource 0 state %d\n", res->state); - res = murphy_resource_get_by_name(cx, rs, "video_playback"); + res = mrp_res_get_resource_by_name(cx, rs, "video_playback"); if (!res) { - printf("video_playback not present in resource set"); + printf("video_playback not present in resource set\n"); return; } @@ -209,11 +267,17 @@ static void resource_callback(murphy_resource_context *cx, * It's up to the user to make sure that there's a working reference * to the resource set. */ - murphy_resource_set_delete(my_data->rs); + mrp_res_delete_resource_set(cx, my_data->rs); /* copying must also have no semantic meaning */ - my_data->rs = murphy_resource_set_copy(rs); + my_data->rs = mrp_res_copy_resource_set(cx, rs); + + /* print the current role attribute */ + res = mrp_res_get_resource_by_name(cx, rs, "audio_playback"); + attr = mrp_res_get_attribute_by_name(cx, res, "role"); + + printf("attribute '%s' has role '%s'\n", res->name, attr->string); /* acquiring a copy of an existing release set means: * - acquired state: update, since otherwise no meaning @@ -221,7 +285,6 @@ static void resource_callback(murphy_resource_context *cx, * - lost state: update, since otherwise will fail * - available: update or acquire */ - } static void handle_input(mrp_mainloop_t *ml, mrp_io_watch_t *watch, int fd, @@ -249,10 +312,16 @@ static void handle_input(mrp_mainloop_t *ml, mrp_io_watch_t *watch, int fd, if (accept_input) { switch (buf[0]) { - case 'C': acquire_resources(app_data); + case 'C': + acquire_resources(app_data); break; - case 'D': giveup_resources(app_data); + case 'D': + giveup_resources(app_data); break; + case 'Q': + if (app_data->rs) + mrp_res_delete_resource_set(app_data->cx, app_data->rs); + mrp_mainloop_quit(ml, 0); default: break; } @@ -273,12 +342,23 @@ int main(int argc, char **argv) if ((ml = mrp_mainloop_create()) == NULL) exit(1); - app_data.cx = murphy_create(ml, state_callback, &app_data); + app_data.rs = NULL; + app_data.cx = mrp_res_create(ml, state_callback, &app_data); mask = MRP_IO_EVENT_IN | MRP_IO_EVENT_HUP | MRP_IO_EVENT_ERR; watch = mrp_add_io_watch(ml, fileno(stdin), mask, handle_input, &app_data); + if (!watch) + exit(1); + + /* start looping */ mrp_mainloop_run(ml); + mrp_res_destroy(app_data.cx); + mrp_mainloop_destroy(ml); + + app_data.cx = NULL; + app_data.rs = NULL; + return 0; } diff --git a/src/plugins/resource-native/libmurphy-resource/attribute.c b/src/plugins/resource-native/libmurphy-resource/attribute.c new file mode 100644 index 0000000..e98489b --- /dev/null +++ b/src/plugins/resource-native/libmurphy-resource/attribute.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "resource-api.h" + +#include "attribute.h" +#include "string_array.h" + +void mrp_attribute_array_free(mrp_res_attribute_t *arr, + uint32_t dim) +{ + uint32_t i; + mrp_res_attribute_t *attr; + + if (arr) { + for (i = 0; i < dim; i++) { + attr = arr + i; + + mrp_free((void *)attr->name); + + if (attr->type == mrp_string) + mrp_free((void *)attr->string); + } + mrp_free(arr); + } +} + + +void attribute_array_free(attribute_array_t *arr) +{ + uint32_t i; + attribute_t *attr; + + if (arr) { + for (i = 0; i < arr->dim; i++) { + attr = arr->elems + i; + + mrp_free((void *)attr->name); + + if (attr->type == 's') + mrp_free((void *)attr->string); + } + mrp_free(arr); + } +} + + +attribute_array_t *attribute_array_dup(uint32_t dim, attribute_t *arr) +{ + size_t size; + uint32_t i; + attribute_t *sattr, *dattr; + attribute_array_t *dup; + int err; + + MRP_ASSERT(dim < ARRAY_MAX && arr, "invalid argument"); + + if (!dim && arr) { + for (dim = 0; arr[dim].name; dim++) + ; + } + + size = sizeof(attribute_array_t) + (sizeof(attribute_t) * (dim + 1)); + + if (!(dup = mrp_allocz(size))) { + err = ENOMEM; + goto failed; + } + + dup->dim = dim; + + for (i = 0; i < dim; i++) { + sattr = arr + i; + dattr = dup->elems + i; + + if (!(dattr->name = mrp_strdup(sattr->name))) { + err = ENOMEM; + goto failed; + } + + switch ((dattr->type = sattr->type)) { + case 's': + if (!(dattr->string = mrp_strdup(sattr->string))) { + err = ENOMEM; + goto failed; + } + break; + case 'i': + dattr->integer = sattr->integer; + break; + case 'u': + dattr->unsignd = sattr->unsignd; + break; + case 'f': + dattr->floating = sattr->floating; + break; + default: + err = EINVAL; + goto failed; + } + } + + return dup; + + failed: + attribute_array_free(dup); + errno = err; + return NULL; +} + + +mrp_res_attribute_t *mrp_attribute_array_dup(uint32_t dim, + mrp_res_attribute_t *arr) +{ + size_t size; + uint32_t i; + mrp_res_attribute_t *sattr, *dattr; + mrp_res_attribute_t *dup; + int err; + + size = (sizeof(mrp_res_attribute_t) * (dim + 1)); + + if (!(dup = mrp_allocz(size))) { + err = ENOMEM; + goto failed; + } + + for (i = 0; i < dim; i++) { + sattr = arr + i; + dattr = dup + i; + + if (!(dattr->name = mrp_strdup(sattr->name))) { + err = ENOMEM; + goto failed; + } + + switch ((dattr->type = sattr->type)) { + case mrp_string: + if (!(dattr->string = mrp_strdup(sattr->string))) { + err = ENOMEM; + goto failed; + } + break; + case mrp_int32: + dattr->integer = sattr->integer; + break; + case mrp_uint32: + dattr->type = mrp_uint32; + dattr->unsignd = sattr->unsignd; + break; + case mrp_double: + dattr->type = mrp_double; + dattr->floating = sattr->floating; + break; + default: + err = EINVAL; + goto failed; + } + } + + return dup; + + failed: + mrp_attribute_array_free(dup, dim); + errno = err; + return NULL; +} + +/* public API */ + +mrp_res_string_array_t * mrp_res_list_attribute_names(mrp_res_context_t *cx, + const mrp_res_resource_t *res) +{ + int i; + mrp_res_string_array_t *ret; + + if (!cx || !res) + return NULL; + + ret = mrp_allocz(sizeof(mrp_res_string_array_t)); + + if (!ret) + return NULL; + + ret->num_strings = res->priv->num_attributes; + ret->strings = mrp_allocz_array(const char *, res->priv->num_attributes); + + if (!ret->strings) { + mrp_free(ret); + return NULL; + } + + for (i = 0; i < res->priv->num_attributes; i++) { + ret->strings[i] = mrp_strdup(res->priv->attrs[i].name); + if (!ret->strings[i]) { + ret->num_strings = i; + mrp_res_free_string_array(ret); + return NULL; + } + } + + return ret; +} + + + +mrp_res_attribute_t * mrp_res_get_attribute_by_name( + mrp_res_context_t *cx, mrp_res_resource_t *res, const char *name) +{ + int i; + + if (!cx || !res) + return NULL; + + for (i = 0; i < res->priv->num_attributes; i++) { + if (strcmp(name, res->priv->attrs[i].name) == 0) { + return &res->priv->attrs[i]; + } + } + + return NULL; +} + + +int mrp_res_set_attribute_string(mrp_res_context_t *cx, + mrp_res_attribute_t *attr, const char *value) +{ + char *str; + + if (!cx || !attr) + return -1; + + /* check the attribute type */ + + if (attr->type != mrp_string) + return -1; + + str = mrp_strdup(value); + + if (!str) + return -1; + + mrp_free((void *) attr->string); + attr->string = str; + + return 0; +} + + +int mrp_res_set_attribute_uint(mrp_res_context_t *cx, + mrp_res_attribute_t *attr, uint32_t value) +{ + if (!cx || !attr || attr->type != mrp_uint32) + return -1; + + attr->unsignd = value; + + return 0; +} + + +int mrp_res_set_attribute_int(mrp_res_context_t *cx, + mrp_res_attribute_t *attr, int32_t value) +{ + if (!cx || !attr || attr->type != mrp_int32) + return -1; + + attr->integer = value; + + return 0; +} + + +int mrp_res_set_attribute_double(mrp_res_context_t *cx, + mrp_res_attribute_t *attr, double value) +{ + if (!cx || !attr || attr->type != mrp_double) + return -1; + + attr->floating = value; + + return 0; +} \ No newline at end of file diff --git a/src/plugins/resource-native/libmurphy-resource/attribute.h b/src/plugins/resource-native/libmurphy-resource/attribute.h new file mode 100644 index 0000000..c815594 --- /dev/null +++ b/src/plugins/resource-native/libmurphy-resource/attribute.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "resource-private.h" + +#define ATTRIBUTE_MAX 32 + +/* TODO: refactor so that there is only one dup/free set left */ + +void mrp_attribute_array_free(mrp_res_attribute_t *arr, + uint32_t dim); + +void attribute_array_free(attribute_array_t *arr); + +mrp_res_attribute_t *mrp_attribute_array_dup(uint32_t dim, + mrp_res_attribute_t *arr); + +attribute_array_t *attribute_array_dup(uint32_t dim, attribute_t *arr); diff --git a/src/plugins/resource-native/libmurphy-resource/message.c b/src/plugins/resource-native/libmurphy-resource/message.c new file mode 100644 index 0000000..1b2849f --- /dev/null +++ b/src/plugins/resource-native/libmurphy-resource/message.c @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "message.h" + +#include "rset.h" +#include "attribute.h" + +bool fetch_resource_set_state(mrp_msg_t *msg, void **pcursor, + mrp_resproto_state_t *pstate) +{ + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != RESPROTO_RESOURCE_STATE || type != MRP_MSG_FIELD_UINT16) + { + *pstate = 0; + return false; + } + + *pstate = value.u16; + return true; +} + + +bool fetch_resource_set_mask(mrp_msg_t *msg, void **pcursor, + int mask_type, mrp_resproto_state_t *pmask) +{ + uint16_t expected_tag; + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + + switch (mask_type) { + case 0: expected_tag = RESPROTO_RESOURCE_GRANT; break; + case 1: expected_tag = RESPROTO_RESOURCE_ADVICE; break; + default: /* don't know what to fetch */ return false; + } + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != expected_tag || type != MRP_MSG_FIELD_UINT32) + { + *pmask = 0; + return false; + } + + *pmask = value.u32; + return true; +} + + +bool fetch_resource_set_id(mrp_msg_t *msg, void **pcursor,uint32_t *pid) +{ + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != RESPROTO_RESOURCE_SET_ID || type != MRP_MSG_FIELD_UINT32) + { + *pid = 0; + return false; + } + + *pid = value.u32; + return true; +} + + +bool fetch_mrp_str_array(mrp_msg_t *msg, void **pcursor, + uint16_t expected_tag, mrp_res_string_array_t **parr) +{ + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != expected_tag || type != MRP_MSG_FIELD_ARRAY_OF(STRING)) + { + *parr = mrp_str_array_dup(0, NULL); + return false; + } + + if (!(*parr = mrp_str_array_dup(size, (const char **)value.astr))) + return false; + + return true; +} + + +bool fetch_seqno(mrp_msg_t *msg, void **pcursor, uint32_t *pseqno) +{ + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != RESPROTO_SEQUENCE_NO || type != MRP_MSG_FIELD_UINT32) + { + *pseqno = 0; + return -1; + } + + *pseqno = value.u32; + return 0; +} + + +int fetch_request(mrp_msg_t *msg, void **pcursor, uint16_t *preqtype) +{ + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != RESPROTO_REQUEST_TYPE || type != MRP_MSG_FIELD_UINT16) + { + *preqtype = 0; + return -1; + } + + *preqtype = value.u16; + return 0; +} + + +bool fetch_status(mrp_msg_t *msg, void **pcursor, int *pstatus) +{ + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != RESPROTO_REQUEST_STATUS || type != MRP_MSG_FIELD_SINT16) + { + *pstatus = EIO; + return false; + } + + *pstatus = value.s16; + return true; +} + + + +int fetch_attribute_array(mrp_msg_t *msg, void **pcursor, + size_t dim, attribute_t *arr) +{ + attribute_t *attr; + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + size_t i; + + i = 0; + + while (mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size)) { + if (tag == RESPROTO_SECTION_END && type == MRP_MSG_FIELD_UINT8) + break; + + if (tag != RESPROTO_ATTRIBUTE_NAME || + type != MRP_MSG_FIELD_STRING || + i >= dim - 1) { + return -1; + } + + attr = arr + i++; + attr->name = value.str; + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != RESPROTO_ATTRIBUTE_VALUE) { + return -1; + } + + switch (type) { + case MRP_MSG_FIELD_STRING: + attr->type = 's'; + attr->string = value.str; + break; + case MRP_MSG_FIELD_SINT32: + attr->type = 'i'; + attr->integer = value.s32; + break; + case MRP_MSG_FIELD_UINT32: + attr->type = 'u'; + attr->unsignd = value.u32; + break; + case MRP_MSG_FIELD_DOUBLE: + attr->type = 'f'; + attr->floating = value.dbl; + break; + default: + return -1; + } + } + + memset(arr + i, 0, sizeof(attribute_t)); + + return 0; +} + + +bool fetch_resource_name(mrp_msg_t *msg, void **pcursor, + const char **pname) +{ + uint16_t tag; + uint16_t type; + mrp_msg_value_t value; + size_t size; + + if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || + tag != RESPROTO_RESOURCE_NAME || type != MRP_MSG_FIELD_STRING) + { + *pname = ""; + return false; + } + + *pname = value.str; + return true; +} + + + +static void priv_attr_to_mrp_attr(attribute_t *attr, + mrp_res_attribute_t *attribute) { + + if (attr == NULL || attribute == NULL) + return; + + attribute->name = mrp_strdup(attr->name); + + switch (attr->type) { + case 's': + attribute->type = mrp_string; + attribute->string = mrp_strdup(attr->string); + break; + case 'i': + attribute->type = mrp_int32; + attribute->integer = attr->integer; + break; + case 'u': + attribute->type = mrp_uint32; + attribute->unsignd = attr->unsignd; + break; + case 'f': + attribute->type = mrp_double; + attribute->floating = attr->floating; + break; + default: + attribute->type = mrp_invalid; + } +} + + +static int priv_res_to_mrp_res(resource_def_t *src, mrp_res_resource_t *dst) { + + uint32_t i = 0; + + dst->name = mrp_strdup(src->name); + dst->state = MRP_RES_RESOURCE_LOST; + dst->priv->mandatory = false; + dst->priv->shared = false; + dst->priv->num_attributes = src->attrs->dim; + + dst->priv->attrs = mrp_allocz( + sizeof(mrp_res_attribute_t) * src->attrs->dim); + + for (i = 0; i < src->attrs->dim; i++) { + priv_attr_to_mrp_attr(&src->attrs->elems[i], &dst->priv->attrs[i]); + } + return 0; +} + + + + +mrp_res_resource_set_t *resource_query_response(mrp_msg_t *msg, + void **pcursor) +{ + int status; + uint32_t dim, i; + resource_def_t rdef[RESOURCE_MAX]; + attribute_t attrs[ATTRIBUTE_MAX + 1]; + resource_def_t *src; + mrp_res_resource_set_t *arr = NULL; + + if (!fetch_status(msg, pcursor, &status)) + goto failed; + + if (status != 0) + printf("Resource query failed (%u): %s\n", status, strerror(status)); + else { + dim = 0; + + while (fetch_resource_name(msg, pcursor, &rdef[dim].name)) { + if (fetch_attribute_array(msg, pcursor, ATTRIBUTE_MAX+1, attrs) < 0) + goto failed; + + if (!(rdef[dim].attrs = attribute_array_dup(0, attrs))) { + mrp_log_error("failed to duplicate attributes"); + return NULL; + } + + dim++; + } + + arr = mrp_allocz(sizeof(mrp_res_resource_set_t)); + + if (!arr) + goto failed; + + arr->priv = mrp_allocz(sizeof(mrp_res_resource_set_private_t)); + + if (!arr->priv) + goto failed; + + arr->application_class = NULL; + arr->state = MRP_RES_RESOURCE_LOST; + arr->priv->num_resources = dim; + + arr->priv->resources = mrp_allocz_array(mrp_res_resource_t *, dim); + + if (!arr->priv->resources) + goto failed; + + for (i = 0; i < dim; i++) { + src = rdef + i; + arr->priv->resources[i] = mrp_allocz(sizeof(mrp_res_resource_t)); + if (!arr->priv->resources[i]) { + arr->priv->num_resources = i; + goto failed; + } + arr->priv->resources[i]->priv = + mrp_allocz(sizeof(mrp_res_resource_private_t)); + if (!arr->priv->resources[i]->priv) { + mrp_free(arr->priv->resources[i]); + arr->priv->num_resources = i; + goto failed; + } + priv_res_to_mrp_res(src, arr->priv->resources[i]); + attribute_array_free(rdef[i].attrs); + } + } + + return arr; + + failed: + mrp_log_error("malformed reply to resource query"); + free_resource_set(arr); + + return NULL; +} + + +mrp_res_string_array_t *class_query_response(mrp_msg_t *msg, void **pcursor) +{ + int status; + mrp_res_string_array_t *arr = NULL; + + if (!fetch_status(msg, pcursor, &status) || (status == 0 && + !fetch_mrp_str_array(msg, pcursor, RESPROTO_CLASS_NAME, &arr))) + { + mrp_log_error("ignoring malformed response to class query"); + return NULL; + } + + if (status) { + mrp_log_error("class query failed with error code %u", status); + mrp_res_free_string_array(arr); + return NULL; + } + + return arr; +} + + +bool create_resource_set_response(mrp_msg_t *msg, + mrp_res_resource_set_t *rset, void **pcursor) +{ + int status; + uint32_t rset_id; + + if (!fetch_status(msg, pcursor, &status) || (status == 0 && + !fetch_resource_set_id(msg, pcursor, &rset_id))) + { + mrp_log_error("ignoring malformed response to resource set creation"); + goto error; + } + + if (status) { + mrp_log_error("creation of resource set failed. error code %u",status); + goto error; + } + + rset->priv->id = rset_id; + + return true; +error: + return false; +} + + +mrp_res_resource_set_t *acquire_resource_set_response(mrp_msg_t *msg, + mrp_res_context_t *cx, void **pcursor) +{ + int status; + uint32_t rset_id; + mrp_res_resource_set_t *rset = NULL; + + if (!fetch_resource_set_id(msg, pcursor, &rset_id) || + !fetch_status(msg, pcursor, &status)) + { + mrp_log_error("ignoring malformed response to resource set"); + goto error; + } + + if (status) { + mrp_log_error("acquiring of resource set failed. error code %u",status); + goto error; + } + + /* we need the previous resource set because the new one doesn't + * tell us the resource set class */ + + rset = mrp_htbl_lookup(cx->priv->rset_mapping, u_to_p(rset_id)); + + if (!rset) { + printf("no rset found!\n"); + goto error; + } + + return rset; + +error: + return NULL; +} + + +int acquire_resource_set_request(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset) +{ + mrp_msg_t *msg = NULL; + + if (!cx->priv->connected) + goto error; + + rset->priv->seqno = cx->priv->next_seqno; + + msg = mrp_msg_create( + RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, cx->priv->next_seqno++, + RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, + RESPROTO_ACQUIRE_RESOURCE_SET, + RESPROTO_RESOURCE_SET_ID, MRP_MSG_FIELD_UINT32, rset->priv->id, + RESPROTO_MESSAGE_END); + + if (!msg) + goto error; + + + if (!mrp_transport_send(cx->priv->transp, msg)) + goto error; + + mrp_msg_unref(msg); + return 0; + +error: + mrp_msg_unref(msg); + return -1; +} + + +int release_resource_set_request(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset) +{ + mrp_msg_t *msg = NULL; + + if (!cx->priv->connected) + goto error; + + rset->priv->seqno = cx->priv->next_seqno; + + msg = mrp_msg_create( + RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, cx->priv->next_seqno++, + RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, + RESPROTO_RELEASE_RESOURCE_SET, + RESPROTO_RESOURCE_SET_ID, MRP_MSG_FIELD_UINT32, rset->priv->id, + RESPROTO_MESSAGE_END); + + if (!msg) + goto error; + + if (!mrp_transport_send(cx->priv->transp, msg)) + goto error; + + mrp_msg_unref(msg); + return 0; + +error: + mrp_msg_unref(msg); + return -1; +} + + +int create_resource_set_request(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset) +{ + mrp_msg_t *msg = NULL; + int i; + + if (!cx || !rset) + return -1; + + if (!cx->priv->connected) + goto error; + + rset->priv->seqno = cx->priv->next_seqno; + + + msg = mrp_msg_create( + RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, cx->priv->next_seqno++, + RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, + RESPROTO_CREATE_RESOURCE_SET, + RESPROTO_RESOURCE_FLAGS, MRP_MSG_FIELD_UINT32, 0, + RESPROTO_RESOURCE_PRIORITY, MRP_MSG_FIELD_UINT32, 0, + RESPROTO_CLASS_NAME, MRP_MSG_FIELD_STRING, rset->application_class, + RESPROTO_ZONE_NAME, MRP_MSG_FIELD_STRING, cx->zone, + RESPROTO_MESSAGE_END); + + if (!msg) + goto error; + + for (i = 0; i < rset->priv->num_resources; i++) { + int j; + uint32_t flags = 0; + mrp_res_resource_t *res = rset->priv->resources[i]; + + if (!res) + goto error; + + printf(" adding %s\n", res->name); + + if (res->priv->shared) + flags |= RESPROTO_RESFLAG_SHARED; + + if (res->priv->mandatory) + flags |= RESPROTO_RESFLAG_MANDATORY; + + mrp_msg_append(msg, RESPROTO_RESOURCE_NAME, MRP_MSG_FIELD_STRING, + res->name); + mrp_msg_append(msg, RESPROTO_RESOURCE_FLAGS, MRP_MSG_FIELD_UINT32, + flags); + + for (j = 0; j < res->priv->num_attributes; j++) { + mrp_res_attribute_t *elem = &res->priv->attrs[j]; + const char *attr_name = elem->name; + + mrp_msg_append(msg, RESPROTO_ATTRIBUTE_NAME, MRP_MSG_FIELD_STRING, + attr_name); + + switch (elem->type) { + case 's': + mrp_msg_append(msg, RESPROTO_ATTRIBUTE_VALUE, + MRP_MSG_FIELD_STRING, elem->string); + break; + case 'i': + mrp_msg_append(msg, RESPROTO_ATTRIBUTE_VALUE, + MRP_MSG_FIELD_SINT32, elem->integer); + break; + case 'u': + mrp_msg_append(msg, RESPROTO_ATTRIBUTE_VALUE, + MRP_MSG_FIELD_UINT32, elem->unsignd); + break; + case 'f': + mrp_msg_append(msg, RESPROTO_ATTRIBUTE_VALUE, + MRP_MSG_FIELD_DOUBLE, elem->floating); + break; + default: + break; + } + } + + mrp_msg_append(msg, RESPROTO_SECTION_END, MRP_MSG_FIELD_UINT8, 0); + } + + if (!mrp_transport_send(cx->priv->transp, msg)) + goto error; + + mrp_msg_unref(msg); + return 0; + +error: + mrp_msg_unref(msg); + return -1; +} + + + +int get_application_classes(mrp_res_context_t *cx) +{ + mrp_msg_t *msg = NULL; + + if (!cx->priv->connected) + goto error; + + msg = mrp_msg_create(RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, 0, + RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, RESPROTO_QUERY_CLASSES, + RESPROTO_MESSAGE_END); + + if (!msg) + goto error; + + if (!mrp_transport_send(cx->priv->transp, msg)) + goto error; + + mrp_msg_unref(msg); + return 0; + +error: + mrp_msg_unref(msg); + return -1; +} + + +int get_available_resources(mrp_res_context_t *cx) +{ + mrp_msg_t *msg = NULL; + + if (!cx->priv->connected) + goto error; + + msg = mrp_msg_create(RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, 0, + RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, + RESPROTO_QUERY_RESOURCES, + RESPROTO_MESSAGE_END); + + if (!msg) + goto error; + + if (!mrp_transport_send(cx->priv->transp, msg)) + goto error; + + mrp_msg_unref(msg); + return 0; + +error: + mrp_msg_unref(msg); + return -1; +} diff --git a/src/plugins/resource-native/libmurphy-resource/message.h b/src/plugins/resource-native/libmurphy-resource/message.h new file mode 100644 index 0000000..5918c6a --- /dev/null +++ b/src/plugins/resource-native/libmurphy-resource/message.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "resource-private.h" +#include "string_array.h" + + +bool fetch_resource_set_state(mrp_msg_t *msg, void **pcursor, + mrp_resproto_state_t *pstate); + +bool fetch_resource_set_mask(mrp_msg_t *msg, void **pcursor, + int mask_type, mrp_resproto_state_t *pmask); + +bool fetch_resource_set_id(mrp_msg_t *msg, void **pcursor,uint32_t *pid); + +bool fetch_mrp_str_array(mrp_msg_t *msg, void **pcursor, + uint16_t expected_tag, mrp_res_string_array_t **parr); + +bool fetch_seqno(mrp_msg_t *msg, void **pcursor, uint32_t *pseqno); + +int fetch_request(mrp_msg_t *msg, void **pcursor, uint16_t *preqtype); + +bool fetch_status(mrp_msg_t *msg, void **pcursor, int *pstatus); + +int fetch_attribute_array(mrp_msg_t *msg, void **pcursor, + size_t dim, attribute_t *arr); + +bool fetch_resource_name(mrp_msg_t *msg, void **pcursor, + const char **pname); + + +mrp_res_resource_set_t *resource_query_response(mrp_msg_t *msg, + void **pcursor); + +mrp_res_string_array_t *class_query_response(mrp_msg_t *msg, void **pcursor); + +bool create_resource_set_response(mrp_msg_t *msg, + mrp_res_resource_set_t *rset, void **pcursor); + +mrp_res_resource_set_t *acquire_resource_set_response(mrp_msg_t *msg, + mrp_res_context_t *cx, void **pcursor); + +int acquire_resource_set_request(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset); + +int release_resource_set_request(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset); + +int create_resource_set_request(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset); + + +int get_application_classes(mrp_res_context_t *cx); + + +int get_available_resources(mrp_res_context_t *cx); diff --git a/src/plugins/resource-native/libmurphy-resource/resource-api.h b/src/plugins/resource-native/libmurphy-resource/resource-api.h index 7a6fd60..d7fa2f9 100644 --- a/src/plugins/resource-native/libmurphy-resource/resource-api.h +++ b/src/plugins/resource-native/libmurphy-resource/resource-api.h @@ -1,71 +1,101 @@ -#ifndef foomurphyresourceapifoo -#define foomurphyresourceapifoo +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MURPHY_RESOURCE_API_H__ +#define __MURPHY_RESOURCE_API_H__ #include -typedef struct murphy_resource_context_private_s murphy_resource_context_private_t; -typedef struct murphy_resource_private_s murphy_resource_private_t; -typedef struct murphy_resource_set_private_s murphy_resource_set_private_t; - -typedef enum murphy_connection_state_ { - murphy_connected, - murphy_disconnected, -} murphy_connection_state; - -typedef enum murphy_resource_state_ { - murphy_resource_lost, - murphy_resource_pending, - murphy_resource_acquired, - murphy_resource_available, -} murphy_resource_state; - -typedef enum murphy_resource_error_ { - murphy_resource_error_none, - murphy_resource_error_connection_lost, - murphy_resource_error_internal, - murphy_resource_error_malformed, -} murphy_resource_error; - -typedef struct murphy_resource_context_ { - murphy_connection_state state; - murphy_resource_context_private_t *priv; -} murphy_resource_context; - -typedef enum murphy_attribute_type_ { - murphy_int32 = 'i', - murphy_uint32 = 'u', - murphy_double = 'f', - murphy_string = 's', - murphy_invalid = '\0' -} murphy_attribute_type; - -typedef struct murphy_resource_attribute_ { - const char *name; - murphy_attribute_type type; +typedef struct mrp_res_context_private_s mrp_res_context_private_t; +typedef struct mrp_res_resource_private_s mrp_res_resource_private_t; +typedef struct mrp_res_resource_set_private_s mrp_res_resource_set_private_t; + +typedef enum { + MRP_RES_CONNECTED, + MRP_RES_DISCONNECTED, +} mrp_res_connection_state_t; + +typedef enum { + MRP_RES_RESOURCE_LOST, + MRP_RES_RESOURCE_PENDING, + MRP_RES_RESOURCE_ACQUIRED, + MRP_RES_RESOURCE_AVAILABLE, +} mrp_res_resource_state_t; + +typedef enum { + MRP_RES_ERROR_NONE, + MRP_RES_ERROR_CONNECTION_LOST, + MRP_RES_ERROR_INTERNAL, + MRP_RES_ERROR_MALFORMED, +} mrp_res_error_t; + +typedef struct { + mrp_res_connection_state_t state; + const char *zone; + mrp_res_context_private_t *priv; +} mrp_res_context_t; + +typedef enum { + mrp_int32 = 'i', + mrp_uint32 = 'u', + mrp_double = 'f', + mrp_string = 's', + mrp_invalid = '\0' +} mrp_res_attribute_type_t; + +typedef struct { + const char *name; + mrp_res_attribute_type_t type; union { const char *string; - int32_t integer; - uint32_t unsignd; - double floating; + int32_t integer; + uint32_t unsignd; + double floating; }; -} murphy_resource_attribute; +} mrp_res_attribute_t; -typedef struct murphy_resource_ { - const char *name; - murphy_resource_state state; - murphy_resource_private_t *priv; -} murphy_resource; +typedef struct { + const char *name; + mrp_res_resource_state_t state; + mrp_res_resource_private_t *priv; +} mrp_res_resource_t; -typedef struct murphy_resource_set_ { - const char *application_class; - murphy_resource_state state; - murphy_resource_set_private_t *priv; -} murphy_resource_set; +typedef struct { + const char *application_class; + mrp_res_resource_state_t state; + mrp_res_resource_set_private_t *priv; +} mrp_res_resource_set_t; -typedef struct murphy_string_array_ { +typedef struct { int num_strings; const char **strings; -} murphy_string_array; +} mrp_res_string_array_t; /** * Prototype for murphy state callback. You have to be in @@ -76,9 +106,8 @@ typedef struct murphy_string_array_ { * @param err error message. * @param userdata data you gave when starting to connect. */ -typedef void (*murphy_state_callback) (murphy_resource_context *cx, - murphy_resource_error err, - void *userdata); +typedef void (*mrp_res_state_callback_t) (mrp_res_context_t *cx, + mrp_res_error_t err, void *userdata); /** * Prototype for resource update callback. All changes related to @@ -91,9 +120,8 @@ typedef void (*murphy_state_callback) (murphy_resource_context *cx, * @param set updated resource set for you to handle. * @param userdata data you gave when starting to acquire resources. */ -typedef void (*murphy_resource_callback) (murphy_resource_context *cx, - const murphy_resource_set *set, - void *userdata); +typedef void (*mrp_res_resource_callback_t) (mrp_res_context_t *cx, + const mrp_res_resource_set_t *rs, void *userdata); /** * Connect to murphy. You have to wait for the callback @@ -106,23 +134,23 @@ typedef void (*murphy_resource_callback) (murphy_resource_context *cx, * * @return pointer to the newly created resource context. */ -murphy_resource_context *murphy_create(mrp_mainloop_t *ml, - murphy_state_callback cb, - void *userdata); +mrp_res_context_t *mrp_res_create(mrp_mainloop_t *ml, + mrp_res_state_callback_t cb, void *userdata); /** * Disconnect from murphy. * * @param cx Murphy connection context to destroy. */ -void murphy_destroy(murphy_resource_context *cx); +void mrp_res_destroy(mrp_res_context_t *cx); /** * List possible application classes that you can assign yourself * when asking for resources. This info is cached to the client * library when creating the connection so it will be synchronous. */ -const murphy_string_array * murphy_application_class_list(murphy_resource_context *cx); +const mrp_res_string_array_t * mrp_res_list_application_classes( + mrp_res_context_t *cx); /** * List all possible resources that you can try to acquire. This info @@ -131,7 +159,7 @@ const murphy_string_array * murphy_application_class_list(murphy_resource_contex * modify or use as your own resource set. It is only meant for * introspecting the possible resources. */ -const murphy_resource_set * murphy_resource_set_list(murphy_resource_context *cx); +const mrp_res_resource_set_t * mrp_res_list_resources(mrp_res_context_t *cx); /** * Create new empty resource set. This is a resource set allocated @@ -144,18 +172,17 @@ const murphy_resource_set * murphy_resource_set_list(murphy_resource_context *cx * * @return pointer to a new empty resource set. */ -murphy_resource_set * murphy_resource_set_create(murphy_resource_context *cx, - const char *app_class, - murphy_resource_callback cb, - void *userdata); +mrp_res_resource_set_t * mrp_res_create_resource_set(mrp_res_context_t *cx, + const char *app_class, mrp_res_resource_callback_t cb, void *userdata); /** - * Delete resource set created with murphy_resource_set_create - * or murphy_resource_set_copy. + * Delete resource set created with mrp_res_create_resource_set + * or mrp_res_copy_resource_set. * * @param set pointer to existing resource set created by the user. */ -void murphy_resource_set_delete(murphy_resource_set *set); +void mrp_res_delete_resource_set(mrp_res_context_t *cx, + mrp_res_resource_set_t *rs); /** * Make a copy of the resource set. This is a helper function to @@ -166,7 +193,8 @@ void murphy_resource_set_delete(murphy_resource_set *set); * * @return pointer to a copy of the resource set. */ -murphy_resource_set *murphy_resource_set_copy(const murphy_resource_set *orig); +mrp_res_resource_set_t *mrp_res_copy_resource_set(mrp_res_context_t *cx, + const mrp_res_resource_set_t *orig); /** * You might have assigned the same update callback for @@ -179,8 +207,8 @@ murphy_resource_set *murphy_resource_set_copy(const murphy_resource_set *orig); * * @return true when matching, false otherwise. */ -bool murphy_resource_set_equals(const murphy_resource_set *a, - const murphy_resource_set *b); +bool mrp_res_equal_resource_set(const mrp_res_resource_set_t *a, + const mrp_res_resource_set_t *b); /** * Acquire resources. Errors in the return value will @@ -194,20 +222,21 @@ bool murphy_resource_set_equals(const murphy_resource_set *a, * * @return murphy error code. */ -int murphy_resource_set_acquire(murphy_resource_context *cx, - murphy_resource_set *set); +int mrp_res_acquire_resource_set(mrp_res_context_t *cx, + const mrp_res_resource_set_t *rs); /** * Release the acquired resource set. Resource callbacks - * for this set will obviously stop. + * for this set will not stop, since updates for the resource + * set available status are still delivered. * * @param cx connnection to Murphy resource engine. * @param set resource set you want to release. * * @return murphy error code. */ -int murphy_resource_set_release(murphy_resource_context *cx, - murphy_resource_set *set); +int mrp_res_release_resource_set(mrp_res_context_t *cx, + mrp_res_resource_set_t *rs); /** * Create new resource by name and init all other fields. @@ -222,24 +251,20 @@ int murphy_resource_set_release(murphy_resource_context *cx, * * @return pointer to new resource if succesful null otherwise. */ -murphy_resource *murphy_resource_create(murphy_resource_context *cx, - murphy_resource_set *set, - const char *name, - bool mandatory, - bool shared); +mrp_res_resource_t *mrp_res_create_resource(mrp_res_context_t *cx, + mrp_res_resource_set_t *rs, const char *name, bool mandatory, + bool shared); /** * Get the names of all resources in this resource set. * * @param cx murphy context. * @param rs resource set where the resource are. - * @param names pointer where the name array with content will - * be allocated. * - * @return murphy error code + * @return string array that needs to be freed with mrp_res_free_string_array */ -murphy_string_array * murphy_resource_list_names(murphy_resource_context *cx, - const murphy_resource_set *rs); +mrp_res_string_array_t * mrp_res_list_resource_names(mrp_res_context_t *cx, + const mrp_res_resource_set_t *rs); /** * Delete resource by name from resource set. @@ -251,9 +276,8 @@ murphy_string_array * murphy_resource_list_names(murphy_resource_context *cx, * * @return 0 if resource found. */ -murphy_resource * murphy_resource_get_by_name(murphy_resource_context *cx, - const murphy_resource_set *rs, - const char *name); +mrp_res_resource_t * mrp_res_get_resource_by_name(mrp_res_context_t *cx, + const mrp_res_resource_set_t *rs, const char *name); /** * Delete a resource from a resource set. @@ -262,8 +286,8 @@ murphy_resource * murphy_resource_get_by_name(murphy_resource_context *cx, * @param res resource to be deleted. * */ -void murphy_resource_delete(murphy_resource_set *set, - murphy_resource *res); +void mrp_res_delete_resource(mrp_res_resource_set_t *rs, + mrp_res_resource_t *res); /** * Delete resource by name from resource set. @@ -273,8 +297,8 @@ void murphy_resource_delete(murphy_resource_set *set, * * @return true if resource found and removed. */ -bool murphy_resource_delete_by_name(murphy_resource_set *rs, - const char *name); +bool mrp_res_delete_resource_by_name(mrp_res_resource_set_t *rs, + const char *name); /** * Get the names of all attributes in this resource. @@ -286,8 +310,8 @@ bool murphy_resource_delete_by_name(murphy_resource_set *rs, * * @return murphy error code */ -murphy_string_array * murphy_attribute_list_names(murphy_resource_context *cx, - const murphy_resource *res); +mrp_res_string_array_t * mrp_res_list_attribute_names(mrp_res_context_t *cx, + const mrp_res_resource_t *res); /** * Get the particular resource attribute by name from the resource. @@ -299,21 +323,66 @@ murphy_string_array * murphy_attribute_list_names(murphy_resource_context *cx, * * @return murphy error code. */ -murphy_resource_attribute * murphy_attribute_get_by_name(murphy_resource_context *cx, - murphy_resource *res, - const char *name); +mrp_res_attribute_t * mrp_res_get_attribute_by_name(mrp_res_context_t *cx, + mrp_res_resource_t *res, const char *name); + +/** + * Set new string attribute value to resource. + * + * @param cx murphy context. + * @param attr attríbute pointer returned by mrp_res_get_attribute_by_name. + * @value value to be set, copied by the library. + * + * @return murphy error code. + */ +int mrp_res_set_attribute_string(mrp_res_context_t *cx, + mrp_res_attribute_t *attr, const char *value); + + +/** + * Set new unsigned integer attribute value to resource. + * + * @param cx murphy context. + * @param attr attríbute pointer returned by mrp_res_get_attribute_by_name. + * @value value to be set. + * + * @return murphy error code. + */ +int mrp_res_set_attribute_uint(mrp_res_context_t *cx, + mrp_res_attribute_t *attr, uint32_t value); + /** - * Set new attribute value to resource. + * Set new integer attribute value to resource. * * @param cx murphy context. - * @param res resource where the attribute is set. - * @param attribute value to be set as new attribute replacing the old. + * @param attr attríbute pointer returned by mrp_res_get_attribute_by_name. + * @value value to be set. * * @return murphy error code. */ -int murphy_attribute_set(murphy_resource_context *cx, - murphy_resource *res, - const murphy_resource_attribute *attr); +int mrp_res_set_attribute_int(mrp_res_context_t *cx, + mrp_res_attribute_t *attr, int32_t value); + + +/** + * Set new unsigned integer attribute value to resource. + * + * @param cx murphy context. + * @param attr attríbute pointer returned by mrp_res_get_attribute_by_name. + * @value value to be set. + * + * @return murphy error code. + */ +int mrp_res_set_attribute_double(mrp_res_context_t *cx, + mrp_res_attribute_t *attr, double value); + + +/** + * Free a string array. + * + * @param arr string array to be freed. + */ +void mrp_res_free_string_array(mrp_res_string_array_t *arr); -#endif /* foomurphyresourceapifoo */ +#endif /* __MURPHY_RESOURCE_API_H__ */ diff --git a/src/plugins/resource-native/libmurphy-resource/resource-private.h b/src/plugins/resource-native/libmurphy-resource/resource-private.h index af9b736..fab6092 100644 --- a/src/plugins/resource-native/libmurphy-resource/resource-private.h +++ b/src/plugins/resource-native/libmurphy-resource/resource-private.h @@ -1,16 +1,40 @@ -#ifndef foomurphyresourceprivatefoo -#define foomurphyresourceprivatefoo +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MURPHY_RESOURCE_API_PRIVATE_H__ +#define __MURPHY_RESOURCE_API_PRIVATE_H__ #include "resource-api.h" typedef struct { - uint32_t dim; - const char *elems[0]; -} string_array_t; - -typedef struct { const char *name; - murphy_attribute_type type; /* s:char *, i:int32_t, u:uint32_t, f:double */ + mrp_res_attribute_type_t type; /* s:char *, i:int32_t, u:uint32_t, f:double */ union { const char *string; int32_t integer; @@ -34,36 +58,42 @@ typedef struct { resource_def_t defs[0]; } resource_def_array_t; -struct murphy_resource_private_s { - murphy_resource *pub; /* composition */ - murphy_resource_set *set; /* owning set */ +struct mrp_res_resource_private_s { + mrp_res_resource_t *pub; /* composition */ + mrp_res_resource_set_t *set; /* owning set */ bool mandatory; bool shared; int num_attributes; - murphy_resource_attribute *attrs; + mrp_res_attribute_t *attrs; }; -struct murphy_resource_set_private_s { - murphy_resource_set *pub; /* composition */ - uint32_t id; +struct mrp_res_resource_set_private_s { + mrp_res_resource_set_t *pub; /* composition */ + uint32_t id; /* id given by the server */ + uint32_t internal_id; /* id for checking identity */ + uint32_t internal_ref_count; uint32_t seqno; - murphy_resource_callback cb; + mrp_res_resource_callback_t cb; void *user_data; int num_resources; - murphy_resource **resources; + mrp_res_resource_t **resources; mrp_list_hook_t hook; }; -struct murphy_resource_context_private_s { +struct mrp_res_context_private_s { int connection_id; + /* mapping of server-side resource set numbers to library resource sets */ mrp_htbl_t *rset_mapping; - murphy_state_callback cb; + /* mapping of library resource sets to client resource sets */ + mrp_htbl_t *internal_rset_mapping; + + mrp_res_state_callback_t cb; void *user_data; mrp_mainloop_t *ml; @@ -71,20 +101,20 @@ struct murphy_resource_context_private_s { mrp_transport_t *transp; bool connected; - /* do we know the resource and class states? */ - string_array_t *classes; - resource_def_array_t *available_resources; - - murphy_string_array *master_classes; - murphy_resource_set *master_resource_set; + mrp_res_string_array_t *master_classes; + mrp_res_resource_set_t *master_resource_set; /* sometimes we need to know which query was answered */ uint32_t next_seqno; + /* running number for identifying resource sets */ + uint32_t next_internal_id; + mrp_list_hook_t pending_sets; }; +uint32_t p_to_u(const void *p); +void *u_to_p(uint32_t u); - -#endif /* foomurphyresourceprivatefoo */ +#endif /* __MURPHY_RESOURCE_API_PRIVATE_H__ */ diff --git a/src/plugins/resource-native/libmurphy-resource/resource.c b/src/plugins/resource-native/libmurphy-resource/resource.c index e70d9ff..fd964bd 100644 --- a/src/plugins/resource-native/libmurphy-resource/resource.c +++ b/src/plugins/resource-native/libmurphy-resource/resource.c @@ -1,35 +1,43 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include #include "resource-api.h" #include "resource-private.h" -#define RES_ADDRESS "unxs:/tmp/murphy/resource-native" - -#define ARRAY_MAX 1024 -#define RESOURCE_MAX 32 -#define ATTRIBUTE_MAX 32 - -#ifndef NO_DEBUG -static void print_resource(murphy_resource *res) -{ - printf(" resource '%s' : %smandatory, %sshared\n", - res->name, res->priv->mandatory ? " " : "not ", res->priv->shared ? "" : "not "); -} - -static void print_resource_set(murphy_resource_set *rset) -{ - int i; - murphy_resource *res; +#include "string_array.h" +#include "message.h" +#include "rset.h" +#include "attribute.h" - printf("Resource set %i (%s):\n", rset->priv->id, rset->application_class); - - for (i = 0; i < rset->priv->num_resources; i++) { - res = rset->priv->resources[i]; - print_resource(res); - } -} -#endif void *u_to_p(uint32_t u) { @@ -45,6 +53,7 @@ void *u_to_p(uint32_t u) return (void *) o; } + uint32_t p_to_u(const void *p) { #ifdef __SIZEOF_POINTER__ @@ -74,887 +83,8 @@ uint32_t int_hash(const void *key) } -#if 0 -static void str_array_free(string_array_t *arr) -{ - uint32_t i; - - if (arr) { - for (i = 0; i < arr->dim; i++) - mrp_free((void *)arr->elems[i]); - - mrp_free(arr); - } -} -#endif - - -static string_array_t *str_array_dup(uint32_t dim, const char **arr) -{ - size_t size; - uint32_t i; - string_array_t *dup; - - if (dim >= ARRAY_MAX || !arr) - return NULL; - - if (!dim && arr) { - for (dim = 0; arr[dim]; dim++) - ; - } - - size = sizeof(string_array_t) + (sizeof(const char *) * (dim + 1)); - - if (!(dup = mrp_allocz(size))) { - errno = ENOMEM; - return NULL; - } - - dup->dim = dim; - - for (i = 0; i < dim; i++) { - if (arr[i]) { - if (!(dup->elems[i] = mrp_strdup(arr[i]))) { - errno = ENOMEM; - /* probably no use for freing anything */ - return NULL; - } - } - } - - return dup; -} - -static murphy_string_array *murphy_str_array_dup(uint32_t dim, const char **arr) -{ - uint32_t i; - murphy_string_array *dup; - - if (dim >= ARRAY_MAX || !arr) - return NULL; - - if (!dim && arr) { - for (dim = 0; arr[dim]; dim++) - ; - } - - if (!(dup = mrp_allocz(sizeof(murphy_string_array)))) { - errno = ENOMEM; - return NULL; - } - - dup->num_strings = dim; - dup->strings = mrp_allocz_array(const char *, dim); - - for (i = 0; i < dim; i++) { - if (arr[i]) { - if (!(dup->strings[i] = mrp_strdup(arr[i]))) { - errno = ENOMEM; - /* probably no use for freing anything */ - return NULL; - } - } - } - - return dup; -} - - -static bool fetch_resource_name(mrp_msg_t *msg, void **pcursor, - const char **pname) -{ - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != RESPROTO_RESOURCE_NAME || type != MRP_MSG_FIELD_STRING) - { - *pname = ""; - return false; - } - - *pname = value.str; - return true; -} - -static void attribute_array_free(attribute_array_t *arr) -{ - uint32_t i; - attribute_t *attr; - - if (arr) { - for (i = 0; i < arr->dim; i++) { - attr = arr->elems + i; - - mrp_free((void *)attr->name); - - if (attr->type == 's') - mrp_free((void *)attr->string); - } - mrp_free(arr); - } -} - -static void murphy_attribute_array_free(murphy_resource_attribute *arr, uint32_t dim) -{ - uint32_t i; - murphy_resource_attribute *attr; - - if (arr) { - for (i = 0; i < dim; i++) { - attr = arr + i; - - mrp_free((void *)attr->name); - - if (attr->type == murphy_string) - mrp_free((void *)attr->string); - } - mrp_free(arr); - } -} - -static attribute_array_t *attribute_array_dup(uint32_t dim, attribute_t *arr) -{ - size_t size; - uint32_t i; - attribute_t *sattr, *dattr; - attribute_array_t *dup; - int err; - - MRP_ASSERT(dim < ARRAY_MAX && arr, "invalid argument"); - - if (!dim && arr) { - for (dim = 0; arr[dim].name; dim++) - ; - } - - size = sizeof(attribute_array_t) + (sizeof(attribute_t) * (dim + 1)); - - if (!(dup = mrp_allocz(size))) { - err = ENOMEM; - goto failed; - } - - dup->dim = dim; - - for (i = 0; i < dim; i++) { - sattr = arr + i; - dattr = dup->elems + i; - - if (!(dattr->name = mrp_strdup(sattr->name))) { - err = ENOMEM; - goto failed; - } - - switch ((dattr->type = sattr->type)) { - case 's': - if (!(dattr->string = mrp_strdup(sattr->string))) { - err = ENOMEM; - goto failed; - } - break; - case 'i': - dattr->integer = sattr->integer; - break; - case 'u': - dattr->unsignd = sattr->unsignd; - break; - case 'f': - dattr->floating = sattr->floating; - break; - default: - errno = EINVAL; - goto failed; - } - } - - return dup; - - failed: - attribute_array_free(dup); - errno = err; - return NULL; -} - -static murphy_resource_attribute *murphy_attribute_array_dup(uint32_t dim, - murphy_resource_attribute *arr) -{ - size_t size; - uint32_t i; - murphy_resource_attribute *sattr, *dattr; - murphy_resource_attribute *dup; - int err; - - size = (sizeof(murphy_resource_attribute) * (dim + 1)); - - if (!(dup = mrp_allocz(size))) { - err = ENOMEM; - goto failed; - } - - for (i = 0; i < dim; i++) { - sattr = arr + i; - dattr = dup + i; - - if (!(dattr->name = mrp_strdup(sattr->name))) { - err = ENOMEM; - goto failed; - } - - switch ((dattr->type = sattr->type)) { - case murphy_string: - if (!(dattr->string = mrp_strdup(sattr->string))) { - err = ENOMEM; - goto failed; - } - break; - case murphy_int32: - dattr->integer = sattr->integer; - break; - case murphy_uint32: - dattr->type = murphy_uint32; - dattr->unsignd = sattr->unsignd; - break; - case murphy_double: - dattr->type = murphy_double; - dattr->floating = sattr->floating; - break; - default: - errno = EINVAL; - goto failed; - } - } - - return dup; - - failed: - murphy_attribute_array_free(dup, dim); - errno = err; - return NULL; -} - - -static int fetch_attribute_array(mrp_msg_t *msg, void **pcursor, - size_t dim, attribute_t *arr) -{ - attribute_t *attr; - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - size_t i; - - i = 0; - - while (mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size)) { - if (tag == RESPROTO_SECTION_END && type == MRP_MSG_FIELD_UINT8) - break; - - if (tag != RESPROTO_ATTRIBUTE_NAME || - type != MRP_MSG_FIELD_STRING || - i >= dim - 1) { - return -1; - } - - attr = arr + i++; - attr->name = value.str; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != RESPROTO_ATTRIBUTE_VALUE) { - return -1; - } - - switch (type) { - case MRP_MSG_FIELD_STRING: - attr->type = 's'; - attr->string = value.str; - break; - case MRP_MSG_FIELD_SINT32: - attr->type = 'i'; - attr->integer = value.s32; - break; - case MRP_MSG_FIELD_UINT32: - attr->type = 'u'; - attr->unsignd = value.u32; - break; - case MRP_MSG_FIELD_DOUBLE: - attr->type = 'f'; - attr->floating = value.dbl; - break; - default: - return -1; - } - } - - memset(arr + i, 0, sizeof(attribute_t)); - - return 0; -} - - -static bool fetch_resource_set_state(mrp_msg_t *msg, void **pcursor, - mrp_resproto_state_t *pstate) -{ - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != RESPROTO_RESOURCE_STATE || type != MRP_MSG_FIELD_UINT16) - { - *pstate = 0; - return false; - } - - *pstate = value.u16; - return true; -} - - -static bool fetch_resource_set_mask(mrp_msg_t *msg, void **pcursor, - int mask_type, mrp_resproto_state_t *pmask) -{ - uint16_t expected_tag; - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - switch (mask_type) { - case 0: expected_tag = RESPROTO_RESOURCE_GRANT; break; - case 1: expected_tag = RESPROTO_RESOURCE_ADVICE; break; - default: /* don't know what to fetch */ return false; - } - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != expected_tag || type != MRP_MSG_FIELD_UINT32) - { - *pmask = 0; - return false; - } - - *pmask = value.u32; - return true; -} - - -static bool fetch_resource_set_id(mrp_msg_t *msg, void **pcursor,uint32_t *pid) -{ - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != RESPROTO_RESOURCE_SET_ID || type != MRP_MSG_FIELD_UINT32) - { - *pid = 0; - return false; - } - - *pid = value.u32; - return true; -} - - -static bool fetch_str_array(mrp_msg_t *msg, void **pcursor, - uint16_t expected_tag, string_array_t **parr) -{ - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != expected_tag || type != MRP_MSG_FIELD_ARRAY_OF(STRING)) - { - *parr = str_array_dup(0, NULL); - return false; - } - - if (!(*parr = str_array_dup(size, (const char **)value.astr))) - return false; - - return true; -} - -static bool fetch_murphy_str_array(mrp_msg_t *msg, void **pcursor, - uint16_t expected_tag, murphy_string_array **parr) -{ - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != expected_tag || type != MRP_MSG_FIELD_ARRAY_OF(STRING)) - { - *parr = murphy_str_array_dup(0, NULL); - return false; - } - - if (!(*parr = murphy_str_array_dup(size, (const char **)value.astr))) - return false; - - return true; -} - - -static bool fetch_seqno(mrp_msg_t *msg, void **pcursor, uint32_t *pseqno) -{ - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != RESPROTO_SEQUENCE_NO || type != MRP_MSG_FIELD_UINT32) - { - *pseqno = 0; - return -1; - } - - *pseqno = value.u32; - return 0; -} - - -static int fetch_request(mrp_msg_t *msg, void **pcursor, uint16_t *preqtype) -{ - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != RESPROTO_REQUEST_TYPE || type != MRP_MSG_FIELD_UINT16) - { - *preqtype = 0; - return -1; - } - - *preqtype = value.u16; - return 0; -} - - -static bool fetch_status(mrp_msg_t *msg, void **pcursor, int *pstatus) -{ - uint16_t tag; - uint16_t type; - mrp_msg_value_t value; - size_t size; - - if (!mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size) || - tag != RESPROTO_REQUEST_STATUS || type != MRP_MSG_FIELD_SINT16) - { - *pstatus = EIO; - return false; - } - - *pstatus = value.s16; - return true; -} - - -static resource_def_t *copy_resource_def(const resource_def_t *orig) -{ - resource_def_t *copy; - - if (!orig) - return NULL; - - copy = mrp_allocz(sizeof(resource_def_t)); - - copy->name = mrp_strdup(orig->name); - copy->attrs = attribute_array_dup(orig->attrs->dim, orig->attrs->elems); - - return copy; -} - - -static void resource_def_free(resource_def_t *def) -{ - if (!def) - return; - - mrp_free((void *)def->name); - attribute_array_free(def->attrs); -} - - -static void resource_def_array_free(resource_def_array_t *arr) -{ - uint32_t i; - resource_def_t *def; - - if (arr) { - for (i = 0; i < arr->dim; i++) { - def = arr->defs + i; - resource_def_free(def); - } - - mrp_free(arr); - } -} - -#if 0 -static resource_def_array_t *resource_query_response(mrp_msg_t *msg, void **pcursor) -{ - int status; - uint32_t dim, i; - resource_def_t rdef[RESOURCE_MAX]; - attribute_t attrs[ATTRIBUTE_MAX + 1]; - resource_def_t *src, *dst; - resource_def_array_t *arr; - size_t size; - - if (!fetch_status(msg, pcursor, &status)) - goto failed; - - if (status != 0) - printf("Resource query failed (%u): %s\n", status, strerror(status)); - else { - dim = 0; - - while (fetch_resource_name(msg, pcursor, &rdef[dim].name)) { - if (fetch_attribute_array(msg, pcursor, ATTRIBUTE_MAX+1, attrs) < 0) - goto failed; - - if (!(rdef[dim].attrs = attribute_array_dup(0, attrs))) { - mrp_log_error("failed to duplicate attributes"); - return NULL; - } - - dim++; - } - - size = sizeof(resource_def_array_t) + sizeof(resource_def_t) * (dim+1); - - arr = mrp_allocz(size); - - arr->dim = dim; - - for (i = 0; i < dim; i++) { - src = rdef + i; - dst = arr->defs + i; - - dst->name = mrp_strdup(src->name); - dst->attrs = src->attrs; - } - } - - return arr; - - failed: - mrp_log_error("malformed reply to recource query"); - - return NULL; -} -#endif - -void priv_attr_to_murphy_attr(attribute_t *attr, murphy_resource_attribute *attribute) { - - if (attr == NULL || attribute == NULL) - return; - - attribute->name = mrp_strdup(attr->name); - - switch (attr->type) { - case 's': - attribute->type = murphy_string; - attribute->string = mrp_strdup(attr->string); - break; - case 'i': - attribute->type = murphy_int32; - attribute->integer = attr->integer; - break; - case 'u': - attribute->type = murphy_uint32; - attribute->unsignd = attr->unsignd; - break; - case 'f': - attribute->type = murphy_double; - attribute->floating = attr->floating; - break; - default: - attribute->type = murphy_invalid; - } - } - -int priv_res_to_murphy_res(resource_def_t *src, murphy_resource *dst) { - - uint32_t i = 0; - - dst->name = mrp_strdup(src->name); - dst->state = murphy_resource_lost; - dst->priv->mandatory = false; - dst->priv->shared = false; - dst->priv->num_attributes = src->attrs->dim; - - dst->priv->attrs = mrp_allocz(sizeof(murphy_resource_attribute) * src->attrs->dim); - - for (i = 0; i < src->attrs->dim; i++) { - priv_attr_to_murphy_attr(&src->attrs->elems[i], &dst->priv->attrs[i]); - } - return 0; -} - -static murphy_resource_set *resource_query_response(mrp_msg_t *msg, void **pcursor) -{ - int status; - uint32_t dim, i; - resource_def_t rdef[RESOURCE_MAX]; - attribute_t attrs[ATTRIBUTE_MAX + 1]; - resource_def_t *src; - murphy_resource_set *arr; - - if (!fetch_status(msg, pcursor, &status)) - goto failed; - - if (status != 0) - printf("Resource query failed (%u): %s\n", status, strerror(status)); - else { - dim = 0; - - while (fetch_resource_name(msg, pcursor, &rdef[dim].name)) { - if (fetch_attribute_array(msg, pcursor, ATTRIBUTE_MAX+1, attrs) < 0) - goto failed; - - if (!(rdef[dim].attrs = attribute_array_dup(0, attrs))) { - mrp_log_error("failed to duplicate attributes"); - return NULL; - } - - dim++; - } - - arr = mrp_allocz(sizeof(murphy_resource_set)); - - if (!arr) - goto failed; - - arr->priv = mrp_allocz(sizeof(murphy_resource_private_t)); - - if (!arr->priv) - goto failed; - - arr->application_class = NULL; - arr->state = murphy_resource_lost; - arr->priv->num_resources = dim; - - arr->priv->resources = mrp_allocz_array(murphy_resource *, dim); - - for (i = 0; i < dim; i++) { - src = rdef + i; - arr->priv->resources[i] = mrp_allocz(sizeof(murphy_resource)); - arr->priv->resources[i]->priv = mrp_allocz(sizeof(murphy_resource_private_t)); - priv_res_to_murphy_res(src, arr->priv->resources[i]); - } - } - - return arr; - - failed: - mrp_log_error("malformed reply to resource query"); - - return NULL; -} - - -#if 0 -static string_array_t *class_query_response(mrp_msg_t *msg, void **pcursor) -{ - int status; - string_array_t *arr; - - if (!fetch_status(msg, pcursor, &status) || (status == 0 && - !fetch_str_array(msg, pcursor, RESPROTO_CLASS_NAME, &arr))) - { - mrp_log_error("ignoring malformed response to class query"); - return NULL; - } - - if (status) { - mrp_log_error("class query failed with error code %u", status); - return NULL; - } - - return arr; -} -#endif - -static murphy_string_array *class_query_response(mrp_msg_t *msg, void **pcursor) -{ - int status; - murphy_string_array *arr; - - if (!fetch_status(msg, pcursor, &status) || (status == 0 && - !fetch_murphy_str_array(msg, pcursor, RESPROTO_CLASS_NAME, &arr))) - { - mrp_log_error("ignoring malformed response to class query"); - return NULL; - } - - if (status) { - mrp_log_error("class query failed with error code %u", status); - return NULL; - } - - return arr; -} - - -static bool create_resource_set_response(mrp_msg_t *msg, murphy_resource_set *rset, void **pcursor) -{ - int status; - uint32_t rset_id; - - if (!fetch_status(msg, pcursor, &status) || (status == 0 && - !fetch_resource_set_id(msg, pcursor, &rset_id))) - { - mrp_log_error("ignoring malformed response to resource set creation"); - goto error; - } - - if (status) { - mrp_log_error("creation of resource set failed. error code %u",status); - goto error; - } - - rset->priv->id = rset_id; - - return true; -error: - return false; -} - - -static murphy_resource_set *acquire_resource_set_response(mrp_msg_t *msg, - murphy_resource_context *cx, void **pcursor) -{ - int status; - uint32_t rset_id; - murphy_resource_set *rset = NULL; - - if (!fetch_resource_set_id(msg, pcursor, &rset_id) || - !fetch_status(msg, pcursor, &status)) - { - mrp_log_error("ignoring malformed response to resource set"); - goto error; - } - - if (status) { - mrp_log_error("acquiring of resource set failed. error code %u",status); - goto error; - } - - /* we need the previous resource set because the new one doesn't - * tell us the resource set class */ - - rset = mrp_htbl_lookup(cx->priv->rset_mapping, u_to_p(rset_id)); - - if (!rset) { - printf("no rset found!\n"); - goto error; - } - -#if 0 - /* mark the resource set as acquired */ - - rset->state = murphy_resource_acquired; -#endif - - return rset; - -error: - return NULL; -} - - -static int acquire_resource_set(murphy_resource_context *cx, murphy_resource_set *rset) -{ - mrp_msg_t *msg = NULL; - - if (!cx->priv->connected) - goto error; - - rset->priv->seqno = cx->priv->next_seqno; - - msg = mrp_msg_create(RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, - cx->priv->next_seqno++, - RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, RESPROTO_ACQUIRE_RESOURCE_SET, - RESPROTO_RESOURCE_SET_ID, MRP_MSG_FIELD_UINT32, rset->priv->id, - RESPROTO_MESSAGE_END); - - if (!msg) - goto error; - - - if (!mrp_transport_send(cx->priv->transp, msg)) - goto error; - - return 0; - -error: - mrp_free(msg); - return -1; -} - - -static int release_resource_set(murphy_resource_context *cx, murphy_resource_set *rset) -{ - mrp_msg_t *msg = NULL; - - if (!cx->priv->connected) - goto error; - - rset->priv->seqno = cx->priv->next_seqno; - - msg = mrp_msg_create(RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, - cx->priv->next_seqno++, - RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, RESPROTO_RELEASE_RESOURCE_SET, - RESPROTO_RESOURCE_SET_ID, MRP_MSG_FIELD_UINT32, rset->priv->id, - RESPROTO_MESSAGE_END); - - if (!msg) - goto error; - - if (!mrp_transport_send(cx->priv->transp, msg)) - goto error; - - return 0; - -error: - mrp_free(msg); - return -1; -} - -static murphy_resource *get_resource_by_name(murphy_resource_set *rset, - const char *name) -{ - int i; - - if (!rset || !name) - return NULL; - - for (i = 0; i < rset->priv->num_resources; i++) { - murphy_resource *res = rset->priv->resources[i]; - printf(" comparing '%s with %s'\n", name, res->name); - if (strcmp(res->name, name) == 0) { - return res; - } - } - - return NULL; -} - - static void resource_event(mrp_msg_t *msg, - murphy_resource_context *cx, + mrp_res_context_t *cx, int32_t seqno, void **pcursor) { @@ -971,35 +101,44 @@ static void resource_event(mrp_msg_t *msg, attribute_array_t *list; uint32_t mask; - murphy_resource_set *rset; + mrp_res_resource_set_t *rset; printf("\nResource event (request no %u):\n", seqno); if (!fetch_resource_set_id(msg, pcursor, &rset_id) || !fetch_resource_set_state(msg, pcursor, &state) || !fetch_resource_set_mask(msg, pcursor, 0, &grant) || - !fetch_resource_set_mask(msg, pcursor, 1, &advice)) + !fetch_resource_set_mask(msg, pcursor, 1, &advice)) { + printf("malformed 0.2\n"); goto malformed; + } /* Update our "master copy" of the resource set. */ + printf("going to get rset of id %d\n", rset_id); rset = mrp_htbl_lookup(cx->priv->rset_mapping, u_to_p(rset_id)); - if (!rset) + if (!rset) { + printf("resource event before creating the resource set!\n"); goto malformed; + } + + printf("resource set %p id: %u\n", rset, rset->priv->id); switch (state) { case RESPROTO_RELEASE: - rset->state = murphy_resource_lost; + rset->state = MRP_RES_RESOURCE_LOST; break; case RESPROTO_ACQUIRE: - rset->state = murphy_resource_acquired; + rset->state = MRP_RES_RESOURCE_ACQUIRED; break; } while (mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size)) { - murphy_resource *res = NULL; + mrp_res_resource_t *res = NULL; + + printf("iterating through the resources...\n"); if ((tag != RESPROTO_RESOURCE_ID || type != MRP_MSG_FIELD_UINT32) || !fetch_resource_name(msg, pcursor, &resnam)) { @@ -1018,13 +157,13 @@ static void resource_event(mrp_msg_t *msg, mask = (1UL << resid); if (grant & mask) { - res->state = murphy_resource_acquired; + res->state = MRP_RES_RESOURCE_ACQUIRED; } else if (advice & mask) { - res->state = murphy_resource_available; + res->state = MRP_RES_RESOURCE_AVAILABLE; } else { - res->state = murphy_resource_lost; + res->state = MRP_RES_RESOURCE_LOST; } if (fetch_attribute_array(msg, pcursor, ATTRIBUTE_MAX + 1, attrs) < 0) { @@ -1046,15 +185,11 @@ static void resource_event(mrp_msg_t *msg, * before that. Otherwise, if this is a real event, call the * callback right away. */ - /* TODO properly */ - if (!rset->priv->seqno) { - murphy_resource_set *rset_new; - if (rset->priv->cb) { - rset_new = murphy_resource_set_copy(rset); - - rset_new->priv->cb(cx, rset_new, rset_new->priv->user_data); + increase_ref(cx, rset); + rset->priv->cb(cx, rset, rset->priv->user_data); + decrease_ref(cx, rset); } } @@ -1069,47 +204,43 @@ static void recvfrom_msg(mrp_transport_t *transp, mrp_msg_t *msg, mrp_sockaddr_t *addr, socklen_t addrlen, void *user_data) { - murphy_resource_context *cx = user_data; + mrp_res_context_t *cx = user_data; void *cursor = NULL; uint32_t seqno; uint16_t req; - (void)transp; - (void)addr; - (void)addrlen; + MRP_UNUSED(transp); + MRP_UNUSED(addr); + MRP_UNUSED(addrlen); - if (fetch_seqno(msg, &cursor, &seqno) < 0 || fetch_request(msg, &cursor, &req) < 0) + if (fetch_seqno(msg, &cursor, &seqno) < 0 || + fetch_request(msg, &cursor, &req) < 0) goto error; printf("received message %d for %p\n", req, cx); switch (req) { case RESPROTO_QUERY_RESOURCES: + printf("received QUERY_RESOURCES response\n"); -#if 0 - cx->priv->available_resources = resource_query_response(msg, &cursor); - if (!cx->priv->available_resources) - goto error; -#endif - cx->priv->master_resource_set = resource_query_response(msg, &cursor); + + cx->priv->master_resource_set = + resource_query_response(msg, &cursor); if (!cx->priv->master_resource_set) goto error; break; case RESPROTO_QUERY_CLASSES: + printf("received QUERY_CLASSES response\n"); -#if 0 - cx->priv->classes = class_query_response(msg, &cursor); - if (!cx->priv->classes) - goto error; -#endif + cx->priv->master_classes = class_query_response(msg, &cursor); if (!cx->priv->master_classes) goto error; break; case RESPROTO_CREATE_RESOURCE_SET: { - murphy_resource_set_private_t *priv = NULL; - murphy_resource_set *rset = NULL; + mrp_res_resource_set_private_t *priv = NULL; + mrp_res_resource_set_t *rset = NULL; mrp_list_hook_t *p, *n; printf("received CREATE_RESOURCE_SET response\n"); @@ -1135,59 +266,59 @@ static void recvfrom_msg(mrp_transport_t *transp, mrp_msg_t *msg, if (!create_resource_set_response(msg, rset, &cursor)) goto error; - mrp_htbl_insert(cx->priv->rset_mapping, u_to_p(rset->priv->id), rset); + printf("inserting rset %p of id %d\n", rset, rset->priv->id); + mrp_htbl_insert(cx->priv->rset_mapping, + u_to_p(rset->priv->id), rset); - if (acquire_resource_set(cx, rset) < 0) { + if (acquire_resource_set_request(cx, rset) < 0) { goto error; } break; } case RESPROTO_ACQUIRE_RESOURCE_SET: { - murphy_resource_set *rset; + mrp_res_resource_set_t *rset; printf("received ACQUIRE_RESOURCE_SET response\n"); rset = acquire_resource_set_response(msg, cx, &cursor); - /* TODO: make new aqcuires fail until seqno == 0 */ - rset->priv->seqno = 0; - if (!rset) { goto error; } + /* TODO: make new aqcuires fail until seqno == 0 */ + rset->priv->seqno = 0; + /* call the resource set callback */ if (rset->priv->cb) { - murphy_resource_set *rset_new; - - rset_new = murphy_resource_set_copy(rset); - rset_new->priv->cb(cx, rset_new, rset_new->priv->user_data); + increase_ref(cx, rset); + rset->priv->cb(cx, rset, rset->priv->user_data); + decrease_ref(cx, rset); } break; } case RESPROTO_RELEASE_RESOURCE_SET: { - murphy_resource_set *rset; + mrp_res_resource_set_t *rset; printf("received RELEASE_RESOURCE_SET response\n"); - rset = acquire_resource_set_response(msg, cx, &cursor); - - /* TODO: make new aqcuires fail until seqno == 0 */ - rset->priv->seqno = 0; + rset = acquire_resource_set_response(msg, cx, &cursor); if (!rset) { goto error; } + /* TODO: make new aqcuires fail until seqno == 0 */ + rset->priv->seqno = 0; + /* call the resource set callback */ if (rset->priv->cb) { - murphy_resource_set *rset_new; - - rset_new = murphy_resource_set_copy(rset); - rset_new->priv->cb(cx, rset_new, rset_new->priv->user_data); + increase_ref(cx, rset); + rset->priv->cb(cx, rset, rset->priv->user_data); + decrease_ref(cx, rset); } break; } @@ -1196,22 +327,25 @@ static void recvfrom_msg(mrp_transport_t *transp, mrp_msg_t *msg, resource_event(msg, cx, seqno, &cursor); break; + case RESPROTO_DESTROY_RESOURCE_SET: + /* TODO */ + break; default: break; } - if (cx->state == murphy_disconnected && + if (cx->state == MRP_RES_DISCONNECTED && cx->priv->master_classes && cx->priv->master_resource_set) { - cx->state = murphy_connected; - cx->priv->cb(cx, murphy_resource_error_none, cx->priv->user_data); + cx->state = MRP_RES_CONNECTED; + cx->priv->cb(cx, MRP_RES_ERROR_NONE, cx->priv->user_data); } return; error: printf("error processing a message from Murphy\n"); - cx->priv->cb(cx, murphy_resource_error_internal, cx->priv->user_data); + cx->priv->cb(cx, MRP_RES_ERROR_INTERNAL, cx->priv->user_data); } @@ -1223,95 +357,57 @@ static void recv_msg(mrp_transport_t *t, mrp_msg_t *msg, void *user_data) void closed_evt(mrp_transport_t *transp, int error, void *user_data) { - murphy_resource_context *cx = user_data; - (void)transp; - (void)error; + mrp_res_context_t *cx = user_data; + MRP_UNUSED(transp); + MRP_UNUSED(error); printf("connection closed for %p\n", cx); cx->priv->connected = FALSE; } -static void destroy_context(murphy_resource_context *cx) +static void destroy_context(mrp_res_context_t *cx) { - if (cx) { + if (!cx) + return; + + if (cx->priv) { if (cx->priv->transp) mrp_transport_destroy(cx->priv->transp); + delete_resource_set(cx, cx->priv->master_resource_set); + /* FIXME: is this the way we want to free all resources and * resource sets? */ if (cx->priv->rset_mapping) - mrp_htbl_destroy(cx->priv->rset_mapping, true); + mrp_htbl_destroy(cx->priv->rset_mapping, false); - if (cx->priv->available_resources) - resource_def_array_free(cx->priv->available_resources); + if (cx->priv->internal_rset_mapping) + mrp_htbl_destroy(cx->priv->internal_rset_mapping, true); + + mrp_res_free_string_array(cx->priv->master_classes); mrp_free(cx->priv); - mrp_free(cx); } -} - - -static int get_application_classes(murphy_resource_context *cx) -{ - mrp_msg_t *msg = NULL; - - if (!cx->priv->connected) - goto error; - - msg = mrp_msg_create(RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, 0, - RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, RESPROTO_QUERY_CLASSES, - RESPROTO_MESSAGE_END); - - if (!msg) - goto error; - - if (!mrp_transport_send(cx->priv->transp, msg)) - goto error; - - return 0; - -error: - mrp_free(msg); - return -1; -} - - -static int get_available_resources(murphy_resource_context *cx) -{ - mrp_msg_t *msg = NULL; - - if (!cx->priv->connected) - goto error; - - msg = mrp_msg_create(RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, 0, - RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, RESPROTO_QUERY_RESOURCES, - RESPROTO_MESSAGE_END); - - if (!msg) - goto error; - - if (!mrp_transport_send(cx->priv->transp, msg)) - goto error; - - return 0; - -error: - mrp_free(msg); - return -1; + mrp_free(cx); } static void htbl_free_rset_mapping(void *key, void *object) { +#if 0 + printf("> htbl_free_rset_mapping(%d, %p)\n", p_to_u(key), object); +#else MRP_UNUSED(key); - MRP_UNUSED(object); +#endif + free_resource_set(object); } +/* public API */ -murphy_resource_context *murphy_create(mrp_mainloop_t *ml, - murphy_state_callback cb, +mrp_res_context_t *mrp_res_create(mrp_mainloop_t *ml, + mrp_res_state_callback_t cb, void *userdata) { static mrp_transport_evt_t evt = { @@ -1324,17 +420,18 @@ murphy_resource_context *murphy_create(mrp_mainloop_t *ml, int alen; const char *type; mrp_htbl_config_t conf; - murphy_resource_context *cx = mrp_allocz(sizeof(murphy_resource_context)); + mrp_res_context_t *cx = mrp_allocz(sizeof(mrp_res_context_t)); if (!cx) goto error; - cx->priv = mrp_allocz(sizeof(struct murphy_resource_context_private_s)); + cx->priv = mrp_allocz(sizeof(struct mrp_res_context_private_s)); if (!cx->priv) goto error; cx->priv->next_seqno = 1; + cx->priv->next_internal_id = 1; cx->priv->ml = ml; cx->priv->connection_id = 0; cx->priv->cb = cb; @@ -1355,10 +452,19 @@ murphy_resource_context *murphy_create(mrp_mainloop_t *ml, if (!cx->priv->rset_mapping) goto error; + /* When a resource set is acquired, we are keeping a "master copy" on the + * server side. The client can free and copy this resource set as much as + * it wants. The internal id is a method for understanding which resource + * set maps to which. */ + cx->priv->internal_rset_mapping = mrp_htbl_create(&conf); + + if (!cx->priv->internal_rset_mapping) + goto error; + /* connect to Murphy */ - alen = mrp_transport_resolve(NULL, RES_ADDRESS, &cx->priv->saddr, - sizeof(cx->priv->saddr), &type); + alen = mrp_transport_resolve(NULL, RESPROTO_DEFAULT_ADDRESS, + &cx->priv->saddr, sizeof(cx->priv->saddr), &type); cx->priv->transp = mrp_transport_create(cx->priv->ml, type, &evt, cx, 0); @@ -1370,12 +476,15 @@ murphy_resource_context *murphy_create(mrp_mainloop_t *ml, goto error; cx->priv->connected = TRUE; - cx->state = murphy_disconnected; + cx->state = MRP_RES_DISCONNECTED; if (get_application_classes(cx) < 0 || get_available_resources(cx) < 0) { goto error; } + /* TODO: this needs to be gotten from an environment variable */ + cx->zone = "driver"; + mrp_list_init(&cx->priv->pending_sets); return cx; @@ -1389,467 +498,9 @@ error: } -void murphy_destroy(murphy_resource_context *cx) +void mrp_res_destroy(mrp_res_context_t *cx) { + printf("> mrp_res_destroy\n"); destroy_context(cx); } -const murphy_string_array * murphy_application_class_list(murphy_resource_context *cx) -{ - if (!cx) - return NULL; - - return cx->priv->master_classes; -} - - -static void delete_resource(murphy_resource *res) -{ - if (!res) - return; - - mrp_free(res->priv); - mrp_free(res); -} - -murphy_resource *murphy_resource_create(murphy_resource_context *cx, - murphy_resource_set *set, - const char *name, - bool mandatory, - bool shared) -{ - murphy_resource *res = NULL, *proto = NULL; - int i = 0; - bool found = false; - - if (cx == NULL || set == NULL || name == NULL) - return NULL; - - for (i = 0; i < cx->priv->master_resource_set->priv->num_resources; i++) { - proto = cx->priv->master_resource_set->priv->resources[i]; - if (strcmp(proto->name, name) == 0) { - found = true; - break; - } - } - - if (!found) - goto error; - - res = mrp_allocz(sizeof(murphy_resource)); - - if (!res) - goto error; - - res->name = mrp_strdup(name); - - res->state = murphy_resource_pending; - - res->priv = mrp_allocz(sizeof(murphy_resource_private_t)); - res->priv->mandatory = mandatory; - res->priv->shared = shared; - - if (!res->priv) - goto error; - - res->priv->pub = res; - - /* copy the attributes with the default values */ - res->priv->attrs = murphy_attribute_array_dup(proto->priv->num_attributes, - proto->priv->attrs); - - res->priv->num_attributes = proto->priv->num_attributes; - - /* add resource to resource set */ - set->priv->resources[set->priv->num_resources++] = res; - - return res; - -error: - printf("murphy_create_resource error\n"); - delete_resource(res); - - return NULL; -} - - -static void delete_resource_set(murphy_resource_set *rs) -{ - int i; - - if (!rs) - return; - - for (i = 0; i < rs->priv->num_resources; i++) { - /* FIXME */ - // delete_resource(rs->resources[i]); - } - - mrp_free(rs->priv); - mrp_free(rs); -} - - -static murphy_resource_set *create_resource_set( - murphy_resource_context *cx, - const char *klass, - murphy_resource_callback cb, - void *userdata) -{ - murphy_resource_set *rs = mrp_allocz(sizeof(murphy_resource_set)); - - if (!rs) - goto error; - - rs->priv = mrp_allocz(sizeof(murphy_resource_set_private_t)); - if (!rs->priv) - goto error; - - rs->application_class = mrp_strdup(klass); - - rs->priv->pub = rs; - rs->priv->id = 0; - rs->priv->seqno = 0; - rs->priv->cb = cb; - rs->priv->user_data = userdata; - rs->state = murphy_resource_pending; - - rs->priv->resources = mrp_allocz_array(murphy_resource *, - cx->priv->master_resource_set->priv->num_resources); - - mrp_list_init(&rs->priv->hook); - - return rs; - -error: - delete_resource_set(rs); - return NULL; -} - -const murphy_resource_set * murphy_resource_set_list(murphy_resource_context *cx) -{ - if (cx == NULL || cx->priv == NULL) - return NULL; - - return cx->priv->master_resource_set; -} - -int murphy_resource_set_acquire(murphy_resource_context *cx, - murphy_resource_set *rset) -{ - mrp_msg_t *msg = NULL; - int i; - - printf("> murphy_acquire_resources\n"); - print_resource_set(rset); - - if (!cx->priv->connected) - goto error; - - if (rset->priv->id) { - - /* the set has been already created */ - - if (rset->state == murphy_resource_acquired) { - /* already requested, updating is not supported yet */ - - /* TODO: when supported by backend - * type = RESPROTO_UPDATE_RESOURCE_SET - */ - goto error; - } - else { - /* re-acquire a lost or released set */ - return acquire_resource_set(cx, rset); - } - } - - /* First, create the resource set. The acquisition is continued - * when the set is created. */ - - rset->priv->seqno = cx->priv->next_seqno; - - msg = mrp_msg_create( - RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, cx->priv->next_seqno++, - RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, RESPROTO_CREATE_RESOURCE_SET, - RESPROTO_RESOURCE_FLAGS, MRP_MSG_FIELD_UINT32, 0, - RESPROTO_RESOURCE_PRIORITY, MRP_MSG_FIELD_UINT32, 0, - RESPROTO_CLASS_NAME, MRP_MSG_FIELD_STRING, rset->application_class, - RESPROTO_ZONE_NAME, MRP_MSG_FIELD_STRING, "driver", - RESPROTO_MESSAGE_END); - - if (!msg) - goto error; - - for (i = 0; i < rset->priv->num_resources; i++) { - uint32_t j; - uint32_t flags = 0; - murphy_resource *res = rset->priv->resources[i]; - - if (!res) - goto error; - - printf(" adding %s\n", res->name); - - if (res->priv->shared) - flags |= RESPROTO_RESFLAG_SHARED; - - if (res->priv->mandatory) - flags |= RESPROTO_RESFLAG_MANDATORY; - - mrp_msg_append(msg, RESPROTO_RESOURCE_NAME, MRP_MSG_FIELD_STRING, res->name); - mrp_msg_append(msg, RESPROTO_RESOURCE_FLAGS, MRP_MSG_FIELD_UINT32, flags); - - for (j = 0; j < res->priv->num_attributes; j++) { - murphy_resource_attribute *elem = &res->priv->attrs[j]; - const char *attr_name = elem->name; - - mrp_msg_append(msg, RESPROTO_ATTRIBUTE_NAME, MRP_MSG_FIELD_STRING, attr_name); - - switch (elem->type) { - case 's': - mrp_msg_append(msg, RESPROTO_ATTRIBUTE_VALUE, - MRP_MSG_FIELD_STRING, elem->string); - break; - case 'i': - mrp_msg_append(msg, RESPROTO_ATTRIBUTE_VALUE, - MRP_MSG_FIELD_SINT32, elem->integer); - break; - case 'u': - mrp_msg_append(msg, RESPROTO_ATTRIBUTE_VALUE, - MRP_MSG_FIELD_UINT32, elem->unsignd); - break; - case 'f': - mrp_msg_append(msg, RESPROTO_ATTRIBUTE_VALUE, - MRP_MSG_FIELD_DOUBLE, elem->floating); - break; - default: - break; - } - } - - mrp_msg_append(msg, RESPROTO_SECTION_END, MRP_MSG_FIELD_UINT8, 0); - } - - - if (!mrp_transport_send(cx->priv->transp, msg)) - goto error; - - mrp_list_append(&cx->priv->pending_sets, &rset->priv->hook); - - return 0; - -error: - mrp_free(msg); - return -1; -} - - -int murphy_resource_set_release(murphy_resource_context *cx, - murphy_resource_set *rset) -{ - printf("> murphy_release_resources\n"); - print_resource_set(rset); - - if (!cx->priv->connected) - goto error; - - if (!rset->priv->id) - goto error; - - if (rset->state != murphy_resource_acquired) { - return 0; - } - - return release_resource_set(cx, rset); - -error: - return -1; -} - -bool murphy_resource_set_equals(const murphy_resource_set *a, - const murphy_resource_set *b) -{ - if (!a || !b) - return false; - - return a->priv->id == b->priv->id; -} - -murphy_resource_set *murphy_resource_set_create(murphy_resource_context *cx, - const char *app_class, - murphy_resource_callback cb, - void *userdata) -{ - if (cx == NULL) - return NULL; - return create_resource_set(cx, app_class, cb, userdata); -} - - -murphy_resource_set *murphy_resource_set_copy(const murphy_resource_set *original) -{ - murphy_resource_set *copy = NULL; - int i; - - printf("> murphy_resource_set_copy\n"); - - copy = mrp_allocz(sizeof(murphy_resource_set)); - - /* copy->id = original->id; */ - - if (!copy) - goto error; - - memcpy(copy, original, sizeof(murphy_resource_set)); - - copy->priv = mrp_allocz(sizeof(murphy_resource_set_private_t)); - - if (!copy->priv) - goto error; - - memcpy(copy->priv, original->priv, sizeof(murphy_resource_set_private_t)); - - for (i = 0; i < copy->priv->num_resources; i++) { - copy->priv->resources[i]->priv->set = copy; - } - - copy->priv->pub = copy; - - mrp_list_init(©->priv->hook); - - return copy; - -error: - delete_resource_set(copy); - return NULL; -} - - -void murphy_resource_set_delete(murphy_resource_set *set) -{ - printf("> murphy_delete_resource_set\n"); - delete_resource_set(set); -} - -void murphy_resource_delete(murphy_resource_set *set, murphy_resource *res) -{ - (void)set; - - if (res->priv->set) { - if (!murphy_resource_delete_by_name(res->priv->set, res->name)) { - /* hmm, strange */ - delete_resource(res); - } - } - else - delete_resource(res); -} - -bool murphy_resource_delete_by_name(murphy_resource_set *rs, const char *name) -{ - int i; - murphy_resource *res; - - /* assumption: only one resource of given name in the resource set */ - for (i = 0; i < rs->priv->num_resources; i++) { - if (strcmp(rs->priv->resources[i]->name, name) == 0) { - /* found at i */ - res = rs->priv->resources[i]; - break; - } - } - - if (i == rs->priv->num_resources) { - /* not found */ - return false; - } - - memmove(rs->priv->resources+i, rs->priv->resources+i+1, - (rs->priv->num_resources-i) * sizeof(murphy_resource *)); - - rs->priv->num_resources--; - rs->priv->resources[rs->priv->num_resources] = NULL; - - delete_resource(res); - - return true; -} - -murphy_string_array * murphy_resource_list_names(murphy_resource_context *cx, - const murphy_resource_set *rs) -{ - int i; - murphy_string_array *ret; - - if (!cx || !rs) - return NULL; - - ret = mrp_allocz(sizeof(murphy_string_array)); - - ret->num_strings = rs->priv->num_resources; - ret->strings = mrp_allocz_array(const char *, rs->priv->num_resources); - - for (i = 0; i < rs->priv->num_resources; i++) { - ret->strings[i] = mrp_strdup(rs->priv->resources[i]->name); - } - - return ret; -} - -murphy_resource * murphy_resource_get_by_name(murphy_resource_context *cx, - const murphy_resource_set *rs, - const char *name) -{ - int i; - - if (!cx || !rs) - return NULL; - - for (i = 0; i < rs->priv->num_resources; i++) { - if (strcmp(name, rs->priv->resources[i]->name) == 0) { - return rs->priv->resources[i]; - } - } - - return NULL; -} - -murphy_string_array * murphy_attribute_list_names(murphy_resource_context *cx, - const murphy_resource *res) -{ - int i; - murphy_string_array *ret; - - if (!cx || !res) - return NULL; - - ret = mrp_allocz(sizeof(murphy_string_array)); - - ret->num_strings = res->priv->num_attributes; - ret->strings = mrp_allocz_array(const char *, res->priv->num_attributes); - - for (i = 0; i < res->priv->num_attributes; i++) { - ret->strings[i] = mrp_strdup(res->priv->attrs[i].name); - } - - return ret; -} - -murphy_resource_attribute * murphy_attribute_get_by_name(murphy_resource_context *cx, - murphy_resource *res, - const char *name) -{ - int i; - - if (!cx || !res) - return NULL; - - for (i = 0; i < res->priv->num_attributes; i++) { - if (strcmp(name, res->priv->attrs[i].name) == 0) { - return &res->priv->attrs[i]; - } - } - - return NULL; -} diff --git a/src/plugins/resource-native/libmurphy-resource/rset.c b/src/plugins/resource-native/libmurphy-resource/rset.c new file mode 100644 index 0000000..6ff5c1d --- /dev/null +++ b/src/plugins/resource-native/libmurphy-resource/rset.c @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "rset.h" +#include "attribute.h" +#include "message.h" + +#ifndef NO_DEBUG +void print_resource(mrp_res_resource_t *res) +{ + printf(" resource '%s' : %smandatory, %sshared\n", + res->name, res->priv->mandatory ? " " : "not ", + res->priv->shared ? "" : "not "); +} + +void print_resource_set(mrp_res_resource_set_t *rset) +{ + int i; + mrp_res_resource_t *res; + + printf("Resource set %i (%s):\n", rset->priv->id, rset->application_class); + + for (i = 0; i < rset->priv->num_resources; i++) { + res = rset->priv->resources[i]; + print_resource(res); + } +} +#endif + + +void increase_ref(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset) +{ + MRP_UNUSED(cx); + + if (!rset) + return; + + rset->priv->internal_ref_count++; + + printf("rset %p ref count increased to %d\n", + rset, rset->priv->internal_ref_count); +} + + +static int destroy_resource_set(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset) +{ + mrp_msg_t *msg = NULL; + + if (!cx->priv->connected) + goto error; + + rset->priv->seqno = cx->priv->next_seqno; + + msg = mrp_msg_create( + RESPROTO_SEQUENCE_NO, MRP_MSG_FIELD_UINT32, cx->priv->next_seqno++, + RESPROTO_REQUEST_TYPE, MRP_MSG_FIELD_UINT16, + RESPROTO_DESTROY_RESOURCE_SET, + RESPROTO_RESOURCE_SET_ID, MRP_MSG_FIELD_UINT32, rset->priv->id, + RESPROTO_MESSAGE_END); + + if (!msg) + goto error; + + if (!mrp_transport_send(cx->priv->transp, msg)) + goto error; + + mrp_msg_unref(msg); + return 0; + +error: + mrp_msg_unref(msg); + return -1; +} + + + + +void decrease_ref(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset) +{ + if (!rset) + return; + + rset->priv->internal_ref_count--; + + printf("rset %p ref count decreased to %d\n", + rset, rset->priv->internal_ref_count); + + if (rset->priv->internal_ref_count == 0) { + printf("delete the server resource set now\n"); + destroy_resource_set(cx, rset); + mrp_htbl_remove(cx->priv->rset_mapping, + u_to_p(rset->priv->id), FALSE); + mrp_htbl_remove(cx->priv->internal_rset_mapping, + u_to_p(rset->priv->internal_id), TRUE); + } +} + + +mrp_res_resource_t *get_resource_by_name(mrp_res_resource_set_t *rset, + const char *name) +{ + int i; + + if (!rset || !name) + return NULL; + + for (i = 0; i < rset->priv->num_resources; i++) { + mrp_res_resource_t *res = rset->priv->resources[i]; + printf(" comparing '%s' with '%s'\n", + name, res->name ? res->name : "NULL"); + if (strcmp(res->name, name) == 0) { + return res; + } + } + + return NULL; +} + + +static void free_resource(mrp_res_resource_t *res) +{ + if (!res) + return; + + mrp_free((void *) res->name); + + if (res->priv) { + mrp_attribute_array_free(res->priv->attrs, + res->priv->num_attributes); + } + + mrp_free(res->priv); + mrp_free(res); +} + + +void free_resource_set(mrp_res_resource_set_t *rset) +{ + int i; + + printf("> free resource set %p\n", rset); + + if (!rset) + return; + + mrp_free((void *) rset->application_class); + + if (!rset->priv) + goto end; + + for (i = 0; i < rset->priv->num_resources; i++) { + free_resource(rset->priv->resources[i]); + } + mrp_free(rset->priv->resources); + mrp_free(rset->priv); + +end: + mrp_free(rset); +} + + + +void delete_resource_set(mrp_res_context_t *cx, + mrp_res_resource_set_t *rs) +{ + if (!rs) + return; + + printf("> delete_resource_set (%p)\n", rs); + + if (cx && rs->priv) { + /* check if the resource set being deleted is a library resource set */ + mrp_res_resource_set_t *internal_rset = mrp_htbl_lookup( + cx->priv->internal_rset_mapping, u_to_p(rs->priv->internal_id)); + + if (internal_rset && internal_rset != rs) { + decrease_ref(cx, internal_rset); + } + } + + free_resource_set(rs); +} + + + +static mrp_res_resource_t *resource_copy(const mrp_res_resource_t *original, + mrp_res_resource_set_t *new_rset) +{ + mrp_res_resource_t *copy; + + printf("> resource_copy\n"); + + copy = mrp_allocz(sizeof(mrp_res_resource_t)); + + if (!copy) + goto error; + + memcpy(copy, original, sizeof(mrp_res_resource_t)); + + copy->name = mrp_strdup(original->name); + + if (!copy->name) + goto error; + + copy->priv = mrp_allocz(sizeof(mrp_res_resource_private_t)); + + if (!copy->priv) + goto error; + + memcpy(copy->priv, original->priv, sizeof(mrp_res_resource_private_t)); + + copy->priv->pub = copy; + copy->priv->set = new_rset; + + copy->priv->attrs = mrp_attribute_array_dup(original->priv->num_attributes, + original->priv->attrs); + + if (!copy->priv->attrs) + goto error; + + return copy; + +error: + printf("resource_copy error\n"); + + if (copy) { + mrp_free((void *) copy->name); + if (copy->priv) { + mrp_attribute_array_free(copy->priv->attrs, + original->priv->num_attributes); + mrp_free(copy->priv); + } + mrp_free(copy); + } + + return NULL; +} + + + +mrp_res_resource_set_t *resource_set_copy( + const mrp_res_resource_set_t *original) +{ + mrp_res_resource_set_t *copy = NULL; + int i; + + copy = mrp_allocz(sizeof(mrp_res_resource_set_t)); + + printf("> resource_set_copy (%p -> %p)\n", original, copy); + + if (!copy) + goto error; + + copy->state = original->state; + copy->application_class = mrp_strdup(original->application_class); + + if (!copy->application_class) + goto error; + + copy->priv = mrp_allocz(sizeof(mrp_res_resource_set_private_t)); + + if (!copy->priv) + goto error; + + memcpy(copy->priv, original->priv, sizeof(mrp_res_resource_set_private_t)); + + copy->priv->pub = copy; + copy->priv->resources = mrp_allocz_array(mrp_res_resource_t *, + original->priv->num_resources); + + for (i = 0; i < copy->priv->num_resources; i++) { + copy->priv->resources[i] = resource_copy(original->priv->resources[i], + copy); + if (!copy->priv->resources[i]) { + copy->priv->num_resources = --i; + goto error; + } + } + + memset(©->priv->hook, 0, sizeof(mrp_list_hook_t)); + mrp_list_init(©->priv->hook); + + return copy; + +error: + free_resource_set(copy); + return NULL; +} + + +static mrp_res_resource_set_t *create_resource_set( + mrp_res_context_t *cx, + const char *klass, + mrp_res_resource_callback_t cb, + void *userdata) +{ + mrp_res_resource_set_t *rs = mrp_allocz(sizeof(mrp_res_resource_set_t)); + mrp_res_resource_set_t *internal; + + if (!rs) + goto error; + + rs->priv = mrp_allocz(sizeof(mrp_res_resource_set_private_t)); + if (!rs->priv) + goto error; + + rs->application_class = mrp_strdup(klass); + + rs->priv->pub = rs; + rs->priv->id = 0; + rs->priv->internal_id = cx->priv->next_internal_id++; + rs->priv->seqno = 0; + rs->priv->cb = cb; + rs->priv->user_data = userdata; + rs->state = MRP_RES_RESOURCE_PENDING; + + rs->priv->resources = mrp_allocz_array(mrp_res_resource_t *, + cx->priv->master_resource_set->priv->num_resources); + + mrp_list_init(&rs->priv->hook); + + /* ok, create an library-side resource set that we can compare this one to */ + + internal = resource_set_copy(rs); + if (!internal) + goto error; + + increase_ref(cx, internal); + + mrp_htbl_insert(cx->priv->internal_rset_mapping, + u_to_p(internal->priv->internal_id), internal); + + printf("< create_resource_set (%p, internal %p)\n", rs, internal); + + return rs; + +error: + delete_resource_set(cx, rs); + return NULL; +} + + +static int update_library_resource_set(mrp_res_context_t *cx, + const mrp_res_resource_set_t *original, + mrp_res_resource_set_t *rset) +{ + char *application_class = NULL; + mrp_res_resource_t **resources = NULL; + int i, num_resources = 0; + + if (!cx || !original) + return -1; + + /* Update the rset with the values in the original resource set. There + * is only one "library-side" resource set corresponding 1-1 to the server + * resource set. The original is the "client-side" resource set, which there + * can be many. */ + + application_class = mrp_strdup(original->application_class); + if (!application_class) + goto error; + + resources = mrp_allocz_array(mrp_res_resource_t *, + original->priv->num_resources); + if (!resources) + goto error; + + for (i = 0; i < original->priv->num_resources; i++) { + resources[i] = resource_copy(original->priv->resources[i], rset); + if (!resources[i]) { + goto error; + } + num_resources++; + } + + mrp_free((void *) rset->application_class); + for (i = 0; i < rset->priv->num_resources; i++) { + free_resource(rset->priv->resources[i]); + } + mrp_free(rset->priv->resources); + + rset->application_class = application_class; + rset->priv->resources = resources; + rset->priv->num_resources = num_resources; + + return 0; + +error: + mrp_free(application_class); + for (i = 0; i < num_resources; i++) { + free_resource(resources[i]); + } + mrp_free(resources); + + return -1; +} + +/* public API */ + +const mrp_res_string_array_t * mrp_res_list_application_classes( + mrp_res_context_t *cx) +{ + if (!cx) + return NULL; + + return cx->priv->master_classes; +} + + +mrp_res_resource_t *mrp_res_create_resource(mrp_res_context_t *cx, + mrp_res_resource_set_t *set, + const char *name, + bool mandatory, + bool shared) +{ + mrp_res_resource_t *res = NULL, *proto = NULL; + int i = 0; + bool found = false; + + if (cx == NULL || set == NULL || name == NULL) + return NULL; + + for (i = 0; i < cx->priv->master_resource_set->priv->num_resources; i++) { + proto = cx->priv->master_resource_set->priv->resources[i]; + if (strcmp(proto->name, name) == 0) { + found = true; + break; + } + } + + if (!found) + goto error; + + res = mrp_allocz(sizeof(mrp_res_resource_t)); + + if (!res) + goto error; + + res->name = mrp_strdup(name); + + res->state = MRP_RES_RESOURCE_PENDING; + + res->priv = mrp_allocz(sizeof(mrp_res_resource_private_t)); + + if (!res->priv) + goto error; + + res->priv->mandatory = mandatory; + res->priv->shared = shared; + res->priv->pub = res; + + /* copy the attributes with the default values */ + res->priv->attrs = mrp_attribute_array_dup(proto->priv->num_attributes, + proto->priv->attrs); + + res->priv->num_attributes = proto->priv->num_attributes; + + /* add resource to resource set */ + set->priv->resources[set->priv->num_resources++] = res; + + return res; + +error: + printf("mrp_res_create_resource error\n"); + free_resource(res); + + return NULL; +} + + +mrp_res_resource_set_t *mrp_res_copy_resource_set(mrp_res_context_t *cx, + const mrp_res_resource_set_t *original) +{ + mrp_res_resource_set_t *copy, *internal; + + copy = resource_set_copy(original); + + if (!copy) + goto error; + + /* increase the reference count of the library resource set */ + + internal = mrp_htbl_lookup(cx->priv->internal_rset_mapping, + u_to_p(original->priv->internal_id)); + + if (!internal) + goto error; + + increase_ref(cx, internal); + + return copy; + +error: + free_resource_set(copy); + return NULL; +} + +const mrp_res_resource_set_t * mrp_res_list_resources( + mrp_res_context_t *cx) +{ + if (cx == NULL || cx->priv == NULL) + return NULL; + + return cx->priv->master_resource_set; +} + + +int mrp_res_release_resource_set(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset) +{ + mrp_res_resource_set_t *internal_set = NULL; + + printf("> mrp_release_resources (rset %d at %p)\n", + rset->priv->id, rset); + + print_resource_set(rset); + + if (!cx->priv->connected) + goto error; + + if (!rset->priv->internal_id) + goto error; + + internal_set = mrp_htbl_lookup(cx->priv->internal_rset_mapping, + u_to_p(rset->priv->internal_id)); + + if (internal_set->state != MRP_RES_RESOURCE_ACQUIRED) { + return 0; + } + + return release_resource_set_request(cx, internal_set); + +error: + return -1; +} + + +bool mrp_res_equal_resource_set(const mrp_res_resource_set_t *a, + const mrp_res_resource_set_t *b) +{ + if (!a || !b) + return false; + + /* Compare the internal IDs to figure out if the both sets are result + * of the same "create" call. */ + + return a->priv->internal_id == b->priv->internal_id; +} + + +mrp_res_resource_set_t *mrp_res_create_resource_set(mrp_res_context_t *cx, + const char *app_class, + mrp_res_resource_callback_t cb, + void *userdata) +{ + if (cx == NULL) + return NULL; + + return create_resource_set(cx, app_class, cb, userdata); +} + + +void mrp_res_delete_resource_set(mrp_res_context_t *cx, + mrp_res_resource_set_t *set) +{ + delete_resource_set(cx, set); +} + + +void mrp_res_delete_resource(mrp_res_resource_set_t *set, mrp_res_resource_t *res) +{ + MRP_UNUSED(set); + + if (res->priv->set) { + if (!mrp_res_delete_resource_by_name(res->priv->set, res->name)) { + /* hmm, strange */ + free_resource(res); + } + } + else + free_resource(res); +} + + +bool mrp_res_delete_resource_by_name(mrp_res_resource_set_t *rs, const char *name) +{ + int i; + mrp_res_resource_t *res = NULL; + + /* assumption: only one resource of given name in the resource set */ + for (i = 0; i < rs->priv->num_resources; i++) { + if (strcmp(rs->priv->resources[i]->name, name) == 0) { + /* found at i */ + res = rs->priv->resources[i]; + break; + } + } + + if (i == rs->priv->num_resources) { + /* not found */ + return false; + } + + memmove(rs->priv->resources+i, rs->priv->resources+i+1, + (rs->priv->num_resources-i) * sizeof(mrp_res_resource_t *)); + + rs->priv->num_resources--; + rs->priv->resources[rs->priv->num_resources] = NULL; + + free_resource(res); + + return true; +} + + +mrp_res_string_array_t * mrp_res_list_resource_names(mrp_res_context_t *cx, + const mrp_res_resource_set_t *rs) +{ + int i; + mrp_res_string_array_t *ret; + + if (!cx || !rs) + return NULL; + + ret = mrp_allocz(sizeof(mrp_res_string_array_t)); + + if (!ret) + return NULL; + + ret->num_strings = rs->priv->num_resources; + ret->strings = mrp_allocz_array(const char *, rs->priv->num_resources); + + if (!ret->strings) { + mrp_free(ret); + return NULL; + } + + for (i = 0; i < rs->priv->num_resources; i++) { + ret->strings[i] = mrp_strdup(rs->priv->resources[i]->name); + if (!ret->strings[i]) { + ret->num_strings = i; + mrp_res_free_string_array(ret); + return NULL; + } + } + + return ret; +} + + +mrp_res_resource_t * mrp_res_get_resource_by_name(mrp_res_context_t *cx, + const mrp_res_resource_set_t *rs, + const char *name) +{ + int i; + + if (!cx || !rs) + return NULL; + + for (i = 0; i < rs->priv->num_resources; i++) { + if (strcmp(name, rs->priv->resources[i]->name) == 0) { + return rs->priv->resources[i]; + } + } + + return NULL; +} + + +int mrp_res_acquire_resource_set(mrp_res_context_t *cx, + const mrp_res_resource_set_t *original) +{ + mrp_msg_t *msg = NULL; + mrp_res_resource_set_t *rset; + + if (!cx->priv->connected) + goto error; + + rset = mrp_htbl_lookup(cx->priv->internal_rset_mapping, + u_to_p(original->priv->internal_id)); + + printf("> mrp_acquire_resources (client %p, internal %p)\n", + original, rset); + + if (!rset) + goto error; + + update_library_resource_set(cx, original, rset); + + print_resource_set(rset); + + if (rset->priv->id) { + + /* the set has been already created on server */ + + if (rset->state == MRP_RES_RESOURCE_ACQUIRED) { + /* already requested, updating is not supported yet */ + + /* TODO: when supported by backend + * type = RESPROTO_UPDATE_RESOURCE_SET + */ + goto error; + } + else { + /* re-acquire a lost or released set */ + return acquire_resource_set_request(cx, rset); + } + } + + /* Create the resource set. The acquisition is continued + * when the set is created. */ + + if (create_resource_set_request(cx, rset) < 0) + goto error; + + mrp_list_append(&cx->priv->pending_sets, &rset->priv->hook); + + mrp_msg_unref(msg); + return 0; + +error: + mrp_msg_unref(msg); + return -1; +} + diff --git a/src/plugins/resource-native/libmurphy-resource/rset.h b/src/plugins/resource-native/libmurphy-resource/rset.h new file mode 100644 index 0000000..8dd37b8 --- /dev/null +++ b/src/plugins/resource-native/libmurphy-resource/rset.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include "resource-api.h" +#include "resource-private.h" + +#define RESOURCE_MAX 32 + +void print_resource(mrp_res_resource_t *res); + +void print_resource_set(mrp_res_resource_set_t *rset); + + +void increase_ref(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset); + +void decrease_ref(mrp_res_context_t *cx, + mrp_res_resource_set_t *rset); + + +void free_resource_set(mrp_res_resource_set_t *rset); + +void delete_resource_set(mrp_res_context_t *cx, + mrp_res_resource_set_t *rs); + +mrp_res_resource_set_t *resource_set_copy( + const mrp_res_resource_set_t *original); + +mrp_res_resource_t *get_resource_by_name(mrp_res_resource_set_t *rset, + const char *name); \ No newline at end of file diff --git a/src/plugins/resource-native/libmurphy-resource/string_array.c b/src/plugins/resource-native/libmurphy-resource/string_array.c new file mode 100644 index 0000000..13913e5 --- /dev/null +++ b/src/plugins/resource-native/libmurphy-resource/string_array.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "string_array.h" +#include + + +mrp_res_string_array_t *mrp_str_array_dup(uint32_t dim, const char **arr) +{ + uint32_t i; + mrp_res_string_array_t *dup; + + if (dim >= ARRAY_MAX || !arr) + return NULL; + + if (!dim && arr) { + for (dim = 0; arr[dim]; dim++) + ; + } + + if (!(dup = mrp_allocz(sizeof(mrp_res_string_array_t)))) { + errno = ENOMEM; + return NULL; + } + + dup->num_strings = dim; + dup->strings = mrp_allocz_array(const char *, dim); + + if (!dup->strings) { + mrp_free(dup); + errno = ENOMEM; + return NULL; + } + + for (i = 0; i < dim; i++) { + if (arr[i]) { + if (!(dup->strings[i] = mrp_strdup(arr[i]))) { + for (; i > 0; i--) { + mrp_free((void *)dup->strings[i-1]); + } + mrp_free(dup->strings); + mrp_free(dup); + errno = ENOMEM; + return NULL; + } + } + } + + return dup; +} + +/* public API */ + +void mrp_res_free_string_array(mrp_res_string_array_t *arr) +{ + int i; + + if (!arr) + return; + + for (i = 0; i < arr->num_strings; i++) + mrp_free((void *) arr->strings[i]); + + mrp_free(arr->strings); + mrp_free(arr); +} \ No newline at end of file diff --git a/src/plugins/resource-native/libmurphy-resource/string_array.h b/src/plugins/resource-native/libmurphy-resource/string_array.h new file mode 100644 index 0000000..93b7fe9 --- /dev/null +++ b/src/plugins/resource-native/libmurphy-resource/string_array.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "resource-api.h" +#include "resource-private.h" + +#define ARRAY_MAX 1024 + +mrp_res_string_array_t *mrp_str_array_dup(uint32_t dim, const char **arr); -- 2.7.4