Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Check if the fields were found in Task.nativeInit and Comm.nativeInit
[simgrid.git] / src / jmsg_task.c
1 /* Functions related to the java task instances.                            */
2
3 /* Copyright (c) 2007, 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 "jmsg.h"
10
11 #include "smx_context_java.h"
12
13 #include "jmsg_host.h"
14 #include "jmsg_task.h"
15
16 #include "jxbt_utilities.h"
17
18 #include <msg/msg.h>
19 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(jmsg);
20
21 static jmethodID jtask_field_Comm_constructor;
22
23 static jfieldID jtask_field_Task_bind;
24 static jfieldID jtask_field_Comm_bind;
25 static jfieldID jtask_field_Comm_taskBind;
26 static jfieldID jtask_field_Comm_receiving;
27
28 void jtask_bind(jobject jtask, m_task_t task, JNIEnv * env)
29 {
30   (*env)->SetLongField(env, jtask, jtask_field_Task_bind, (jlong) (long) (task));
31 }
32
33 m_task_t jtask_to_native_task(jobject jtask, JNIEnv * env)
34 {
35   return (m_task_t) (long) (*env)->GetLongField(env, jtask, jtask_field_Task_bind);
36 }
37
38 jboolean jtask_is_valid(jobject jtask, JNIEnv * env)
39 {
40   return (*env)->GetLongField(env, jtask, jtask_field_Task_bind) ? JNI_TRUE : JNI_FALSE;
41 }
42
43 JNIEXPORT void JNICALL
44 Java_org_simgrid_msg_Task_nativeInit(JNIEnv *env, jclass cls) {
45         jclass jtask_class_Comm = (*env)->FindClass(env, "org/simgrid/msg/Comm");
46
47         jtask_field_Comm_constructor = (*env)->GetMethodID(env, jtask_class_Comm, "<init>", "()V");
48         //FIXME: Don't use jxbt_get_sfield directly, it is slower.
49         jtask_field_Task_bind = jxbt_get_sfield(env, "org/simgrid/msg/Task", "bind", "J");
50         jtask_field_Comm_bind = jxbt_get_sfield(env, "org/simgrid/msg/Comm", "bind", "J");
51         jtask_field_Comm_taskBind = jxbt_get_sfield(env, "org/simgrid/msg/Comm", "taskBind", "J");
52         jtask_field_Comm_receiving = jxbt_get_sfield(env, "org/simgrid/msg/Comm", "receiving", "Z");
53         if (!jtask_field_Task_bind || !jtask_field_Comm_bind || !jtask_field_Comm_taskBind ||
54                   !jtask_field_Comm_receiving || !jtask_field_Comm_constructor) {
55                         jxbt_throw_native(env,bprintf("Can't find some fields in Java class."));
56                   }
57 }
58
59 JNIEXPORT void JNICALL
60 Java_org_simgrid_msg_Task_create(JNIEnv * env,
61                                       jobject jtask, jstring jname,
62                                       jdouble jcomputeDuration,
63                                       jdouble jmessageSize)
64 {
65   m_task_t task;                /* the native task to create                            */
66   const char *name = NULL;      /* the name of the task                                 */
67
68   if (jcomputeDuration < 0) {
69     jxbt_throw_illegal(env,
70                        bprintf
71                        ("Task ComputeDuration (%f) cannot be negative",
72                         (double) jcomputeDuration));
73     return;
74   }
75
76   if (jmessageSize < 0) {
77     jxbt_throw_illegal(env,
78                        bprintf("Task MessageSize (%f) cannot be negative",
79                                (double) jmessageSize));
80     return;
81   }
82
83   if (jname) {
84     /* get the C string from the java string */
85     name = (*env)->GetStringUTFChars(env, jname, 0);
86   }
87
88
89   /* create the task */
90   task =
91       MSG_task_create(name, (double) jcomputeDuration,
92                       (double) jmessageSize, NULL);
93   if (jname)
94     (*env)->ReleaseStringUTFChars(env, jname, name);
95
96   /* bind & store the task */
97   jtask_bind(jtask, task, env);
98   MSG_task_set_data(task, jtask);
99 }
100
101 JNIEXPORT void JNICALL
102 Java_org_simgrid_msg_Task_parallelCreate(JNIEnv * env,
103                                                jobject jtask,
104                                                jstring jname,
105                                                jobjectArray jhosts,
106                                                jdoubleArray
107                                                jcomputeDurations_arg,
108                                                jdoubleArray
109                                                jmessageSizes_arg) {
110
111   m_task_t task;                /* the native parallel task to create           */
112   const char *name;             /* the name of the task                         */
113   int host_count;
114   m_host_t *hosts;
115   double *computeDurations;
116   double *messageSizes;
117   jdouble *jcomputeDurations;
118   jdouble *jmessageSizes;
119
120   jobject jhost;
121   int index;
122
123
124   if (!jcomputeDurations_arg) {
125     jxbt_throw_null(env,
126                     xbt_strdup
127                     ("Parallel task compute durations cannot be null"));
128     return;
129   }
130
131   if (!jmessageSizes_arg) {
132     jxbt_throw_null(env,
133                     xbt_strdup
134                     ("Parallel task message sizes cannot be null"));
135     return;
136   }
137
138   if (!jname) {
139     jxbt_throw_null(env, xbt_strdup("Parallel task name cannot be null"));
140     return;
141   }
142
143   host_count = (int) (*env)->GetArrayLength(env, jhosts);
144
145
146   hosts = xbt_new0(m_host_t, host_count);
147   computeDurations = xbt_new0(double, host_count);
148   messageSizes = xbt_new0(double, host_count * host_count);
149
150   jcomputeDurations =
151       (*env)->GetDoubleArrayElements(env, jcomputeDurations_arg, 0);
152   jmessageSizes =
153       (*env)->GetDoubleArrayElements(env, jmessageSizes_arg, 0);
154
155   for (index = 0; index < host_count; index++) {
156     jhost = (*env)->GetObjectArrayElement(env, jhosts, index);
157     hosts[index] = jhost_get_native(env, jhost);
158     computeDurations[index] = jcomputeDurations[index];
159   }
160   for (index = 0; index < host_count * host_count; index++) {
161     messageSizes[index] = jmessageSizes[index];
162   }
163
164   (*env)->ReleaseDoubleArrayElements(env, jcomputeDurations_arg,
165                                      jcomputeDurations, 0);
166   (*env)->ReleaseDoubleArrayElements(env, jmessageSizes_arg, jmessageSizes,
167                                      0);
168
169
170   /* get the C string from the java string */
171   name = (*env)->GetStringUTFChars(env, jname, 0);
172
173   task =
174       MSG_parallel_task_create(name, host_count, hosts, computeDurations,
175                                messageSizes, NULL);
176
177   (*env)->ReleaseStringUTFChars(env, jname, name);
178
179   /* associate the java task object and the native task */
180   jtask_bind(jtask, task, env);
181
182   MSG_task_set_data(task, (void *) jtask);
183
184   if (!MSG_task_get_data(task))
185     jxbt_throw_jni(env, "global ref allocation failed");
186 }
187
188 JNIEXPORT void JNICALL
189 Java_org_simgrid_msg_Task_cancel(JNIEnv * env,
190                                       jobject jtask)
191 {
192   m_task_t ptask = jtask_to_native_task(jtask, env);
193
194   if (!ptask) {
195     jxbt_throw_notbound(env, "task", jtask);
196     return;
197   }
198
199   MSG_error_t rv = MSG_task_cancel(ptask);
200
201   jxbt_check_res("MSG_task_cancel()", rv, MSG_OK,
202                  bprintf("unexpected error , please report this bug"));
203 }
204
205 JNIEXPORT void JNICALL
206 Java_org_simgrid_msg_Task_execute(JNIEnv * env,
207                                        jobject jtask)
208 {
209   m_task_t task = jtask_to_native_task(jtask, env);
210
211   if (!task) {
212     jxbt_throw_notbound(env, "task", jtask);
213     return;
214   }
215
216   MSG_error_t rv = MSG_task_execute(task);
217
218   jxbt_check_res("MSG_task_execute()", rv,
219                  MSG_HOST_FAILURE | MSG_TASK_CANCELED,
220                  bprintf("while executing task %s",
221                          MSG_task_get_name(task)));
222 }
223
224 JNIEXPORT jstring JNICALL
225 Java_org_simgrid_msg_Task_getName(JNIEnv * env,
226                                        jobject jtask) {
227   m_task_t task = jtask_to_native_task(jtask, env);
228
229   if (!task) {
230     jxbt_throw_notbound(env, "task", jtask);
231     return NULL;
232   }
233
234   return (*env)->NewStringUTF(env, MSG_task_get_name(task));
235 }
236
237 JNIEXPORT jobject JNICALL
238 Java_org_simgrid_msg_Task_getSender(JNIEnv * env,
239                                          jobject jtask) {
240   m_process_t process;
241
242   m_task_t task = jtask_to_native_task(jtask, env);
243
244   if (!task) {
245     jxbt_throw_notbound(env, "task", jtask);
246     return NULL;
247   }
248
249   process = MSG_task_get_sender(task);
250   return (jobject) native_to_java_process(process);
251 }
252
253 JNIEXPORT jobject JNICALL
254 Java_org_simgrid_msg_Task_getSource(JNIEnv * env,
255                                          jobject jtask)
256 {
257   m_host_t host;
258   m_task_t task = jtask_to_native_task(jtask, env);
259
260   if (!task) {
261     jxbt_throw_notbound(env, "task", jtask);
262     return NULL;
263   }
264
265   host = MSG_task_get_source(task);
266
267   if (!MSG_host_get_data(host)) {
268     jxbt_throw_jni(env, "MSG_task_get_source() failed");
269     return NULL;
270   }
271
272   return (jobject) MSG_host_get_data(host);
273 }
274
275 JNIEXPORT jdouble JNICALL
276 Java_org_simgrid_msg_Task_getComputeDuration(JNIEnv * env,
277                                                   jobject jtask)
278 {
279   m_task_t ptask = jtask_to_native_task(jtask, env);
280
281   if (!ptask) {
282     jxbt_throw_notbound(env, "task", jtask);
283     return -1;
284   }
285   return (jdouble) MSG_task_get_compute_duration(ptask);
286 }
287
288 JNIEXPORT jdouble JNICALL
289 Java_org_simgrid_msg_Task_getRemainingDuration(JNIEnv * env, jobject jtask)
290 {
291   m_task_t ptask = jtask_to_native_task(jtask, env);
292
293   if (!ptask) {
294     jxbt_throw_notbound(env, "task", jtask);
295     return -1;
296   }
297   return (jdouble) MSG_task_get_remaining_computation(ptask);
298 }
299
300 JNIEXPORT void JNICALL
301 Java_org_simgrid_msg_Task_setPriority(JNIEnv * env,
302                                            jobject jtask, jdouble priority)
303 {
304   m_task_t task = jtask_to_native_task(jtask, env);
305
306   if (!task) {
307     jxbt_throw_notbound(env, "task", jtask);
308     return;
309   }
310   MSG_task_set_priority(task, (double) priority);
311 }
312 JNIEXPORT void JNICALL
313 Java_org_simgrid_msg_Task_send(JNIEnv * env,jobject jtask,
314                                     jstring jalias,
315                                     jdouble jtimeout)
316 {
317   MSG_error_t rv;
318   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
319
320   m_task_t task = jtask_to_native_task(jtask, env);
321
322
323   if (!task) {
324     (*env)->ReleaseStringUTFChars(env, jalias, alias);
325     jxbt_throw_notbound(env, "task", jtask);
326     return;
327   }
328
329   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
330   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
331   rv = MSG_task_send_with_timeout(task, alias, (double) jtimeout);
332
333   (*env)->ReleaseStringUTFChars(env, jalias, alias);
334
335   jxbt_check_res("MSG_task_send_with_timeout()", rv,
336                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
337                  bprintf("while sending task %s to mailbox %s",
338                          MSG_task_get_name(task), alias));
339 }
340
341 JNIEXPORT void JNICALL
342 Java_org_simgrid_msg_Task_sendBounded(JNIEnv * env, jobject jtask,
343                                            jstring jalias,
344                                            jdouble jmaxRate)
345 {
346   m_task_t task = jtask_to_native_task(jtask, env);
347   MSG_error_t rv;
348   const char *alias;
349
350   if (!task) {
351     jxbt_throw_notbound(env, "task", jtask);
352     return;
353   }
354
355   alias = (*env)->GetStringUTFChars(env, jalias, 0);
356
357   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
358   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
359   rv = MSG_task_send_bounded(task, alias, (double) jmaxRate);
360
361   (*env)->ReleaseStringUTFChars(env, jalias, alias);
362
363   jxbt_check_res("MSG_task_send_bounded()", rv,
364                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
365                  bprintf
366                  ("while sending task %s to mailbox %s with max rate %f",
367                   MSG_task_get_name(task), alias, (double) jmaxRate));
368
369 }
370
371
372 JNIEXPORT jobject JNICALL
373 Java_org_simgrid_msg_Task_receive(JNIEnv * env, jclass cls,
374                                        jstring jalias, jdouble jtimeout,
375                                        jobject jhost)
376 {
377   MSG_error_t rv;
378   m_task_t task = NULL;
379   m_host_t host = NULL;
380   jobject jtask_global, jtask_local;
381   const char *alias;
382
383   if (jhost) {
384     host = jhost_get_native(env, jhost);
385
386     if (!host) {
387       jxbt_throw_notbound(env, "host", jhost);
388       return NULL;
389     }
390   }
391
392   alias = (*env)->GetStringUTFChars(env, jalias, 0);
393
394   rv = MSG_task_receive_ext(&task, alias, (double) jtimeout, host);
395   if (rv != MSG_OK) {
396         switch (rv) {
397                 case MSG_TIMEOUT:
398                         jxbt_throw_time_out_failure(env,NULL);
399                 break;
400                 case MSG_TRANSFER_FAILURE:
401                         jxbt_throw_transfer_failure(env,NULL);
402                 break;
403                 case MSG_HOST_FAILURE:
404                         jxbt_throw_host_failure(env,NULL);
405                 break;
406                 default:
407                         jxbt_throw_native(env,bprintf("receive failed"));
408         }
409         return NULL;
410   }
411   jtask_global = MSG_task_get_data(task);
412
413   /* Convert the global ref into a local ref so that the JVM can free the stuff */
414   jtask_local = (*env)->NewLocalRef(env, jtask_global);
415   (*env)->DeleteGlobalRef(env, jtask_global);
416   MSG_task_set_data(task, NULL);
417
418   (*env)->ReleaseStringUTFChars(env, jalias, alias);
419
420   jxbt_check_res("MSG_task_receive_ext()", rv,
421                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
422                  bprintf("while receiving from mailbox %s", alias));
423
424   return (jobject) jtask_local;
425 }
426
427
428 JNIEXPORT jobject JNICALL
429 Java_org_simgrid_msg_Task_irecv(JNIEnv * env, jclass cls, jstring jmailbox) {
430         msg_comm_t comm;
431         const char *mailbox;
432         jclass comm_class;
433         //pointer to store the task object pointer.
434         m_task_t *task = xbt_new(m_task_t,1);
435         *task = NULL;
436         /* There should be a cache here */
437         comm_class = (*env)->FindClass(env, "org/simgrid/msg/Comm");
438
439         if (!comm_class) {
440                 jxbt_throw_native(env,bprintf("fieldID or methodID or class not found."));
441                 return NULL;
442         }
443
444         jobject jcomm = (*env)->NewObject(env, comm_class, jtask_field_Comm_constructor);
445         if (!jcomm) {
446                 jxbt_throw_native(env,bprintf("Can't create a Comm object."));
447                 return NULL;
448         }
449
450         mailbox = (*env)->GetStringUTFChars(env, jmailbox, 0);
451
452         comm = MSG_task_irecv(task,mailbox);
453
454         (*env)->SetLongField(env, jcomm, jtask_field_Comm_bind, (jlong) (long)(comm));
455         (*env)->SetLongField(env, jcomm, jtask_field_Comm_taskBind, (jlong) (long)(task));
456         (*env)->SetBooleanField(env, jcomm, jtask_field_Comm_receiving, JNI_TRUE);
457
458         (*env)->ReleaseStringUTFChars(env, jmailbox, mailbox);
459
460         return jcomm;
461 }
462
463 JNIEXPORT jobject JNICALL
464 Java_org_simgrid_msg_Task_isend(JNIEnv *env, jobject jtask, jstring jmailbox) {
465         jclass comm_class;
466
467         const char *mailbox;
468
469         m_task_t task;
470
471         jobject jcomm;
472         msg_comm_t comm;
473
474         comm_class = (*env)->FindClass(env, "org/simgrid/msg/Comm");
475
476         if (!comm_class) return NULL;
477
478         jcomm = (*env)->NewObject(env, comm_class, jtask_field_Comm_constructor);
479         mailbox = (*env)->GetStringUTFChars(env, jmailbox, 0);
480
481         task = jtask_to_native_task(jtask, env);
482
483         if (!task) {
484     (*env)->ReleaseStringUTFChars(env, jmailbox, mailbox);
485     (*env)->DeleteLocalRef(env, jcomm);
486     jxbt_throw_notbound(env, "task", jtask);
487                 return NULL;
488         }
489
490   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
491         comm = MSG_task_isend(task,mailbox);
492
493         (*env)->SetLongField(env, jcomm, jtask_field_Comm_bind, (jlong) (long)(comm));
494         (*env)->SetLongField(env, jcomm, jtask_field_Comm_taskBind, (jlong) (long)(NULL));
495         (*env)->SetBooleanField(env, jcomm, jtask_field_Comm_receiving, JNI_FALSE);
496
497         (*env)->ReleaseStringUTFChars(env, jmailbox, mailbox);
498
499         return jcomm;
500 }
501
502 static void msg_task_cancel_on_failed_dsend(void*t) {
503         m_task_t task = t;
504         JNIEnv *env =get_current_thread_env();
505         jobject jtask_global = MSG_task_get_data(task);
506
507         /* Destroy the global ref so that the JVM can free the stuff */
508         (*env)->DeleteGlobalRef(env, jtask_global);
509         MSG_task_set_data(task, NULL);
510         MSG_task_destroy(task);
511 }
512
513 JNIEXPORT void JNICALL
514 Java_org_simgrid_msg_Task_dsend(JNIEnv * env, jobject jtask,
515                                 jstring jalias) {
516
517   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
518
519   m_task_t task = jtask_to_native_task(jtask, env);
520
521
522   if (!task) {
523     (*env)->ReleaseStringUTFChars(env, jalias, alias);
524     jxbt_throw_notbound(env, "task", jtask);
525     return;
526   }
527
528   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
529   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
530   MSG_task_dsend(task, alias, msg_task_cancel_on_failed_dsend);
531
532   (*env)->ReleaseStringUTFChars(env, jalias, alias);
533 }
534
535 JNIEXPORT jboolean JNICALL
536 Java_org_simgrid_msg_Task_listen(JNIEnv * env, jclass cls,
537                                                                                                            jstring jalias) {
538
539   const char *alias;
540   int rv;
541
542   alias = (*env)->GetStringUTFChars(env, jalias, 0);
543
544   rv = MSG_task_listen(alias);
545
546   (*env)->ReleaseStringUTFChars(env, jalias, alias);
547
548   return (jboolean) rv;
549 }
550
551 JNIEXPORT jint JNICALL
552 Java_org_simgrid_msg_Task_listenFromHost(JNIEnv * env, jclass cls,
553                                                                                                                                            jstring jalias,
554                                                                                                                                            jobject jhost) {
555   int rv;
556   const char *alias;
557
558   m_host_t host = jhost_get_native(env, jhost);
559
560   if (!host) {
561     jxbt_throw_notbound(env, "host", jhost);
562     return -1;
563   }
564   alias = (*env)->GetStringUTFChars(env, jalias, 0);
565
566   rv = MSG_task_listen_from_host(alias, host);
567
568   (*env)->ReleaseStringUTFChars(env, jalias, alias);
569
570   return (jint) rv;
571 }
572
573
574 JNIEXPORT jint JNICALL
575 Java_org_simgrid_msg_Task_listenFrom(JNIEnv * env, jclass cls,
576                                                         jstring jalias) {
577
578   int rv;
579   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
580
581   rv = MSG_task_listen_from(alias);
582
583   (*env)->ReleaseStringUTFChars(env, jalias, alias);
584
585   return (jint) rv;
586 }