]> rtime.felk.cvut.cz Git - orte.git/blob - orte/libjorte/JORTESubscriptionCreate.c
Java: rewrite receive callback
[orte.git] / orte / libjorte / JORTESubscriptionCreate.c
1 /* JORTESubscriptionCreate.c  */
2
3 /**
4   * This code provides conversion between JAVA a C environments.
5   * The C functions are calling here and results are send to JAVA
6   * native functions. It uses the header pregenerated by JAVA
7   * (by command 'javah -jni class_with_native_function')
8   *
9   * @author Lukas Pokorny (lukas_pokorny@centrum.cz)
10   * @author CTU FEE Prague - Department of Control Engineering (dce.felk.cvut.cz)
11   * @author Project ORTE - OCERA Real Time Ethernet (www.ocera.org)
12   * @author dedication to Kj
13   * @version 0.1
14   *
15   *
16   * This program is free software; you can redistribute it and/or modify
17   * it under the terms of the GNU General Public License as published by
18   * the Free Software Foundation; either version 2 of the License, or
19   * (at your option) any later version.
20   *
21   * This program is distributed in the hope that it will be useful,
22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24   * GNU General Public License for more details.
25   *
26   */
27
28
29 #include <stdlib.h>
30 #include <inttypes.h>
31 #include <string.h>
32
33 // library header file's path
34 #include "orte_all.h"
35 // pregenerated header
36 #include "jorte/org_ocera_orte_Subscription.h"
37 // enable TEST_STAGE run level
38 #include "jorte/4all.h"
39 // new data types
40 #include "jorte/jorte_typedefs_defines.h"
41 #include "jorte/jorte_protos_api.h"
42
43 /* ****************************************************************** *
44  *                           CallBack function                        *
45  * ****************************************************************** */
46
47 void
48 recvCallBack(const ORTERecvInfo *info, void *vinstance, void *recvCallBackParam)
49 {
50   // jni varialbles
51   JavaVM          *jvm = 0;
52   JNIEnv          *env = 0;
53   jobject          obj_bo = 0;
54
55   JORTECallbackContext_t   *callback_cont;
56
57   // if the subscriber has been destroyed, return
58   if ((*(JORTECallbackContext_t **)recvCallBackParam) == 0)
59     return;
60
61   callback_cont = *((JORTECallbackContext_t **)recvCallBackParam);
62
63   #ifdef TEST_STAGE
64   printf("\n\n:c: --------------- recvCallBack called.. --------------- \n");
65   #endif
66
67   do {
68     // set local variables from struct
69     jvm = callback_cont->jvm;
70     // get env
71     if((*jvm)->AttachCurrentThread(jvm,
72                                 #ifdef __ANDROID__
73                                 &env,
74                                 #else
75                                 (void **)&env,
76                                 #endif
77                                 NULL) != JNI_OK)
78     {
79       #ifdef TEST_STAGE
80       printf(":!c: recvCallBack: AttachCurrentThread() failed \n");
81       #endif
82       return;
83     }
84
85     // set byte order only if it differs from that currently set
86     if (info->data_endian != callback_cont->cur_endian) {
87       if (info->data_endian == BigEndian) {
88         obj_bo = callback_cont->obj_BO_BE;
89         callback_cont->cur_endian = BigEndian;
90       } else {
91         obj_bo = callback_cont->obj_BO_LE;
92         callback_cont->cur_endian = LittleEndian;
93       }
94
95       // set byte order to ByteBuffer
96       (*env)->CallObjectMethod(env, callback_cont->obj_buf, callback_cont->mid_order, obj_bo);
97     }
98
99       #ifdef TEST_STAGE
100     printf(":c: #0 \n");
101     printf(":c: env = %#" PRIxPTR ", obj_msg = %#" PRIxPTR " \n", (intptr_t)env, (intptr_t)callback_cont->msg);
102       #endif
103
104     ////////////////////////////////////////////////////
105     memcpy(callback_cont->info_buf, (void*)info, sizeof(ORTERecvInfo));
106     ////////////////////////////////////////////////////
107
108     // control print - only in TEST_STAGE
109     #ifdef TEST_STAGE
110     printf(":c: rinfo created :] \n");
111     printf(":c:----- ORTERecvInfo members  ------ \n");
112     printf(":c:    recvStatus: %#x \n", info->status);
113     printf(":c:    senderGuid: hid = %#" PRIx32 ", aid = %#" PRIx32 ", oid = %#" PRIx32 " \n",
114            info->senderGUID.hid, info->senderGUID.aid, info->senderGUID.oid);
115     printf(":c:         topic: %s \n", info->topic);
116     printf(":c:          type: %s \n", info->type);
117     printf(":c: localTimeRecv: sec = %" PRId32 ", fract = %" PRIu32 " \n",
118            info->localTimeReceived.seconds, info->localTimeReceived.fraction);
119     printf(":c: remoteTimePub: sec = %" PRId32 ", fract = %" PRIu32 " \n",
120            info->remoteTimePublished.seconds, info->remoteTimePublished.fraction);
121     printf(":c:         seqNr: high = %" PRId32 ", low = %" PRIu32 " \n", info->sn.high, info->sn.low);
122     printf(":c:---------------------------------- \n");
123     #endif
124     ////////////////////////////////////////////////////
125     // update MessageData instance
126     // call method
127     (*env)->CallVoidMethod(env,
128                            callback_cont->msg,
129                            callback_cont->mid_read);
130
131     /* *************************** *
132      *  call JAVA CallBack method  *
133      * *************************** */
134     #ifdef TEST_STAGE
135     printf(":c: volam callback metodu.. halo jsi tam?? \n");
136     #endif
137     // call object's method
138     (*env)->CallVoidMethod(env,
139                            callback_cont->obj, /*obj*/
140                            callback_cont->mid_callback,
141                            callback_cont->rinfo,
142                            callback_cont->msg);
143   } while (0);
144
145   // detach current thread
146   if ((*jvm)->DetachCurrentThread(jvm) != JNI_OK)
147     printf(":c!: DetachCurrentThread failed! \n");
148   //
149   #ifdef TEST_STAGE
150   printf(":c: ------------ thats all from recvCallBack ------------ \n\n");
151   #endif
152 }
153
154 /* ****************************************************************** *
155  *                            native method                           *
156  * ****************************************************************** */
157 JNIEXPORT jlong JNICALL
158 Java_org_ocera_orte_Subscription_jORTESubscriptionCreate
159   (JNIEnv   *env,
160   jobject   obj,
161   jlong     dhandle,  // appDomain handle
162   jint      jsmode,   // subs mode
163   jint      jstype,   // subs type
164   jstring   jtopic,   // subs topic
165   jstring   jtname,   // subs typeName
166   jobject   jinstance, // direct ByteBuffer
167   jint      jbyteOrder, // byte order of ByteBuffer
168   jobject   obj_msg,  // messageData instance
169   jobject   jdeadline,
170   jobject   jminSeparation,
171   jobject   obj_callback,
172   jlong     j_multicastIP)
173 {
174   // jni variables
175   JavaVM                 *jvm;
176   jfieldID                fid;
177   jclass                  cls;
178   jmethodID           mid;
179   jobject                obj_info_buffer;
180   // orte variables
181   ORTESubscription       *s = 0;
182   ORTEDomain             *d;
183   SubscriptionMode        smode;
184   SubscriptionType        stype;
185   NtpTime                 deadline;
186   NtpTime                 minSeparation;
187   // jorte variable
188   JORTECallbackContext_t *callback_cont;
189   JORTECallbackContext_t **callback_cont_ptr;
190
191   // standart variables
192   const char             *topic = 0;
193   const char             *typename = 0;
194   void                   *buffer;
195   int                     flag_ok = 0;
196
197   // memory alocation
198   // don't forget use free() funct.!!
199   callback_cont = (JORTECallbackContext_t *)malloc(sizeof(JORTECallbackContext_t));
200   callback_cont_ptr = (JORTECallbackContext_t **)malloc(sizeof(JORTECallbackContext_t *));
201   *callback_cont_ptr = callback_cont;
202
203   do {
204
205     // get direct ByteBuffer pointer from Java
206     buffer = (*env)->GetDirectBufferAddress(env, jinstance);
207     // check obj_callback
208     if (obj_callback == 0) {
209       #ifdef TEST_STAGE
210       printf(":!c: obj_callback = NULL \n");
211       #endif
212       break;
213     }
214     // get jvm
215     jint b = (*env)->GetJavaVM(env, &jvm);
216     if (b == JNI_OK) {
217       #ifdef TEST_STAGE
218       printf(":c: getJavaVM succesfull.. \n");
219       #endif
220     }
221     else {
222       #ifdef TEST_STAGE
223       printf(":!c: getJavaVM() failed! \n");
224       #endif
225       break;
226     }
227     callback_cont->jvm = jvm;
228     callback_cont->cur_endian = (CDR_Endianness)jbyteOrder;
229     // create global references
230     callback_cont->obj = (*env)->NewGlobalRef(env, obj_callback);
231     //
232     if (callback_cont->obj == 0) {
233       #ifdef TEST_STAGE
234       printf(":c: global reference not created! \n");
235       #endif
236       break;
237     }
238     // get ReceiveCallback class
239     cls = (*env)->GetObjectClass(env, callback_cont->obj);
240     if (cls == 0) {
241       #ifdef TEST_STAGE
242       printf(":!c: cls = NULL \n");
243       #endif
244       break;
245     }
246     // get callback method ID
247     callback_cont->mid_callback = (*env)->GetMethodID(env,
248                               cls,
249                               "callback",
250                               "(Lorg/ocera/orte/types/RecvInfo;Lorg/ocera/orte/types/MessageData;)V");
251     if (callback_cont->mid_callback == 0) {
252       #ifdef TEST_STAGE
253       printf(":!c: mid_callback = NULL \n");
254       #endif
255       break;
256     }
257     // create global references
258     callback_cont->obj_buf = (*env)->NewGlobalRef(env, jinstance);
259     //
260     if (callback_cont->obj_buf == 0) {
261       #ifdef TEST_STAGE
262       printf(":c: global reference not created! \n");
263       #endif
264       break;
265     }
266     // create global references
267     callback_cont->msg = (*env)->NewGlobalRef(env, obj_msg);
268     //
269     if (callback_cont->msg == 0) {
270       #ifdef TEST_STAGE
271       printf(":c: global reference not created! \n");
272       #endif
273       break;
274     }
275     // get MessageData class
276     cls = (*env)->GetObjectClass(env, callback_cont->msg);
277     if (cls == 0) {
278       #ifdef TEST_STAGE
279       printf(":!c: cls_msg = NULL \n");
280       #endif
281       break;
282     }
283     /////////////////////////////////////////////////////
284     // methodID - read()
285     callback_cont->mid_read = (*env)->GetMethodID(env,
286                               cls,
287                               "read",
288                               "()V");
289     if (callback_cont->mid_read == 0) {
290       #ifdef TEST_STAGE
291       printf(":!c: mid_read = NULL \n");
292       #endif
293       break;
294     }
295     // init RecvInfo pointer
296     // find cls
297     cls = findClass(env, "org.ocera.orte.types.RecvInfo");
298     if (cls == 0) {
299         #ifdef TEST_STAGE
300         printf(":!c: cls = NULL \n");
301         #endif
302         break;
303     }
304     // call object constructor
305     mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
306     if (mid == 0) {
307         #ifdef TEST_STAGE
308         printf(":!c: constructor failed! \n");
309         #endif
310         break;
311     }
312     // create new object
313     callback_cont->rinfo = (*env)->NewObject(env, cls, mid);
314     if (callback_cont->rinfo == 0) {
315         #ifdef TEST_STAGE
316         printf(":!c: rinfo = NULL \n");
317         #endif
318         break;
319     }
320     // create global reference
321     callback_cont->rinfo = (*env)->NewGlobalRef(env, callback_cont->rinfo);
322     if (callback_cont->rinfo == 0) {
323         #ifdef TEST_STAGE
324         printf(":!c: callback_cont->rinfo = NULL \n");
325         #endif
326         break;
327     }
328     // lookup getBuffer() ID
329     mid = (*env)->GetMethodID(env, cls, "getBuffer", "()Ljava/nio/ByteBuffer;");
330     if (mid == 0) {
331         #ifdef TEST_STAGE
332         printf(":!c: getBuffer() failed! \n");
333         #endif
334         break;
335     }
336     // get ByteBuffer reference
337     obj_info_buffer = (*env)->CallObjectMethod(env, callback_cont->rinfo, mid);
338     callback_cont->info_buf = (*env)->GetDirectBufferAddress(env, obj_info_buffer);
339     // create global references for ByteOrders
340     cls = (*env)->FindClass(env, "java/nio/ByteOrder");
341     fid = (*env)->GetStaticFieldID(env,
342                                    cls,
343                                    "BIG_ENDIAN",
344                                    "Ljava/nio/ByteOrder;");
345     callback_cont->obj_BO_BE = (*env)->GetStaticObjectField(env, cls, fid);
346     callback_cont->obj_BO_BE = (*env)->NewGlobalRef(env, callback_cont->obj_BO_BE);
347     fid = (*env)->GetStaticFieldID(env,
348                                    cls,
349                                    "LITTLE_ENDIAN",
350                                    "Ljava/nio/ByteOrder;");
351     callback_cont->obj_BO_LE = (*env)->GetStaticObjectField(env, cls, fid);
352     callback_cont->obj_BO_LE = (*env)->NewGlobalRef(env, callback_cont->obj_BO_LE);
353     // get methodID - order(ByteOrder)
354     cls = (*env)->GetObjectClass(env, callback_cont->obj_buf);
355     callback_cont->mid_order = (*env)->GetMethodID(env,
356                                                    cls,
357                                                    "order",
358                                                    "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
359     //
360     cls = (*env)->GetObjectClass(env, obj);
361     if (cls == 0) {
362       #ifdef TEST_STAGE
363       printf(":!c: cls = NULL \n");
364       #endif
365       break;
366     }
367     // fieldID - callbackContextHandle
368     fid = (*env)->GetFieldID(env,
369                              cls,
370                              "callbackContextHandle",
371                              "J");
372     if (fid == 0) {
373       #ifdef TEST_STAGE
374       printf(":!c: fid = NULL \n");
375       #endif
376       break;
377     }
378     (*env)->SetLongField(env,
379                          obj,
380                          fid,
381                          (jlong)callback_cont_ptr);
382     #ifdef TEST_STAGE
383     printf(":c: ORTESubscriptionCreate() calling..\n");
384     #endif
385     //
386     d = (ORTEDomain *)dhandle;
387     if (d == 0) {
388       #ifdef TEST_STAGE
389       printf(":!c: d = NULL [bad domain handle] \n");
390       #endif
391       break;
392     }
393     //
394     smode = (SubscriptionMode)jsmode;
395     stype = (SubscriptionType)jstype;
396     topic = (*env)->GetStringUTFChars(env, jtopic, 0);
397     typename = (*env)->GetStringUTFChars(env, jtname, 0);
398     deadline = getNtpTime(env, jdeadline); //
399     minSeparation = getNtpTime(env, jminSeparation); //
400     // call ORTE function
401     s = ORTESubscriptionCreate(d,
402                                smode,
403                                stype,
404                                topic,
405                                typename,
406                                buffer,
407                                &deadline,
408                                &minSeparation,
409                                recvCallBack,
410                                (void *)callback_cont_ptr,
411                                (uint32_t)j_multicastIP);
412     if (s == 0) {
413       #ifdef TEST_STAGE
414       printf(":!c: s = NULL [subscription not created] \n");
415       #endif
416       break;
417     }
418
419     // set flag
420     flag_ok = 1;
421   } while (0);
422
423   // free memory
424   (*env)->ReleaseStringUTFChars(env, jtopic, topic);
425   (*env)->ReleaseStringUTFChars(env, jtname, typename);
426   // returns handle of new created Subscription
427   if (flag_ok == 0)
428     return 0;
429   return ((jlong)s);
430
431 }