001 package toolbus;
002
003 import toolbus.logging.ILogger;
004 import toolbus.logging.IToolBusLoggerConstants;
005 import toolbus.logging.LoggerFactory;
006 import toolbus.tool.ToolInstance;
007 import toolbus.util.collections.ConcurrentHashMap;
008 import toolbus.util.collections.ConcurrentHashSet;
009 import toolbus.util.collections.EntryHandlerConstants;
010 import toolbus.util.collections.ConcurrentHashMap.HashMapEntryHandler;
011 import toolbus.util.collections.ConcurrentHashMap.ReadOnlyHashMapEntryHandler;
012 import toolbus.util.collections.ConcurrentHashSet.HashSetEntryHandler;
013 import toolbus.util.collections.ConcurrentHashSet.ReadOnlyHashSetEntryHandler;
014 import aterm.ATerm;
015
016 /**
017 * This class manages all the tool instances.
018 *
019 * @author Arnold Lankamp
020 */
021 public class ToolInstanceManager{
022 private final ConcurrentHashMap<ATerm, ToolInstance> activeTools;
023 private final ConcurrentHashMap<ATerm, ToolInstance> pendingTools;
024 private final ConcurrentHashSet<ToolInstance> dynamiclyConnectedTools;
025
026 /**
027 * Default constructor.
028 */
029 public ToolInstanceManager(){
030 super();
031
032 activeTools = new ConcurrentHashMap<ATerm, ToolInstance>();
033 pendingTools = new ConcurrentHashMap<ATerm, ToolInstance>();
034 dynamiclyConnectedTools = new ConcurrentHashSet<ToolInstance>();
035 }
036
037 /**
038 * Returns the tool with the given id, if it's present in the collection.
039 *
040 * @param toolKey
041 * The key of the tool we want to retrieve.
042 * @return The tool instance associated with the given id.
043 */
044 public ToolInstance get(ATerm toolKey){
045 return activeTools.get(toolKey);
046 }
047
048 /**
049 * Removes the tool instance that is associated with the given id from the collection.
050 *
051 * @param toolKey
052 * The key of the tool instance that we want to remove.
053 */
054 public void remove(ATerm toolKey){
055 activeTools.remove(toolKey);
056 }
057
058 /**
059 * Adds a connect tool instance to the collection. Connected tools are tools that are connected
060 * but are not being used by any process yet.
061 *
062 * @param toolInstance
063 * The pending tool instance we want to add.
064 */
065 public void addDynamiclyConnectedTool(ToolInstance toolInstance){
066 dynamiclyConnectedTools.put(toolInstance);
067 }
068
069 /**
070 * Activates and returns a tool instance of the given type. This method moves the found tool
071 * instance from the dynamicly connected collection to the active collection.
072 *
073 * @param toolName
074 * The name identifying the type of the tool instance.
075 * @return The tool instance that was activated; if none is found NULL will be returned.
076 */
077 public ToolInstance activateDynamiclyConnectedTool(String toolName){
078 // Find a dynamicly connected tool that's ready for use.
079 ToolInstance toolInstance = getReadyDynamiclyConnectedTool(toolName);
080
081 // Move the tool to the active tool collection (if the correct dyncamicly connected tool
082 // was found).
083 if(toolInstance != null){
084 activeTools.put(toolInstance.getToolKey(), toolInstance);
085 }
086
087 return toolInstance;
088 }
089
090 /**
091 * Attempts to locate a dynamicly connected tool instance that is ready to be processed by the
092 * 'connect atom'.
093 *
094 * @param toolName
095 * The name of the tool.
096 * @return The located tool instance (if present); if none is found NULL will be returned.
097 */
098 private ToolInstance getReadyDynamiclyConnectedTool(final String toolName){
099 class DynamicToolsIterationHandler extends HashSetEntryHandler<ToolInstance>{
100 public ToolInstance toolInstance = null;
101
102 public int handle(ToolInstance ti){
103 if(ti.isConnected() && ti.getToolKey().getAFun().getName().equals(toolName)){
104 toolInstance = ti;
105 return EntryHandlerConstants.BREAK | EntryHandlerConstants.REMOVE;
106 }
107
108 return EntryHandlerConstants.CONTINUE;
109 }
110 }
111 DynamicToolsIterationHandler dynamicToolsIterationHandler = new DynamicToolsIterationHandler();
112 dynamiclyConnectedTools.iterate(dynamicToolsIterationHandler);
113
114 return dynamicToolsIterationHandler.toolInstance;
115 }
116
117 /**
118 * Removes the given tool instance from the dynamicly connected tools list (if present).
119 *
120 * @param toolInstance
121 * The tool instance that needs to be removed.
122 */
123 public void removeDynamiclyConnectedTool(ToolInstance toolInstance){
124 dynamiclyConnectedTools.remove(toolInstance);
125 }
126
127 /**
128 * Adds a tool instance to the list of which the tool application is currently being started.
129 *
130 * @param toolInstance
131 * The tool instance we want to add.
132 */
133 public void addPendingTool(ToolInstance toolInstance){
134 pendingTools.put(toolInstance.getToolKey(), toolInstance);
135 }
136
137 /**
138 * Returns the tool with the given key, if it's present in the pending tool collection.
139 *
140 * @param toolKey
141 * The key of the tool we want to retrieve.
142 * @return The tool instance associated with the given id.
143 */
144 public ToolInstance getPendingTool(ATerm toolKey){
145 return pendingTools.get(toolKey);
146 }
147
148 /**
149 * Attempts to activate the tool instance associated with the given key. If the tool instance
150 * associated with the given key is ready / connected, it will moved it to the activated
151 * collection.
152 *
153 * @param toolKey
154 * The key of the tool that has connected.
155 * @return The tool instance that was activated; if the tool instance associated with the given
156 * key is not connected / ready, NULL will be returned.
157 */
158 public ToolInstance activatePendingTool(ATerm toolKey){
159 ToolInstance toolInstance = pendingTools.get(toolKey);
160
161 if(toolInstance == null){
162 LoggerFactory.log("Unable to locate pending tool with id: "+toolKey+".", ILogger.ERROR, IToolBusLoggerConstants.TOOLINSTANCE);
163 return null;
164 }
165
166 if(!toolInstance.isConnected()) return null;
167
168 toolInstance = pendingTools.remove(toolKey);
169 if(toolInstance == null){
170 LoggerFactory.log("Pending tool with id: "+toolKey+" disappeared; huh where did it go, it was here a moment ago....", ILogger.ERROR, IToolBusLoggerConstants.TOOLINSTANCE);
171 return null;
172 }
173
174 activeTools.put(toolKey, toolInstance);
175
176 return toolInstance;
177 }
178
179 /**
180 * Removes the given tool instance from the pending tools list (if present).
181 *
182 * @param toolKey
183 * The key that is associated with the tool instance that needs to be removed.
184 */
185 public void removePendingTool(ATerm toolKey){
186 pendingTools.remove(toolKey);
187 }
188
189 /**
190 * Notifies all tools that the ToolBus was shut down, by sending a terminate(\<term\>) message.
191 *
192 * @param message
193 * The message that will be encapsulated in the terminate message.
194 */
195 public void shutDown(final ATerm message){
196 // Shut down the active tools.
197 HashMapEntryHandler<ATerm, ToolInstance> activeToolsIterationHandler = new ReadOnlyHashMapEntryHandler<ATerm, ToolInstance>(){
198 public int handle(ATerm toolKey, ToolInstance toolInstance){
199 toolInstance.sendTerminate(message);
200
201 return EntryHandlerConstants.CONTINUE;
202 }
203 };
204 activeTools.iterate(activeToolsIterationHandler);
205
206 // Don't attempt to terminate the pending tools, since they are not connected.
207
208 // Shut down the dynamicly connected tools.
209 HashSetEntryHandler<ToolInstance> dynamicToolsIterationHandler = new ReadOnlyHashSetEntryHandler<ToolInstance>(){
210 public int handle(ToolInstance toolInstance){
211 toolInstance.sendTerminate(message);
212
213 return EntryHandlerConstants.CONTINUE;
214 }
215 };
216 dynamiclyConnectedTools.iterate(dynamicToolsIterationHandler);
217 }
218
219 /**
220 * Kills all known executed tools immidiately.
221 */
222 public void killExecutedToolsNow(){
223 HashMapEntryHandler<ATerm, ToolInstance> toolsIterationHandler = new ReadOnlyHashMapEntryHandler<ATerm, ToolInstance>(){
224 public int handle(ATerm toolKey, ToolInstance toolInstance){
225 toolInstance.kill();
226
227 return EntryHandlerConstants.CONTINUE;
228 }
229 };
230
231 // Kill the active tools.
232 activeTools.iterate(toolsIterationHandler);
233
234 // Kill the pending tools.
235 pendingTools.iterate(toolsIterationHandler);
236
237 // We can't kill dynamicly connected tools.
238 // The ToolBus adapter will terminate the tool as soon as it finds out the connection with the ToolBus is lost.
239 }
240
241 /**
242 * Counts the number of connected tools that are registered with this tool instance manager.
243 *
244 * @return The number of connected tools that are registered with this tool instance manager.
245 */
246 public int numberOfConnectedTools(){
247 return (activeTools.size() + dynamiclyConnectedTools.size());
248 }
249
250 /**
251 * Prints all currently queued values, events and requests.
252 */
253 public void printQueueTerms(){
254 HashMapEntryHandler<ATerm, ToolInstance> activeToolsIterationHandler = new ReadOnlyHashMapEntryHandler<ATerm, ToolInstance>(){
255 public int handle(ATerm toolKey, ToolInstance toolInstance){
256 ATerm[] queuedValues = toolInstance.getQueuedValues();
257 ATerm[] queuedEvents = toolInstance.getQueuedEvents();
258 ATerm[] queuedRequests = toolInstance.getQueuedRequests();
259
260 int nrOfQueueValues = queuedValues.length;
261 int nrOfQueueEvents = queuedEvents.length;
262 int nrOfQueuedRequests = queuedRequests.length;
263
264 if((nrOfQueueValues + nrOfQueueEvents + nrOfQueuedRequests) > 0){
265 System.err.println(toolKey+":");
266
267 for(int i = nrOfQueueValues - 1; i >= 0; i--){
268 System.err.println("rec-value("+queuedValues[i]+")");
269 }
270
271 for(int i = nrOfQueueEvents - 1; i >= 0; i--){
272 System.err.println("rec-event("+queuedEvents[i]+")");
273 }
274
275 for(int i = nrOfQueuedRequests - 1; i >= 0; i--){
276 System.err.println("rec-request("+queuedRequests[i]+")");
277 }
278 }
279
280 return EntryHandlerConstants.CONTINUE;
281 }
282 };
283 activeTools.iterate(activeToolsIterationHandler);
284 }
285
286 public void showStatus(){
287 // Show the active tools.
288 HashMapEntryHandler<ATerm, ToolInstance> activeToolsIterationHandler = new ReadOnlyHashMapEntryHandler<ATerm, ToolInstance>(){
289 public int handle(ATerm toolKey, ToolInstance toolInstance){
290 System.err.println("A: " + toolInstance.showStatus());
291
292 return EntryHandlerConstants.CONTINUE;
293 }
294 };
295 activeTools.iterate(activeToolsIterationHandler);
296
297 // Show the pending tools.
298 HashMapEntryHandler<ATerm, ToolInstance> pendingToolsIterationHandler = new ReadOnlyHashMapEntryHandler<ATerm, ToolInstance>(){
299 public int handle(ATerm toolKey, ToolInstance toolInstance){
300 System.err.println("P: " + toolInstance.showStatus());
301
302 return EntryHandlerConstants.CONTINUE;
303 }
304 };
305 pendingTools.iterate(pendingToolsIterationHandler);
306
307 // Show the dynamicly connected tools.
308 HashSetEntryHandler<ToolInstance> dynamicToolsIterationHandler = new ReadOnlyHashSetEntryHandler<ToolInstance>(){
309 public int handle(ToolInstance toolInstance){
310 System.err.println("D: " + toolInstance.showStatus());
311
312 return EntryHandlerConstants.CONTINUE;
313 }
314 };
315 dynamiclyConnectedTools.iterate(dynamicToolsIterationHandler);
316 }
317 }