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 }