Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
0f513d10c217127f539e67b2f784714976a69689
[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           * The PID of the process
81           */
82         protected int pid = -1;
83         /**
84          * The PPID of the process 
85          */
86         protected int ppid = -1;
87         /**
88          * The host of the process
89          */
90         protected Host host = null;
91     /**
92      *
93      * @return
94      */
95     public String msgName() {
96                 return this.name;
97         }
98         /** The arguments of the method function of the process. */     
99         public Vector<String> args;
100
101         /* process synchronization tools */
102     /**
103      *
104      */
105     /**
106      *
107      */
108     protected Sem schedBegin, schedEnd;
109     private boolean nativeStop = false;
110
111         /**
112          * Default constructor (used in ApplicationHandler to initialize it)
113          */
114         protected Process() {
115                 super();
116                 this.id = nextProcessId++;
117                 this.name = null;
118                 this.bind = 0;
119                 this.args = new Vector<String>();
120                 this.properties = null;
121                 schedBegin = new Sem(0);
122                 schedEnd = new Sem(0);
123         }
124
125
126         /**
127          * Constructs a new process from the name of a host and his name. The method
128          * function of the process doesn't have argument.
129          *
130          * @param hostname              The name of the host of the process to create.
131          * @param name                  The name of the process.
132          *
133          * @exception                   HostNotFoundException  if no host with this name exists.
134          *                      
135          *
136          */
137         public Process(String hostname, String name) throws HostNotFoundException {
138                 this(Host.getByName(hostname), name, null);
139         }
140         /**
141          * Constructs a new process from the name of a host and his name. The arguments
142          * of the method function of the process are specified by the parameter args.
143          *
144          * @param hostname              The name of the host of the process to create.
145          * @param name                  The name of the process.
146          * @param args                  The arguments of the main function of the process.
147          *
148          * @exception                   HostNotFoundException  if no host with this name exists.
149      *                      NativeException
150      * @throws NativeException
151          *
152          */ 
153         public Process(String hostname, String name, String args[]) throws HostNotFoundException, NativeException {
154                 this(Host.getByName(hostname), name, args);
155         }
156         /**
157          * Constructs a new process from a host and his name. The method function of the 
158          * process doesn't have argument.
159          *
160          * @param host                  The host of the process to create.
161          * @param name                  The name of the process.
162          *
163          */
164         public Process(Host host, String name) {
165                 this(host, name, null);
166         }
167         /**
168          * Constructs a new process from a host and his name, the arguments of here method function are
169          * specified by the parameter args.
170          *
171          * @param host                  The host of the process to create.
172          * @param name                  The name of the process.
173          * @param args                  The arguments of main method of the process.
174          *
175          */
176         public Process(Host host, String name, String[]args) {
177                 /* This is the constructor called by all others */
178                 this();
179                 
180                 if (name == null)
181                         throw new NullPointerException("Process name cannot be NULL");
182                 this.name = name;
183
184                 this.args = new Vector<String>();
185                 if (null != args)
186                         this.args.addAll(Arrays.asList(args));
187
188                 MsgNative.processCreate(this, host);
189                 
190         }
191
192
193         /**
194          * This method kills all running process of the simulation.
195          *
196          * @param resetPID              Should we reset the PID numbers. A negative number means no reset
197          *                                              and a positive number will be used to set the PID of the next newly
198          *                                              created process.
199          *
200          * @return                              The function returns the PID of the next created process.
201          *                      
202          */ 
203         public static int killAll(int resetPID) {
204                 return MsgNative.processKillAll(resetPID);
205         }
206
207         /**
208          * This method sets a flag to indicate that this thread must be killed. End user must use static method kill
209          *
210          * @return                              
211          *                      
212          */ 
213         public void nativeStop()
214         {
215         nativeStop = true;
216         }
217         /**
218          * getter for the flag that indicates that this thread must be killed
219          *
220          * @return                              
221          *                      
222          */ 
223         public boolean getNativeStop()
224         {
225                 return nativeStop;
226         }
227         /**
228          * 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
229          * 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 
230          * your method. 
231          *
232          * @return                              
233          *                      
234          */ 
235         public static void ifInterruptedStop() {
236           if ( (Thread.currentThread() instanceof Process) &&((Process) Thread.currentThread()).getNativeStop()) {                              
237                         throw new RuntimeException("Interrupted");
238                 }
239         }
240
241
242         /**
243          * This method kill a process.
244          * @param process  the process to be killed.
245          *
246          */
247         public void kill() {
248                  nativeStop();
249                  Msg.info("Process " + msgName() + " will be killed.");                         
250                                  
251         }
252
253         /**
254          * Suspends the process by suspending the task on which it was
255          * waiting for the completion.
256          *
257          */
258         public void pause() {
259                 Process.ifInterruptedStop();
260                 MsgNative.processSuspend(this);
261         }
262         /**
263          * Resumes a suspended process by resuming the task on which it was
264          * waiting for the completion.
265          *
266          *
267          */ 
268         public void restart()  {
269                 Process.ifInterruptedStop();
270                 MsgNative.processResume(this);
271         }
272         /**
273          * Tests if a process is suspended.
274          *
275          * @return                              The method returns true if the process is suspended.
276          *                                              Otherwise the method returns false.
277          */ 
278         public boolean isSuspended() {
279                 Process.ifInterruptedStop();
280                 return MsgNative.processIsSuspended(this);
281         }
282         /**
283          * Returns the host of a process.
284          *
285          * @return                              The host instance of the process.
286          *
287          *
288          */ 
289         public Host getHost() {
290                 Process.ifInterruptedStop();
291                 if (this.host == null) {
292                         this.host = MsgNative.processGetHost(this);
293                 }
294                 return this.host;
295         }
296         /**
297          * This static method gets a process from a PID.
298          *
299          * @param PID                   The process identifier of the process to get.
300          *
301          * @return                              The process with the specified PID.
302          *
303          * @exception                   NativeException on error in the native SimGrid code
304          */ 
305         public static Process fromPID(int PID) throws NativeException {
306                 Process.ifInterruptedStop();
307                 return MsgNative.processFromPID(PID);
308         }
309         /**
310          * This method returns the PID of the process.
311          *
312          * @return                              The PID of the process.
313          *
314          */ 
315         public int getPID()  {
316                 Process.ifInterruptedStop();
317                 if (pid == -1) {
318                         pid = MsgNative.processGetPID(this);
319                 }
320                 return pid;
321         }
322         /**
323          * This method returns the PID of the parent of a process.
324          *
325          * @return                              The PID of the parent of the process.
326          *
327          */ 
328         public int getPPID()  {
329                 Process.ifInterruptedStop();
330                 if (ppid == -1) {
331                         ppid = MsgNative.processGetPPID(this);
332                 }
333                 return ppid;
334         }
335         /**
336          * This static method returns the currently running process.
337          *
338          * @return                              The current process.
339          *
340          */ 
341         public static Process currentProcess()  {
342                 Process.ifInterruptedStop();
343                 return MsgNative.processSelf();
344         }
345         /**
346          * Migrates a process to another host.
347          *
348          * @param process               The process to migrate.
349          * @param host                  The host where to migrate the process.
350          *
351          */
352         public static void migrate(Process process, Host host)  {
353                 Process.ifInterruptedStop();
354                 MsgNative.processMigrate(process, host);
355                 process.host = null;
356         }
357         /**
358          * Makes the current process sleep until time seconds have elapsed.
359          *
360          * @param seconds               The time the current process must sleep.
361          *
362          * @exception                   HostFailureException on error in the native SimGrid code
363          */ 
364         public static void waitFor(double seconds) throws HostFailureException {
365                 Process.ifInterruptedStop();
366                 MsgNative.processWaitFor(seconds);
367         } 
368     /**
369      *
370      */
371     public void showArgs() {
372                 Process.ifInterruptedStop();
373                 Msg.info("[" + this.name + "/" + this.getHost().getName() + "] argc=" +
374                                 this.args.size());
375                 for (int i = 0; i < this.args.size(); i++)
376                         Msg.info("[" + this.msgName() + "/" + this.getHost().getName() +
377                                         "] args[" + i + "]=" + (String) (this.args.get(i)));
378         }
379     /**
380      * Let the simulated process sleep for the given amount of millisecond in the simulated world.
381      * 
382      *  You don't want to use sleep instead, because it would freeze your simulation 
383      *  run without any impact on the simulated world.
384      * @param millis
385      */
386     public native void simulatedSleep(double seconds);
387
388         /**
389          * This method runs the process. Il calls the method function that you must overwrite.
390          */
391         public void run() {
392
393                 String[]args = null;      /* do not fill it before the signal or this.args will be empty */
394
395                 //waitSignal(); /* wait for other people to fill the process in */
396
397
398                 try {
399                         schedBegin.acquire();
400                 } catch(InterruptedException e) {
401                 }
402
403                 try {
404                         args = new String[this.args.size()];
405                         if (this.args.size() > 0) {
406                                 this.args.toArray(args);
407                         }
408
409                         this.main(args);
410                         MsgNative.processExit(this);
411                         schedEnd.release();
412                 } catch(MsgException e) {
413                         e.printStackTrace();
414                         Msg.info("Unexpected behavior. Stopping now");
415                         System.exit(1);
416                 }
417                  catch(RuntimeException re) {
418                         if (nativeStop)                 
419                         {
420                         MsgNative.processExit(this);
421                         Msg.info(" Process " + ((Process) Thread.currentThread()).msgName() + " has been killed.");                                             
422                         schedEnd.release();                     
423                         }
424                         else {
425                         re.printStackTrace();
426                         Msg.info("Unexpected behavior. Stopping now");
427                         System.exit(1);
428                         }
429                 }       
430         }
431
432         /**
433          * The main function of the process (to implement).
434      *
435      * @param args
436      * @throws MsgException
437      */
438         public abstract void main(String[]args) throws MsgException;
439
440
441     /**
442      *
443      */
444     public void unschedule() {
445                 //Process.ifInterruptedStop();
446                 try {
447                         schedEnd.release();
448                         schedBegin.acquire();
449                 } catch (InterruptedException e) {                      
450                 }
451         }
452
453     /**
454      *
455      */
456     public void schedule() {
457            //System.err.println("Scheduling process in Java");
458                 //Process.ifInterruptedStop();
459                 try {
460                         schedBegin.release();
461                         schedEnd.acquire();
462                 } catch(InterruptedException e) {
463                    System.err.println("Got an interuption while scheduling process in Java");
464                    e.printStackTrace();
465                 }
466         }
467
468         /** Send the given task in the mailbox associated with the specified alias  (waiting at most given time) 
469      * @param mailbox
470      * @param task 
471      * @param timeout
472      * @throws TimeoutException
473          * @throws HostFailureException 
474          * @throws TransferFailureException */
475         public void taskSend(String mailbox, Task task, double timeout) throws TransferFailureException, HostFailureException, TimeoutException {
476                 Process.ifInterruptedStop();
477                 MsgNative.taskSend(mailbox, task, timeout);
478         }
479
480         /** Send the given task in the mailbox associated with the specified alias
481      * @param mailbox
482      * @param task
483      * @throws TimeoutException
484          * @throws HostFailureException 
485          * @throws TransferFailureException */
486         public void taskSend(String mailbox, Task task) throws  TransferFailureException, HostFailureException, TimeoutException {
487                 Process.ifInterruptedStop();
488                 MsgNative.taskSend(mailbox, task, -1);
489         }
490
491     /** Receive a task on mailbox associated with the specified mailbox
492      * @param mailbox
493      * @return
494      * @throws TransferFailureException
495      * @throws HostFailureException
496      * @throws TimeoutException
497      */
498         public Task taskReceive(String mailbox) throws TransferFailureException, HostFailureException, TimeoutException {
499                 Process.ifInterruptedStop();
500                 return MsgNative.taskReceive(mailbox, -1.0, null);
501         }
502
503     /** Receive a task on mailbox associated with the specified alias (waiting at most given time)
504      * @param mailbox
505      * @param timeout
506      * @return
507      * @throws TransferFailureException
508      * @throws HostFailureException
509      * @throws TimeoutException
510      */
511         public Task taskReceive(String mailbox, double timeout) throws  TransferFailureException, HostFailureException, TimeoutException {
512                 Process.ifInterruptedStop();
513                 return MsgNative.taskReceive(mailbox, timeout, null);
514         }
515
516     /** Receive a task on mailbox associated with the specified alias from given sender
517      * @param mailbox
518      * @param host
519      * @param timeout
520      * @return
521      * @throws TransferFailureException
522      * @throws HostFailureException
523      * @throws TimeoutException
524      */
525         public Task taskReceive(String mailbox, double timeout, Host host) throws  TransferFailureException, HostFailureException, TimeoutException {
526                 Process.ifInterruptedStop();
527                 return MsgNative.taskReceive(mailbox, timeout, host);
528         }
529
530     /** Receive a task on mailbox associated with the specified alias from given sender
531      * @param mailbox
532      * @param host
533      * @return
534      * @throws TransferFailureException
535      * @throws HostFailureException
536      * @throws TimeoutException
537      */
538         public Task taskReceive(String mailbox, Host host) throws  TransferFailureException, HostFailureException, TimeoutException {
539                 Process.ifInterruptedStop();
540                 return MsgNative.taskReceive(mailbox, -1.0, host);
541         }
542 }