]> rtime.felk.cvut.cz Git - orte.git/blob - orte/libjorte/JORTESubscriptionCreate.c
JORTE: coding style fixes
[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   // HACK: 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       #ifdef TEST_STAGE
79       printf(":!c: recvCallBack: AttachCurrentThread() failed \n");
80       #endif
81       return;
82     }
83
84     // set byte order only if it differs from that currently set
85     if (info->data_endian != callback_cont->cur_endian) {
86       if (info->data_endian == BigEndian) {
87         obj_bo = callback_cont->obj_BO_BE;
88         callback_cont->cur_endian = BigEndian;
89       } else {
90         obj_bo = callback_cont->obj_BO_LE;
91         callback_cont->cur_endian = LittleEndian;
92       }
93
94       // set byte order to ByteBuffer
95       (*env)->CallObjectMethod(env, callback_cont->obj_buf, callback_cont->mid_order, obj_bo);
96     }
97
98       #ifdef TEST_STAGE
99     printf(":c: #0 \n");
100     printf(":c: env = %#" PRIxPTR ", obj_msg = %#" PRIxPTR " \n", (intptr_t)env, (intptr_t)callback_cont->msg);
101       #endif
102
103     ////////////////////////////////////////////////////
104     memcpy(callback_cont->info_buf, (void *)info, sizeof(ORTERecvInfo));
105     ////////////////////////////////////////////////////
106
107     // control print - only in TEST_STAGE
108     #ifdef TEST_STAGE
109     printf(":c: rinfo created :] \n");
110     printf(":c:----- ORTERecvInfo members  ------ \n");
111     printf(":c:    recvStatus: %#x \n", info->status);
112     printf(":c:    senderGuid: hid = %#" PRIx32 ", aid = %#" PRIx32 ", oid = %#" PRIx32 " \n",
113            info->senderGUID.hid, info->senderGUID.aid, info->senderGUID.oid);
114     printf(":c:         topic: %s \n", info->topic);
115     printf(":c:          type: %s \n", info->type);
116     printf(":c: localTimeRecv: sec = %" PRId32 ", fract = %" PRIu32 " \n",
117            info->localTimeReceived.seconds, info->localTimeReceived.fraction);
118     printf(":c: remoteTimePub: sec = %" PRId32 ", fract = %" PRIu32 " \n",
119            info->remoteTimePublished.seconds, info->remoteTimePublished.fraction);
120     printf(":c:         seqNr: high = %" PRId32 ", low = %" PRIu32 " \n", info->sn.high, info->sn.low);
121     printf(":c:---------------------------------- \n");
122     #endif
123     ////////////////////////////////////////////////////
124     // update MessageData instance
125     // call method
126     (*env)->CallVoidMethod(env,
127                            callback_cont->msg,
128                            callback_cont->mid_read);
129
130     /* *************************** *
131      *  call JAVA CallBack method  *
132      * *************************** */
133     #ifdef TEST_STAGE
134     printf(":c: volam callback metodu.. halo jsi tam?? \n");
135     #endif
136     // call object's method
137     (*env)->CallVoidMethod(env,
138                            callback_cont->obj, /*obj*/
139                            callback_cont->mid_callback,
140                            callback_cont->rinfo,
141                            callback_cont->msg);
142   } while (0);
143
144   // detach current thread
145   if ((*jvm)->DetachCurrentThread(jvm) != JNI_OK)
146     printf(":c!: DetachCurrentThread failed! \n");
147   //
148   #ifdef TEST_STAGE
149   printf(":c: ------------ thats all from recvCallBack ------------ \n\n");
150   #endif
151 }
152
153 /* ****************************************************************** *
154  *                            native method                           *
155  * ****************************************************************** */
156 JNIEXPORT jlong JNICALL
157 Java_org_ocera_orte_Subscription_jORTESubscriptionCreate
158   (JNIEnv   *env,
159   jobject   obj,
160   jlong     dhandle,  // appDomain handle
161   jint      jsmode,   // subs mode
162   jint      jstype,   // subs type
163   jstring   jtopic,   // subs topic
164   jstring   jtname,   // subs typeName
165   jobject   jinstance, // direct ByteBuffer
166   jint      jbyteOrder, // byte order of ByteBuffer
167   jobject   obj_msg,  // messageData instance
168   jobject   jdeadline,
169   jobject   jminSeparation,
170   jobject   obj_callback,
171   jlong     j_multicastIP)
172 {
173   // jni variables
174   JavaVM                 *jvm;
175   jfieldID                fid;
176   jclass                  cls;
177   jmethodID           mid;
178   jobject                obj_info_buffer;
179   // orte variables
180   ORTESubscription       *s = 0;
181   ORTEDomain             *d;
182   SubscriptionMode        smode;
183   SubscriptionType        stype;
184   NtpTime                 deadline;
185   NtpTime                 minSeparation;
186   // jorte variable
187   JORTECallbackContext_t *callback_cont;
188   JORTECallbackContext_t **callback_cont_ptr;
189
190   // standart variables
191   const char             *topic = 0;
192   const char             *typename = 0;
193   void                   *buffer;
194   int                     flag_ok = 0;
195
196   /* HACK: allocate space for callback context structure and than for a pointer to it */
197
198   // memory alocation
199   // don't forget use free() funct.!!
200   callback_cont = (JORTECallbackContext_t *)malloc(sizeof(JORTECallbackContext_t));
201   callback_cont_ptr = (JORTECallbackContext_t **)malloc(sizeof(JORTECallbackContext_t *));
202   *callback_cont_ptr = callback_cont;
203
204   do {
205
206     // get direct ByteBuffer pointer from Java
207     buffer = (*env)->GetDirectBufferAddress(env, jinstance);
208     // check obj_callback
209     if (obj_callback == 0) {
210       #ifdef TEST_STAGE
211       printf(":!c: obj_callback = NULL \n");
212       #endif
213       break;
214     }
215     // get jvm
216     jint b = (*env)->GetJavaVM(env, &jvm);
217     if (b == JNI_OK) {
218       #ifdef TEST_STAGE
219       printf(":c: getJavaVM succesfull.. \n");
220       #endif
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 }