Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Make Process.kill(process) an instance method, not a static one
[simgrid.git] / org / simgrid / msg / Process.java
1 /*
2  * $Id$
3  *
4  * Copyright 2006,2007 Martin Quinson, Malek Cherier           
5  * All right reserved. 
6  *
7  * This program is free software; you can redistribute 
8  * it and/or modify it under the terms of the license 
9  *(GNU LGPL) which comes with this package. 
10  */
11
12 package org.simgrid.msg;
13  
14 import java.util.Arrays;
15 import java.util.Hashtable;
16 import java.util.Vector;
17
18 /**
19  * A process may be defined as a code, with some private data, executing 
20  * in a location (host). All the process used by your simulation must be
21  * declared in the deployment file (XML format).
22  * To create your own process you must inherit your own process from this 
23  * class and override the method "main()". For example if you want to use 
24  * a process named Slave proceed as it :
25  *
26  * (1) import the class Process of the package simgrid.msg
27  * import simgrid.msg.Process;
28  * 
29  * public class Slave extends simgrid.msg.Process {
30  *
31  *  (2) Override the method function
32  * 
33  *  \verbatim
34  *      public void main(String[] args) {
35  *              System.out.println("Hello MSG");
36  *      }
37  *  \endverbatim
38  * }
39  * The name of your process must be declared in the deployment file of your simulation.
40  * For the example, for the previous process Slave this file must contains a line :
41  * <process host="Maxims" function="Slave"/>, where Maxims is the host of the process
42  * Slave. All the process of your simulation are automatically launched and managed by Msg.
43  * A process use tasks to simulate communications or computations with another process. 
44  * For more information see Task. For more information on host concept 
45  * see Host.
46  * 
47  */
48
49 public abstract class Process extends Thread {
50         /**
51          * This attribute represents a bind between a java process object and
52          * a native process. Even if this attribute is public you must never
53          * access to it. It is set automatically during the build of the object.
54          */
55         public long bind;
56
57         /**
58          * Even if this attribute is public you must never access to it.
59          * It is used to compute the id of an MSG process.
60          */
61         public static long nextProcessId = 0;
62
63         /**
64          * Even if this attribute is public you must never access to it.
65          * It is compute automatically during the creation of the object. 
66          * The native functions use this identifier to synchronize the process.
67          */
68         public long id;
69
70     /**
71      *
72      */
73     public Hashtable<String,String> properties;
74
75         /**
76          * The name of the process.                                                     
77          */
78         protected String name;
79     /**
80      *
81      * @return
82      */
83     public String msgName() {
84                 return this.name;
85         }
86         /** The arguments of the method function of the process. */     
87         public Vector<String> args;
88
89         /* process synchronization tools */
90     /**
91      *
92      */
93     /**
94      *
95      */
96     protected Sem schedBegin, schedEnd;
97     private boolean nativeStop = false;
98
99         /**
100          * Default constructor (used in ApplicationHandler to initialize it)
101          */
102         protected Process() {
103                 super();
104                 this.id = nextProcessId++;
105                 this.name = null;
106                 this.bind = 0;
107                 this.args = new Vector<String>();
108                 this.properties = null;
109                 schedBegin = new Sem(0);
110                 schedEnd = new Sem(0);
111         }
112
113
114         /**
115          * Constructs a new process from the name of a host and his name. The method
116          * function of the process doesn't have argument.
117          *
118          * @param hostname              The name of the host of the process to create.
119          * @param name                  The name of the process.
120          *
121          * @exception                   HostNotFoundException  if no host with this name exists.
122          *                      
123          *
124          */
125         public Process(String hostname, String name) throws HostNotFoundException {
126                 this(Host.getByName(hostname), name, null);
127         }
128         /**
129          * Constructs a new process from the name of a host and his name. The arguments
130          * of the method function of the process are specified by the parameter args.
131          *
132          * @param hostname              The name of the host of the process to create.
133          * @param name                  The name of the process.
134          * @param args                  The arguments of the main function of the process.
135          *
136          * @exception                   HostNotFoundException  if no host with this name exists.
137      *                      NativeException
138      * @throws NativeException
139          *
140          */ 
141         public Process(String hostname, String name, String args[]) throws HostNotFoundException, NativeException {
142                 this(Host.getByName(hostname), name, args);
143         }
144         /**
145          * Constructs a new process from a host and his name. The method function of the 
146          * process doesn't have argument.
147          *
148          * @param host                  The host of the process to create.
149          * @param name                  The name of the process.
150          *
151          */
152         public Process(Host host, String name) {
153                 this(host, name, null);
154         }
155         /**
156          * Constructs a new process from a host and his name, the arguments of here method function are
157          * specified by the parameter args.
158          *
159          * @param host                  The host of the process to create.
160          * @param name                  The name of the process.
161          * @param args                  The arguments of main method of the process.
162          *
163          */
164         public Process(Host host, String name, String[]args) {
165                 /* This is the constructor called by all others */
166                 this();
167                 
168                 if (name == null)
169                         throw new NullPointerException("Process name cannot be NULL");
170                 this.name = name;
171
172                 this.args = new Vector<String>();
173                 if (null != args)
174                         this.args.addAll(Arrays.asList(args));
175
176                 MsgNative.processCreate(this, host);
177         }
178
179
180         /**
181          * This method kills all running process of the simulation.
182          *
183          * @param resetPID              Should we reset the PID numbers. A negative number means no reset
184          *                                              and a positive number will be used to set the PID of the next newly
185          *                                              created process.
186          *
187          * @return                              The function returns the PID of the next created process.
188          *                      
189          */ 
190         public static int killAll(int resetPID) {
191                 return MsgNative.processKillAll(resetPID);
192         }
193
194         /**
195          * This method sets a flag to indicate that this thread must be killed. End user must use static method kill
196          *
197          * @return                              
198          *                      
199          */ 
200         public void nativeStop()
201         {
202         nativeStop = true;
203         }
204         /**
205          * getter for the flag that indicates that this thread must be killed
206          *
207          * @return                              
208          *                      
209          */ 
210         public boolean getNativeStop()
211         {
212                 return nativeStop;
213         }
214         /**
215          * checks  if the flag that indicates that this thread must be killed is set to true; if true, starts to kill it. End users should not have to deal with it
216          * If you develop a new MSG native call, please include a call to interruptedStop() at the beginning of your method code, so as the process can be killed if he call 
217          * your method. 
218          *
219          * @return                              
220          *                      
221          */ 
222         public static void ifInterruptedStop() {
223           if ( (Thread.currentThread() instanceof Process) &&((Process) Thread.currentThread()).getNativeStop()) {                              
224                         throw new RuntimeException("Interrupted");
225                 }
226         }
227
228
229         /**
230          * This method kill a process.
231          * @param process  the process to be killed.
232          *
233          */
234         public void kill() {
235                  nativeStop();
236                  Msg.info("Process " + msgName() + " will be killed.");                         
237                                  
238         }
239         /**
240          * This method adds an argument in the list of the arguments of the main function
241          * of the process. 
242          *
243          * @param arg                   The argument to add.
244      *
245      * @deprecated
246      */
247         @Deprecated
248         protected void addArg(String arg) {
249                 args.add(arg);
250         }
251
252         /**
253          * Suspends the process by suspending the task on which it was
254          * waiting for the completion.
255          *
256          */
257         public void pause() {
258                 Process.ifInterruptedStop();
259                 MsgNative.processSuspend(this);
260         }
261         /**
262          * Resumes a suspended process by resuming the task on which it was
263          * waiting for the completion.
264          *
265          *
266          */ 
267         public void restart()  {
268                 Process.ifInterruptedStop();
269                 MsgNative.processResume(this);
270         }
271         /**
272          * Tests if a process is suspended.
273          *
274          * @return                              The method returns true if the process is suspended.
275          *                                              Otherwise the method returns false.
276          */ 
277         public boolean isSuspended() {
278                 Process.ifInterruptedStop();
279                 return MsgNative.processIsSuspended(this);
280         }
281         /**
282          * Returns the host of a process.
283          *
284          * @return                              The host instance of the process.
285          *
286          *
287          */ 
288         public Host getHost() {
289                 Process.ifInterruptedStop();
290                 return MsgNative.processGetHost(this);
291         }
292         /**
293          * This static method gets a process from a PID.
294          *
295          * @param PID                   The process identifier of the process to get.
296          *
297          * @return                              The process with the specified PID.
298          *
299          * @exception                   NativeException on error in the native SimGrid code
300          */ 
301         public static Process fromPID(int PID) throws NativeException {
302                 Process.ifInterruptedStop();
303                 return MsgNative.processFromPID(PID);
304         }
305         /**
306          * This method returns the PID of the process.
307          *
308          * @return                              The PID of the process.
309          *
310          */ 
311         public int getPID()  {
312                 Process.ifInterruptedStop();
313                 return MsgNative.processGetPID(this);
314         }
315         /**
316          * This method returns the PID of the parent of a process.
317          *
318          * @return                              The PID of the parent of the process.
319          *
320          */ 
321         public int getPPID()  {
322                 Process.ifInterruptedStop();
323                 return MsgNative.processGetPPID(this);
324         }
325         /**
326          * This static method returns the currently running process.
327          *
328          * @return                              The current process.
329          *
330          */ 
331         public static Process currentProcess()  {
332                 Process.ifInterruptedStop();
333                 return MsgNative.processSelf();
334         }
335         /**
336          * Migrates a process to another host.
337          *
338          * @param process               The process to migrate.
339          * @param host                  The host where to migrate the process.
340          *
341          */
342         public static void migrate(Process process, Host host)  {
343                 Process.ifInterruptedStop();
344                 MsgNative.processMigrate(process, host);
345         }
346         /**
347          * Makes the current process sleep until time seconds have elapsed.
348          *
349          * @param seconds               The time the current process must sleep.
350          *
351          * @exception                   HostFailureException on error in the native SimGrid code
352          */ 
353         public static void waitFor(double seconds) throws HostFailureException {
354                 Process.ifInterruptedStop();
355                 MsgNative.processWaitFor(seconds);
356         } 
357     /**
358      *
359      */
360     public void showArgs() {
361                 Process.ifInterruptedStop();
362                 Msg.info("[" + this.name + "/" + this.getHost().getName() + "] argc=" +
363                                 this.args.size());
364                 for (int i = 0; i < this.args.size(); i++)
365                         Msg.info("[" + this.msgName() + "/" + this.getHost().getName() +
366                                         "] args[" + i + "]=" + (String) (this.args.get(i)));
367         }
368     /**
369      * Let the simulated process sleep for the given amount of millisecond in the simulated world.
370      * 
371      *  You don't want to use sleep instead, because it would freeze your simulation 
372      *  run without any impact on the simulated world.
373      * @param millis
374      */
375     public native void simulatedSleep(double seconds);
376
377         /**
378          * This method runs the process. Il calls the method function that you must overwrite.
379          */
380         public void run() {
381
382                 String[]args = null;      /* do not fill it before the signal or this.args will be empty */
383
384                 //waitSignal(); /* wait for other people to fill the process in */
385
386
387                 try {
388                         schedBegin.acquire();
389                 } catch(InterruptedException e) {
390                 }
391
392                 try {
393                         args = new String[this.args.size()];
394                         if (this.args.size() > 0) {
395                                 this.args.toArray(args);
396                         }
397
398                         this.main(args);
399                         MsgNative.processExit(this);
400                         schedEnd.release();
401                 } catch(MsgException e) {
402                         e.printStackTrace();
403                         Msg.info("Unexpected behavior. Stopping now");
404                         System.exit(1);
405                 }
406                  catch(RuntimeException re) {
407                         if (nativeStop)                 
408                         {
409                         MsgNative.processExit(this);
410                         Msg.info(" Process " + ((Process) Thread.currentThread()).msgName() + " has been killed.");                                             
411                         schedEnd.release();                     
412                         }
413                         else {
414                         re.printStackTrace();
415                         Msg.info("Unexpected behavior. Stopping now");
416                         System.exit(1);
417                         }
418                 }       
419         }
420
421         /**
422          * The main function of the process (to implement).
423      *
424      * @param args
425      * @throws MsgException
426      */
427         public abstract void main(String[]args) throws MsgException;
428
429
430     /**
431      *
432      */
433     public void unschedule() {
434                 //Process.ifInterruptedStop();
435                 try {
436                         schedEnd.release();
437                         schedBegin.acquire();
438                 } catch (InterruptedException e) {                      
439                 }
440         }
441
442     /**
443      *
444      */
445     public void schedule() {
446            //System.err.println("Scheduling process in Java");
447                 //Process.ifInterruptedStop();
448                 try {
449                         schedBegin.release();
450                         schedEnd.acquire();
451                 } catch(InterruptedException e) {
452                    System.err.println("Got an interuption while scheduling process in Java");
453                    e.printStackTrace();
454                 }
455         }
456
457         /** Send the given task in the mailbox associated with the specified alias  (waiting at most given time) 
458      * @param mailbox
459      * @param task 
460      * @param timeout
461      * @throws TimeoutException
462          * @throws HostFailureException 
463          * @throws TransferFailureException */
464         public void taskSend(String mailbox, Task task, double timeout) throws TransferFailureException, HostFailureException, TimeoutException {
465                 Process.ifInterruptedStop();
466                 MsgNative.taskSend(mailbox, task, timeout);
467         }
468
469         /** Send the given task in the mailbox associated with the specified alias
470      * @param mailbox
471      * @param task
472      * @throws TimeoutException
473          * @throws HostFailureException 
474          * @throws TransferFailureException */
475         public void taskSend(String mailbox, Task task) throws  TransferFailureException, HostFailureException, TimeoutException {
476                 Process.ifInterruptedStop();
477                 MsgNative.taskSend(mailbox, task, -1);
478         }
479
480     /** Receive a task on mailbox associated with the specified mailbox
481      * @param mailbox
482      * @return
483      * @throws TransferFailureException
484      * @throws HostFailureException
485      * @throws TimeoutException
486      */
487         public Task taskReceive(String mailbox) throws TransferFailureException, HostFailureException, TimeoutException {
488                 Process.ifInterruptedStop();
489                 return MsgNative.taskReceive(mailbox, -1.0, null);
490         }
491
492     /** Receive a task on mailbox associated with the specified alias (waiting at most given time)
493      * @param mailbox
494      * @param timeout
495      * @return
496      * @throws TransferFailureException
497      * @throws HostFailureException
498      * @throws TimeoutException
499      */
500         public Task taskReceive(String mailbox, double timeout) throws  TransferFailureException, HostFailureException, TimeoutException {
501                 Process.ifInterruptedStop();
502                 return MsgNative.taskReceive(mailbox, timeout, null);
503         }
504
505     /** Receive a task on mailbox associated with the specified alias from given sender
506      * @param mailbox
507      * @param host
508      * @param timeout
509      * @return
510      * @throws TransferFailureException
511      * @throws HostFailureException
512      * @throws TimeoutException
513      */
514         public Task taskReceive(String mailbox, double timeout, Host host) throws  TransferFailureException, HostFailureException, TimeoutException {
515                 Process.ifInterruptedStop();
516                 return MsgNative.taskReceive(mailbox, timeout, host);
517         }
518
519     /** Receive a task on mailbox associated with the specified alias from given sender
520      * @param mailbox
521      * @param host
522      * @return
523      * @throws TransferFailureException
524      * @throws HostFailureException
525      * @throws TimeoutException
526      */
527         public Task taskReceive(String mailbox, Host host) throws  TransferFailureException, HostFailureException, TimeoutException {
528                 Process.ifInterruptedStop();
529                 return MsgNative.taskReceive(mailbox, -1.0, host);
530         }
531 }