1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 
7 /*
8  *  @author  Anthony Chan
9  */
10 
11 #include <jni.h>
12 #include <stdio.h>
13 #include "logformat_trace_InputLog.h"
14 #include "trace_API.h"
15 #include <stdlib.h>
16 #include "mpimem.h"
17 
18 /* style: allow:fprintf:20 sig:0 */
19 
20 #define ACHAR_LENGTH   256
21 #define AINT_LENGTH    100
22 #define ADOUBLE_LENGTH 100
23 
24 /* File descriptor for the output stream */
25 #define  outfile  stdout
26 /* File descriptor for the error stream */
27 #define  errfile  stderr
28 
29 /* JNI Global Reference Variables */
30        jfieldID   fid4filehandle   = NULL;
31 static jclass     cid4String       = NULL;
32 static jclass     cid4DobjDef      = NULL;    /* for Category */
33 static jmethodID  mid4NewDobjDef   = NULL;
34 static jclass     cid4YMap         = NULL;    /* for YCoordMap */
35 static jmethodID  mid4NewYMap      = NULL;
36 static jclass     cid4Prime        = NULL;    /* for Primitive */
37 static jmethodID  mid4NewPrime     = NULL;
38 static jclass     cid4Cmplx        = NULL;    /* for Composite */
39 static jmethodID  mid4NewCmplx     = NULL;
40 
41 JNIEXPORT void JNICALL
Java_logformat_trace_InputLog_initIDs(JNIEnv * env,jclass myclass)42 Java_logformat_trace_InputLog_initIDs( JNIEnv *env , jclass myclass )
43 {
44     fid4filehandle = (*env)->GetFieldID( env, myclass, "filehandle", "J" );
45 }
46 
47 /*
48  *   tracefile != NULL, ierr == any  => Continue
49  *   tracefile == NULL, ierr ==  0   => help message, exit normally, TRUE
50  *   tracefile == NULL, ierr !=  0   => error message, exit w/ error, FALSE
51  */
52 JNIEXPORT jboolean JNICALL
Java_logformat_trace_InputLog_open(JNIEnv * env,jobject this)53 Java_logformat_trace_InputLog_open( JNIEnv *env, jobject this )
54 {
55     jclass       myclass;
56     jfieldID     fid4filespec;
57     jstring      j_filespec;
58     const char  *c_filespec;
59     TRACE_file   tracefile;
60     int          ierr;
61 
62     myclass       = (*env)->GetObjectClass( env, this );
63     fid4filespec  = (*env)->GetFieldID( env, myclass, "filespec",
64                                         "Ljava/lang/String;" );
65     if ( fid4filespec == NULL )
66         (*env)->SetLongField( env, this, fid4filehandle, (jlong) 0 );
67 
68     j_filespec  = (*env)->GetObjectField( env, this, fid4filespec );
69     c_filespec  = (*env)->GetStringUTFChars( env, j_filespec, NULL );
70     /* c_filespec = JNU_GetStringNativeChars( env, jfilespec ); */
71     ierr  = TRACE_Open( c_filespec, &tracefile );
72     /* Set the private variable "filehandle" in java class */
73     if ( tracefile != NULL ) {
74         fprintf( outfile, "C: Opening trace %s ..... \n", c_filespec );
75         fflush( outfile );
76         (*env)->SetLongField( env, this, fid4filehandle, (jlong) tracefile );
77         return JNI_TRUE;
78     }
79     else {
80         if ( ierr == 0 ) {    /* if ( tracefile == NULL && ierr == 0 ) */
81             (*env)->SetLongField( env, this, fid4filehandle, (jlong) 0 );
82             fprintf( outfile, "%s\n", TRACE_Get_err_string( ierr ) );
83             fflush( outfile );
84             return JNI_TRUE;
85         }
86         else {                /* if ( tracefile == NULL && ierr != 0 ) */
87             (*env)->SetLongField( env, this, fid4filehandle, (jlong) 0 );
88             fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
89             fflush( errfile );
90             return JNI_FALSE;
91         }
92     }
93 }
94 
95 JNIEXPORT jboolean JNICALL
Java_logformat_trace_InputLog_close(JNIEnv * env,jobject this)96 Java_logformat_trace_InputLog_close( JNIEnv *env, jobject this )
97 {
98     TRACE_file    tracefile;
99     jlong         filehandle;
100     int           ierr;
101 
102     /* Clean up all created Global References */
103     if ( cid4String != NULL ) {
104         (*env)->DeleteGlobalRef( env, cid4String );
105     }
106     if ( cid4DobjDef != NULL ) {
107         (*env)->DeleteGlobalRef( env, cid4DobjDef );
108         /*
109         if ( mid4NewDobjDef != NULL )
110             (*env)->DeleteGlobalRef( env, mid4NewDobjDef );
111         */
112     }
113     if ( cid4YMap != NULL ) {
114         (*env)->DeleteGlobalRef( env, cid4YMap );
115         /*
116         if ( mid4NewYMap != NULL )
117             (*env)->DeleteGlobalRef( env, mid4NewYMap );
118         */
119     }
120     if ( cid4Prime != NULL ) {
121         (*env)->DeleteGlobalRef( env, cid4Prime );
122         /*
123         if ( mid4NewPrime != NULL )
124             (*env)->DeleteGlobalRef( env, mid4NewPrime );
125         */
126     }
127     if ( cid4Cmplx != NULL ) {
128         (*env)->DeleteGlobalRef( env, cid4Cmplx );
129         /*
130         if ( mid4NewCmplx != NULL )
131             (*env)->DeleteGlobalRef( env, mid4NewCmplx );
132         */
133     }
134 
135     filehandle = (*env)->GetLongField( env, this, fid4filehandle );
136     if ( filehandle == 0 ) {
137         fprintf( errfile, "Java_logformat_trace_InputLog_close(): "
138                           "Inaccessible filehandle in Java side\n" );
139         return JNI_FALSE;
140     }
141     tracefile  = (TRACE_file) filehandle;
142     fprintf( outfile, "C: Closing trace ..... \n" );
143     fflush( outfile );
144     ierr  = TRACE_Close( &tracefile );
145     if ( ierr == 0 || tracefile == NULL )
146         return JNI_TRUE;
147     else {
148         fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
149         fflush( errfile );
150         return JNI_FALSE;
151     }
152 }
153 
154 JNIEXPORT jint JNICALL
Java_logformat_trace_InputLog_peekNextKindIndex(JNIEnv * env,jobject this)155 Java_logformat_trace_InputLog_peekNextKindIndex( JNIEnv *env, jobject this )
156 {
157     TRACE_file        tracefile;
158     jlong             filehandle;
159     TRACE_Rec_Kind_t  next_kind;
160     int               ierr;
161 
162     filehandle = (*env)->GetLongField( env, this, fid4filehandle );
163     if ( filehandle == 0 ) {
164         fprintf( errfile, "Java_logformat_trace_InputLog_peekNextKindIndex(): "
165                           "Inaccessible filehandle in Java side\n" );
166         return TRACE_EOF;
167     }
168     tracefile  = (TRACE_file) filehandle;
169 
170     ierr = TRACE_Peek_next_kind( tracefile, &next_kind );
171     if ( ierr != 0 ) {
172         fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
173         fflush( errfile );
174         return TRACE_EOF;
175     }
176 
177 	return next_kind;
178 }
179 
180 JNIEXPORT jobject JNICALL
Java_logformat_trace_InputLog_getNextCategory(JNIEnv * env,jobject this)181 Java_logformat_trace_InputLog_getNextCategory( JNIEnv *env, jobject this )
182 {
183     TRACE_file              tracefile;
184     jlong                   filehandle;
185     TRACE_Category_head_t   type_head;
186     int                     legend_sz, legend_pos, legend_max;
187     char                   *legend_base;
188     jstring                 jlegend;
189     int                     label_sz, label_pos, label_max = 0;
190     char                   *label_base;
191     jstring                 jlabel;
192     int                     methods_sz, methods_pos, methods_max = 0;
193     int                    *methods_base;
194     jintArray               jmethods;
195     jclass                  cid_local;
196     jobject                 objdef;
197     int                     ierr;
198     char slegend_base[ACHAR_LENGTH];
199     char slabel_base[ACHAR_LENGTH];
200     int smethods_base[AINT_LENGTH];
201 
202     filehandle = (*env)->GetLongField( env, this, fid4filehandle );
203     if ( filehandle == 0 ) {
204         fprintf( errfile, "Java_logformat_trace_InputLog_getNextCategory(): "
205                           "Inaccessible filehandle in Java side\n" );
206         return NULL;
207     }
208     tracefile  = (TRACE_file) filehandle;
209 
210     label_sz   = 0;
211     legend_sz  = 0;
212     methods_sz = 0;
213     ierr = TRACE_Peek_next_category( tracefile,
214                                      &legend_sz, &label_sz, &methods_sz );
215     if ( ierr != 0 || legend_sz <= 0 ) {
216         fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
217         fflush( errfile );
218         return NULL;
219     }
220 
221     legend_pos  = 0;
222     if ( legend_sz ) {
223         legend_max  = legend_sz+1;
224 	if (legend_max > ACHAR_LENGTH)
225 	    legend_base = (char *) MPIU_Malloc( legend_max * sizeof( char ) );
226 	else
227 	    legend_base = slegend_base;
228     }
229     else
230         legend_base = NULL;
231 
232     label_pos   = 0;
233     if ( label_sz > 0 ) {
234         label_max   = label_sz+1;
235 	if (label_max > ACHAR_LENGTH)
236 	    label_base  = (char *) MPIU_Malloc( label_max * sizeof( char ) );
237 	else
238 	    label_base = slabel_base;
239     }
240     else
241         label_base  = NULL;
242 
243    	methods_pos  = 0;
244     if ( methods_sz > 0 ) {
245         methods_max  = methods_sz;
246 	if (methods_max > AINT_LENGTH)
247 	    methods_base = (int *)  MPIU_Malloc( methods_max * sizeof( int ) );
248 	else
249 	    methods_base = smethods_base;
250     }
251     else
252         methods_base = NULL;
253 
254     ierr = TRACE_Get_next_category( tracefile, &type_head,
255                                     &legend_sz, legend_base,
256                                     &legend_pos, legend_max,
257                                     &label_sz, label_base,
258                                     &label_pos, label_max,
259                                     &methods_sz, methods_base,
260                                     &methods_pos, methods_max );
261     if ( ierr != 0 || legend_pos <= 0 ) {
262         fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
263         fflush( errfile );
264 	if ( legend_base != NULL && legend_base != slegend_base )
265 	    MPIU_Free( legend_base );
266 	if ( label_base != NULL && label_base != slabel_base )
267 	    MPIU_Free( label_base );
268 	if ( methods_base != NULL && methods_base != smethods_base )
269 	    MPIU_Free( methods_base );
270         return NULL;
271     }
272 
273     /* Obtain various array references for calling DobjDef's constructor */
274     if ( legend_base != NULL && legend_pos > 0 ) {
275         legend_base[ legend_pos ]  = '\0';
276         jlegend  = (*env)->NewStringUTF( env, legend_base );
277     }
278     else
279         jlegend  = NULL;
280 
281     if ( label_base != NULL && label_pos > 0 ) {
282         label_base[ label_pos ]  = '\0';
283         jlabel   = (*env)->NewStringUTF( env, label_base );
284     }
285     else
286         jlabel   = NULL;
287 
288     if ( methods_base != NULL && methods_pos > 0 ) {
289         jmethods = (*env)->NewIntArray( env, methods_sz );
290         (*env)->SetIntArrayRegion( env, jmethods,
291                                    0, methods_sz, (jint *) methods_base );
292     }
293     else
294         jmethods = NULL;
295 
296     /* Cache DobjDef Class's constructor as Global Reference */
297     if ( cid4DobjDef == NULL ) {
298         cid_local = (*env)->FindClass( env, "logformat/trace/DobjDef" );
299         if ( cid_local != NULL ) {
300             cid4DobjDef    = (*env)->NewGlobalRef( env, cid_local );
301             (*env)->DeleteLocalRef( env, cid_local );  /* avoid memory leak */
302             mid4NewDobjDef = (*env)->GetMethodID( env, cid4DobjDef, "<init>",
303                          "(ILjava/lang/String;IIIIIILjava/lang/String;[I)V" );
304         }
305     }
306 
307     /* Call DobjDef's constructor  */
308     objdef = (*env)->NewObject( env, cid4DobjDef, mid4NewDobjDef,
309                                 type_head.index, jlegend, type_head.shape,
310                                 type_head.red, type_head.green, type_head.blue,
311                                 type_head.alpha, type_head.width,
312                                 jlabel, jmethods );
313 
314     /* Clean up the unused reference and free local memory */
315     if ( jlegend != NULL )
316         (*env)->DeleteLocalRef( env, jlegend );
317     if ( legend_base != NULL && legend_base != slegend_base )
318         MPIU_Free( legend_base );
319 
320     if ( jlabel != NULL )
321         (*env)->DeleteLocalRef( env, jlabel );
322     if ( label_base != NULL && label_base != slabel_base )
323         MPIU_Free( label_base );
324 
325     if ( jmethods != NULL )
326         (*env)->DeleteLocalRef( env, jmethods );
327     if ( methods_base != NULL && methods_base != smethods_base )
328         MPIU_Free( methods_base );
329 
330     return objdef;
331 }
332 
333 JNIEXPORT jobject JNICALL
Java_logformat_trace_InputLog_getNextYCoordMap(JNIEnv * env,jobject this)334 Java_logformat_trace_InputLog_getNextYCoordMap( JNIEnv *env, jobject this )
335 {
336     TRACE_file              tracefile;
337     jlong                   filehandle;
338     int                     nrows, ncolumns;
339     int                     max_column_name, max_title_name;
340     char                   *title_name;
341     char                  **column_names;
342     int                     coordmap_sz, coordmap_pos, coordmap_max;
343     int                    *coordmap_base;
344     jintArray               j_coordmap_elems;
345     int                     methods_sz, methods_pos, methods_max;
346     int                    *methods_base;
347     jintArray               jmethods;
348 
349     jclass                  cid_local;
350     jstring                 jtitle;
351     jstring                 jcolname;
352     jobjectArray            jcolnames;
353     jobject                 ycoordmap;
354 
355     int                     icol;
356     int                     ierr;
357 
358     filehandle = (*env)->GetLongField( env, this, fid4filehandle );
359     if ( filehandle == 0 ) {
360         fprintf( errfile, "Java_logformat_trace_InputLog_getNextYCoordMap(): "
361                           "Inaccessible filehandle in Java side\n" );
362         return NULL;
363     }
364     tracefile  = (TRACE_file) filehandle;
365 
366     nrows            = 0;
367     ncolumns         = 0;
368     max_column_name  = 0;
369     max_title_name   = 0;
370     methods_sz       = 0;
371     ierr = TRACE_Peek_next_ycoordmap( tracefile, &nrows, &ncolumns,
372                                       &max_column_name, &max_title_name,
373                                       &methods_sz );
374     if ( ierr != 0 ) {
375         fprintf( errfile, "Error: %s\n", TRACE_Get_err_string( ierr ) );
376         fflush( errfile );
377         return NULL;
378     }
379 
380     /* Prepare various arrays for C data */
381     title_name    = (char *) MPIU_Malloc( max_title_name * sizeof(char) );
382     column_names  = (char **) MPIU_Malloc( (ncolumns-1) * sizeof(char *) );
383     for ( icol = 0; icol < ncolumns-1; icol++ )
384         column_names[ icol ] = (char *) MPIU_Malloc( max_column_name
385                                               * sizeof(char) );
386     coordmap_max  = nrows * ncolumns;
387     coordmap_base = (int *) MPIU_Malloc( coordmap_max * sizeof( int ) );
388     coordmap_sz   = 0;
389     coordmap_pos  = 0;
390 
391    	methods_pos  = 0;
392     if ( methods_sz > 0 ) {
393         methods_max  = methods_sz;
394         methods_base = (int *) MPIU_Malloc( methods_max * sizeof( int ) );
395     }
396     else
397         methods_base = NULL;
398 
399     ierr = TRACE_Get_next_ycoordmap( tracefile, title_name, column_names,
400                                      &coordmap_sz, coordmap_base,
401                                      &coordmap_pos, coordmap_max,
402                                      &methods_sz, methods_base,
403                                      &methods_pos, methods_max );
404     if ( ierr != 0 ) {
405         fprintf( errfile, "Error: %s\n", TRACE_Get_err_string( ierr ) );
406         fflush( errfile );
407 	if ( coordmap_base != NULL )
408 	    MPIU_Free( coordmap_base );
409 	if ( title_name != NULL )
410 	    MPIU_Free( title_name );
411 	if ( column_names != NULL ) {
412 	    for ( icol = 0; icol < ncolumns-1; icol++ )
413 		if ( column_names[ icol ] != NULL )
414 		    MPIU_Free( column_names[ icol ] );
415 		MPIU_Free( column_names );
416 	}
417 	if ( methods_base != NULL )
418 	    MPIU_Free( methods_base );
419         return NULL;
420     }
421 
422     /* Title Label String */
423     jtitle    = (*env)->NewStringUTF( env, title_name );
424 
425     /* Cache String class as a Global Reference */
426     if ( cid4String == NULL ) {
427         cid_local  = (*env)->FindClass( env, "java/lang/String" );
428         if ( cid_local != NULL ) {
429             cid4String  = (*env)->NewGlobalRef( env, cid_local );
430             (*env)->DeleteLocalRef( env, cid_local );  /* avoid mem leak */
431         }
432     }
433     /* Column Label String[ num_column - 1 ] */
434     jcolnames = (*env)->NewObjectArray( env, ncolumns - 1, cid4String, NULL );
435     for ( icol = 0; icol < ncolumns-1; icol++ ) {
436         jcolname = (*env)->NewStringUTF( env, column_names[ icol ] );
437         (*env)->SetObjectArrayElement( env, jcolnames, icol, jcolname );
438     }
439 
440     /* YCoordMap element: int[] */
441     if ( coordmap_pos > 0 ) {
442         j_coordmap_elems = (*env)->NewIntArray( env, coordmap_sz );
443         (*env)->SetIntArrayRegion( env, j_coordmap_elems,
444                                    0, coordmap_sz, (jint *) coordmap_base );
445     }
446     else
447         j_coordmap_elems = NULL;
448 
449     /* MethodID elements: int[] */
450     if ( methods_base != NULL && methods_pos > 0 ) {
451         jmethods = (*env)->NewIntArray( env, methods_sz );
452         (*env)->SetIntArrayRegion( env, jmethods,
453                                    0, methods_sz, (jint *) methods_base );
454     }
455     else
456         jmethods = NULL;
457 
458     /* Cache YCoordMap Class's constructor as a Global Reference */
459     if ( cid4YMap == NULL ) {
460         cid_local  = (*env)->FindClass( env, "base/drawable/YCoordMap" );
461         if ( cid_local != NULL ) {
462             cid4YMap    = (*env)->NewGlobalRef( env, cid_local );
463             (*env)->DeleteLocalRef( env, cid_local );  /* avoid mem leak */
464             mid4NewYMap = (*env)->GetMethodID( env, cid4YMap, "<init>",
465                           "(IILjava/lang/String;[Ljava/lang/String;[I[I)V" );
466         }
467     }
468     /* Call YCoordMap's constructor */
469     ycoordmap = (*env)->NewObject( env, cid4YMap, mid4NewYMap,
470                                    (jint) nrows, (jint) ncolumns,
471                                    jtitle, jcolnames,
472                                    j_coordmap_elems, jmethods );
473 
474     /* Clean up the unused reference and free local memory */
475     if ( coordmap_pos > 0 )
476         (*env)->DeleteLocalRef( env, j_coordmap_elems );
477     if ( coordmap_base != NULL )
478         MPIU_Free( coordmap_base );
479 
480     if ( title_name != NULL )
481         MPIU_Free( title_name );
482     if ( column_names != NULL ) {
483         for ( icol = 0; icol < ncolumns-1; icol++ )
484             if ( column_names[ icol ] != NULL )
485                 MPIU_Free( column_names[ icol ] );
486         MPIU_Free( column_names );
487     }
488 
489     if ( jmethods != NULL )
490         (*env)->DeleteLocalRef( env, jmethods );
491     if ( methods_base != NULL )
492         MPIU_Free( methods_base );
493 
494     return ycoordmap;
495 }
496 
497 JNIEXPORT jobject JNICALL
Java_logformat_trace_InputLog_getNextPrimitive(JNIEnv * env,jobject this)498 Java_logformat_trace_InputLog_getNextPrimitive( JNIEnv *env, jobject this )
499 {
500     TRACE_file              tracefile;
501     jlong                   filehandle;
502     double                  starttime, endtime;
503     int                     type_idx;
504     int                     tcoord_sz, tcoord_pos, tcoord_max;
505     double                 *tcoord_base;
506     jdoubleArray            j_tcoords;
507     int                     ycoord_sz, ycoord_pos, ycoord_max;
508     int                    *ycoord_base;
509     jintArray               j_ycoords;
510     int                     info_sz, info_pos, info_max;
511     char                   *info_base;
512     jbyteArray              j_infos;
513     jclass                  cid_local;
514     jobject                 prime;
515     int                     ierr;
516     double stcoord_base[ADOUBLE_LENGTH];
517     int sycoord_base[AINT_LENGTH];
518     char sinfo_base[ACHAR_LENGTH];
519 
520     filehandle = (*env)->GetLongField( env, this, fid4filehandle );
521     if ( filehandle == 0 ) {
522         fprintf( errfile, "Java_logformat_trace_InputLog_getNextPrimitive(): "
523                           "Inaccessible filehandle in Java side\n" );
524         return NULL;
525     }
526     tracefile  = (TRACE_file) filehandle;
527 
528     tcoord_sz  = 0;
529     ycoord_sz  = 0;
530     info_sz    = 0;
531     ierr = TRACE_Peek_next_primitive( tracefile, &starttime, &endtime,
532                                       &tcoord_sz, &ycoord_sz, &info_sz );
533     if ( ierr != 0 || ( tcoord_sz <= 0 || ycoord_sz <= 0 ) ) {
534         fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
535         fflush( errfile );
536         return NULL;
537     }
538 
539     tcoord_pos  = 0;
540     tcoord_max  = tcoord_sz;
541     if (tcoord_max > ADOUBLE_LENGTH)
542 	tcoord_base = (double *) MPIU_Malloc( tcoord_max * sizeof( double ) );
543     else
544 	tcoord_base = stcoord_base;
545     ycoord_pos  = 0;
546     ycoord_max  = ycoord_sz;
547     if (ycoord_max > AINT_LENGTH)
548 	ycoord_base = (int *)    MPIU_Malloc( ycoord_max * sizeof( int ) );
549     else
550 	ycoord_base = sycoord_base;
551     info_pos    = 0;
552     info_max    = info_sz;
553     if (info_max > AINT_LENGTH)
554 	info_base   = (char *)   MPIU_Malloc( info_max * sizeof( char ) );
555     else
556 	info_base = sinfo_base;
557     ierr = TRACE_Get_next_primitive( tracefile, &type_idx,
558                                      &tcoord_sz, tcoord_base,
559                                      &tcoord_pos, tcoord_max,
560                                      &ycoord_sz, ycoord_base,
561                                      &ycoord_pos, ycoord_max,
562                                      &info_sz, info_base,
563                                      &info_pos, info_max );
564     if ( ierr != 0 || ( tcoord_pos <= 0 || ycoord_pos <= 0 ) ) {
565         fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
566         fflush( errfile );
567 	if ( tcoord_base != NULL && tcoord_base != stcoord_base )
568 	    MPIU_Free( tcoord_base );
569 	if ( ycoord_base != NULL && ycoord_base != sycoord_base )
570 	    MPIU_Free( ycoord_base );
571 	if ( info_base != NULL && info_base != sinfo_base )
572 	    MPIU_Free( info_base );
573         return NULL;
574     }
575 
576     /*  Obtain primitive array references for calling Dobj's constructor */
577     if ( tcoord_pos > 0 ) {
578         j_tcoords = (*env)->NewDoubleArray( env, tcoord_sz );
579         (*env)->SetDoubleArrayRegion( env, j_tcoords,
580                                       0, tcoord_sz, tcoord_base );
581     }
582     else
583         j_tcoords = NULL;
584 
585     if ( ycoord_pos > 0 ) {
586         j_ycoords = (*env)->NewIntArray( env, ycoord_sz );
587         (*env)->SetIntArrayRegion( env, j_ycoords,
588                                    0, ycoord_sz, (jint *) ycoord_base );
589     }
590     else
591         j_ycoords = NULL;
592 
593     if ( info_pos > 0 ) {
594         j_infos = (*env)->NewByteArray( env, info_sz );
595         (*env)->SetByteArrayRegion( env, j_infos,
596                                     0, info_sz, (jbyte *) info_base );
597     }
598     else
599         j_infos = NULL;
600 
601     /* Cache Primitive Class's constructor as a Global Reference */
602     if ( cid4Prime == NULL ) {
603         cid_local  = (*env)->FindClass( env, "base/drawable/Primitive" );
604         if ( cid_local != NULL ) {
605             cid4Prime    = (*env)->NewGlobalRef( env, cid_local );
606             (*env)->DeleteLocalRef( env, cid_local );  /* avoid mem leak */
607             mid4NewPrime = (*env)->GetMethodID( env, cid4Prime, "<init>",
608                                                 "(IDD[D[I[B)V" );
609         }
610     }
611     /* Call Primitive's constructor */
612     prime = (*env)->NewObject( env, cid4Prime, mid4NewPrime,
613                                type_idx, starttime, endtime,
614                                j_tcoords, j_ycoords, j_infos );
615 
616     /* Clean up the unused reference and free local memory */
617     if ( tcoord_pos > 0 )
618         (*env)->DeleteLocalRef( env, j_tcoords );
619     if ( tcoord_base != NULL && tcoord_base != stcoord_base )
620         MPIU_Free( tcoord_base );
621 
622     if ( ycoord_pos > 0 )
623         (*env)->DeleteLocalRef( env, j_ycoords );
624     if ( ycoord_base != NULL && ycoord_base != sycoord_base )
625         MPIU_Free( ycoord_base );
626 
627     if ( info_pos > 0 )
628         (*env)->DeleteLocalRef( env, j_infos );
629     if ( info_base != NULL && info_base != sinfo_base )
630         MPIU_Free( info_base );
631 
632     return prime;
633 }
634 
635 JNIEXPORT jobject JNICALL
Java_logformat_trace_InputLog_getNextComposite(JNIEnv * env,jobject this)636 Java_logformat_trace_InputLog_getNextComposite( JNIEnv *env, jobject this )
637 {
638     TRACE_file              tracefile;
639     jlong                   filehandle;
640     double                  cmplx_starttime, cmplx_endtime;
641     int                     cmplx_type_idx;
642     int                     n_primitives;
643     int                     cm_info_sz, cm_info_pos, cm_info_max;
644     char                   *cm_info_base;
645     jbyteArray              j_cm_infos;
646     jobjectArray            primes;
647     jobject                 prime;
648     jobject                 cmplx;
649     jclass                  cid_local;
650     int                     idx, ierr;
651 
652 
653     filehandle = (*env)->GetLongField( env, this, fid4filehandle );
654     if ( filehandle == 0 ) {
655         fprintf( errfile, "Java_logformat_trace_InputLog_getNextComposite(): "
656                           "Inaccessible filehandle in Java side\n" );
657         return NULL;
658     }
659     tracefile  = (TRACE_file) filehandle;
660 
661     cm_info_sz = 0;
662     ierr = TRACE_Peek_next_composite( tracefile,
663                                       &cmplx_starttime, &cmplx_endtime,
664                                       &n_primitives, &cm_info_sz );
665     if ( ierr != 0 ) {
666         fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
667         fflush( errfile );
668         return NULL;
669     }
670 
671     /* return when there is no primitives */
672     if ( n_primitives <= 0 )
673         return NULL;
674 
675     j_cm_infos = NULL;
676     if ( cm_info_sz > 0 ) {
677         cm_info_pos    = 0;
678         cm_info_max    = cm_info_sz;
679         cm_info_base   = (char *)   MPIU_Malloc( cm_info_max * sizeof( char ) );
680         ierr = TRACE_Get_next_composite( tracefile, &cmplx_type_idx,
681                                          &cm_info_sz, cm_info_base,
682                                          &cm_info_pos, cm_info_max );
683         if ( ierr != 0 ) {
684             fprintf( errfile, "%s\n", TRACE_Get_err_string( ierr ) );
685             fflush( errfile );
686             return NULL;
687         }
688         if ( cm_info_pos > 0 ) {
689             j_cm_infos = (*env)->NewByteArray( env, cm_info_sz );
690             (*env)->SetByteArrayRegion( env, j_cm_infos,
691                                         0, cm_info_sz, (jbyte *) cm_info_base );
692         }
693         else
694             j_cm_infos = NULL;
695     }
696 
697     /* Cache Primitive Class's constructor as a Global Reference */
698     if ( cid4Prime == NULL ) {
699         cid_local  = (*env)->FindClass( env, "base/drawable/Primitive" );
700         if ( cid_local != NULL ) {
701             cid4Prime    = (*env)->NewGlobalRef( env, cid_local );
702             (*env)->DeleteLocalRef( env, cid_local );  /* avoid mem leak */
703             mid4NewPrime = (*env)->GetMethodID( env, cid4Prime, "<init>",
704                                                 "(IDD[D[I[B)V" );
705         }
706     }
707 
708     /* Create Primitives[] */
709     primes = (*env)->NewObjectArray( env, n_primitives, cid4Prime, NULL );
710     if ( primes == NULL )
711         return NULL;
712 
713     /*  Create the Primitive[] inside the Composite from the TRACE */
714     for ( idx = 0; idx < n_primitives; idx++ ) {
715          prime = Java_logformat_trace_InputLog_getNextPrimitive( env, this );
716          (*env)->SetObjectArrayElement( env, primes, idx, prime );
717     }
718 
719     /* Cache Composite Class's constructor as a Global Reference */
720     if ( cid4Cmplx == NULL ) {
721         cid_local  = (*env)->FindClass( env, "base/drawable/Composite" );
722         if ( cid_local != NULL ) {
723             cid4Cmplx    = (*env)->NewGlobalRef( env, cid_local );
724             (*env)->DeleteLocalRef( env, cid_local );  /* avoid mem leak */
725             mid4NewCmplx = (*env)->GetMethodID( env, cid4Cmplx, "<init>",
726                                    "(IDD[Lbase/drawable/Primitive;[B)V" );
727         }
728     }
729 
730     /* Invoke the Composite's constructor */
731     cmplx = (*env)->NewObject( env, cid4Cmplx, mid4NewCmplx,
732                                cmplx_type_idx, cmplx_starttime, cmplx_endtime,
733                                primes, j_cm_infos );
734 
735     /* Clean up the unused reference and free local memory */
736     if ( cm_info_sz > 0 && cm_info_pos > 0 )
737         (*env)->DeleteLocalRef( env, j_cm_infos );
738     if ( cm_info_base != NULL )
739         MPIU_Free( cm_info_base );
740 
741     return cmplx;
742 }
743