Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
cf6962fb5e91e103fc47d62df7846ea5b058de03
[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   if (process == NULL) {
251         jxbt_throw_illegal(env,bprintf("Tried to get the sender of a task that hasn't been sent yet."));
252         return NULL;
253   }
254   return (jobject) native_to_java_process(process);
255 }
256
257 JNIEXPORT jobject JNICALL
258 Java_org_simgrid_msg_Task_getSource(JNIEnv * env,
259                                          jobject jtask)
260 {
261   m_host_t host;
262   m_task_t task = jtask_to_native_task(jtask, env);
263
264   if (!task) {
265     jxbt_throw_notbound(env, "task", jtask);
266     return NULL;
267   }
268
269   host = MSG_task_get_source(task);
270   if (host == NULL) {
271         jxbt_throw_illegal(env,bprintf("Tried to get the source of a task that hasn't been sent yet."));
272         return NULL;
273   }
274   if (!MSG_host_get_data(host)) {
275     jxbt_throw_jni(env, "MSG_task_get_source() failed");
276     return NULL;
277   }
278
279   return (jobject) MSG_host_get_data(host);
280 }
281
282 JNIEXPORT jdouble JNICALL
283 Java_org_simgrid_msg_Task_getComputeDuration(JNIEnv * env,
284                                                   jobject jtask)
285 {
286   m_task_t ptask = jtask_to_native_task(jtask, env);
287
288   if (!ptask) {
289     jxbt_throw_notbound(env, "task", jtask);
290     return -1;
291   }
292   return (jdouble) MSG_task_get_compute_duration(ptask);
293 }
294
295 JNIEXPORT jdouble JNICALL
296 Java_org_simgrid_msg_Task_getRemainingDuration(JNIEnv * env, jobject jtask)
297 {
298   m_task_t ptask = jtask_to_native_task(jtask, env);
299
300   if (!ptask) {
301     jxbt_throw_notbound(env, "task", jtask);
302     return -1;
303   }
304   return (jdouble) MSG_task_get_remaining_computation(ptask);
305 }
306
307 JNIEXPORT void JNICALL
308 Java_org_simgrid_msg_Task_setPriority(JNIEnv * env,
309                                            jobject jtask, jdouble priority)
310 {
311   m_task_t task = jtask_to_native_task(jtask, env);
312
313   if (!task) {
314     jxbt_throw_notbound(env, "task", jtask);
315     return;
316   }
317   MSG_task_set_priority(task, (double) priority);
318 }
319 JNIEXPORT void JNICALL
320 Java_org_simgrid_msg_Task_send(JNIEnv * env,jobject jtask,
321                                     jstring jalias,
322                                     jdouble jtimeout)
323 {
324   MSG_error_t rv;
325   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
326
327   m_task_t task = jtask_to_native_task(jtask, env);
328
329
330   if (!task) {
331     (*env)->ReleaseStringUTFChars(env, jalias, alias);
332     jxbt_throw_notbound(env, "task", jtask);
333     return;
334   }
335
336   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
337   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
338   rv = MSG_task_send_with_timeout(task, alias, (double) jtimeout);
339
340   (*env)->ReleaseStringUTFChars(env, jalias, alias);
341
342   jxbt_check_res("MSG_task_send_with_timeout()", rv,
343                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
344                  bprintf("while sending task %s to mailbox %s",
345                          MSG_task_get_name(task), alias));
346 }
347
348 JNIEXPORT void JNICALL
349 Java_org_simgrid_msg_Task_sendBounded(JNIEnv * env, jobject jtask,
350                                            jstring jalias,
351                                            jdouble jmaxRate)
352 {
353   m_task_t task = jtask_to_native_task(jtask, env);
354   MSG_error_t rv;
355   const char *alias;
356
357   if (!task) {
358     jxbt_throw_notbound(env, "task", jtask);
359     return;
360   }
361
362   alias = (*env)->GetStringUTFChars(env, jalias, 0);
363
364   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
365   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
366   rv = MSG_task_send_bounded(task, alias, (double) jmaxRate);
367
368   (*env)->ReleaseStringUTFChars(env, jalias, alias);
369
370   jxbt_check_res("MSG_task_send_bounded()", rv,
371                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
372                  bprintf
373                  ("while sending task %s to mailbox %s with max rate %f",
374                   MSG_task_get_name(task), alias, (double) jmaxRate));
375
376 }
377
378
379 JNIEXPORT jobject JNICALL
380 Java_org_simgrid_msg_Task_receive(JNIEnv * env, jclass cls,
381                                        jstring jalias, jdouble jtimeout,
382                                        jobject jhost)
383 {
384   MSG_error_t rv;
385   m_task_t task = NULL;
386   m_host_t host = NULL;
387   jobject jtask_global, jtask_local;
388   const char *alias;
389
390   if (jhost) {
391     host = jhost_get_native(env, jhost);
392
393     if (!host) {
394       jxbt_throw_notbound(env, "host", jhost);
395       return NULL;
396     }
397   }
398
399   alias = (*env)->GetStringUTFChars(env, jalias, 0);
400
401   rv = MSG_task_receive_ext(&task, alias, (double) jtimeout, host);
402   if (rv != MSG_OK) {
403         switch (rv) {
404                 case MSG_TIMEOUT:
405                         jxbt_throw_time_out_failure(env,NULL);
406                 break;
407                 case MSG_TRANSFER_FAILURE:
408                         jxbt_throw_transfer_failure(env,NULL);
409                 break;
410                 case MSG_HOST_FAILURE:
411                         jxbt_throw_host_failure(env,NULL);
412                 break;
413                 default:
414                         jxbt_throw_native(env,bprintf("receive failed"));
415         }
416         return NULL;
417   }
418   jtask_global = MSG_task_get_data(task);
419
420   /* Convert the global ref into a local ref so that the JVM can free the stuff */
421   jtask_local = (*env)->NewLocalRef(env, jtask_global);
422   (*env)->DeleteGlobalRef(env, jtask_global);
423   MSG_task_set_data(task, NULL);
424
425   (*env)->ReleaseStringUTFChars(env, jalias, alias);
426
427   jxbt_check_res("MSG_task_receive_ext()", rv,
428                  MSG_HOST_FAILURE | MSG_TRANSFER_FAILURE | MSG_TIMEOUT,
429                  bprintf("while receiving from mailbox %s", alias));
430
431   return (jobject) jtask_local;
432 }
433
434
435 JNIEXPORT jobject JNICALL
436 Java_org_simgrid_msg_Task_irecv(JNIEnv * env, jclass cls, jstring jmailbox) {
437         msg_comm_t comm;
438         const char *mailbox;
439         jclass comm_class;
440         //pointer to store the task object pointer.
441         m_task_t *task = xbt_new(m_task_t,1);
442         *task = NULL;
443         /* There should be a cache here */
444         comm_class = (*env)->FindClass(env, "org/simgrid/msg/Comm");
445
446         if (!comm_class) {
447                 jxbt_throw_native(env,bprintf("fieldID or methodID or class not found."));
448                 return NULL;
449         }
450
451         jobject jcomm = (*env)->NewObject(env, comm_class, jtask_field_Comm_constructor);
452         if (!jcomm) {
453                 jxbt_throw_native(env,bprintf("Can't create a Comm object."));
454                 return NULL;
455         }
456
457         mailbox = (*env)->GetStringUTFChars(env, jmailbox, 0);
458
459         comm = MSG_task_irecv(task,mailbox);
460
461         (*env)->SetLongField(env, jcomm, jtask_field_Comm_bind, (jlong) (long)(comm));
462         (*env)->SetLongField(env, jcomm, jtask_field_Comm_taskBind, (jlong) (long)(task));
463         (*env)->SetBooleanField(env, jcomm, jtask_field_Comm_receiving, JNI_TRUE);
464
465         (*env)->ReleaseStringUTFChars(env, jmailbox, mailbox);
466
467         return jcomm;
468 }
469
470 JNIEXPORT jobject JNICALL
471 Java_org_simgrid_msg_Task_isend(JNIEnv *env, jobject jtask, jstring jmailbox) {
472         jclass comm_class;
473
474         const char *mailbox;
475
476         m_task_t task;
477
478         jobject jcomm;
479         msg_comm_t comm;
480
481         comm_class = (*env)->FindClass(env, "org/simgrid/msg/Comm");
482
483         if (!comm_class) return NULL;
484
485         jcomm = (*env)->NewObject(env, comm_class, jtask_field_Comm_constructor);
486         mailbox = (*env)->GetStringUTFChars(env, jmailbox, 0);
487
488         task = jtask_to_native_task(jtask, env);
489
490         if (!task) {
491     (*env)->ReleaseStringUTFChars(env, jmailbox, mailbox);
492     (*env)->DeleteLocalRef(env, jcomm);
493     jxbt_throw_notbound(env, "task", jtask);
494                 return NULL;
495         }
496
497   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
498         comm = MSG_task_isend(task,mailbox);
499
500         (*env)->SetLongField(env, jcomm, jtask_field_Comm_bind, (jlong) (long)(comm));
501         (*env)->SetLongField(env, jcomm, jtask_field_Comm_taskBind, (jlong) (long)(NULL));
502         (*env)->SetBooleanField(env, jcomm, jtask_field_Comm_receiving, JNI_FALSE);
503
504         (*env)->ReleaseStringUTFChars(env, jmailbox, mailbox);
505
506         return jcomm;
507 }
508
509 static void msg_task_cancel_on_failed_dsend(void*t) {
510         m_task_t task = t;
511         JNIEnv *env =get_current_thread_env();
512         jobject jtask_global = MSG_task_get_data(task);
513
514         /* Destroy the global ref so that the JVM can free the stuff */
515         (*env)->DeleteGlobalRef(env, jtask_global);
516         MSG_task_set_data(task, NULL);
517         MSG_task_destroy(task);
518 }
519
520 JNIEXPORT void JNICALL
521 Java_org_simgrid_msg_Task_dsend(JNIEnv * env, jobject jtask,
522                                 jstring jalias) {
523
524   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
525
526   m_task_t task = jtask_to_native_task(jtask, env);
527
528
529   if (!task) {
530     (*env)->ReleaseStringUTFChars(env, jalias, alias);
531     jxbt_throw_notbound(env, "task", jtask);
532     return;
533   }
534
535   /* Pass a global ref to the Jtask into the Ctask so that the receiver can use it */
536   MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
537   MSG_task_dsend(task, alias, msg_task_cancel_on_failed_dsend);
538
539   (*env)->ReleaseStringUTFChars(env, jalias, alias);
540 }
541
542 JNIEXPORT jboolean JNICALL
543 Java_org_simgrid_msg_Task_listen(JNIEnv * env, jclass cls,
544                                                                                                            jstring jalias) {
545
546   const char *alias;
547   int rv;
548
549   alias = (*env)->GetStringUTFChars(env, jalias, 0);
550
551   rv = MSG_task_listen(alias);
552
553   (*env)->ReleaseStringUTFChars(env, jalias, alias);
554
555   return (jboolean) rv;
556 }
557
558 JNIEXPORT jint JNICALL
559 Java_org_simgrid_msg_Task_listenFromHost(JNIEnv * env, jclass cls,
560                                                                                                                                            jstring jalias,
561                                                                                                                                            jobject jhost) {
562   int rv;
563   const char *alias;
564
565   m_host_t host = jhost_get_native(env, jhost);
566
567   if (!host) {
568     jxbt_throw_notbound(env, "host", jhost);
569     return -1;
570   }
571   alias = (*env)->GetStringUTFChars(env, jalias, 0);
572
573   rv = MSG_task_listen_from_host(alias, host);
574
575   (*env)->ReleaseStringUTFChars(env, jalias, alias);
576
577   return (jint) rv;
578 }
579
580
581 JNIEXPORT jint JNICALL
582 Java_org_simgrid_msg_Task_listenFrom(JNIEnv * env, jclass cls,
583                                                         jstring jalias) {
584
585   int rv;
586   const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
587
588   rv = MSG_task_listen_from(alias);
589
590   (*env)->ReleaseStringUTFChars(env, jalias, alias);
591
592   return (jint) rv;
593 }