]> rtime.felk.cvut.cz Git - orte.git/commitdiff
Java: rewrite receive callback
authorMartin Vajnar <martin.vajnar@gmail.com>
Mon, 20 Apr 2015 17:55:29 +0000 (19:55 +0200)
committerMartin Vajnar <martin.vajnar@gmail.com>
Mon, 20 Apr 2015 17:55:29 +0000 (19:55 +0200)
This commit results in significant increase of subscriber's performance
in Java.

Previously we used to create many Java objects during the reception of fresh
issue. These objects carried the same information as the ORTERecvInfo C
structure. Now we handle it in a way similar to how data reception is taken
care of.

That is, we allocate a direct ByteBuffer upon the creation of subscriber.
This buffer's address is then stored in a helper structure, which is passed
to this receive callback function.

When new issue arrives, we copy it's ORTERecvInfo C structure into this
ByteBuffer by calling memcpy(). We are not immediately parsing the contents
of this buffer for performance reasons. We do it only when someone
requests information included in the buffer (this is handled in the
org.ocera.orte.types.RecvInfo class).

Many method IDs and field IDs previously looked-up upon every callback
invocation are now cached in a helper structure, since the IDs remain
valid until the mentioned classes are unloaded by the ClassLoader
(that is until all their instances are GC'd). Also many unnecessary checks
are removed from the receive callback. This patch increases the probability,
that the callback function remains in the I-cache, because many procedures
are moved away.

Performance comparison before and after applying this patch:
(Reception of 10,000 issues)

PC, Intel C2Q Q9550 @ 2GHz, OpenJDK 7
Before: 2.01 s
Now:    1.68 s

SE Xperia Ray, Android 4.1
Before (Thumb): 10.95 s
Before (ARM):   10.90 s
Now (Thumb):     9.43 s
Now (ARM):       9.53 s

As could be seen the Thumb-2 mode outperforms the ARM mode, so there is now
no need to switch to the ARM mode.

12 files changed:
orte/include/jorte/jorte.h
orte/include/jorte/jorte_protos_api.h
orte/include/jorte/jorte_typedefs_defines.h
orte/include/jorte/org_ocera_orte_types_RecvInfo.h [new file with mode: 0644]
orte/java/src/org/ocera/orte/types/RecvInfo.java
orte/libaorte/jni/Android.mk
orte/libjorte/JORTERecvInfoHelpers.c [new file with mode: 0644]
orte/libjorte/JORTESubscriptionCreate.c
orte/libjorte/JORTESubscriptionDestroy.c
orte/libjorte/Makefile.am
orte/libjorte/Makefile.omk
orte/libjorte/setRecvInfo.c [deleted file]

index 9c7a5e339a253ff05c2060b0aba8f897effca471..3dce75555c8084c8f3fe07f520ffdf733ac132c2 100644 (file)
@@ -49,6 +49,7 @@ extern "C" {
 #include "org_ocera_orte_JOrte.h"
 #include "org_ocera_orte_Manager.h"
 #include "org_ocera_orte_Publication.h"
+#include "org_ocera_orte_types_RecvInfo.h"
 #include "org_ocera_orte_Subscription.h"
 
 #ifdef __cplusplus
index a42f0123aa87c85144d1193b317a070e3705ec35..6b617ad4fa793e4c589bd387731d10e6ea759ff8 100644 (file)
@@ -9,9 +9,6 @@ setTopic(JNIEnv *env, jclass cls, jobject obj, const char *topic);
 extern int
 setType(JNIEnv *env, jclass cls, jobject obj, const char *type);
 
-extern int
-setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo, jobject obj);
-
 extern jobject
 createAppInfo(JNIEnv *env, const ORTEAppInfo *ainfo);
 
index 14b31ac4499a88c1eaf3103ee89d66d8570f8572..f252bca37caaef9f2ce8a162ba7a46ddf146dc6d 100644 (file)
@@ -27,6 +27,12 @@ typedef struct {
   jobject        rinfo;
   jobject        msg;
   jobject        obj_buf; // byte buffer object
+  void          *info_buf; // RecvInfo buffer pointer
+  jmethodID  mid_read;
+  jmethodID  mid_callback;
+  jmethodID  mid_order;
+  jobject    obj_BO_BE;
+  jobject    obj_BO_LE;
   CDR_Endianness cur_endian;
 } JORTECallbackContext_t;
 
diff --git a/orte/include/jorte/org_ocera_orte_types_RecvInfo.h b/orte/include/jorte/org_ocera_orte_types_RecvInfo.h
new file mode 100644 (file)
index 0000000..cd7e20a
--- /dev/null
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_ocera_orte_types_RecvInfo */
+
+#ifndef _Included_org_ocera_orte_types_RecvInfo
+#define _Included_org_ocera_orte_types_RecvInfo
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_ocera_orte_types_RecvInfo
+ * Method:    get_string
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_ocera_orte_types_RecvInfo_get_1string
+  (JNIEnv *, jobject, jlong);
+
+/*
+ * Class:     org_ocera_orte_types_RecvInfo
+ * Method:    c_helper
+ * Signature: (Ljava/nio/ByteBuffer;)V
+ */
+JNIEXPORT void JNICALL Java_org_ocera_orte_types_RecvInfo_c_1helper
+  (JNIEnv *, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
index b7117305ed0a3b387d6e3d98af9187695eecfee0..2baddba6d64ccc23b88dde5d6c96f1bedece8fe0 100644 (file)
 
 package org.ocera.orte.types;
 
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 public class RecvInfo
 {
-  private byte            status;
-  private String          topic;
-  private String          typeName;
-  private GUID_RTPS       senderGUID;
-  private NtpTime         localTimeRecv;
-  private NtpTime         remoteTimePub;
-  private SequenceNumber  sn;
+
+  private ByteBuffer      info_buffer;
+  
+  /*      Helper buffer structure (all 32-bit integers):
+   *       [0]  sizeof(ORTERecvInfo),
+   *       [1]  sizeof(ORTERecvStatus),
+   *       [2]  sizeof(char*),
+   *       [3]  offsetof(ORTERecvInfo,status),
+   *       [4]  offsetof(ORTERecvInfo,topic),
+   *       [5]  offsetof(ORTERecvInfo,type),
+   *       [6]  offsetof(ORTERecvInfo,senderGUID),
+   *       [7]  offsetof(ORTERecvInfo,localTimeReceived),
+   *       [8]  offsetof(ORTERecvInfo,remoteTimePublished),
+   *       [9]  offsetof(ORTERecvInfo,sn),
+   *     [10]  offsetof(GUID_RTPS,hid),
+   *     [11]  offsetof(GUID_RTPS,aid),
+   *     [12]  offsetof(GUID_RTPS,oid),
+   *     [13]  offsetof(NtpTime,seconds),
+   *     [14]  offsetof(NtpTime,fraction),
+   *     [15]  offsetof(SequenceNumber,high),
+   *     [16]  offsetof(SequenceNumber,low)
+   */
+  private ByteBuffer      helper_buffer;
 
   public RecvInfo()
   {
        //System.out.println(":j: instance of RecvInfo created..");
+    this.helper_buffer = ByteBuffer.allocateDirect(17*Integer.SIZE/8);
+    this.helper_buffer.order(ByteOrder.nativeOrder());
+    this.c_helper(helper_buffer);
+
+    this.info_buffer = ByteBuffer.allocateDirect(helper_buffer.getInt(0));
+    this.info_buffer.order(ByteOrder.nativeOrder());
   }
 
 
   public byte getRecvStatus()
   {
-    return this.status;
+    byte ret_val;
+    
+    switch(helper_buffer.getInt(Integer.SIZE/8)) {
+      case 4:
+        ret_val = (byte) info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*3/8));
+        break;
+      case 1:
+        ret_val = info_buffer.get(helper_buffer.getInt(Integer.SIZE*3/8));
+        break;
+      case 2:
+        ret_val = (byte) info_buffer.getShort(helper_buffer.getInt(Integer.SIZE*3/8));
+        break;
+      case 8:
+        ret_val = (byte) info_buffer.getLong(helper_buffer.getInt(Integer.SIZE*3/8));
+        break;
+    default:
+        System.out.println("j: ORTERecvStatus of unknown size!");
+        return -1;
+    }
+
+    return ret_val;
   }
 
   public String getTopic()
   {
-    return this.topic;
+    long topic_pointer;
+    
+    switch(helper_buffer.getInt(Integer.SIZE*2/8)) {
+      case 4:
+        topic_pointer = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*4/8));
+        break;
+      case 8:
+        topic_pointer = info_buffer.getLong(helper_buffer.getInt(Integer.SIZE*4/8));
+        break;
+      case 1:
+        topic_pointer = info_buffer.get(helper_buffer.getInt(Integer.SIZE*4/8));
+        break;
+      case 2:
+        topic_pointer = info_buffer.getShort(helper_buffer.getInt(Integer.SIZE*4/8));
+        break;
+      default:
+        return null;
+    }
+    
+    return get_string(topic_pointer);
   }
 
   public String getTypeName()
   {
-    return this.typeName;
+    long type_pointer;
+    
+    switch(helper_buffer.getInt(Integer.SIZE*2/8)) {
+      case 4:
+        type_pointer = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*5/8));
+        break;
+      case 8:
+        type_pointer = info_buffer.getLong(helper_buffer.getInt(Integer.SIZE*5/8));
+        break;
+      case 1:
+        type_pointer = info_buffer.get(helper_buffer.getInt(Integer.SIZE*5/8));
+        break;
+      case 2:
+        type_pointer = info_buffer.getShort(helper_buffer.getInt(Integer.SIZE*5/8));
+        break;
+      default:
+        return null;
+    }
+    
+    return get_string(type_pointer);
   }
 
   public GUID_RTPS getSenderGuid()
   {
-    return this.senderGUID.get();
+    long hostId   = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*6/8)+helper_buffer.getInt(Integer.SIZE*10/8)) & 0xffffffffL;
+    long appId    = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*6/8)+helper_buffer.getInt(Integer.SIZE*11/8)) & 0xffffffffL;
+    long objectId = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*6/8)+helper_buffer.getInt(Integer.SIZE*12/8)) & 0xffffffffL;
+    
+    
+    return new GUID_RTPS(hostId, appId, objectId);
   }
 
   public NtpTime getLocalTimeRecv()
   {
-    return this.localTimeRecv.get();
+    int  seconds  = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*7/8)+helper_buffer.getInt(Integer.SIZE*13/8));
+    long fraction = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*7/8)+helper_buffer.getInt(Integer.SIZE*14/8)) & 0xffffffffL;
+
+    return new NtpTime(seconds, fraction);
   }
 
   public NtpTime getRemoteTimePub()
   {
-    return this.remoteTimePub.get();
+    int  seconds  = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*8/8)+helper_buffer.getInt(Integer.SIZE*13/8));
+    long fraction = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*8/8)+helper_buffer.getInt(Integer.SIZE*14/8)) & 0xffffffffL;
+
+    return new NtpTime(seconds, fraction);
   }
 
   public SequenceNumber getSeqNumber()
   {
-    return this.sn.get();
+    int high = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*9/8)+helper_buffer.getInt(Integer.SIZE*15/8));
+    long low  = info_buffer.getInt(helper_buffer.getInt(Integer.SIZE*9/8)+helper_buffer.getInt(Integer.SIZE*16/8));
+
+    return new SequenceNumber(high, low);
   }
 
   /** only for test purposes */
