Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Stop using SIMGRID_ROOT at compile time, use SIMGRID_LIB/INCLUDE instead
[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 static void kill(Process process) {
235                  process.nativeStop();
236                  Msg.info("Process " + 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          * This method runs the process. Il calls the method function that you must overwrite.
370          */
371         public void run() {
372
373                 String[]args = null;      /* do not fill it before the signal or this.args will be empty */
374
375                 //waitSignal(); /* wait for other people to fill the process in */
376
377
378                 try {
379                         schedBegin.acquire();
380                 } catch(InterruptedException e) {
381                 }
382
383                 try {
384                         args = new String[this.args.size()];
385                         if (this.args.size() > 0) {
386                                 this.args.toArray(args);
387                         }
388
389                         this.main(args);
390                         MsgNative.processExit(this);
391                         schedEnd.release();
392                 } catch(MsgException e) {
393                         e.printStackTrace();
394                         Msg.info("Unexpected behavior. Stopping now");
395                         System.exit(1);
396                 }
397                  catch(RuntimeException re) {
398                         if (nativeStop)                 
399                         {
400                         MsgNative.processExit(this);
401                         Msg.info(" Process " + ((Process) Thread.currentThread()).msgName() + " has been killed.");                                             
402                         schedEnd.release();                     
403                         }
404                         else {
405                         re.printStackTrace();
406                         Msg.info("Unexpected behavior. Stopping now");
407                         System.exit(1);
408                         }
409                 }       
410         }
411
412         /**
413          * The main function of the process (to implement).
414      *
415      * @param args
416      * @throws MsgException
417      */
418         public abstract void main(String[]args) throws MsgException;
419
420
421     /**
422      *
423      */
424     public void unschedule() {
425                 //Process.ifInterruptedStop();
426                 try {
427                         schedEnd.release();
428                         schedBegin.acquire();
429                 } catch (InterruptedException e) {                      
430                 }
431         }
432
433     /**
434      *
435      */
436     public void schedule() {
437            //System.err.println("Scheduling process in Java");
438                 //Process.ifInterruptedStop();
439                 try {
440                         schedBegin.release();
441                         schedEnd.acquire();
442                 } catch(InterruptedException e) {
443                    System.err.println("Got an interuption while scheduling process in Java");
444                    e.printStackTrace();
445                 }
446         }
447
448         /** Send the given task in the mailbox associated with the specified alias  (waiting at most given time) 
449      * @param mailbox
450      * @param task 
451      * @param timeout
452      * @throws TimeoutException
453          * @throws HostFailureException 
454          * @throws TransferFailureException */
455         public void taskSend(String mailbox, Task task, double timeout) throws TransferFailureException, HostFailureException, TimeoutException {
456                 Process.ifInterruptedStop();
457                 MsgNative.taskSend(mailbox, task, timeout);
458         }
459
460         /** Send the given task in the mailbox associated with the specified alias
461      * @param mailbox
462      * @param task
463      * @throws TimeoutException
464          * @throws HostFailureException 
465          * @throws TransferFailureException */
466         public void taskSend(String mailbox, Task task) throws  TransferFailureException, HostFailureException, TimeoutException {
467                 Process.ifInterruptedStop();
468                 MsgNative.taskSend(mailbox, task, -1);
469         }
470
471     /** Receive a task on mailbox associated with the specified mailbox
472      * @param mailbox
473      * @return
474      * @throws TransferFailureException
475      * @throws HostFailureException
476      * @throws TimeoutException
477      */
478         public Task taskReceive(String mailbox) throws TransferFailureException, HostFailureException, TimeoutException {
479                 Process.ifInterruptedStop();
480                 return MsgNative.taskReceive(mailbox, -1.0, null);
481         }
482
483     /** Receive a task on mailbox associated with the specified alias (waiting at most given time)
484      * @param mailbox
485      * @param timeout
486      * @return
487      * @throws TransferFailureException
488      * @throws HostFailureException
489      * @throws TimeoutException
490      */
491         public Task taskReceive(String mailbox, double timeout) throws  TransferFailureException, HostFailureException, TimeoutException {
492                 Process.ifInterruptedStop();
493                 return MsgNative.taskReceive(mailbox, timeout, null);
494         }
495
496     /** Receive a task on mailbox associated with the specified alias from given sender
497      * @param mailbox
498      * @param host
499      * @param timeout
500      * @return
501      * @throws TransferFailureException
502      * @throws HostFailureException
503      * @throws TimeoutException
504      */
505         public Task taskReceive(String mailbox, double timeout, Host host) throws  TransferFailureException, HostFailureException, TimeoutException {
506                 Process.ifInterruptedStop();
507                 return MsgNative.taskReceive(mailbox, timeout, host);
508         }
509
510     /** Receive a task on mailbox associated with the specified alias from given sender
511      * @param mailbox
512      * @param host
513      * @return
514      * @throws TransferFailureException
515      * @throws HostFailureException
516      * @throws TimeoutException
517      */
518         public Task taskReceive(String mailbox, Host host) throws  TransferFailureException, HostFailureException, TimeoutException {
519                 Process.ifInterruptedStop();
520                 return MsgNative.taskReceive(mailbox, -1.0, host);
521         }
522 }