]> rtime.felk.cvut.cz Git - orte.git/blob - orte/libjorte/JORTESubscriptionCreate.c
JORTE: fix bug in subscriber 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
32 // library header file's path
33 #include "orte_all.h"
34 // pregenerated header
35 #include "jorte/org_ocera_orte_Subscription.h"
36 // enable TEST_STAGE run level
37 #include "jorte/4all.h"
38 // new data types
39 #include "jorte/jorte_typedefs_defines.h"
40 #include "jorte/jorte_protos_api.h"
41
42 /* ****************************************************************** *
43  *                           CallBack function                        *
44  * ****************************************************************** */
45
46 void
47 recvCallBack(const ORTERecvInfo *info,void *vinstance, void *recvCallBackParam)
48 {
49   // jni varialbles
50   JavaVM          *jvm = 0;
51   JNIEnv          *env = 0;
52   jclass           cls = 0; // local reference!
53   jclass           cls_msg = 0;
54   jobject          rinfo = 0;
55   jobject          obj_msg;
56   jobject          obj_bo = 0;
57   jfieldID         fid = 0;
58   jmethodID        mid = 0;
59   jmethodID        mid_callback = 0;
60   //
61   // if the subscriber has been destroyed, return
62   if((*(JORTECallbackContext_t**)recvCallBackParam) == 0)
63     return;
64
65   JORTECallbackContext_t   *callback_cont = *((JORTECallbackContext_t**)recvCallBackParam);
66
67   #ifdef TEST_STAGE
68     printf("\n\n:c: --------------- recvCallBack called.. --------------- \n");
69   #endif
70
71   do
72   {
73     // set local variables from struct
74     if(callback_cont->jvm == 0)
75     {
76       #ifdef TEST_STAGE
77         printf(":!c: jvm = NULL \n");
78       #endif
79       break;
80     }
81     jvm = callback_cont->jvm;
82     // get env
83     (*jvm)->AttachCurrentThread(jvm,
84                                 #ifdef __ANDROID__
85                                   &env,
86                                 #else
87                                   (void **)&env,
88                                 #endif
89                                 NULL);
90     if(env == 0)
91     {
92       #ifdef TEST_STAGE
93        printf(":!c: env = NULL \n");
94       #endif
95       break;
96     }
97     //
98     // set byte order only if it differs from that currently set
99     if(info->data_endian != callback_cont->cur_endian) {
100       //prepare ByteOrder
101       cls = (*env)->FindClass(env, "java/nio/ByteOrder");
102       if (cls == 0) {
103         #ifdef TEST_STAGE
104           printf(":!c: cls = NULL \n");
105         #endif
106       }
107       if(info->data_endian == BigEndian) {
108         fid = (*env)->GetStaticFieldID(env,
109                                        cls,
110                                        "BIG_ENDIAN",
111                                        "Ljava/nio/ByteOrder;");
112         callback_cont->cur_endian = BigEndian;
113       }
114       else {
115         fid = (*env)->GetStaticFieldID(env,
116                                        cls,
117                                        "LITTLE_ENDIAN",
118                                        "Ljava/nio/ByteOrder;");
119         callback_cont->cur_endian = LittleEndian;
120       }
121       if(fid == 0) {
122         #ifdef TEST_STAGE
123           printf(":!c: fid = NULL \n");
124         #endif
125       }
126       obj_bo = (*env)->GetStaticObjectField(env, cls, fid);
127       if(obj_bo == 0) {
128         #ifdef TEST_STAGE
129           printf(":!c: cls = NULL \n");
130         #endif
131       }
132
133       // set byte order to ByteBuffer
134       // get BB class
135       cls = (*env)->GetObjectClass(env, callback_cont->obj_buf);
136       if(cls == 0)
137       {
138         #ifdef TEST_STAGE
139           printf(":!c: cls = NULL \n");
140         #endif
141       }
142       // get methodID - order(ByteOrder)
143       mid = (*env)->GetMethodID(env,
144                                 cls,
145                                 "order",
146                                 "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
147       if(mid == 0)
148       {
149         #ifdef TEST_STAGE
150           printf(":!c: mid = NULL \n");
151         #endif
152       }
153
154       // set ByteOrder
155       if((*env)->CallObjectMethod(env,callback_cont->obj_buf,mid,obj_bo) == 0)
156       {
157         #ifdef TEST_STAGE
158           printf(":!c: set byte order failed.. \n");
159         #endif
160       }
161     }
162     //
163     if(callback_cont->obj == 0)
164     {
165       #ifdef TEST_STAGE
166         printf(":!c: obj = NULL \n");
167       #endif
168       break;
169     }
170     // set local vars
171     rinfo = callback_cont->rinfo;
172     obj_msg = callback_cont->msg;
173
174
175       #ifdef TEST_STAGE
176          printf(":c: #0 \n");
177          printf(":c: env = %#"PRIxPTR", obj_msg = %#"PRIxPTR" \n", (intptr_t)env, (intptr_t)obj_msg);
178       #endif
179
180
181         //
182     if(rinfo == 0)
183     {
184       // find cls
185       cls = findClass(env, "org.ocera.orte.types.RecvInfo");
186       if(cls == 0)
187       {
188         #ifdef TEST_STAGE
189           printf(":!c: cls = NULL \n");
190         #endif
191         break;
192       }
193       // call object constructor
194       mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
195       if(mid == 0)
196       {
197         #ifdef TEST_STAGE
198           printf(":!c: constructor failed! \n");
199         #endif
200         break;
201       }
202       // create new object
203       rinfo = (*env)->NewObject(env, cls, mid);
204       if(rinfo == 0)
205       {
206         #ifdef TEST_STAGE
207           printf(":!c: rinfo = NULL \n");
208         #endif
209         break;
210       }
211       // create global reference
212       callback_cont->rinfo = (*env)->NewGlobalRef(env, rinfo);
213       if (callback_cont->rinfo == 0)
214       {
215         #ifdef TEST_STAGE
216           printf(":!c: callback_cont->rinfo = NULL \n");
217         #endif
218         break;
219       }
220     }
221     ////////////////////////////////////////////////////
222     // set RecvInfo instance
223     if(setRecvInfo(env,info,callback_cont->rinfo) == 0)
224     {
225       #ifdef TEST_STAGE
226         printf(":!c: setRecvInfo() failed! \n");
227       #endif
228       break;
229     }
230     ////////////////////////////////////////////////////
231     // control print - only in TEST_STAGE
232     #ifdef TEST_STAGE
233       printf(":c: rinfo created :] \n");
234       printf(":c:----- ORTERecvInfo members  ------ \n");
235       printf(":c:    recvStatus: %#x \n", info->status);
236       printf(":c:    senderGuid: hid = %#"PRIx32", aid = %#"PRIx32", oid = %#"PRIx32" \n",
237              info->senderGUID.hid,info->senderGUID.aid,info->senderGUID.oid);
238       printf(":c:         topic: %s \n",info->topic);
239       printf(":c:          type: %s \n",info->type);
240       printf(":c: localTimeRecv: sec = %"PRId32", fract = %"PRIu32" \n",
241              info->localTimeReceived.seconds,info->localTimeReceived.fraction);
242       printf(":c: remoteTimePub: sec = %"PRId32", fract = %"PRIu32" \n",
243              info->remoteTimePublished.seconds,info->remoteTimePublished.fraction);
244       printf(":c:         seqNr: high = %"PRId32", low = %"PRIu32" \n",info->sn.high,info->sn.low);
245       printf(":c:---------------------------------- \n");
246     #endif
247     ////////////////////////////////////////////////////
248     // update MessageData instance
249     // get cls
250     cls_msg = (*env)->GetObjectClass(env, obj_msg);
251     if(cls_msg == 0)
252     {
253       #ifdef TEST_STAGE
254          printf(":!c: cls_msg = NULL \n");
255       #endif
256       break;
257     }
258     /////////////////////////////////////////////////////
259     // methodID - read()
260     mid = (*env)->GetMethodID(env,
261                               cls_msg,
262                               "read",
263                               "()V");
264     if(mid == 0)
265     {
266       #ifdef TEST_STAGE
267          printf(":!c: mid = NULL \n");
268       #endif
269       break;
270     }
271     // call method
272     (*env)->CallVoidMethod(env,
273                            obj_msg,
274                            mid);
275
276    /* *************************** *
277     *  call JAVA CallBack method  *
278     * *************************** */
279       #ifdef TEST_STAGE
280         printf(":c: call JAVA CallBack method \n");
281       #endif
282
283
284         // get class
285     cls = (*env)->GetObjectClass(env,callback_cont->obj);
286     if(cls == 0)
287     {
288       #ifdef TEST_STAGE
289         printf(":!c: cls = NULL \n");
290       #endif
291       break;
292     }
293     // get method ID
294     mid = (*env)->GetMethodID(env,
295                               cls,
296                               "callback",
297                               "(Lorg/ocera/orte/types/RecvInfo;Lorg/ocera/orte/types/MessageData;)V");
298     if(mid == 0)
299     {
300       #ifdef TEST_STAGE
301         printf(":!c: cls = NULL \n");
302       #endif
303       break;
304     }
305     mid_callback = mid;
306     //
307     #ifdef TEST_STAGE
308       printf(":c: volam callback metodu.. halo jsi tam?? \n");
309     #endif
310     // call object's method
311     (*env)->CallVoidMethod(env,
312                            callback_cont->obj, /*obj*/
313                            mid_callback,
314                            callback_cont->rinfo,
315                            obj_msg);
316   } while(0);
317
318   // detach current thread
319   if((*jvm)->DetachCurrentThread(jvm) != 0)
320      printf(":c!: DetachCurrentThread failed! \n");
321   //
322   #ifdef TEST_STAGE
323      printf(":c: ------------ thats all from recvCallBack ------------ \n\n");
324   #endif
325
326 }
327
328 /* ****************************************************************** *
329  *                            native method                           *
330  * ****************************************************************** */
331 JNIEXPORT jlong JNICALL
332 Java_org_ocera_orte_Subscription_jORTESubscriptionCreate
333 (JNIEnv   *env,
334  jobject   obj,
335  jlong     dhandle,   // appDomain handle
336  jint      jsmode,    // subs mode
337  jint      jstype,    // subs type
338  jstring   jtopic,    // subs topic
339  jstring   jtname,    // subs typeName
340  jobject   jinstance, // direct ByteBuffer
341  jint      jbyteOrder,// byte order of ByteBuffer
342  jobject   obj_msg,   // messageData instance
343  jobject   jdeadline,
344  jobject   jminSeparation,
345  jobject   obj_callback,
346  jlong     j_multicastIP)
347 {
348   // jni variables
349   JavaVM                 *jvm;
350   jfieldID                fid;
351   jclass                  cls;
352   // orte variables
353   ORTESubscription       *s = 0;
354   ORTEDomain             *d;
355   SubscriptionMode        smode;
356   SubscriptionType        stype;
357   NtpTime                 deadline;
358   NtpTime                 minSeparation;
359   // jorte variable
360   JORTECallbackContext_t *callback_cont;
361   JORTECallbackContext_t **callback_cont_ptr;
362
363   // standart variables
364   const char             *topic = 0;
365   const char             *typename = 0;
366   void                   *buffer;
367   int                     flag_ok = 0;
368   // memory alocation
369   // don't forget use free() funct.!!
370   callback_cont = (JORTECallbackContext_t*)malloc(sizeof(JORTECallbackContext_t));
371   callback_cont_ptr = (JORTECallbackContext_t**)malloc(sizeof(JORTECallbackContext_t*));
372   *callback_cont_ptr = callback_cont;
373
374   do
375   {
376
377     // get direct ByteBuffer pointer from Java
378     buffer = (*env)->GetDirectBufferAddress(env, jinstance);
379     // check obj_callback
380     if (obj_callback == 0)
381     {
382       #ifdef TEST_STAGE
383         printf(":!c: obj_callback = NULL \n");
384       #endif
385       break;
386     }
387     // get jvm
388     jint b = (*env)->GetJavaVM(env,&jvm);
389     if (b <  0)
390     {
391       #ifdef TEST_STAGE
392         printf(":!c: getJavaVM() failed! \n");
393       #endif
394       break;
395     }
396     if (b == 0)
397     {
398       #ifdef TEST_STAGE
399         printf(":c: getJavaVM succesfull.. \n");
400       #endif
401     }
402     callback_cont->jvm = jvm;
403     callback_cont->cur_endian = (CDR_Endianness) jbyteOrder;
404     // create global references
405     callback_cont->obj = (*env)->NewGlobalRef(env, obj_callback);
406     //
407     if (callback_cont->obj == 0)
408     {
409       #ifdef TEST_STAGE
410         printf(":c: global reference not created! \n");
411       #endif
412       break;
413     }
414     // create global references
415     callback_cont->obj_buf = (*env)->NewGlobalRef(env, jinstance);
416     //
417     if (callback_cont->obj_buf == 0)
418     {
419       #ifdef TEST_STAGE
420         printf(":c: global reference not created! \n");
421       #endif
422       break;
423     }
424     // create global references
425     callback_cont->msg = (*env)->NewGlobalRef(env, obj_msg);
426     //
427     if (callback_cont->msg == 0)
428     {
429       #ifdef TEST_STAGE
430         printf(":c: global reference not created! \n");
431       #endif
432       break;
433     }
434     // init RecvInfo pointer
435     callback_cont->rinfo = 0;
436     //
437     cls = (*env)->GetObjectClass(env, obj);
438     if(cls == 0)
439     {
440       #ifdef TEST_STAGE
441         printf(":!c: cls = NULL \n");
442       #endif
443       break;
444     }
445     // fieldID - callbackContextHandle
446     fid = (*env)->GetFieldID(env,
447                              cls,
448                              "callbackContextHandle",
449                              "J");
450     if(fid == 0)
451     {
452       #ifdef TEST_STAGE
453         printf(":!c: fid = NULL \n");
454       #endif
455       break;
456     }
457     (*env)->SetLongField(env,
458                         obj,
459                         fid,
460                         (jlong) callback_cont_ptr);
461     #ifdef TEST_STAGE
462        printf(":c: ORTESubscriptionCreate() calling..\n");
463     #endif
464     //
465     d = (ORTEDomain *) dhandle;
466     if (d == 0)
467     {
468       #ifdef TEST_STAGE
469         printf(":!c: d = NULL [bad domain handle] \n");
470       #endif
471       break;
472     }
473     //
474     smode = (SubscriptionMode) jsmode;
475     stype = (SubscriptionType) jstype;
476     topic = (*env)->GetStringUTFChars(env, jtopic, 0);
477     typename = (*env)->GetStringUTFChars(env, jtname, 0);
478     deadline = getNtpTime(env, jdeadline);//
479     minSeparation = getNtpTime(env, jminSeparation);//
480     // call ORTE function
481     s = ORTESubscriptionCreate(d,
482                                smode,
483                                stype,
484                                topic,
485                                typename,
486                                buffer,
487                                &deadline,
488                                &minSeparation,
489                                recvCallBack,
490                                (void*)callback_cont_ptr,
491                                (uint32_t) j_multicastIP);
492     if (s == 0)
493     {
494       #ifdef TEST_STAGE
495         printf(":!c: s = NULL [subscription not created] \n");
496       #endif
497       break;
498     }
499
500     // set flag
501     flag_ok = 1;
502   } while(0);
503
504   // free memory
505   (*env)->ReleaseStringUTFChars(env, jtopic, topic);
506   (*env)->ReleaseStringUTFChars(env, jtname, typename);
507   // returns handle of new created Subscription
508   if(flag_ok == 0) return 0;
509   return ((jlong) s);
510
511 }