@@ -85,8 +181,17 @@ public class RecvInfo
       System.out.println(":j:    senderGuid: " + this.getSenderGuid()); 
       System.out.println(":j: localTimerecv: " + this.getLocalTimeRecv()); 
       System.out.println(":j: remoteTimePub: " + this.getRemoteTimePub()); 
-      sn = this.getSeqNumber();
-      System.out.println(":j:         seqNr: " + sn.getDecimal());     
+    System.out.println(":j:         seqNr: " + this.getSeqNumber().getDecimal());      
+  }
+  
+  public ByteBuffer getBuffer()
+  {
+    return this.info_buffer;
   }
   
+  /* NATIVE FUNCTIONS */
+  
+  private native String get_string(long string_pointer);
+  private native void c_helper(ByteBuffer buffer);
+  
 }
index 6299530a67a0f0156a21e996ffacdea154d4727d..228a2cfe2837788ea5c709b6f85b2ef9d415eb8b 100644 (file)
@@ -66,7 +66,6 @@ libjorte/setTopic.c \
 libjorte/createAppInfo.c \
 libjorte/createPubInfo.c \
 libjorte/createSubInfo.c \
-libjorte/setRecvInfo.c \
 libjorte/JGetORTEConstant.c \
 libjorte/JIPAddressToString.c \
 libjorte/JNtpTimeToStringMs.c \
