From 9c366a8529292d2344ee4896c1acfb81484a657c Mon Sep 17 00:00:00 2001 From: Martin Vajnar Date: Mon, 20 Apr 2015 19:55:29 +0200 Subject: [PATCH] Java: rewrite receive callback 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. --- orte/include/jorte/jorte.h | 1 + orte/include/jorte/jorte_protos_api.h | 3 - orte/include/jorte/jorte_typedefs_defines.h | 6 + .../jorte/org_ocera_orte_types_RecvInfo.h | 29 ++ .../src/org/ocera/orte/types/RecvInfo.java | 137 +++++++- orte/libaorte/jni/Android.mk | 5 +- orte/libjorte/JORTERecvInfoHelpers.c | 53 +++ orte/libjorte/JORTESubscriptionCreate.c | 314 ++++++++---------- orte/libjorte/JORTESubscriptionDestroy.c | 12 + orte/libjorte/Makefile.am | 3 +- orte/libjorte/Makefile.omk | 2 +- orte/libjorte/setRecvInfo.c | 290 ---------------- 12 files changed, 358 insertions(+), 497 deletions(-) create mode 100644 orte/include/jorte/org_ocera_orte_types_RecvInfo.h create mode 100644 orte/libjorte/JORTERecvInfoHelpers.c delete mode 100644 orte/libjorte/setRecvInfo.c diff --git a/orte/include/jorte/jorte.h b/orte/include/jorte/jorte.h index 9c7a5e3..3dce755 100644 --- a/orte/include/jorte/jorte.h +++ b/orte/include/jorte/jorte.h @@ -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 diff --git a/orte/include/jorte/jorte_protos_api.h b/orte/include/jorte/jorte_protos_api.h index a42f012..6b617ad 100644 --- a/orte/include/jorte/jorte_protos_api.h +++ b/orte/include/jorte/jorte_protos_api.h @@ -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); diff --git a/orte/include/jorte/jorte_typedefs_defines.h b/orte/include/jorte/jorte_typedefs_defines.h index 14b31ac..f252bca 100644 --- a/orte/include/jorte/jorte_typedefs_defines.h +++ b/orte/include/jorte/jorte_typedefs_defines.h @@ -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 index 0000000..cd7e20a --- /dev/null +++ b/orte/include/jorte/org_ocera_orte_types_RecvInfo.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* 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 diff --git a/orte/java/src/org/ocera/orte/types/RecvInfo.java b/orte/java/src/org/ocera/orte/types/RecvInfo.java index b711730..2baddba 100644 --- a/orte/java/src/org/ocera/orte/types/RecvInfo.java +++ b/orte/java/src/org/ocera/orte/types/RecvInfo.java @@ -23,56 +23,152 @@ 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); + } diff --git a/orte/libaorte/jni/Android.mk b/orte/libaorte/jni/Android.mk index 6299530..228a2cf 100644 --- a/orte/libaorte/jni/Android.mk +++ b/orte/libaorte/jni/Android.mk @@ -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 index 0000000..32740b1 --- /dev/null +++ b/orte/libjorte/JORTERecvInfoHelpers.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +// 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); + } diff --git a/orte/libjorte/JORTESubscriptionCreate.c b/orte/libjorte/JORTESubscriptionCreate.c index 0a9c877..e5d37ad 100644 --- a/orte/libjorte/JORTESubscriptionCreate.c +++ b/orte/libjorte/JORTESubscriptionCreate.c @@ -28,6 +28,7 @@ #include #include +#include // 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, "", "()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, "", "()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) { diff --git a/orte/libjorte/JORTESubscriptionDestroy.c b/orte/libjorte/JORTESubscriptionDestroy.c index 833070c..d499f68 100644 --- a/orte/libjorte/JORTESubscriptionDestroy.c +++ b/orte/libjorte/JORTESubscriptionDestroy.c @@ -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); } diff --git a/orte/libjorte/Makefile.am b/orte/libjorte/Makefile.am index 0888c76..e70c435 100644 --- a/orte/libjorte/Makefile.am +++ b/orte/libjorte/Makefile.am @@ -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 diff --git a/orte/libjorte/Makefile.omk b/orte/libjorte/Makefile.omk index 3a89215..8aea1fe 100644 --- a/orte/libjorte/Makefile.omk +++ b/orte/libjorte/Makefile.omk @@ -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 index 6acb985..0000000 --- a/orte/libjorte/setRecvInfo.c +++ /dev/null @@ -1,290 +0,0 @@ -/* setRecvInfo.c */ - -#include -#include -#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, - "", - "(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, - "", - "(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, - "", - "(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, - "", - "(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; -} -- 2.39.2