Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
323d3aa4e45bb09c80832e6ffaa324080a98a5f3
[simgrid.git] / src / jmsg.c
1 /* Java Wrappers to the MSG API.                                            */
2
3 /* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7   * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #include <msg/msg.h>
10 #include <simix/context.h>
11 #include <surf/surfxml_parse.h>
12
13 #include "smx_context_java.h"
14
15 #include "jmsg_process.h"
16 #include "jmsg_host.h"
17 #include "jmsg_task.h"
18 #include "jmsg_application_handler.h"
19 #include "jxbt_utilities.h"
20
21 #include "jmsg.h"
22
23 /* Shut up some errors in eclipse online compiler. I wish such a pimple wouldn't be needed */
24 #ifndef JNIEXPORT
25 #define JNIEXPORT
26 #endif
27 #ifndef JNICALL
28 #define JNICALL
29 #endif
30 /* end of eclipse-mandated pimple */
31
32 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(jmsg);
33
34 static JavaVM *__java_vm = NULL;
35
36 static jobject native_to_java_process(m_process_t process);
37
38 JavaVM *get_java_VM(void)
39 {
40   return __java_vm;
41 }
42
43 JNIEnv *get_current_thread_env(void)
44 {
45   JNIEnv *env;
46
47   (*__java_vm)->AttachCurrentThread(__java_vm, (void **) &env, NULL);
48
49   return env;
50 }
51
52 static jobject native_to_java_process(m_process_t process)
53 {
54   return ((smx_ctx_java_t)MSG_process_get_smx_ctx(process))->jprocess;
55 }
56
57 /*
58  * The MSG process connected functions implementation.                                 
59  */
60
61 JNIEXPORT void JNICALL
62 Java_org_simgrid_msg_MsgNative_processCreate(JNIEnv * env, jclass cls,
63                                          jobject jprocess_arg,
64                                          jobject jhost)
65 {
66      
67    
68   jobject jprocess;             /* the global reference to the java process instance    */
69   jstring jname;                /* the name of the java process instance                */
70   const char *name;             /* the C name of the process                            */
71   m_process_t process;          /* the native process to create                         */
72   m_host_t host;                /* Where that process lives */
73    
74   XBT_DEBUG("Java_org_simgrid_msg_MsgNative_processCreate(env=%p,cls=%p,jproc=%p,jhost=%p)",
75          env, cls, jprocess_arg, jhost);
76    
77    
78   /* get the name of the java process */
79   jname = jprocess_get_name(jprocess_arg, env);
80   if (!jname) {
81     jxbt_throw_null(env,
82             xbt_strdup("Internal error: Process name cannot be NULL"));
83     return;
84   }
85
86   /* bind/retrieve the msg host */
87   host = jhost_get_native(env, jhost);
88
89   if (!(host)) {    /* not binded */
90     jxbt_throw_notbound(env, "host", jhost);
91     return;
92   }
93
94   /* create a global java process instance */
95   jprocess = jprocess_new_global_ref(jprocess_arg, env);
96   if (!jprocess) {
97     jxbt_throw_jni(env, "Can't get a global ref to the java process");
98     return;
99   }
100
101   /* build the C name of the process */
102   name = (*env)->GetStringUTFChars(env, jname, 0);
103   name = xbt_strdup(name);
104   
105   /* Actually build the MSG process */
106   process = MSG_process_create_with_environment(name,
107                                                 (xbt_main_func_t) jprocess,
108                                                 /*data*/ NULL,
109                                                 host,
110                                                 /*argc, argv, properties*/
111                                                 0,NULL,NULL);
112      
113   MSG_process_set_data(process,&process);
114    
115   /* release our reference to the process name (variable name becomes invalid) */
116   //FIXME : This line should be uncommented but with mac it doesn't work. BIG WARNING
117   //(*env)->ReleaseStringUTFChars(env, jname, name);
118    
119   /* bind the java process instance to the native process */
120   jprocess_bind(jprocess, process, env);
121
122 }
123
124 JNIEXPORT void JNICALL
125 Java_org_simgrid_msg_MsgNative_processSuspend(JNIEnv * env, jclass cls,
126                                           jobject jprocess)
127 {
128   m_process_t process = jprocess_to_native_process(jprocess, env);
129
130   if (!process) {
131     jxbt_throw_notbound(env, "process", jprocess);
132     return;
133   }
134
135   /* try to suspend the process */
136   MSG_error_t rv = MSG_process_suspend(process);
137
138   jxbt_check_res("MSG_process_suspend()", rv, MSG_OK,
139                  bprintf("unexpected error , please report this bug"));
140
141 }
142
143 JNIEXPORT void JNICALL
144 Java_org_simgrid_msg_Process_simulatedSleep(JNIEnv * env, jobject jprocess,
145                                            jdouble jseconds) {
146           m_process_t process = jprocess_to_native_process(jprocess, env);
147
148           if (!process) {
149             jxbt_throw_notbound(env, "process", jprocess);
150             return;
151           }
152           MSG_error_t rv = MSG_process_sleep((double)jseconds);
153
154           jxbt_check_res("MSG_process_sleep()", rv, MSG_OK,
155                          bprintf("unexpected error , please report this bug"));
156 }
157
158
159 JNIEXPORT void JNICALL
160 Java_org_simgrid_msg_MsgNative_processResume(JNIEnv * env, jclass cls,
161                                          jobject jprocess)
162 {
163   m_process_t process = jprocess_to_native_process(jprocess, env);
164
165   if (!process) {
166     jxbt_throw_notbound(env, "process", jprocess);
167     return;
168   }
169
170   /* try to resume the process */
171   MSG_error_t rv = MSG_process_resume(process);
172
173   jxbt_check_res("MSG_process_resume()", rv, MSG_OK,
174                  bprintf("unexpected error , please report this bug"));
175 }
176
177 JNIEXPORT jboolean JNICALL
178 Java_org_simgrid_msg_MsgNative_processIsSuspended(JNIEnv * env, jclass cls,
179                                               jobject jprocess)
180 {
181   m_process_t process = jprocess_to_native_process(jprocess, env);
182
183   if (!process) {
184     jxbt_throw_notbound(env, "process", jprocess);
185     return 0;
186   }
187
188   /* true is the process is suspended, false otherwise */
189   return (jboolean) MSG_process_is_suspended(process);
190 }
191
192 JNIEXPORT void JNICALL
193 Java_org_simgrid_msg_MsgNative_processKill(JNIEnv * env, jclass cls,
194                                        jobject jprocess)
195 {
196   /* get the native instances from the java ones */
197   m_process_t process = jprocess_to_native_process(jprocess, env);
198
199   if (!process) {
200     jxbt_throw_notbound(env, "process", jprocess);
201     return;
202   }
203
204   /* kill the native process (this wrapper is call by the destructor of the java 
205    * process instance)
206    */
207   MSG_process_kill(process);
208 }
209
210 JNIEXPORT jobject JNICALL
211 Java_org_simgrid_msg_MsgNative_processGetHost(JNIEnv * env, jclass cls,
212                                           jobject jprocess)
213 {
214   /* get the native instances from the java ones */
215   m_process_t process = jprocess_to_native_process(jprocess, env);
216   m_host_t host;
217
218   if (!process) {
219     jxbt_throw_notbound(env, "process", jprocess);
220     return NULL;
221   }
222
223   host = MSG_process_get_host(process);
224
225   if (!MSG_host_get_data(host)) {
226     jxbt_throw_jni(env, "MSG_process_get_host() failed");
227     return NULL;
228   }
229
230   /* return the global reference to the java host instance */
231   return (jobject) MSG_host_get_data(host);
232
233 }
234
235 JNIEXPORT jobject JNICALL
236 Java_org_simgrid_msg_MsgNative_processFromPID(JNIEnv * env, jclass cls,
237                                           jint PID)
238 {
239   m_process_t process = MSG_process_from_PID(PID);
240
241   if (!process) {
242     jxbt_throw_process_not_found(env, bprintf("PID = %d",(int) PID));
243     return NULL;
244   }
245
246   if (!native_to_java_process(process)) {
247     jxbt_throw_jni(env, "SIMIX_process_get_jprocess() failed");
248     return NULL;
249   }
250
251   return (jobject) (native_to_java_process(process));
252 }
253
254
255 JNIEXPORT jint JNICALL
256 Java_org_simgrid_msg_MsgNative_processGetPID(JNIEnv * env, jclass cls,
257                                          jobject jprocess)
258 {
259   m_process_t process = jprocess_to_native_process(jprocess, env);
260
261   if (!process) {
262     jxbt_throw_notbound(env, "process", jprocess);
263     return 0;
264   }
265
266   return (jint) MSG_process_get_PID(process);
267 }
268
269
270 JNIEXPORT jint JNICALL
271 Java_org_simgrid_msg_MsgNative_processGetPPID(JNIEnv * env, jclass cls,
272                                           jobject jprocess)
273 {
274   m_process_t process = jprocess_to_native_process(jprocess, env);
275
276   if (!process) {
277     jxbt_throw_notbound(env, "process", jprocess);
278     return 0;
279   }
280
281   return (jint) MSG_process_get_PPID(process);
282 }
283
284 JNIEXPORT jobject JNICALL
285 Java_org_simgrid_msg_MsgNative_processSelf(JNIEnv * env, jclass cls)
286 {
287   m_process_t process = MSG_process_self();
288   jobject jprocess;
289
290   if (!process) {
291     jxbt_throw_jni(env, xbt_strdup("MSG_process_self() failed"));
292     return NULL;
293   }
294
295   jprocess = native_to_java_process(process);
296
297   if (!jprocess)
298     jxbt_throw_jni(env, xbt_strdup("SIMIX_process_get_jprocess() failed"));
299
300   return jprocess;
301 }
302
303 JNIEXPORT void JNICALL
304 Java_org_simgrid_msg_MsgNative_processMigrate(JNIEnv * env, jclass cls,
305                                              jobject jprocess, jobject jhost)
306 {
307   m_process_t process = jprocess_to_native_process(jprocess, env);
308
309   if (!process) {
310     jxbt_throw_notbound(env, "process", jprocess);
311     return;
312   }
313
314   m_host_t host = jhost_get_native(env, jhost);
315
316   if (!host) {
317     jxbt_throw_notbound(env, "host", jhost);
318     return;
319   }
320
321   /* try to change the host of the process */
322   MSG_error_t rv = MSG_process_migrate(process, host);
323   jxbt_check_res("MSG_process_migrate()", rv, MSG_OK,
324                  bprintf("unexpected error , please report this bug"));
325
326 }
327
328 JNIEXPORT void JNICALL
329 Java_org_simgrid_msg_MsgNative_processWaitFor(JNIEnv * env, jclass cls,
330                                           jdouble seconds)
331 {
332   MSG_error_t rv = MSG_process_sleep((double) seconds);
333
334   jxbt_check_res("MSG_process_sleep()", rv, MSG_HOST_FAILURE,
335                  bprintf("while process was waiting for %f seconds",
336                          (double) seconds));
337
338 }
339
340
341 /***************************************************************************************
342  * The MSG host connected functions implementation.                                    *
343  ***************************************************************************************/
344
345 JNIEXPORT jobject JNICALL
346 Java_org_simgrid_msg_MsgNative_hostGetByName(JNIEnv * env, jclass cls,
347                                          jstring jname)
348 {
349   m_host_t host;                /* native host                                          */
350   jobject jhost;                /* global reference to the java host instance returned  */
351
352   /* get the C string from the java string */
353   const char *name = (*env)->GetStringUTFChars(env, jname, 0);
354   XBT_DEBUG("Looking for host '%s'",name);
355   /* get the host by name       (the hosts are created during the grid resolution) */
356   host = MSG_get_host_by_name(name);
357   XBT_DEBUG("MSG gave %p as native host (simdata=%p)", host,host? host->simdata:NULL);
358
359   if (!host) {                  /* invalid name */
360     jxbt_throw_host_not_found(env, name);
361     (*env)->ReleaseStringUTFChars(env, jname, name);
362     return NULL;
363   }
364   (*env)->ReleaseStringUTFChars(env, jname, name);
365
366   if (!MSG_host_get_data(host)) {       /* native host not associated yet with java host */
367
368     /* Instantiate a new java host */
369     jhost = jhost_new_instance(env);
370
371     if (!jhost) {
372       jxbt_throw_jni(env, "java host instantiation failed");
373       return NULL;
374     }
375
376     /* get a global reference to the newly created host */
377     jhost = jhost_ref(env, jhost);
378
379     if (!jhost) {
380       jxbt_throw_jni(env, "new global ref allocation failed");
381       return NULL;
382     }
383
384     /* bind the java host and the native host */
385     jhost_bind(jhost, host, env);
386
387     /* the native host data field is set with the global reference to the 
388      * java host returned by this function 
389      */
390     MSG_host_set_data(host, (void *) jhost);
391   }
392
393   /* return the global reference to the java host instance */
394   return (jobject) MSG_host_get_data(host);
395 }
396
397 JNIEXPORT jstring JNICALL
398 Java_org_simgrid_msg_MsgNative_hostGetName(JNIEnv * env, jclass cls,
399                                        jobject jhost)
400 {
401   m_host_t host = jhost_get_native(env, jhost);
402
403   if (!host) {
404     jxbt_throw_notbound(env, "host", jhost);
405     return NULL;
406   }
407
408   return (*env)->NewStringUTF(env, MSG_host_get_name(host));
409 }
410
411 JNIEXPORT jint JNICALL
412 Java_org_simgrid_msg_MsgNative_hostGetNumber(JNIEnv * env, jclass cls)
413 {
414   xbt_dynar_t hosts =  MSG_hosts_as_dynar();
415   int nb_host = xbt_dynar_length(hosts);
416   xbt_dynar_free(&hosts);
417   return (jint) nb_host;
418 }
419
420 JNIEXPORT jobject JNICALL
421 Java_org_simgrid_msg_MsgNative_hostSelf(JNIEnv * env, jclass cls)
422 {
423   jobject jhost;
424
425   m_host_t host = MSG_host_self();
426
427   if (!MSG_host_get_data(host)) {
428     /* the native host not yet associated with the java host instance */
429
430     /* instanciate a new java host instance */
431     jhost = jhost_new_instance(env);
432
433     if (!jhost) {
434       jxbt_throw_jni(env, "java host instantiation failed");
435       return NULL;
436     }
437
438     /* get a global reference to the newly created host */
439     jhost = jhost_ref(env, jhost);
440
441     if (!jhost) {
442       jxbt_throw_jni(env, "global ref allocation failed");
443       return NULL;
444     }
445
446     /* Bind & store it */
447     jhost_bind(jhost, host, env);
448     MSG_host_set_data(host, (void *) jhost);
449   } else {
450     jhost = (jobject) MSG_host_get_data(host);
451   }
452
453   return jhost;
454 }
455
456 JNIEXPORT jdouble JNICALL
457 Java_org_simgrid_msg_MsgNative_hostGetSpeed(JNIEnv * env, jclass cls,
458                                         jobject jhost)
459 {
460   m_host_t host = jhost_get_native(env, jhost);
461
462   if (!host) {
463     jxbt_throw_notbound(env, "host", jhost);
464     return -1;
465   }
466
467   return (jdouble) MSG_get_host_speed(host);
468 }
469
470 JNIEXPORT jint JNICALL
471 Java_org_simgrid_msg_MsgNative_hostGetLoad(JNIEnv * env, jclass cls,
472                                        jobject jhost)
473 {
474   m_host_t host = jhost_get_native(env, jhost);
475
476   if (!host) {
477     jxbt_throw_notbound(env, "host", jhost);
478     return -1;
479   }
480
481   return (jint) MSG_get_host_msgload(host);
482 }
483
484
485 JNIEXPORT jboolean JNICALL
486 Java_org_simgrid_msg_MsgNative_hostIsAvail(JNIEnv * env, jclass cls,
487                                        jobject jhost)
488 {
489   m_host_t host = jhost_get_native(env, jhost);
490
491   if (!host) {
492     jxbt_throw_notbound(env, "host", jhost);
493     return 0;
494   }
495
496   return (jboolean) MSG_host_is_avail(host);
497 }
498
499
500 /***************************************************************************************
501  * The MSG task connected functions implementation.                                    *
502  ***************************************************************************************/
503
504 JNIEXPORT void JNICALL
505 Java_org_simgrid_msg_MsgNative_taskCreate(JNIEnv * env, jclass cls,
506                                       jobject jtask, jstring jname,
507                                       jdouble jcomputeDuration,
508                                       jdouble jmessageSize)
509 {
510   m_task_t task;                /* the native task to create                            */
511   const char *name = NULL;      /* the name of the task                                 */
512
513   if (jcomputeDuration < 0) {
514     jxbt_throw_illegal(env,
515                        bprintf
516                        ("Task ComputeDuration (%f) cannot be negative",
517                         (double) jcomputeDuration));
518     return;
519   }
520
521   if (jmessageSize < 0) {
522     jxbt_throw_illegal(env,
523                        bprintf("Task MessageSize (%f) cannot be negative",
524                                (double) jmessageSize));
525     return;
526   }
527
528   if (jname) {
529     /* get the C string from the java string */
530     name = (*env)->GetStringUTFChars(env, jname, 0);
531   }
532
533
534   /* create the task */
535   task =
536       MSG_task_create(name, (double) jcomputeDuration,
537                       (double) jmessageSize, NULL);
538
539   if (jname)
540     (*env)->ReleaseStringUTFChars(env, jname, name);
541
542   /* bind & store the task */
543   jtask_bind(jtask, task, env);
544   MSG_task_set_data(task, jtask);
545 }
546
547 JNIEXPORT void JNICALL
548 Java_org_simgrid_msg_MsgNative_parallel_taskCreate(JNIEnv * env, jclass cls,
549                                                jobject jtask,
550                                                jstring jname,
551                                                jobjectArray jhosts,
552                                                jdoubleArray
553                                                jcomputeDurations_arg,
554                                                jdoubleArray
555                                                jmessageSizes_arg)
556 {
557
558   m_task_t task;                /* the native parallel task to create           */
559   const char *name;             /* the name of the task                         */
560   int host_count;
561   m_host_t *hosts;
562   double *computeDurations;
563   double *messageSizes;
564   jdouble *jcomputeDurations;
565   jdouble *jmessageSizes;
566
567   jobject jhost;
568   int index;
569
570
571   if (!jcomputeDurations_arg) {
572     jxbt_throw_null(env,
573                     xbt_strdup
574                     ("Parallel task compute durations cannot be null"));
575     return;
576   }
577
578   if (!jmessageSizes_arg) {
579     jxbt_throw_null(env,
580                     xbt_strdup
581                     ("Parallel task message sizes cannot be null"));
582     return;
583   }
584
585   if (!jname) {
586     jxbt_throw_null(env, xbt_strdup("Parallel task name cannot be null"));
587     return;
588   }
589
590   host_count = (int) (*env)->GetArrayLength(env, jhosts);
591
592
593   hosts = xbt_new0(m_host_t, host_count);
594   computeDurations = xbt_new0(double, host_count);
595   messageSizes = xbt_new0(double, host_count * host_count);
596
597   jcomputeDurations =
598       (*env)->GetDoubleArrayElements(env, jcomputeDurations_arg, 0);
599   jmessageSizes =
600       (*env)->GetDoubleArrayElements(env, jmessageSizes_arg, 0);
601
602   for (index = 0; index < host_count; index++) {
603     jhost = (*env)->GetObjectArrayElement(env, jhosts, index);
604     hosts[index] = jhost_get_native(env, jhost);
605     computeDurations[index] = jcomputeDurations[index];
606   }
607   for (index = 0; index < host_count * host_count; index++) {
608     messageSizes[index] = jmessageSizes[index];
609   }
610
611   (*env)->ReleaseDoubleArrayElements(env, jcomputeDurations_arg,
612                                      jcomputeDurations, 0);
613   (*env)->ReleaseDoubleArrayElements(env, jmessageSizes_arg, jmessageSizes,
614                                      0);
615
616
617   /* get the C string from the java string */
618   name = (*env)->GetStringUTFChars(env, jname, 0);
619
620   task =
621       MSG_parallel_task_create(name, host_count, hosts, computeDurations,
622                                messageSizes, NULL);
623
624   (*env)->ReleaseStringUTFChars(env, jname, name);
625
626   /* associate the java task object and the native task */
627   jtask_bind(jtask, task, env);
628
629   MSG_task_set_data(task, (void *) jtask);
630
631   if (!MSG_task_get_data(task))
632     jxbt_throw_jni(env, "global ref allocation failed");
633 }
634
635 JNIEXPORT jobject JNICALL
636 Java_org_simgrid_msg_MsgNative_taskGetSender(JNIEnv * env, jclass cls,
637                                          jobject jtask)
638 {
639   m_process_t process;
640
641   m_task_t task = jtask_to_native_task(jtask, env);
642
643   if (!task) {
644     jxbt_throw_notbound(env, "task", jtask);
645     return NULL;
646   }
647
648   process = MSG_task_get_sender(task);
649   return (jobject) native_to_java_process(process);
650 }
651
652 JNIEXPORT jobject JNICALL
653 Java_org_simgrid_msg_MsgNative_taskGetSource(JNIEnv * env, jclass cls,
654                                          jobject jtask)
655 {
656   m_host_t host;
657   m_task_t task = jtask_to_native_task(jtask, env);
658
659   if (!task) {
660     jxbt_throw_notbound(env, "task", jtask);
661     return NULL;
662   }
663
664   host = MSG_task_get_source(task);
665
666   if (!MSG_host_get_data(host)) {
667     jxbt_throw_jni(env, "MSG_task_get_source() failed");
668     return NULL;
669   }
670
671   return (jobject) MSG_host_get_data(host);
672 }
673
674
675 JNIEXPORT jstring JNICALL
676 Java_org_simgrid_msg_MsgNative_taskGetName(JNIEnv * env, jclass cls,
677                                        jobject jtask)
678 {
679   m_task_t task = jtask_to_native_task(jtask, env);
680
681   if (!task) {
682     jxbt_throw_notbound(env, "task", jtask);
683     return NULL;
684   }
685
686   return (*env)->NewStringUTF(env, MSG_task_get_name(task));
687 }
688
689 JNIEXPORT void JNICALL
690 Java_org_simgrid_msg_MsgNative_taskCancel(JNIEnv * env, jclass cls,
691                                       jobject jtask)
692 {
693   m_task_t ptask = jtask_to_native_task(jtask, env);
694
695   if (!ptask) {
696     jxbt_throw_notbound(env, "task", jtask);
697     return;
698   }
699
700   MSG_error_t rv = MSG_task_cancel(ptask);
701
702   jxbt_check_res("MSG_task_cancel()", rv, MSG_OK,
703                  bprintf("unexpected error , please report this bug"));
704 }
705
706 JNIEXPORT jdouble JNICALL
707 Java_org_simgrid_msg_MsgNative_taskGetComputeDuration(JNIEnv * env, jclass cls,
708                                                   jobject jtask)
709 {
710   m_task_t ptask = jtask_to_native_task(jtask, env);
711
712   if (!ptask) {
713     jxbt_throw_notbound(env, "task", jtask);
714     return -1;
715   }
716   return (jdouble) MSG_task_get_compute_duration(ptask);
717 }
718
719 JNIEXPORT jdouble JNICALL
720 Java_org_simgrid_msg_MsgNative_taskGetRemainingDuration(JNIEnv * env,
721                                                     jclass cls,
722                                                     jobject jtask)
723 {
724   m_task_t ptask = jtask_to_native_task(jtask, env);
725
726   if (!ptask) {
727     jxbt_throw_notbound(env, "task", jtask);
728     return -1;
729   }
730   return (jdouble) MSG_task_get_remaining_computation(ptask);
731 }
732
733 JNIEXPORT void JNICALL
734 Java_org_simgrid_msg_MsgNative_taskSetPriority(JNIEnv * env, jclass cls,
735                                            jobject jtask, jdouble priority)
736 {
737   m_task_t task = jtask_to_native_task(jtask, env);
738
739   if (!task) {
740     jxbt_throw_notbound(env, "task", jtask);
741     return;
742   }
743   MSG_task_set_priority(task, (double) priority);
744 }
745
746 JNIEXPORT void JNICALL
747 Java_org_simgrid_msg_MsgNative_taskDestroy(JNIEnv * env, jclass cls,
748                                        jobject jtask_arg)
749 {
750
751   /* get the native task */
752   m_task_t task = jtask_to_native_task(jtask_arg, env);
753
754   if (!task) {
755     jxbt_throw_notbound(env, "task", task);
756     return;
757   }
758
759   MSG_error_t rv = MSG_task_destroy(task);
760
761   jxbt_check_res("MSG_task_destroy()", rv, MSG_OK,
762                  bprintf("unexpected error , please report this bug"));
763 }
764
765 JNIEXPORT void JNICALL
766 Java_org_simgrid_msg_MsgNative_taskExecute(JNIEnv * env, jclass cls,
767                                        jobject jtask)
768 {
769   m_task_t task = jtask_to_native_task(jtask, env);
770
771   if (!task) {
772     jxbt_throw_notbound(env, "task", jtask);
773     return;
774   }
775
776   MSG_error_t rv = MSG_task_execute(task);
777
778   jxbt_check_res("MSG_task_execute()", rv,
779                  MSG_HOST_FAILURE | MSG_TASK_CANCELED,
780                  bprintf("while executing task %s",
781                          MSG_task_get_name(task)));
782 }
783
784 /***************************************************************************************
785  * Unsortable functions                                                        *
786  ***************************************************************************************/
787
788 JNIEXPORT jdouble JNICALL
789 Java_org_simgrid_msg_Msg_getClock(JNIEnv * env, jclass cls)
790 {
791   return (jdouble) MSG_get_clock();
792 }
793
794 JNIEXPORT void JNICALL
795 Java_org_simgrid_msg_Msg_init(JNIEnv * env, jclass cls, jobjectArray jargs)
796 {
797   char **argv = NULL;
798   int index;
799   int argc = 0;
800   jstring jval;
801   const char *tmp;
802
803   smx_factory_initializer_to_use = SIMIX_ctx_java_factory_init;
804
805   if (jargs)
806     argc = (int) (*env)->GetArrayLength(env, jargs);
807
808   argc++;
809   argv = xbt_new(char *, argc + 1);
810   argv[0] = strdup("java");
811
812   for (index = 0; index < argc - 1; index++) {
813     jval = (jstring) (*env)->GetObjectArrayElement(env, jargs, index);
814     tmp = (*env)->GetStringUTFChars(env, jval, 0);
815     argv[index + 1] = strdup(tmp);
816     (*env)->ReleaseStringUTFChars(env, jval, tmp);
817   }
818   argv[argc] = NULL;
819
820   MSG_global_init(&argc, argv);
821
822   for (index = 0; index < argc; index++)
823     free(argv[index]);
824
825   free(argv);
826
827   (*env)->GetJavaVM(env, &__java_vm);
828 }
829
830 JNIEXPORT void JNICALL
831     JNICALL Java_org_simgrid_msg_Msg_run(JNIEnv * env, jclass cls)
832 {
833   MSG_error_t rv;
834   int index;
835   xbt_dynar_t hosts;
836   jobject jhost;
837
838   /* Run everything */
839   XBT_INFO("Ready to run MSG_MAIN");
840   rv = MSG_main();
841   XBT_INFO("Done running MSG_MAIN");
842   jxbt_check_res("MSG_main()", rv, MSG_OK,
843                  bprintf
844                  ("unexpected error : MSG_main() failed .. please report this bug "));
845
846   XBT_INFO("MSG_main finished");
847
848   XBT_INFO("Clean java world");
849   /* Cleanup java hosts */
850   hosts = MSG_hosts_as_dynar();
851   for (index = 0; index < xbt_dynar_length(hosts) - 1; index++) {
852     jhost = (jobject) xbt_dynar_get_as(hosts,index,m_host_t)->data;
853     if (jhost)
854       jhost_unref(env, jhost);
855
856   }
857   xbt_dynar_free(&hosts);
858   XBT_INFO("Clean native world");
859 }
860 JNIEXPORT void JNICALL
861     JNICALL Java_org_simgrid_msg_Msg_clean(JNIEnv * env, jclass cls)
862 {
863   /* cleanup native stuff. Calling it is ... useless since leaking memory at the end of the simulation is a non-issue */
864   MSG_error_t rv = MSG_OK != MSG_clean();
865   jxbt_check_res("MSG_clean()", rv, MSG_OK,
866                  bprintf
867                  ("unexpected error : MSG_clean() failed .. please report this bug "));
868 }
869    
870 JNIEXPORT jint JNICALL
871 Java_org_simgrid_msg_MsgNative_processKillAll(JNIEnv * env, jclass cls,
872                                           jint jresetPID)
873 {
874   return (jint) MSG_process_killall((int) jresetPID);
875 }
876
877 JNIEXPORT void JNICALL
878 Java_org_simgrid_msg_Msg_createEnvironment(JNIEnv * env, jclass cls,
879                                        jstring jplatformFile)
880 {
881
882   const char *platformFile =
883       (*env)->GetStringUTFChars(env, jplatformFile, 0);
884
885   MSG_create_environment(platformFile);
886
887   (*env)->ReleaseStringUTFChars(env, jplatformFile, platformFile);
888 }
889
890 JNIEXPORT void JNICALL
891 Java_org_simgrid_msg_MsgNative_processExit(JNIEnv * env, jclass cls,
892                                        jobject jprocess)
893 {
894
895   m_process_t process = jprocess_to_native_process(jprocess, env);
896
897   if (!process) {
898     jxbt_throw_notbound(env, "process", jprocess);
899     return;
900   }
901
902   smx_ctx_java_stop(MSG_process_get_smx_ctx(process));
903 }
904
905 JNIEXPORT void JNICALL
906 Java_org_simgrid_msg_Msg_info(JNIEnv * env, jclass cls, jstring js)
907 {
908   const char *s = (*env)->GetStringUTFChars(env, js, 0);
909   XBT_INFO("%s", s);
910   (*env)->ReleaseStringUTFChars(env, js, s);
911 }
912
913 JNIEXPORT jobjectArray JNICALL
914 Java_org_simgrid_msg_MsgNative_allHosts(JNIEnv * env, jclass cls_arg)
915 {
916   int index;
917   jobjectArray jtable;
918   jobject jhost;
919   jstring jname;
920   m_host_t host;
921
922   xbt_dynar_t table =  MSG_hosts_as_dynar();
923   int count = xbt_dynar_length(table);
924
925   jclass cls = jxbt_get_class(env, "org/simgrid/msg/Host");
926
927   if (!cls) {
928     return NULL;
929   }
930
931   jtable = (*env)->NewObjectArray(env, (jsize) count, cls, NULL);
932
933   if (!jtable) {
934     jxbt_throw_jni(env, "Hosts table allocation failed");
935     return NULL;
936   }
937
938   for (index = 0; index < count; index++) {
939     host = xbt_dynar_get_as(table,index,m_host_t);
940     jhost = (jobject) (MSG_host_get_data(host));
941
942     if (!jhost) {
943       jname = (*env)->NewStringUTF(env, MSG_host_get_name(host));
944
945       jhost =
946           Java_org_simgrid_msg_MsgNative_hostGetByName(env, cls_arg, jname);
947       /* FIXME: leak of jname ? */
948     }
949
950     (*env)->SetObjectArrayElement(env, jtable, index, jhost);
951   }
952   xbt_dynar_free(&table);
953   return jtable;
954 }
955
956 JNIEXPORT void JNICALL
957 Java_org_simgrid_msg_MsgNative_taskSend(JNIEnv * env, jclass cls,
958                                     jstring jalias, jobject jtask,
959                                     jdouble jtimeout)
960 {
961
962   MSG_error_t rv;
963   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
964
965   m_task_t task = jtask_to_native_task(jtask, env);
966
967
968   if (!task) {
969     (*env)->ReleaseStringUTFChars(env, jalias, alias);
970     jxbt_throw_notbound(env, "task", jtask);
971     return;
972   }
973
974   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
975   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
976   rv = MSG_task_send_with_timeout(task, alias, (double) jtimeout);
977
978   (*env)->ReleaseStringUTFChars(env, jalias, alias);
979
980   jxbt_check_res("MSG_task_send_with_timeout()", rv,
981                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
982                  bprintf("while sending task %s to mailbox %s",
983                          MSG_task_get_name(task), alias));
984 }
985
986 static void msg_task_cancel_on_failed_dsend(void*t) {
987         m_task_t task = t;
988         JNIEnv *env =get_current_thread_env();
989         jobject jtask_global = MSG_task_get_data(task);
990
991         /* Destroy the global ref so that the JVM can free the stuff */
992         (*env)->DeleteGlobalRef(env, jtask_global);
993         MSG_task_set_data(task, NULL);
994         MSG_task_destroy(task);
995 }
996
997 JNIEXPORT void JNICALL
998 Java_org_simgrid_msg_MsgNative_taskDSend(JNIEnv * env, jclass cls,
999                                     jstring jalias, jobject jtask)
1000 {
1001
1002   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
1003
1004   m_task_t task = jtask_to_native_task(jtask, env);
1005
1006
1007   if (!task) {
1008     (*env)->ReleaseStringUTFChars(env, jalias, alias);
1009     jxbt_throw_notbound(env, "task", jtask);
1010     return;
1011   }
1012
1013   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
1014   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
1015   MSG_task_dsend(task, alias, msg_task_cancel_on_failed_dsend);
1016
1017   (*env)->ReleaseStringUTFChars(env, jalias, alias);
1018 }
1019
1020
1021 JNIEXPORT void JNICALL
1022 Java_org_simgrid_msg_MsgNative_taskSendBounded(JNIEnv * env, jclass cls,
1023                                            jstring jalias, jobject jtask,
1024                                            jdouble jmaxRate)
1025 {
1026   m_task_t task = jtask_to_native_task(jtask, env);
1027   MSG_error_t rv;
1028   const char *alias;
1029
1030   if (!task) {
1031     jxbt_throw_notbound(env, "task", jtask);
1032     return;
1033   }
1034
1035   alias = (*env)->GetStringUTFChars(env, jalias, 0);
1036
1037   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
1038   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
1039   rv = MSG_task_send_bounded(task, alias, (double) jmaxRate);
1040
1041   (*env)->ReleaseStringUTFChars(env, jalias, alias);
1042
1043   jxbt_check_res("MSG_task_send_bounded()", rv,
1044                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
1045                  bprintf
1046                  ("while sending task %s to mailbox %s with max rate %f",
1047                   MSG_task_get_name(task), alias, (double) jmaxRate));
1048
1049 }
1050
1051 JNIEXPORT jobject JNICALL
1052 Java_org_simgrid_msg_MsgNative_taskReceive(JNIEnv * env, jclass cls,
1053                                        jstring jalias, jdouble jtimeout,
1054                                        jobject jhost)
1055 {
1056   MSG_error_t rv;
1057   m_task_t task = NULL;
1058   m_host_t host = NULL;
1059   jobject jtask_global, jtask_local;
1060   const char *alias;
1061
1062   if (jhost) {
1063     host = jhost_get_native(env, jhost);
1064
1065     if (!host) {
1066       jxbt_throw_notbound(env, "host", jhost);
1067       return NULL;
1068     }
1069   }
1070
1071   alias = (*env)->GetStringUTFChars(env, jalias, 0);
1072
1073   rv = MSG_task_receive_ext(&task, alias, (double) jtimeout, host);
1074   if (rv != MSG_OK) {
1075         switch (rv) {
1076                 case MSG_TIMEOUT:
1077                         jxbt_throw_time_out_failure(env,NULL);
1078                 break;
1079                 case MSG_TRANSFER_FAILURE:
1080                         jxbt_throw_transfer_failure(env,NULL);
1081                 break;
1082                 case MSG_HOST_FAILURE:
1083                         jxbt_throw_host_failure(env,NULL);
1084                 break;
1085                 default:
1086                         jxbt_throw_native(env,bprintf("receive failed"));
1087         }
1088         return NULL;
1089   }
1090   jtask_global = MSG_task_get_data(task);
1091
1092   /* Convert the global ref into a local ref so that the JVM can free the stuff */
1093   jtask_local = (*env)->NewLocalRef(env, jtask_global);
1094   (*env)->DeleteGlobalRef(env, jtask_global);
1095   MSG_task_set_data(task, NULL);
1096
1097   (*env)->ReleaseStringUTFChars(env, jalias, alias);
1098
1099   jxbt_check_res("MSG_task_receive_ext()", rv,
1100                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
1101                  bprintf("while receiving from mailbox %s", alias));
1102
1103   return (jobject) jtask_local;
1104 }
1105
1106 JNIEXPORT jboolean JNICALL
1107 Java_org_simgrid_msg_MsgNative_taskListen(JNIEnv * env, jclass cls,
1108                                       jstring jalias)
1109 {
1110
1111   const char *alias;
1112   int rv;
1113
1114   alias = (*env)->GetStringUTFChars(env, jalias, 0);
1115
1116   rv = MSG_task_listen(alias);
1117
1118   (*env)->ReleaseStringUTFChars(env, jalias, alias);
1119
1120   return (jboolean) rv;
1121 }
1122
1123 JNIEXPORT jint JNICALL
1124 Java_org_simgrid_msg_MsgNative_taskListenFromHost(JNIEnv * env, jclass cls,
1125                                               jstring jalias,
1126                                               jobject jhost)
1127 {
1128   int rv;
1129   const char *alias;
1130
1131   m_host_t host = jhost_get_native(env, jhost);
1132
1133   if (!host) {
1134     jxbt_throw_notbound(env, "host", jhost);
1135     return -1;
1136   }
1137   alias = (*env)->GetStringUTFChars(env, jalias, 0);
1138
1139   rv = MSG_task_listen_from_host(alias, host);
1140
1141   (*env)->ReleaseStringUTFChars(env, jalias, alias);
1142
1143   return (jint) rv;
1144 }
1145
1146 JNIEXPORT jint JNICALL
1147 Java_org_simgrid_msg_MsgNative_taskListenFrom(JNIEnv * env, jclass cls,
1148                                           jstring jalias)
1149 {
1150
1151   int rv;
1152   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
1153
1154   rv = MSG_task_listen_from(alias);
1155
1156   (*env)->ReleaseStringUTFChars(env, jalias, alias);
1157
1158   return (jint) rv;
1159 }
1160
1161 JNIEXPORT void JNICALL
1162 Java_org_simgrid_msg_Msg_deployApplication(JNIEnv * env, jclass cls,
1163                                        jstring jdeploymentFile)
1164 {
1165
1166   const char *deploymentFile =
1167       (*env)->GetStringUTFChars(env, jdeploymentFile, 0);
1168
1169   surf_parse_reset_callbacks();
1170
1171   surfxml_add_callback(STag_surfxml_process_cb_list,
1172                        japplication_handler_on_begin_process);
1173
1174   surfxml_add_callback(ETag_surfxml_argument_cb_list,
1175                        japplication_handler_on_process_arg);
1176
1177   surfxml_add_callback(STag_surfxml_prop_cb_list,
1178                        japplication_handler_on_property);
1179
1180   surfxml_add_callback(ETag_surfxml_process_cb_list,
1181                        japplication_handler_on_end_process);
1182
1183   surf_parse_open(deploymentFile);
1184
1185   japplication_handler_on_start_document();
1186
1187   if (surf_parse())
1188     jxbt_throw_jni(env, "surf_parse() failed");
1189
1190   surf_parse_close();
1191
1192   japplication_handler_on_end_document();
1193
1194   (*env)->ReleaseStringUTFChars(env, jdeploymentFile, deploymentFile);
1195 }