@@ -90,6 +89,7 @@ libjorte/JORTEPublicationPropertiesSet.c \
 libjorte/JORTEPublicationPropertiesGet.c \
 libjorte/JORTEPublicationGetStatus.c \
 libjorte/JORTEPublicationWaitForSubscriptions.c \
+libjorte/JORTERecvInfoHelpers.c \
 libjorte/JORTESleepMs.c \
 libjorte/JORTESubscriptionCreate.c \
 libjorte/JORTESubscriptionDestroy.c \
@@ -106,4 +106,5 @@ libjorte/JStringToIPAddress.c
 
 LOCAL_STATIC_LIBRARIES := orte
 
-include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/orte/libjorte/JORTERecvInfoHelpers.c b/orte/libjorte/JORTERecvInfoHelpers.c
new file mode 100644 (file)
index 0000000..32740b1
--- /dev/null
@@ -0,0 +1,53 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stddef.h>
+
+// library header file's path
+#include "orte_all.h"
+// pregenerated header
+#include "jorte/org_ocera_orte_types_RecvInfo.h"
+// enable TEST_STAGE run level
+#include "jorte/4all.h"
+// new data types
+#include "jorte/jorte_typedefs_defines.h"
+#include "jorte/jorte_protos_api.h"
+
+/*
+ * Class:     org_ocera_orte_types_RecvInfo
+ * Method:    c_helper
+ * Signature: (Ljava/nio/ByteBuffer;)V
+ */
+JNIEXPORT void JNICALL Java_org_ocera_orte_types_RecvInfo_c_1helper
+  (JNIEnv *env, jobject obj, jobject b_buffer) {
+
+    int32_t* buffer = (*env)->GetDirectBufferAddress(env, b_buffer);
+    
+    buffer[0] = (int32_t)sizeof(ORTERecvInfo);
+    buffer[1] = (int32_t)sizeof(ORTERecvStatus);
+    buffer[2] = (int32_t)sizeof(char*);
+    buffer[3] = (int32_t)offsetof(ORTERecvInfo,status);
+    buffer[4] = (int32_t)offsetof(ORTERecvInfo,topic);
+    buffer[5] = (int32_t)offsetof(ORTERecvInfo,type);
+    buffer[6] = (int32_t)offsetof(ORTERecvInfo,senderGUID);
+    buffer[7] = (int32_t)offsetof(ORTERecvInfo,localTimeReceived);
+    buffer[8] = (int32_t)offsetof(ORTERecvInfo,remoteTimePublished);
+    buffer[9] = (int32_t)offsetof(ORTERecvInfo,sn);
+    buffer[10] = (int32_t)offsetof(GUID_RTPS,hid);
+    buffer[11] = (int32_t)offsetof(GUID_RTPS,aid);
+    buffer[12] = (int32_t)offsetof(GUID_RTPS,oid);
+    buffer[13] = (int32_t)offsetof(NtpTime,seconds);
+    buffer[14] = (int32_t)offsetof(NtpTime,fraction);
+    buffer[15] = (int32_t)offsetof(SequenceNumber,high);
+    buffer[16] = (int32_t)offsetof(SequenceNumber,low);
+  }
+
+/*
+ * Class:     org_ocera_orte_types_RecvInfo
+ * Method:    get_string
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_ocera_orte_types_RecvInfo_get_1string
+  (JNIEnv *env, jobject obj, jlong string_ptr) {
+    return (*env)->NewStringUTF(env, (char*) string_ptr);
+  }
index 0a9c87767bded0a16080c9f48b05e71fdfa5d07f..e5d37ad41c5707f927bd8757db690f74b543e04c 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <stdlib.h>
 #include <inttypes.h>
+#include <string.h>
 
 // library header file's path
 #include "orte_all.h"
@@ -49,21 +50,15 @@ recvCallBack(const ORTERecvInfo *info, void *vinstance, void *recvCallBackParam)
   // jni varialbles
   JavaVM          *jvm = 0;
   JNIEnv          *env = 0;
-  jclass           cls = 0; // local reference!
-  jclass           cls_msg = 0;
-  jobject          rinfo = 0;
-  jobject          obj_msg;
   jobject          obj_bo = 0;
-  jfieldID         fid = 0;
-  jmethodID        mid = 0;
-  jmethodID        mid_callback = 0;
 
-  //
+  JORTECallbackContext_t   *callback_cont;
+
   // if the subscriber has been destroyed, return
   if ((*(JORTECallbackContext_t **)recvCallBackParam) == 0)
     return;
 
-  JORTECallbackContext_t   *callback_cont = *((JORTECallbackContext_t **)recvCallBackParam);
+  callback_cont = *((JORTECallbackContext_t **)recvCallBackParam);
 
   #ifdef TEST_STAGE
   printf("\n\n:c: --------------- recvCallBack called.. --------------- \n");
@@ -71,150 +66,45 @@ recvCallBack(const ORTERecvInfo *info, void *vinstance, void *recvCallBackParam)
 
   do {
     // set local variables from struct
-    if (callback_cont->jvm == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: jvm = NULL \n");
-      #endif
-      break;
-    }
     jvm = callback_cont->jvm;
     // get env
-    (*jvm)->AttachCurrentThread(jvm,
+    if((*jvm)->AttachCurrentThread(jvm,
                                #ifdef __ANDROID__
                                &env,
                                #else
                                (void **)&env,
                                #endif
-                               NULL);
-    if (env == 0) {
+                               NULL) != JNI_OK)
+    {
       #ifdef TEST_STAGE
-      printf(":!c: env = NULL \n");
+      printf(":!c: recvCallBack: AttachCurrentThread() failed \n");
       #endif
-      break;
+      return;
     }
-    //
+
     // set byte order only if it differs from that currently set
     if (info->data_endian != callback_cont->cur_endian) {
-      //prepare ByteOrder
-      cls = (*env)->FindClass(env, "java/nio/ByteOrder");
-      if (cls == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: cls = NULL \n");
-       #endif
-      }
       if (info->data_endian == BigEndian) {
-       fid = (*env)->GetStaticFieldID(env,
-                                      cls,
-                                      "BIG_ENDIAN",
-                                      "Ljava/nio/ByteOrder;");
+       obj_bo = callback_cont->obj_BO_BE;
        callback_cont->cur_endian = BigEndian;
       } else {
-       fid = (*env)->GetStaticFieldID(env,
-                                      cls,
-                                      "LITTLE_ENDIAN",
-                                      "Ljava/nio/ByteOrder;");
+       obj_bo = callback_cont->obj_BO_LE;
        callback_cont->cur_endian = LittleEndian;
       }
-      if (fid == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: fid = NULL \n");
-       #endif
-      }
-      obj_bo = (*env)->GetStaticObjectField(env, cls, fid);
-      if (obj_bo == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: cls = NULL \n");
-       #endif
-      }
 
       // set byte order to ByteBuffer
-      // get BB class
-      cls = (*env)->GetObjectClass(env, callback_cont->obj_buf);
-      if (cls == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: cls = NULL \n");
-       #endif
-      }
-      // get methodID - order(ByteOrder)
-      mid = (*env)->GetMethodID(env,
-                               cls,
-                               "order",
-                               "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
-      if (mid == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: mid = NULL \n");
-       #endif
-      }
-
-      // set ByteOrder
-      if ((*env)->CallObjectMethod(env, callback_cont->obj_buf, mid, obj_bo) == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: set byte order failed.. \n");
-       #endif
-      }
-    }
-    //
-    if (callback_cont->obj == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: obj = NULL \n");
-      #endif
-      break;
+      (*env)->CallObjectMethod(env, callback_cont->obj_buf, callback_cont->mid_order, obj_bo);
     }
-    // set local vars
-    rinfo = callback_cont->rinfo;
-    obj_msg = callback_cont->msg;
-
 
       #ifdef TEST_STAGE
     printf(":c: #0 \n");
-    printf(":c: env = %#" PRIxPTR ", obj_msg = %#" PRIxPTR " \n", (intptr_t)env, (intptr_t)obj_msg);
+    printf(":c: env = %#" PRIxPTR ", obj_msg = %#" PRIxPTR " \n", (intptr_t)env, (intptr_t)callback_cont->msg);
       #endif
 
-
-    //
-    if (rinfo == 0) {
-      // find cls
-      cls = findClass(env, "org.ocera.orte.types.RecvInfo");
-      if (cls == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: cls = NULL \n");
-       #endif
-       break;
-      }
-      // call object constructor
-      mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
-      if (mid == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: constructor failed! \n");
-       #endif
-       break;
-      }
-      // create new object
-      rinfo = (*env)->NewObject(env, cls, mid);
-      if (rinfo == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: rinfo = NULL \n");
-       #endif
-       break;
-      }
-      // create global reference
-      callback_cont->rinfo = (*env)->NewGlobalRef(env, rinfo);
-      if (callback_cont->rinfo == 0) {
-       #ifdef TEST_STAGE
-       printf(":!c: callback_cont->rinfo = NULL \n");
-       #endif
-       break;
-      }
-    }
     ////////////////////////////////////////////////////
-    // set RecvInfo instance
-    if (setRecvInfo(env, info, callback_cont->rinfo) == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: setRecvInfo() failed! \n");
-      #endif
-      break;
-    }
+    memcpy(callback_cont->info_buf, (void*)info, sizeof(ORTERecvInfo));
     ////////////////////////////////////////////////////
+
     // control print - only in TEST_STAGE
     #ifdef TEST_STAGE
     printf(":c: rinfo created :] \n");
@@ -233,79 +123,32 @@ recvCallBack(const ORTERecvInfo *info, void *vinstance, void *recvCallBackParam)
     #endif
     ////////////////////////////////////////////////////
     // update MessageData instance
-    // get cls
-    cls_msg = (*env)->GetObjectClass(env, obj_msg);
-    if (cls_msg == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: cls_msg = NULL \n");
-      #endif
-      break;
-    }
-    /////////////////////////////////////////////////////
-    // methodID - read()
-    mid = (*env)->GetMethodID(env,
-                             cls_msg,
-                             "read",
-                             "()V");
-    if (mid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: mid = NULL \n");
-      #endif
-      break;
-    }
     // call method
     (*env)->CallVoidMethod(env,
-                          obj_msg,
-                          mid);
+                          callback_cont->msg,
+                          callback_cont->mid_read);
 
     /* *************************** *
      *  call JAVA CallBack method  *
      * *************************** */
