Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
63c44a5e35caf676335199301a48330e923241e2
[simgrid.git] / src / bindings / java / jmsg_process.cpp
1 /* Functions related to the java process instances.                         */
2
3 /* Copyright (c) 2007-2017. The SimGrid Team. All rights reserved.          */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include <xbt/ex.hpp>
9
10 #include "jmsg_process.h"
11
12 #include "jmsg.h"
13 #include "jmsg_host.h"
14 #include "jxbt_utilities.h"
15 #include "JavaContext.hpp"
16
17 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(jmsg);
18
19 SG_BEGIN_DECL()
20
21 jfieldID jprocess_field_Process_bind;
22 jfieldID jprocess_field_Process_host;
23 jfieldID jprocess_field_Process_killTime;
24 jfieldID jprocess_field_Process_name;
25 jfieldID jprocess_field_Process_pid;
26 jfieldID jprocess_field_Process_ppid;
27
28 jobject jprocess_from_native(msg_process_t process)
29 {
30   simgrid::kernel::context::JavaContext* context = (simgrid::kernel::context::JavaContext*) MSG_process_get_smx_ctx(process);
31   return context->jprocess;
32 }
33
34 jobject jprocess_ref(jobject jprocess, JNIEnv* env)
35 {
36   return env->NewGlobalRef(jprocess);
37 }
38
39 void jprocess_unref(jobject jprocess, JNIEnv* env)
40 {
41   env->DeleteGlobalRef(jprocess);
42 }
43
44 msg_process_t jprocess_to_native(jobject jprocess, JNIEnv* env)
45 {
46   return (msg_process_t)(intptr_t)env->GetLongField(jprocess, jprocess_field_Process_bind);
47 }
48
49 void jprocess_bind(jobject jprocess, msg_process_t process, JNIEnv * env)
50 {
51   env->SetLongField(jprocess, jprocess_field_Process_bind, (intptr_t)process);
52 }
53
54 jstring jprocess_get_name(jobject jprocess, JNIEnv * env)
55 {
56   jstring jname = (jstring) env->GetObjectField(jprocess, jprocess_field_Process_name);
57   return (jstring) env->NewGlobalRef(jname);
58 }
59
60 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_nativeInit(JNIEnv *env, jclass cls) {
61   jclass jprocess_class_Process = env->FindClass("org/simgrid/msg/Process");
62   xbt_assert(jprocess_class_Process, "Native initialization of msg/Process failed. Please report that bug");
63
64   jprocess_field_Process_name = jxbt_get_jfield(env, jprocess_class_Process, "name", "Ljava/lang/String;");
65   jprocess_field_Process_bind = jxbt_get_jfield(env, jprocess_class_Process, "bind", "J");
66   jprocess_field_Process_pid = jxbt_get_jfield(env, jprocess_class_Process, "pid", "I");
67   jprocess_field_Process_ppid = jxbt_get_jfield(env, jprocess_class_Process, "ppid", "I");
68   jprocess_field_Process_host = jxbt_get_jfield(env, jprocess_class_Process, "host", "Lorg/simgrid/msg/Host;");
69   jprocess_field_Process_killTime = jxbt_get_jfield(env, jprocess_class_Process, "killTime", "D");
70   xbt_assert(jprocess_field_Process_name && jprocess_field_Process_pid && jprocess_field_Process_ppid &&
71                  jprocess_field_Process_host,
72              "Native initialization of msg/Process failed. Please report that bug");
73 }
74
75 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_create(JNIEnv * env, jobject jprocess_arg, jobject jhostname)
76 {
77   jobject jprocess;             /* the global reference to the java process instance    */
78   jstring jname;                /* the name of the java process instance                */
79   const char *name;             /* the C name of the process                            */
80   const char *hostname;
81   msg_process_t process;          /* the native process to create                         */
82   msg_host_t host;                /* Where that process lives */
83
84   hostname = env->GetStringUTFChars((jstring) jhostname, 0);
85
86   /* get the name of the java process */
87   jname = jprocess_get_name(jprocess_arg, env);
88   if (!jname) {
89     jxbt_throw_null(env,
90             xbt_strdup("Internal error: Process name cannot be nullptr"));
91     return;
92   }
93
94   /* bind/retrieve the msg host */
95   host = MSG_host_by_name(hostname);
96
97   if (!(host)) {    /* not bound */
98     jxbt_throw_host_not_found(env, hostname);
99     return;
100   }
101
102   /* create a global java process instance */
103   jprocess = jprocess_ref(jprocess_arg, env);
104   if (!jprocess) {
105     jxbt_throw_jni(env, "Can't get a global ref to the java process");
106     return;
107   }
108
109   /* build the C name of the process */
110   name = env->GetStringUTFChars(jname, 0);
111   name = xbt_strdup(name);
112
113   /* Retrieve the kill time from the process */
114   jdouble jkill = env->GetDoubleField(jprocess, jprocess_field_Process_killTime);
115   /* Actually build the MSG process */
116   process = MSG_process_create_with_environment(name, [](int argc, char** argv) -> int {
117               smx_actor_t process = SIMIX_process_self();
118               // This is the jprocess passed as environment.
119               // It would be simplet if we could use a closure.
120               jobject jprocess = (jobject) MSG_process_get_data(process);
121               simgrid::kernel::context::java_main_jprocess(jprocess);
122               return 0;
123             }, jprocess,
124             host,
125             /*argc, argv, properties*/
126             0, nullptr, nullptr);
127   MSG_process_set_kill_time(process, (double)jkill);
128   /* bind the java process instance to the native process */
129   jprocess_bind(jprocess, process, env);
130
131   /* release our reference to the process name (variable name becomes invalid) */
132   //FIXME : This line should be uncommented but with mac it doesn't work. BIG WARNING
133   //env->ReleaseStringUTFChars(jname, name);
134   env->ReleaseStringUTFChars((jstring) jhostname, hostname);
135
136   /* sets the PID and the PPID of the process */
137   env->SetIntField(jprocess, jprocess_field_Process_pid,(jint) MSG_process_get_PID(process));
138   env->SetIntField(jprocess, jprocess_field_Process_ppid, (jint) MSG_process_get_PPID(process));
139   /* sets the Host of the process */
140   jobject jhost = Java_org_simgrid_msg_Host_getByName(env,nullptr, (jstring)jhostname);
141
142   env->SetObjectField(jprocess, jprocess_field_Process_host, jhost);
143 }
144
145 JNIEXPORT jint JNICALL Java_org_simgrid_msg_Process_killAll(JNIEnv * env, jclass cls, jint jresetPID)
146 {
147   return (jint) MSG_process_killall((int) jresetPID);
148 }
149
150 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Process_fromPID(JNIEnv * env, jclass cls, jint pid)
151 {
152   msg_process_t process = MSG_process_from_PID(pid);
153
154   if (!process) {
155     jxbt_throw_process_not_found(env, bprintf("PID = %d",static_cast<int>(pid)));
156     return nullptr;
157   }
158
159   jobject jprocess = jprocess_from_native(process);
160
161   if (!jprocess) {
162     jxbt_throw_jni(env, "get process failed");
163     return nullptr;
164   }
165
166   return jprocess;
167 }
168
169 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Process_getProperty(JNIEnv *env, jobject jprocess, jobject jname) {
170   msg_process_t process = jprocess_to_native(jprocess, env);
171
172   if (!process) {
173     jxbt_throw_notbound(env, "process", jprocess);
174     return nullptr;
175   }
176   const char *name = env->GetStringUTFChars((jstring)jname, 0);
177
178   const char *property = MSG_process_get_property_value(process, name);
179   if (!property) {
180     return nullptr;
181   }
182
183   jobject jproperty = env->NewStringUTF(property);
184
185   env->ReleaseStringUTFChars((jstring)jname, name);
186
187   return jproperty;
188 }
189
190 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Process_getCurrentProcess(JNIEnv * env, jclass cls)
191 {
192   msg_process_t process = MSG_process_self();
193   jobject jprocess;
194
195   if (!process) {
196     jxbt_throw_jni(env, xbt_strdup("MSG_process_self() failed"));
197     return nullptr;
198   }
199
200   jprocess = jprocess_from_native(process);
201
202   if (!jprocess)
203     jxbt_throw_jni(env, xbt_strdup("SIMIX_process_get_jprocess() failed"));
204
205   return jprocess;
206 }
207
208 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_suspend(JNIEnv * env, jobject jprocess)
209 {
210   msg_process_t process = jprocess_to_native(jprocess, env);
211
212   if (!process) {
213     jxbt_throw_notbound(env, "process", jprocess);
214     return;
215   }
216
217   /* try to suspend the process */
218   msg_error_t rv = MSG_process_suspend(process);
219
220   jxbt_check_res("MSG_process_suspend()", rv, MSG_OK, bprintf("unexpected error , please report this bug"));
221 }
222
223 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_resume(JNIEnv * env, jobject jprocess)
224 {
225   msg_process_t process = jprocess_to_native(jprocess, env);
226
227   if (!process) {
228     jxbt_throw_notbound(env, "process", jprocess);
229     return;
230   }
231
232   /* try to resume the process */
233   msg_error_t rv = MSG_process_resume(process);
234
235   jxbt_check_res("MSG_process_resume()", rv, MSG_OK, bprintf("unexpected error , please report this bug"));
236 }
237 JNIEXPORT void
238 JNICALL Java_org_simgrid_msg_Process_setAutoRestart (JNIEnv *env, jobject jprocess, jboolean jauto_restart) {
239   msg_process_t process = jprocess_to_native(jprocess, env);
240   xbt_ex_t e;
241
242   int auto_restart = jauto_restart == JNI_TRUE ? 1 : 0;
243
244   if (!process) {
245     jxbt_throw_notbound(env, "process", jprocess);
246     return;
247   }
248
249   try {
250     MSG_process_auto_restart_set(process,auto_restart);
251   }
252   catch (xbt_ex& e) {
253     // Nothing to do
254   }
255 }
256
257 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_restart (JNIEnv *env, jobject jprocess) {
258   msg_process_t process = jprocess_to_native(jprocess, env);
259   xbt_ex_t e;
260
261   if (!process) {
262     jxbt_throw_notbound(env, "process", jprocess);
263     return;
264   }
265
266   try {
267     MSG_process_restart(process);
268   }
269   catch (xbt_ex& e) {
270     // Nothing to do
271   }
272
273 }
274 JNIEXPORT jboolean JNICALL Java_org_simgrid_msg_Process_isSuspended(JNIEnv * env, jobject jprocess)
275 {
276   msg_process_t process = jprocess_to_native(jprocess, env);
277
278   if (!process) {
279     jxbt_throw_notbound(env, "process", jprocess);
280     return 0;
281   }
282
283   /* true is the process is suspended, false otherwise */
284   return (jboolean) MSG_process_is_suspended(process);
285 }
286
287 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_sleep(JNIEnv *env, jclass cls, jlong jmillis, jint jnanos)
288  {
289   double time =  ((double)jmillis) / 1000 + ((double)jnanos) / 1000000000;
290   msg_error_t rv;
291   rv = MSG_process_sleep(time);
292   if (rv != MSG_OK) {
293     XBT_DEBUG("Something during the MSG_process_sleep invocation was wrong, trigger a HostFailureException");
294
295     //jmsg_throw_status(env,rv);
296
297     // adsein, the code above as been replaced by the code below. Indeed, according to the documentation, a sleep can only
298     // trigger a host_failure exception. When the sleep crashes due to a host shutdown, the exception thrown by smx_context_java.c
299     // is a cancelled_error, see bindings/java/smx_context_java.c, function void smx_ctx_java_stop(smx_context_t context) and src/msg/msg_gos.c
300     // function  msg_error_t MSG_process_sleep(double nb_sec)
301
302     jxbt_throw_host_failure(env,nullptr);
303   }
304 }
305
306 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_waitFor(JNIEnv * env, jobject jprocess, jdouble jseconds)
307 {
308   msg_error_t rv;
309   rv = MSG_process_sleep((double)jseconds);
310   if (env->ExceptionOccurred())
311     return;
312   if (rv != MSG_OK) {
313     XBT_DEBUG("Status NOK");
314     jmsg_throw_status(env,rv);
315   }
316 }
317
318 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_kill(JNIEnv * env, jobject jprocess)
319 {
320   /* get the native instances from the java ones */
321   msg_process_t process = jprocess_to_native(jprocess, env);
322   if (!process) {
323     jxbt_throw_notbound(env, "process", jprocess);
324     return;
325   }
326
327   try {
328     MSG_process_kill(process);
329   } catch (xbt_ex& ex) {
330     XBT_VERB("This process just killed itself.");
331   }
332 }
333
334 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_migrate(JNIEnv * env, jobject jprocess, jobject jhost)
335 {
336   msg_process_t process = jprocess_to_native(jprocess, env);
337
338   if (!process) {
339     jxbt_throw_notbound(env, "process", jprocess);
340     return;
341   }
342
343   msg_host_t host = jhost_get_native(env, jhost);
344
345   if (!host) {
346     jxbt_throw_notbound(env, "host", jhost);
347     return;
348   }
349
350   /* try to change the host of the process */
351   msg_error_t rv = MSG_process_migrate(process, host);
352   if (rv != MSG_OK) {
353     jmsg_throw_status(env,rv);
354     return;
355   }
356   /* change the host java side */
357   env->SetObjectField(jprocess, jprocess_field_Process_host, jhost);
358 }
359
360 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_yield(JNIEnv* env, jclass cls)
361 {
362   MSG_process_yield();
363 }
364
365 JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_setKillTime (JNIEnv *env , jobject jprocess, jdouble jkilltime) {
366   msg_process_t process = jprocess_to_native(jprocess, env);
367   MSG_process_set_kill_time(process, (double)jkilltime);
368 }
369
370 JNIEXPORT jint JNICALL Java_org_simgrid_msg_Process_getCount(JNIEnv * env, jclass cls) {
371   return (jint) MSG_process_get_number();
372 }
373
374 SG_END_DECL()