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