-      #ifdef TEST_STAGE
-    printf(":c: call JAVA CallBack method \n");
-      #endif
-
-
-    // get class
-    cls = (*env)->GetObjectClass(env, callback_cont->obj);
-    if (cls == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: cls = NULL \n");
-      #endif
-      break;
-    }
-    // get method ID
-    mid = (*env)->GetMethodID(env,
-                             cls,
-                             "callback",
-                             "(Lorg/ocera/orte/types/RecvInfo;Lorg/ocera/orte/types/MessageData;)V");
-    if (mid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: cls = NULL \n");
-      #endif
-      break;
-    }
-    mid_callback = mid;
-    //
     #ifdef TEST_STAGE
     printf(":c: volam callback metodu.. halo jsi tam?? \n");
     #endif
     // call object's method
     (*env)->CallVoidMethod(env,
                           callback_cont->obj, /*obj*/
-                          mid_callback,
+                          callback_cont->mid_callback,
                           callback_cont->rinfo,
-                          obj_msg);
+                          callback_cont->msg);
   } while (0);
 
   // detach current thread
-  if ((*jvm)->DetachCurrentThread(jvm) != 0)
+  if ((*jvm)->DetachCurrentThread(jvm) != JNI_OK)
     printf(":c!: DetachCurrentThread failed! \n");
   //
   #ifdef TEST_STAGE
   printf(":c: ------------ thats all from recvCallBack ------------ \n\n");
   #endif
