You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2015/09/07 12:33:33 UTC
celix git commit: CELIX-237: Fixed issue with sequence and removed
mem leaks from json_rpc
Repository: celix
Updated Branches:
refs/heads/feature/CELIX-237_rsa-ffi c0d4f75af -> f99de6ed1
CELIX-237: Fixed issue with sequence and removed mem leaks from json_rpc
Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/f99de6ed
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/f99de6ed
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/f99de6ed
Branch: refs/heads/feature/CELIX-237_rsa-ffi
Commit: f99de6ed13f730840d233bb1b87ace041f966631
Parents: c0d4f75
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Mon Sep 7 12:32:45 2015 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Mon Sep 7 12:32:45 2015 +0200
----------------------------------------------------------------------
.../dynamic_function_interface/dyn_function.c | 9 +-
.../dynamic_function_interface/dyn_type.c | 6 +
.../dynamic_function_interface/json_rpc.c | 93 +++++++++------
.../descriptors/example1.descriptor | 8 +-
.../dyn_function_tests.cpp | 45 +++++++-
.../json_rpc_tests.cpp | 115 ++++++++++++++++++-
6 files changed, 226 insertions(+), 50 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/celix/blob/f99de6ed/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 abd27d0..e059078 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
@@ -135,13 +135,11 @@ static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descrip
}
}
- if (status == 0) {
+ if (status == OK) {
TAILQ_INSERT_TAIL(&dynFunc->arguments, arg, entries);
} else {
if (arg != NULL) {
- if (arg->name != NULL) {
- free(arg->name);
- }
+ free(arg->name);
if (arg->type != NULL) {
dynType_destroy(arg->type);
}
@@ -218,8 +216,7 @@ void dynFunction_destroy(dyn_function_type *dynFunc) {
}
int dynFunction_call(dyn_function_type *dynFunc, void(*fn)(void), void *returnValue, void **argValues) {
- //TODO check dynFunc arg
- ffi_call(&dynFunc->cif, fn, returnValue, argValues);
+ ffi_call(&dynFunc->cif, fn, returnValue, argValues);
return 0;
}
http://git-wip-us.apache.org/repos/asf/celix/blob/f99de6ed/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 aae7ebc..70f6a7b 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
@@ -443,11 +443,16 @@ static int dynType_parseSequence(FILE *stream, dyn_type *type) {
type->descriptor = '[';
type->sequence.seqType.elements = seq_types;
+ type->sequence.seqType.type = FFI_TYPE_STRUCT;
+ type->sequence.seqType.size = 0;
+ type->sequence.seqType.alignment = 0;
+
status = dynType_parseWithStream(stream, NULL, type, NULL, &type->sequence.itemType);
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;
@@ -513,6 +518,7 @@ static void dynType_clear(dyn_type *type) {
if (mEntry != NULL) {
free(mEntry->name);
free(mEntry->value);
+ free(mEntry);
}
mEntry = next;
}
http://git-wip-us.apache.org/repos/asf/celix/blob/f99de6ed/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 5b49f2b..9acd3fb 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
@@ -5,7 +5,6 @@
#include "json_serializer.h"
#include "dyn_type.h"
#include "dyn_interface.h"
-
#include <jansson.h>
#include <assert.h>
#include <stdint.h>
@@ -62,6 +61,8 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
LOG_DEBUG("RSA: found method '%s'\n", entry->id);
}
+ dyn_type *returnType = dynFunction_returnType(method->dynFunc);
+
void (*fp)(void) = NULL;
void *handle = NULL;
if (status == OK) {
@@ -83,22 +84,19 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
int i;
int index = 0;
+
for (i = 0; i < nrOfArgs; i += 1) {
dyn_type *argType = dynFunction_argumentTypeForIndex(func, i);
const char *argMeta = dynType_getMetaInfo(argType, "am");
if (argMeta == NULL) {
- printf("setting std for %i\n", i);
value = json_array_get(arguments, index++);
status = jsonSerializer_deserializeJson(argType, value, &(args[i]));
} else if (strcmp(argMeta, "pre") == 0) {
- printf("setting pre alloc output for %i\n", i);
dynType_alloc(argType, &args[i]);
-
- } else if ( strcmp(argMeta, "out") == 0) {
- printf("setting output for %i\n", i);
- args[i] = NULL;
+ } else if (strcmp(argMeta, "out") == 0) {
+ void *inMemPtr = calloc(1, sizeof(void *));
+ args[i] = &inMemPtr;
} else if (strcmp(argMeta, "handle") == 0) {
- printf("setting handle for %i\n", i);
args[i] = &handle;
}
@@ -108,32 +106,54 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
}
json_decref(js_request);
+ if (dynType_descriptorType(returnType) != 'N') {
+ //NOTE To be able to handle exception only N as returnType is supported
+ LOG_ERROR("Only interface methods with a native int are supported. Found type '%c'", (char)dynType_descriptorType(returnType));
+ status = ERROR;
+ }
+
+ ffi_sarg returnVal;
- //TODO assert return type is native int
- int returnVal = 0;
- dynFunction_call(func, fp, (void *)&returnVal, args);
- printf("done calling\n");
- double **r = args[2];
- printf("result ptrptr is %p, result ptr %p, result is %f\n", r, *r, **r);
+ if (status == OK) {
+ dynFunction_call(func, fp, (void *) &returnVal, args);
+ }
+ int funcCallStatus = (int)returnVal;
+ if (funcCallStatus != 0) {
+ LOG_WARNING("Error calling remote endpoint function, got error code %i", funcCallStatus);
+ }
json_t *jsonResult = NULL;
- for (i = 0; i < nrOfArgs; i += 1) {
- dyn_type *argType = dynFunction_argumentTypeForIndex(func, i);
- const char *argMeta = dynType_getMetaInfo(argType, "am");
- if (argMeta == NULL) {
- //ignore
- } else if (strcmp(argMeta, "pre") == 0) {
- if (status == OK) {
- status = jsonSerializer_serializeJson(argType, args[i], &jsonResult);
+ 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) {
+ dynType_free(argType, args[i]);
+ } else if (strcmp(argMeta, "pre") == 0) {
+ if (status == OK) {
+ status = jsonSerializer_serializeJson(argType, args[i], &jsonResult);
+ }
+ dynType_free(argType, args[i]);
+ } else if (strcmp(argMeta, "out") == 0) {
+ void ***out = args[i];
+ if (out != NULL && *out != NULL && **out != NULL) {
+ status = jsonSerializer_serializeJson(argType, out, &jsonResult);
+ dyn_type *typedType = NULL;
+ if (status == OK) {
+ status = dynType_typedPointer_getTypedType(argType, &typedType);
+ }
+ if (status == OK) {
+ dynType_free(typedType, *out);
+ }
+ } else {
+ LOG_DEBUG("Output ptr is null");
+ }
}
- } else if (strcmp(argMeta, "out") == 0) {
- printf("TODO\n");
- assert(false);
- }
- if (status != OK) {
- break;
+ if (status != OK) {
+ break;
+ }
}
}
@@ -141,18 +161,22 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
if (status == OK) {
LOG_DEBUG("creating payload\n");
json_t *payload = json_object();
- json_object_set_new(payload, "r", jsonResult);
+ if (funcCallStatus == 0) {
+ LOG_DEBUG("Setting result payload");
+ json_object_set_new(payload, "r", jsonResult);
+ } else {
+ LOG_DEBUG("Setting error payload");
+ json_object_set_new(payload, "e", json_integer(funcCallStatus));
+ }
response = json_dumps(payload, JSON_DECODE_ANY);
json_decref(payload);
- LOG_DEBUG("status ptr is %p. response if '%s'\n", status, response);
+ LOG_DEBUG("status ptr is %p. response is '%s'\n", status, response);
}
if (status == OK) {
*out = response;
} else {
- if (response != NULL) {
- free(response);
- }
+ free(response);
}
//TODO free args (created by jsonSerializer and dynType_alloc) (dynType_free)
@@ -165,7 +189,7 @@ int jsonRpc_prepareInvokeRequest(dyn_function_type *func, const char *id, void *
LOG_DEBUG("Calling remote function '%s'\n", id);
json_t *invoke = json_object();
- json_object_set(invoke, "m", json_string(id));
+ json_object_set_new(invoke, "m", json_string(id));
json_t *arguments = json_array();
json_object_set_new(invoke, "a", arguments);
@@ -216,7 +240,6 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
if (argMeta == NULL) {
//skip
} else if (strcmp(argMeta, "pre") == 0) {
- LOG_DEBUG("found pre argument at %i", i);
dyn_type *subType = NULL;
dynType_typedPointer_getTypedType(argType, &subType);
void *tmp = NULL;
http://git-wip-us.apache.org/repos/asf/celix/blob/f99de6ed/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/example1.descriptor
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/example1.descriptor b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/example1.descriptor
index 97b1df8..771dc5e 100644
--- a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/example1.descriptor
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/example1.descriptor
@@ -7,7 +7,7 @@ classname=org.example.Calculator
:types
StatsResult={DDD[D average min max input}
:methods
-add(DD)D=add(PDD*D)N
-sub(DD)D=sub(PDD*D)N
-sqrt(D)D=sqrt(PD*D)N
-stats([D)LStatsResult;=stats(P[D*LStatsResult;)N
+add(DD)D=add(#am=handle;PDD#am=pre;*D)N
+sub(DD)D=sub(#am=handle;PDD*#am=pre;D)N
+sqrt(D)D=sqrt(#am=handle;PD*#am=pre;D)N
+stats([D)LStatsResult;=stats(#am=handle;P[D#am=out;*LStatsResult;)N
http://git-wip-us.apache.org/repos/asf/celix/blob/f99de6ed/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_function_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_function_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_function_tests.cpp
index 413f6e9..14f2f54 100644
--- a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_function_tests.cpp
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_function_tests.cpp
@@ -166,6 +166,45 @@ extern "C" {
dynFunction_destroy(dynFunc);
}
+
+ struct tst_seq {
+ uint32_t cap;
+ uint32_t len;
+ double *buf;
+ };
+
+ #define EXAMPLE4_DESCRIPTOR "example([D)V"
+
+ static void example4Func(struct tst_seq seq) {
+ CHECK_EQUAL(4, seq.cap);
+ CHECK_EQUAL(2, seq.len);
+ CHECK_EQUAL(1.1, seq.buf[0]);
+ CHECK_EQUAL(2.2, seq.buf[1]);
+ }
+
+ static void test_example4(void) {
+ dyn_function_type *dynFunc = NULL;
+ void (*fp)(void) = (void(*)(void)) example4Func;
+ int rc;
+
+ rc = dynFunction_parseWithStr(EXAMPLE4_DESCRIPTOR, NULL, &dynFunc);
+ CHECK_EQUAL(0, rc);
+
+ double buf[4];
+ buf[0] = 1.1;
+ buf[1] = 2.2;
+ struct tst_seq seq;
+ seq.cap = 4;
+ seq.len = 2;
+ seq.buf = buf;
+
+ void *args[1];
+ args[0] = &seq;
+ rc = dynFunction_call(dynFunc, fp, NULL, args);
+ CHECK_EQUAL(0, rc);
+
+ dynFunction_destroy(dynFunc);
+ }
}
TEST_GROUP(DynFunctionTests) {
@@ -190,4 +229,8 @@ TEST(DynFunctionTests, DynFuncAccTest) {
TEST(DynFunctionTests, DynFuncTest3) {
test_example3();
-}
\ No newline at end of file
+}
+
+TEST(DynFunctionTests, DynFuncTest4) {
+ test_example4();
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/f99de6ed/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 60b028f..5e116a5 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
@@ -2,6 +2,8 @@
* Licensed under Apache License v2. See LICENSE for more information.
*/
#include <CppUTest/TestHarness.h>
+#include <float.h>
+#include <assert.h>
#include "CppUTest/CommandLineTestRunner.h"
extern "C" {
@@ -74,9 +76,110 @@ static void stdLog(void *handle, int level, const char *file, int line, const ch
dynFunction_destroy(dynFunc);
}
+ int add(void *handle, double a, double b, double *result) {
+ *result = a + b;
+ return 0;
+ }
+
+ struct tst_seq {
+ uint32_t cap;
+ uint32_t len;
+ double *buf;
+ };
+
+
+ //StatsResult={DDD[D average min max input}
+ struct tst_StatsResult {
+ double average;
+ double min;
+ double max;
+ struct tst_seq input;
+ };
+
+
+ int stats(void *handle, struct tst_seq input, struct tst_StatsResult **out) {
+ assert(out != NULL);
+ assert(*out == NULL);
+ double total = 0.0;
+ int count = 0;
+ double max = DBL_MIN;
+ double min = DBL_MAX;
+
+ int i;
+ for (i = 0; i<input.len; i += 1) {
+ total += input.buf[i];
+ count += 1;
+ if (input.buf[i] > max) {
+ max = input.buf[i];
+ }
+ if (input.buf[i] < min) {
+ min = input.buf[i];
+ }
+ }
+
+ struct tst_StatsResult *result = (struct tst_StatsResult *) calloc(1, sizeof(*result));
+ result->average = total / count;
+ result->min = min;
+ result->max = max;
+ double *buf = (double *)calloc(input.len, sizeof(double));
+ memcpy(buf, input.buf, input.len * sizeof(double));
+ result->input.len = input.len;
+ result->input.cap = input.len;
+ result->input.buf = buf;
+
+ *out = result;
+ return 0;
+ }
+
+ struct tst_serv {
+ void *handle;
+ int (*add)(void *, double, double, double *);
+ int (*sub)(void *, double, double, double *);
+ int (*sqrt)(void *, double, double *);
+ int (*stats)(void *, struct tst_seq, struct tst_StatsResult **);
+ };
+
+ void callTestPreAllocated(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);
+
+ char *result = NULL;
+
+ struct tst_serv serv;
+ serv.handle = NULL;
+ serv.add = add;
+
+
+ rc = jsonRpc_call(intf, &serv, "{\"m\":\"add(DD)D\", \"a\": [1.0,2.0]}", &result);
+ CHECK_EQUAL(0, rc);
+ STRCMP_CONTAINS("3.0", result);
+
+ free(result);
+ dynInterface_destroy(intf);
+ }
+
+ void callTestOutput(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);
+
+ char *result = NULL;
- void callTest(void) {
- //TODO
+ struct tst_serv serv;
+ serv.handle = NULL;
+ serv.stats = stats;
+
+ rc = jsonRpc_call(intf, &serv, "{\"m\":\"stats([D)LStatsResult;\", \"a\": [[1.0,2.0]]}", &result);
+ CHECK_EQUAL(0, rc);
+ STRCMP_CONTAINS("1.5", result); //avg
+
+ free(result);
+ dynInterface_destroy(intf);
}
}
@@ -103,8 +206,12 @@ TEST(JsonRpcTests, handleTest) {
handleTest();
}
-TEST(JsonRpcTests, call) {
- callTest();
+TEST(JsonRpcTests, callPre) {
+ callTestPreAllocated();
+}
+
+TEST(JsonRpcTests, callOut) {
+ callTestOutput();
}