KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > dyade > aaa > agent > Driver


1 /*
2  * Copyright (C) 2001 - 2006 ScalAgent Distributed Technologies
3  * Copyright (C) 1996 - 2000 BULL
4  * Copyright (C) 1996 - 2000 INRIA
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA.
20  */

21 package fr.dyade.aaa.agent;
22
23 import java.io.*;
24 import java.util.*;
25 import fr.dyade.aaa.util.*;
26
27 import org.objectweb.util.monolog.api.BasicLevel;
28 import org.objectweb.util.monolog.api.Logger;
29
30 /**
31  * Internal class to catch the end of the thread running the driver.
32  */

33 class ThreadFinalizer implements Runnable JavaDoc {
34
35   /** driver to start */
36   Driver driver;
37
38   /**
39    * Allocates a new daemon for specified driver.
40    *
41    * @param driver driver to start
42    */

43   ThreadFinalizer(Driver driver) {
44     this.driver = driver;
45   }
46
47   /**
48    * Starts the driver. Catches the driver thread termination and calls
49    * the driver <code>end</code> function.
50    */

51   public void run() {
52     try {
53       driver.logmon.log(BasicLevel.DEBUG,
54                         driver.getName() + " start");
55       driver.run();
56       driver.canStop = false;
57     } catch (ThreadDeath JavaDoc death) {
58       // the thread has been killed, prints no error message
59
throw death;
60     } catch (Throwable JavaDoc exc) {
61       driver.canStop = false;
62       driver.logmon.log(BasicLevel.ERROR,
63                         driver.getName() + " failed", exc);
64     } finally {
65       driver.canStop = false;
66       driver.reset();
67       if (!Thread.interrupted()) {
68         driver.logmon.log(BasicLevel.DEBUG, driver.getName() + "end");
69       }
70       driver.end();
71     }
72   }
73 }
74
75
76 /**
77  * Abstract base class for drivers such as <code>DriverIn</code> used by
78  * <code>ProxyAgent</code>.
79  * <p>
80  * Multithreading in the agent server is special, as the code executed
81  * outside of the main engine thread is no longer part of a transaction.
82  * The class <code>Driver</code> has been designed to help programming in
83  * a separate thread in the agent server.
84  * <p>
85  * A key difference between the main thread and a driver thread is the semantics
86  * of sending a notification. When in the main thread of the agent server,
87  * a notification is sent as part of an agent reaction. It is then part of
88  * a transaction, and is actually sent only when the transaction commits.
89  * When in a separate thread, the <code>directSendto</code> function of class
90  * <code>Channel</code> is used instead, actually creating a new transaction
91  * for the single purpose of sending the notification. When the function returns
92  * the notification sending has been committed. The function <code>sendTo</code>
93  * in this class encapsulates the call to the special <code>Channel</code>
94  * function, and should be used by derived classes.
95  * <p>
96  * This class is designed to be derived. Derived classes should define the
97  * function <code>run</code>, providing the actual code to be executed in the
98  * separate thread, and may define the function <code>end</code>, providing
99  * finalizing code executed when the thread terminates. The <code>end</code>
100  * function is always called, even when the <code>run</code> function raises
101  * an exception.
102  */

103 public abstract class Driver {
104
105   /** separate thread running the driver */
106   protected Thread JavaDoc thread;
107   /** identifier local to the driver creator */
108   protected int id;
109   /**
110    * Boolean variable used to stop the driver properly. If this variable is
111    * true then it indicates that the driver is stopping.
112    */

113   public volatile boolean isRunning = false;
114   public volatile boolean canStop = false;
115
116   protected Logger logmon = null;
117   protected String JavaDoc name = null;
118
119   protected static Hashtable drivers = new Hashtable();
120
121   /**
122    * Constructor.
123    *
124    * @param id identifier local to the driver creator
125    */

126   protected Driver(int id) {
127     thread = null;
128     this.id = id;
129     isRunning = true;
130
131     // Get the logging monitor from current server MonologLoggerFactory
132
// It should be overloaded in subclass in order to specialize traces.
133
String JavaDoc classname = getClass().getName();
134     logmon = Debug.getLogger(Debug.A3Proxy + '.' +
135       classname.substring(classname.lastIndexOf('.') +1));
136
137     this.name = classname + '#' + id;
138   }
139
140   /**
141    * Constructor with default id.
142    */

143   protected Driver() {
144     this(0);
145     isRunning =true;
146   }
147
148   /**
149    * Returns name of driver, actually classname and driver id. It should
150    * be overloaded in subclass to take in account the proxy name.
151    */

152   public String JavaDoc getName() {
153     return name;
154   }
155
156   /**
157    * Provides a string image for this object.
158    *
159    * @return printable image of this object
160    */

161   public String JavaDoc toString() {
162     return "(" + getClass().getName() +
163       ",name=" + getName() +
164       ",id=" + id + ")" +
165       ",isRunning=" + isRunning +
166       ",canStop=" + canStop;
167   }
168
169   /**
170    * Actually executes the driver code.
171    * To be defined in derived classes.
172    * <p>
173    * Beware: this code is executed in a separate thread, outside from any
174    * transaction. Notifications may be sent using function <code>sendTo</code>,
175    * and they will actually be sent as soon as the function is called; there is
176    * no atomic treatment as there is in an agent reaction.
177    *
178    * @exception Exception
179    * unspecialized exception
180    */

181   public abstract void run() throws Exception JavaDoc;
182
183   /**
184    * Finalizes driver; called in <code>finally</code> clause of driver thread.
185    * May be overloaded in derived classes.
186    */

187   protected void end() {}
188
189   /**
190    * Starts the driver execution.
191    */

192   public void start() {
193     thread = new Thread JavaDoc(new ThreadFinalizer(this), getName());
194     thread.setDaemon(true);
195     drivers.put(this, this);
196     thread.start();
197   }
198
199   /**
200    * Nullify thread variable. To be used by ThreadFinalizer.
201    */

202   synchronized void reset() {
203     thread = null;
204     drivers.remove(this);
205   }
206
207   /**
208    * Stops the driver execution.
209    */

210   public synchronized void stop() {
211     if (thread == null) return;
212     isRunning = false;
213     if (canStop) {
214       thread.interrupt();
215       close();
216     }
217     thread = null;
218   }
219
220   public abstract void close();
221
222   static void stopAll() {
223     Logger logmon = Debug.getLogger(Debug.A3Proxy);
224     if ((drivers == null) || (drivers.size() == 0)) return;
225     Driver[] tab = (Driver[]) (drivers.values().toArray(new Driver[0]));
226     for (int i=0; i<tab.length; i++) {
227       logmon.log(BasicLevel.WARN, tab[i].getName() + " " + tab[i].isRunning + "/" + tab[i].canStop + " stop()");
228       tab[i].stop();
229     }
230   }
231  
232   /**
233    * Sends a notification to an agent.
234    * <p>
235    * Provides a similar function as the <code>sendTo</code> function in
236    * <code>Agent</code> class, except that the notification is sent directly
237    * via a <code>directSendTo</code> method.
238    *
239    * @param to target agent
240    * @param not notification to send
241    */

242   protected final void sendTo(AgentId to, Notification not) throws IOException {
243     Channel.sendTo(to, not);
244   }
245 }
246
Popular Tags