-
 }
 
 /* ****************************************************************** *
@@ -332,6 +175,8 @@ Java_org_ocera_orte_Subscription_jORTESubscriptionCreate
   JavaVM                 *jvm;
   jfieldID                fid;
   jclass                  cls;
+  jmethodID           mid;
+  jobject                obj_info_buffer;
   // orte variables
   ORTESubscription       *s = 0;
   ORTEDomain             *d;
@@ -368,16 +213,16 @@ Java_org_ocera_orte_Subscription_jORTESubscriptionCreate
     }
     // get jvm
     jint b = (*env)->GetJavaVM(env, &jvm);
-    if (b <  0) {
+    if (b == JNI_OK) {
       #ifdef TEST_STAGE
-      printf(":!c: getJavaVM() failed! \n");
+      printf(":c: getJavaVM succesfull.. \n");
       #endif
-      break;
     }
-    if (b == 0) {
+    else {
       #ifdef TEST_STAGE
-      printf(":c: getJavaVM succesfull.. \n");
+      printf(":!c: getJavaVM() failed! \n");
       #endif
+      break;
     }
     callback_cont->jvm = jvm;
     callback_cont->cur_endian = (CDR_Endianness)jbyteOrder;
@@ -390,6 +235,25 @@ Java_org_ocera_orte_Subscription_jORTESubscriptionCreate
       #endif
       break;
     }
+    // get ReceiveCallback class
+    cls = (*env)->GetObjectClass(env, callback_cont->obj);
+    if (cls == 0) {
+      #ifdef TEST_STAGE
+      printf(":!c: cls = NULL \n");
+      #endif
+      break;
+    }
+    // get callback method ID
+    callback_cont->mid_callback = (*env)->GetMethodID(env,
+                             cls,
+                             "callback",
+                             "(Lorg/ocera/orte/types/RecvInfo;Lorg/ocera/orte/types/MessageData;)V");
+    if (callback_cont->mid_callback == 0) {
+      #ifdef TEST_STAGE
+      printf(":!c: mid_callback = NULL \n");
+      #endif
+      break;
+    }
     // create global references
     callback_cont->obj_buf = (*env)->NewGlobalRef(env, jinstance);
     //
@@ -408,8 +272,90 @@ Java_org_ocera_orte_Subscription_jORTESubscriptionCreate
       #endif
       break;
     }
+    // get MessageData class
+    cls = (*env)->GetObjectClass(env, callback_cont->msg);
+    if (cls == 0) {
+      #ifdef TEST_STAGE
+      printf(":!c: cls_msg = NULL \n");
+      #endif
+      break;
+    }
+    /////////////////////////////////////////////////////
+    // methodID - read()
+    callback_cont->mid_read = (*env)->GetMethodID(env,
+                             cls,
+                             "read",
+                             "()V");
+    if (callback_cont->mid_read == 0) {
+      #ifdef TEST_STAGE
+      printf(":!c: mid_read = NULL \n");
+      #endif
+      break;
+    }
     // init RecvInfo pointer
-    callback_cont->rinfo = 0;
+    // find cls
+    cls = findClass(env, "org.ocera.orte.types.RecvInfo");
+    if (cls == 0) {
+        #ifdef TEST_STAGE
+        printf(":!c: cls = NULL \n");
+        #endif
+        break;
+    }
+    // call object constructor
+    mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
+    if (mid == 0) {
+        #ifdef TEST_STAGE
+        printf(":!c: constructor failed! \n");
+        #endif
+        break;
+    }
+    // create new object
+    callback_cont->rinfo = (*env)->NewObject(env, cls, mid);
+    if (callback_cont->rinfo == 0) {
+        #ifdef TEST_STAGE
+        printf(":!c: rinfo = NULL \n");
+        #endif
+        break;
+    }
+    // create global reference
+    callback_cont->rinfo = (*env)->NewGlobalRef(env, callback_cont->rinfo);
+    if (callback_cont->rinfo == 0) {
+        #ifdef TEST_STAGE
+        printf(":!c: callback_cont->rinfo = NULL \n");
+        #endif
+        break;
+    }
+    // lookup getBuffer() ID
+    mid = (*env)->GetMethodID(env, cls, "getBuffer", "()Ljava/nio/ByteBuffer;");
+    if (mid == 0) {
+        #ifdef TEST_STAGE
+        printf(":!c: getBuffer() failed! \n");
+        #endif
+        break;
+    }
+    // get ByteBuffer reference
+    obj_info_buffer = (*env)->CallObjectMethod(env, callback_cont->rinfo, mid);
+    callback_cont->info_buf = (*env)->GetDirectBufferAddress(env, obj_info_buffer);
+    // create global references for ByteOrders
+    cls = (*env)->FindClass(env, "java/nio/ByteOrder");
+    fid = (*env)->GetStaticFieldID(env,
+                                   cls,
+                                   "BIG_ENDIAN",
+                                   "Ljava/nio/ByteOrder;");
+    callback_cont->obj_BO_BE = (*env)->GetStaticObjectField(env, cls, fid);
+    callback_cont->obj_BO_BE = (*env)->NewGlobalRef(env, callback_cont->obj_BO_BE);
+    fid = (*env)->GetStaticFieldID(env,
+                                   cls,
+                                   "LITTLE_ENDIAN",
+                                   "Ljava/nio/ByteOrder;");
+    callback_cont->obj_BO_LE = (*env)->GetStaticObjectField(env, cls, fid);
+    callback_cont->obj_BO_LE = (*env)->NewGlobalRef(env, callback_cont->obj_BO_LE);
+    // get methodID - order(ByteOrder)
+    cls = (*env)->GetObjectClass(env, callback_cont->obj_buf);
+    callback_cont->mid_order = (*env)->GetMethodID(env,
+                                                   cls,
+                                                   "order",
+                                                   "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
     //
     cls = (*env)->GetObjectClass(env, obj);
     if (cls == 0) {
index 833070c739418c702bb7119a4893090a30e5e1d6..d499f6801da2c19b79402f11311e676fb8a1dd0c 100644 (file)
@@ -114,6 +114,18 @@ Java_org_ocera_orte_Subscription_jORTESubscriptionDestroy
        #endif
        (*env)->DeleteGlobalRef(env, ctx->obj_buf);
       }
+      if (ctx->obj_BO_BE) {
+       #ifdef TEST_STAGE
+       printf(":c: deleting ctx->obj_BO_BE\n");
+       #endif
+       (*env)->DeleteGlobalRef(env, ctx->obj_BO_BE);
+      }
+      if (ctx->obj_BO_LE) {
+       #ifdef TEST_STAGE
+       printf(":c: deleting ctx->obj_BO_LE\n");
+       #endif
+       (*env)->DeleteGlobalRef(env, ctx->obj_BO_LE);
+      }
       //
       free(ctx);
     }
index 0888c76b5a6ac9cecd0c767e28394174b352eb8d..e70c435bd4d504091b37dcc69d35e278e8a34b2c 100644 (file)
@@ -26,6 +26,7 @@ JORTEInit.c \
 JORTEPublicationCreate.c \
 JORTEPublicationDestroy.c \
 JORTEPublicationSend.c \
+JORTERecvInfoHelpers.c \
 JORTESleepMs.c \
 JORTESubscriptionCreate.c \
 JORTESubscriptionDestroy.c \
@@ -54,7 +55,7 @@ JORTESubscriptionWaitForPublications.c \
 JORTETypeRegisterDestroyAll.c \
 JORTEVerbositySetLogFile.c \
 JORTEVerbositySetOptions.c \
-setRecvInfo.c setTopic.c setType.c
+setTopic.c setType.c
 
 dist-hook:
        cp -f  $(srcdir)/Makefile $(distdir)/Makefile
index 3a892159c36c78ceb3a0fecf09957c806b2ae01b..8aea1fe3c1f6ffbeb44834415573b8152b557de8 100644 (file)
@@ -22,7 +22,6 @@ setTopic.c \
 createAppInfo.c \
 createPubInfo.c \
 createSubInfo.c \
-setRecvInfo.c \
 JGetORTEConstant.c \
 JIPAddressToString.c \
 JNtpTimeToStringMs.c \
@@ -46,6 +45,7 @@ JORTEPublicationPropertiesSet.c \
 JORTEPublicationPropertiesGet.c \
 JORTEPublicationGetStatus.c \
 JORTEPublicationWaitForSubscriptions.c \
+JORTERecvInfoHelpers.c \
 JORTESleepMs.c \
 JORTESubscriptionCreate.c \
 JORTESubscriptionDestroy.c \
diff --git a/orte/libjorte/setRecvInfo.c b/orte/libjorte/setRecvInfo.c
deleted file mode 100644 (file)
index 6acb985..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/* setRecvInfo.c  */
-
-#include <jni.h>
-#include <inttypes.h>
-#include "orte.h"
-#include "jorte/4all.h"
-#include "jorte/jorte_protos_api.h"
-
-int
-setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo, jobject obj)
-{
-  jclass    cls;
-  jclass    cls_tmp;
-//  jobject   obj;
-  jobject   obj_tmp;
-  jfieldID  fid;
-  jmethodID mid;
-  //
-  int flag_ok = 0;
-
-  #ifdef TEST_STAGE
-  int32_t sec;
-  uint32_t us;
-  #endif
-
-  do {
-    // find cls
-    cls = findClass(env, "org.ocera.orte.types.RecvInfo");
-    if (cls == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: cls = NULL \n");
-      #endif
-      break;
-    }
-    // field ID - status
-    fid = (*env)->GetFieldID(env, cls, "status", "B");
-    if (fid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: fid = NULL \n");
-      #endif
-      break;
-    }
-    #ifdef TEST_STAGE
-    printf(":c: rinfo.status = %d \n",
-          rinfo->status);
-    #endif
-    (*env)->SetByteField(env,
-                        obj,
-                        fid,
-                        (jbyte)rinfo->status);
-/////////////////////////////////////////////////
-    // set topic
-    if (!setTopic(env, cls, obj, rinfo->topic)) {
-      #ifdef TEST_STAGE
-      printf(":!c: seTopic() failed! \n");
-      #endif
-      break;
-    }
-    // set type
-    if (!setType(env, cls, obj, rinfo->type)) {
-      #ifdef TEST_STAGE
-      printf(":!c: seType() failed! \n");
-      #endif
-      break;
-    }
-/////////////////////////////////////////////////
-    // find cls - GUID_RTPS
-    cls_tmp = findClass(env, "org.ocera.orte.types.GUID_RTPS");
-    if (cls_tmp == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: cls_tmp = NULL \n");
-      #endif
-      break;
-    }
-    // call object constructor
-    mid = (*env)->GetMethodID(env,
-                             cls_tmp,
-                             "<init>",
-                             "(JJJ)V");
-    if (mid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: constructor failed! \n");
-      #endif
-      break;
-    }
-    // create new object
-    obj_tmp = (*env)->NewObject(env,
-                               cls_tmp,
-                               mid,
-                               (jlong)rinfo->senderGUID.hid,
-                               (jlong)rinfo->senderGUID.aid,
-                               (jlong)rinfo->senderGUID.oid);
-    if (obj_tmp == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: obj = NULL \n");
-      #endif
-      break;
-    }
-    // set AppInfo's field
-    fid = (*env)->GetFieldID(env,
-                            cls,
-                            "senderGUID",
-                            "Lorg/ocera/orte/types/GUID_RTPS;");
-    if (fid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: fid = NULL \n");
-      #endif
-      break;
-    }
-    #ifdef TEST_STAGE
-    printf(":c: rinfo.senderGUID: hid = %#" PRIx32 ", aid = %#" PRIx32 ", oid = %#" PRIx32 " \n",
-          rinfo->senderGUID.hid, rinfo->senderGUID.aid, rinfo->senderGUID.oid);
-    #endif
-    (*env)->SetObjectField(env,
-                          obj,
-                          fid,
-                          obj_tmp);
-/////////////////////////////////////////////////
-    // find cls - NtpTime
-    cls_tmp = findClass(env, "org.ocera.orte.types.NtpTime");
-    if (cls_tmp == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: cls_tmp = NULL \n");
-      #endif
-      break;
-    }
-    // call object constructor
-    mid = (*env)->GetMethodID(env,
-                             cls_tmp,
-                             "<init>",
-                             "(IJ)V");
-    if (mid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: constructor failed! \n");
-      #endif
-      break;
-    }
-    // create new object
-    obj_tmp = (*env)->NewObject(env,
-                               cls_tmp,
-                               mid,
-                               (jint)rinfo->localTimeReceived.seconds,
-                               (jlong)rinfo->localTimeReceived.fraction);
-    if (obj_tmp == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: obj = NULL \n");
-      #endif
-      break;
-    }
-    // set AppInfo's field
-    fid = (*env)->GetFieldID(env,
-                            cls,
-                            "localTimeRecv",
-                            "Lorg/ocera/orte/types/NtpTime;");
-    if (fid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: fid = NULL \n");
-      #endif
-      break;
-    }
-    #ifdef TEST_STAGE
-    NtpTimeDisAssembToUs(sec, us, rinfo->localTimeReceived);
-    printf(":c: rinfo.NtpTime: %" PRId32 ".%" PRIu32 " (sec = %" PRId32 " fract = %" PRIu32 ") \n",
-          sec, us,
-          rinfo->localTimeReceived.seconds, rinfo->localTimeReceived.fraction);
-    #endif
-    (*env)->SetObjectField(env,
-                          obj,
-                          fid,
-                          obj_tmp);
-/////////////////////////////////////////////////
-    // find cls - NtpTime
-/*
-    cls_tmp = (*env)->FindClass(env, "org/ocera/orte/types/NtpTime");
-    if(cls_tmp == 0)
-    {
-      #ifdef TEST_STAGE
-        printf(":!c: cls_tmp = NULL \n");
-      #endif
-      break;
-    }
-    // call object constructor
-    mid = (*env)->GetMethodID(env,
-                              cls_tmp,
-                              "<init>",
-                              "(IJ)V");
-    if(mid == 0)
-    {
-      #ifdef TEST_STAGE
-        printf(":!c: constructor failed! \n");
-      #endif
-      break;
-    }
-*/
-    // create new object
-    obj_tmp = (*env)->NewObject(env,
-                               cls_tmp,
-                               mid,
-                               (jint)rinfo->remoteTimePublished.seconds,
-                               (jlong)rinfo->remoteTimePublished.fraction);
-    if (obj_tmp == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: obj = NULL \n");
-      #endif
-      break;
-    }
-    // set AppInfo's field
-    fid = (*env)->GetFieldID(env,
-                            cls,
-                            "remoteTimePub",
-                            "Lorg/ocera/orte/types/NtpTime;");
-    if (fid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: fid = NULL \n");
-      #endif
-      break;
-    }
-    #ifdef TEST_STAGE
-    NtpTimeDisAssembToUs(sec, us, rinfo->remoteTimePublished);
-    printf(":c: rinfo.remoteTimePub: %" PRId32 ".%" PRIu32 " (sec = %" PRId32 " fract = %" PRIu32 ") \n",
-          sec, us,
-          rinfo->remoteTimePublished.seconds, rinfo->remoteTimePublished.fraction);
-    #endif
-    (*env)->SetObjectField(env,
-                          obj,
-                          fid,
-                          obj_tmp);
-/////////////////////////////////////////////////
-    // find cls - SequenceNumber
-    cls_tmp = findClass(env, "org.ocera.orte.types.SequenceNumber");
-    if (cls_tmp == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: cls_tmp = NULL \n");
-      #endif
-      break;
-    }
-    // call object constructor
-    mid = (*env)->GetMethodID(env,
-                             cls_tmp,
-                             "<init>",
-                             "(IJ)V");
-    if (mid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: constructor failed! # \n");
-      #endif
-      break;
-    }
-    // create new object
-    obj_tmp = (*env)->NewObject(env,
-                               cls_tmp,
-                               mid,
-                               (jint)rinfo->sn.high,
-                               (jlong)rinfo->sn.low);
-    if (obj_tmp == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: obj = NULL \n");
-      #endif
-      break;
-    }
-    // set AppInfo's field
-    fid = (*env)->GetFieldID(env,
-                            cls,
-                            "sn",
-                            "Lorg/ocera/orte/types/SequenceNumber;");
-    if (fid == 0) {
-      #ifdef TEST_STAGE
-      printf(":!c: fid = NULL \n");
-      #endif
-      break;
-    }
-    #ifdef TEST_STAGE
-    printf(":c: rinfo.sn: %" PRId64 " (high = %" PRId32 " low = %" PRId32 ") \n",
-          (((int64_t)rinfo->sn.high << 32) + rinfo->sn.low), rinfo->sn.high, rinfo->sn.low);
-    #endif
-    (*env)->SetObjectField(env,
-                          obj,
-                          fid,
-                          obj_tmp);
-/////////////////////////////////////////////////
-
-    flag_ok = 1;
-  } while (0);
-
-  if (!flag_ok) {
-    //detach...()
-    return 0;
-  }
-
-  return 1;
-}