CELIX-237: Added support for handling reply for output pointers.
Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/2d6ef1ba Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/2d6ef1ba Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/2d6ef1ba Branch: refs/heads/develop Commit: 2d6ef1ba83abee0a62b6aa726dbaed4cea4f1742 Parents: f99de6e Author: Pepijn Noltes <[email protected]> Authored: Mon Sep 7 13:44:11 2015 +0200 Committer: Pepijn Noltes <[email protected]> Committed: Mon Sep 7 13:44:11 2015 +0200 ---------------------------------------------------------------------- .../dynamic_function_interface/dyn_function.c | 37 ++++++++- .../dynamic_function_interface/dyn_function.h | 8 ++ .../dynamic_function_interface/dyn_interface.c | 12 +++ .../dynamic_function_interface/dyn_type.c | 1 - .../dynamic_function_interface/json_rpc.c | 87 ++++++++++++-------- .../json_rpc_tests.cpp | 49 ++++++++++- 6 files changed, 154 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/2d6ef1ba/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c index e059078..7a6a24d 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c @@ -27,7 +27,7 @@ typedef struct _dyn_function_argument_type dyn_function_argument_type; struct _dyn_function_argument_type { int index; char *name; - int argumentType; + enum dyn_function_argument_meta argumentMeta; dyn_type *type; TAILQ_ENTRY(_dyn_function_argument_type) entries; }; @@ -65,8 +65,27 @@ int dynFunction_parse(FILE *descriptor, struct types_head *refTypes, dyn_functio LOG_ERROR("Error allocationg memory for dyn functipn\n"); status = MEM_ERROR; } + + if (status == OK) { + dyn_function_argument_type *arg = NULL; + TAILQ_FOREACH(arg, &dynFunc->arguments, entries) { + const char *meta = dynType_getMetaInfo(arg->type, "am"); + if (meta == NULL) { + arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__STD; + } else if (strcmp(meta, "handle") == 0) { + arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__HANDLE; + } else if (strcmp(meta, "pre") == 0) { + arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT; + } else if (strcmp(meta, "out") == 0) { + arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__OUTPUT; + } else { + LOG_WARNING("unknown argument meta '%s' encountered", meta); + arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__STD; + } + } + } - if (status == 0) { + if (status == OK) { *out = dynFunc; } else { if (dynFunc != NULL) { @@ -156,6 +175,20 @@ static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descrip return status; } +enum dyn_function_argument_meta dynFunction_argumentMetaForIndex(dyn_function_type *dynFunc, int argumentNr) { + enum dyn_function_argument_meta result = 0; + dyn_function_argument_type *arg = NULL; + int index = 0; + TAILQ_FOREACH(arg, &dynFunc->arguments, entries) { + if (index == argumentNr) { + result = arg->argumentMeta; + break; + } + index += 1; + } + return result; +} + static int dynFunction_initCif(dyn_function_type *dynFunc) { int status = 0; http://git-wip-us.apache.org/repos/asf/celix/blob/2d6ef1ba/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h index de8853c..b756e76 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h @@ -22,11 +22,19 @@ typedef struct _dyn_function_type dyn_function_type; DFI_SETUP_LOG_HEADER(dynFunction); +enum dyn_function_argument_meta { + DYN_FUNCTION_ARGUMENT_META__STD = 0, + DYN_FUNCTION_ARGUMENT_META__HANDLE = 1, + DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT = 2, + DYN_FUNCTION_ARGUMENT_META__OUTPUT = 3 +}; + int dynFunction_parse(FILE *descriptorStream, struct types_head *refTypes, dyn_function_type **dynFunc); int dynFunction_parseWithStr(const char *descriptor, struct types_head *refTypes, dyn_function_type **dynFunc); int dynFunction_nrOfArguments(dyn_function_type *dynFunc); dyn_type *dynFunction_argumentTypeForIndex(dyn_function_type *dynFunc, int argumentNr); +enum dyn_function_argument_meta dynFunction_argumentMetaForIndex(dyn_function_type *dynFunc, int argumentNr); dyn_type * dynFunction_returnType(dyn_function_type *dynFunction); void dynFunction_destroy(dyn_function_type *dynFunc); http://git-wip-us.apache.org/repos/asf/celix/blob/2d6ef1ba/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c index 5cd7104..ab436b7 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_interface.c @@ -279,6 +279,18 @@ static int dynInterface_parseMethods(dyn_interface_type *intf, FILE *stream) { entry->index = index++; entry->id = id; entry->dynFunc = func; + entry->name = strndup(id, 1024); + if (entry->name != NULL) { + int i; + for (i = 0; i < 1024; i += 1) { + if (entry->name[i] == '\0') { + break; + } else if (entry->name[i] == '(') { + entry->name[i] = '\0'; + break; + } + } + } TAILQ_INSERT_TAIL(&intf->methods, entry, entries); } else { status = ERROR; http://git-wip-us.apache.org/repos/asf/celix/blob/2d6ef1ba/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c index 70f6a7b..3967e15 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c @@ -452,7 +452,6 @@ static int dynType_parseSequence(FILE *stream, dyn_type *type) { if (status == OK) { type->ffiType = &type->sequence.seqType; dynType_prepCif(&type->sequence.seqType); - LOG_DEBUG("seq size is %zu\n", type->ffiType->size); } return status; http://git-wip-us.apache.org/repos/asf/celix/blob/2d6ef1ba/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_rpc.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_rpc.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_rpc.c index 9acd3fb..56c237c 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_rpc.c +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/json_rpc.c @@ -87,16 +87,16 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c for (i = 0; i < nrOfArgs; i += 1) { dyn_type *argType = dynFunction_argumentTypeForIndex(func, i); - const char *argMeta = dynType_getMetaInfo(argType, "am"); - if (argMeta == NULL) { + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__STD) { value = json_array_get(arguments, index++); status = jsonSerializer_deserializeJson(argType, value, &(args[i])); - } else if (strcmp(argMeta, "pre") == 0) { + } else if (meta == DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT) { dynType_alloc(argType, &args[i]); - } else if (strcmp(argMeta, "out") == 0) { + } else if (meta == DYN_FUNCTION_ARGUMENT_META__OUTPUT) { void *inMemPtr = calloc(1, sizeof(void *)); args[i] = &inMemPtr; - } else if (strcmp(argMeta, "handle") == 0) { + } else if (meta == DYN_FUNCTION_ARGUMENT_META__HANDLE) { args[i] = &handle; } @@ -127,15 +127,15 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c if (funcCallStatus == 0 && status == OK) { for (i = 0; i < nrOfArgs; i += 1) { dyn_type *argType = dynFunction_argumentTypeForIndex(func, i); - const char *argMeta = dynType_getMetaInfo(argType, "am"); - if (argMeta == NULL) { + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__STD) { dynType_free(argType, args[i]); - } else if (strcmp(argMeta, "pre") == 0) { + } else if (meta == DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT) { if (status == OK) { status = jsonSerializer_serializeJson(argType, args[i], &jsonResult); } dynType_free(argType, args[i]); - } else if (strcmp(argMeta, "out") == 0) { + } else if (meta == DYN_FUNCTION_ARGUMENT_META__OUTPUT) { void ***out = args[i]; if (out != NULL && *out != NULL && **out != NULL) { status = jsonSerializer_serializeJson(argType, out, &jsonResult); @@ -179,7 +179,6 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c free(response); } - //TODO free args (created by jsonSerializer and dynType_alloc) (dynType_free) return status; } @@ -198,8 +197,8 @@ int jsonRpc_prepareInvokeRequest(dyn_function_type *func, const char *id, void * int nrOfArgs = dynFunction_nrOfArguments(func); for (i = 0; i < nrOfArgs; i +=1) { dyn_type *type = dynFunction_argumentTypeForIndex(func, i); - const char *argMeta = dynType_getMetaInfo(type, "am"); - if (argMeta == NULL) { + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__STD) { json_t *val = NULL; int rc = jsonSerializer_serializeJson(type, args[i], &val); @@ -225,31 +224,51 @@ int jsonRpc_prepareInvokeRequest(dyn_function_type *func, const char *id, void * } int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]) { - int status = 0; + int status = OK; - json_t *replyJson = json_loads(reply, JSON_DECODE_ANY, NULL); //TODO check - json_t *result = json_object_get(replyJson, "r"); //TODO check + json_error_t error; + json_t *replyJson = json_loads(reply, JSON_DECODE_ANY, &error); + if (replyJson == NULL) { + status = ERROR; + LOG_ERROR("Error parsing json '%s', got error '%s'", reply, error.text); + } - LOG_DEBUG("replyJson ptr is %p and result ptr is %p\n", replyJson, result); + json_t *result = NULL; + if (status == OK) { + result = json_object_get(replyJson, "r"); //TODO check + if (result == NULL) { + status = ERROR; + LOG_ERROR("Cannot find r entry in json reply '%s'", reply); + } + } - int nrOfArgs = dynFunction_nrOfArguments(func); - int i; - for (i = 0; i < nrOfArgs; i += 1) { - dyn_type *argType = dynFunction_argumentTypeForIndex(func, i); - const char *argMeta = dynType_getMetaInfo(argType, "am"); - if (argMeta == NULL) { - //skip - } else if (strcmp(argMeta, "pre") == 0) { - dyn_type *subType = NULL; - dynType_typedPointer_getTypedType(argType, &subType); - void *tmp = NULL; - size_t size = dynType_size(subType); - status = jsonSerializer_deserializeJson(subType, result, &tmp); - void **out = (void **)args[i]; - memcpy(*out, tmp, size); - dynType_free(subType, tmp); - } else if (strcmp(argMeta, "out") == 0) { - assert(false); //TODO + if (status == OK) { + int nrOfArgs = dynFunction_nrOfArguments(func); + int i; + for (i = 0; i < nrOfArgs; i += 1) { + dyn_type *argType = dynFunction_argumentTypeForIndex(func, i); + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT) { + //FIXME need a tmp because deserialize does always does a create (add option?) + dyn_type *subType = NULL; + dynType_typedPointer_getTypedType(argType, &subType); + void *tmp = NULL; + size_t size = dynType_size(subType); + status = jsonSerializer_deserializeJson(subType, result, &tmp); + void **out = (void **)args[i]; + memcpy(*out, tmp, size); + dynType_free(subType, tmp); + } else if (meta == DYN_FUNCTION_ARGUMENT_META__OUTPUT) { + dyn_type *subType = NULL; + dynType_typedPointer_getTypedType(argType, &subType); + dyn_type *subSubType = NULL; + dynType_typedPointer_getTypedType(subType, &subSubType); + void ***out = (void **)args[i]; + //status = jsonSerializer_deserializeJson(subType, result, *out); + status = jsonSerializer_deserializeJson(subSubType, result, *out); + } else { + //skip + } } } http://git-wip-us.apache.org/repos/asf/celix/blob/2d6ef1ba/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/json_rpc_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/json_rpc_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/json_rpc_tests.cpp index 5e116a5..6ebf1c3 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/json_rpc_tests.cpp +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/json_rpc_tests.cpp @@ -59,7 +59,7 @@ static void stdLog(void *handle, int level, const char *file, int line, const ch dynFunction_destroy(dynFunc); } - void handleTest(void) { + void handleTestPre(void) { dyn_function_type *dynFunc = NULL; int rc = dynFunction_parseWithStr("add(#am=handle;PDD#am=pre;*D)N", NULL, &dynFunc); CHECK_EQUAL(0, rc); @@ -182,6 +182,45 @@ static void stdLog(void *handle, int level, const char *file, int line, const ch dynInterface_destroy(intf); } + void handleTestOut(void) { + dyn_interface_type *intf = NULL; + FILE *desc = fopen("descriptors/example1.descriptor", "r"); + CHECK(desc != NULL); + int rc = dynInterface_parse(desc, &intf); + CHECK_EQUAL(0, rc); + + struct methods_head *head; + dynInterface_methods(intf, &head); + dyn_function_type *func = NULL; + struct method_entry *entry = NULL; + TAILQ_FOREACH(entry, head, entries) { + if (strcmp(entry->name, "stats") == 0) { + func = entry->dynFunc; + break; + } + } + CHECK(func != NULL); + + const char *reply = "{\"r\":{\"input\":[1.0,2.0],\"max\":2.0,\"average\":1.5,\"min\":1.0}}"; + + void *args[3]; + args[0] = NULL; + args[1] = NULL; + args[2] = NULL; + + struct tst_StatsResult *result = NULL; + void *out = &result; + args[2] = &out; + + rc = jsonRpc_handleReply(func, reply, args); + CHECK_EQUAL(0, rc); + CHECK_EQUAL(1.5, result->average); + + free(result->input.buf); + free(result); + dynInterface_destroy(intf); + } + } TEST_GROUP(JsonRpcTests) { @@ -202,8 +241,12 @@ TEST(JsonRpcTests, prepareTest) { prepareTest(); } -TEST(JsonRpcTests, handleTest) { - handleTest(); +TEST(JsonRpcTests, handleTestPre) { + handleTestPre(); +} + +TEST(JsonRpcTests, handleTestOut) { + handleTestOut(); } TEST(JsonRpcTests, callPre) {
