Logo AND Algorithmique Numérique Distribuée

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