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();
 }