001/* 002 * Copyright (c) 1997-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.domains; 031 032import java.util.Iterator; 033 034import org.sdm.spa.WebService; 035 036import ptolemy.actor.Actor; 037import ptolemy.actor.FiringEvent; 038import ptolemy.actor.sched.Firing; 039import ptolemy.actor.sched.Schedule; 040import ptolemy.actor.sched.Scheduler; 041import ptolemy.domains.sdf.kernel.SDFDirector; 042import ptolemy.gui.GraphicalMessageHandler; 043import ptolemy.kernel.ComponentEntity; 044import ptolemy.kernel.CompositeEntity; 045import ptolemy.kernel.util.IllegalActionException; 046import ptolemy.kernel.util.InvalidStateException; 047import ptolemy.kernel.util.NameDuplicationException; 048import ptolemy.kernel.util.Workspace; 049 050////////////////////////////////////////////////////////////////////////// 051//// SDFDirector for Web Services 052 053/** 054 * The SDF4WS is an SDFDirector for the domain of WebServices. SDF4WS provides 055 * the abilty to monitor WebService actors in a workflow, catching their 056 * exceptions and error messages. Additional domain-specific operations can be 057 * "three re-trials" of failing web services before finally switching to another 058 * server providing the same service (if available) OR determining if the web 059 * service operation failure was caused due to invalid user input or internal 060 * web service errors. 061 * 062 * Based on the Director for the synchronous dataflow (SDF) model of 063 * computation. 064 * 065 * <h1>SDF4WS overview</h1> The Synchronous Dataflow(SDF) for Web Services 066 * director, like its parent SDF Director supports the efficient execution of 067 * Dataflow graphs that lack control structures. SDF4WS is a director made 068 * specifically for web services with added functionality. This director catches 069 * possible exception from Web Service incase of a scenario and hence failures 070 * in web service access. 071 * 072 * <h2>More SDF Director Information</h2> Dataflow graphs that contain control 073 * structures should be executed using the Process Networks(PN) domain instead. 074 * SDF allows efficient execution, with very little overhead at runtime. It 075 * requires that the rates on the ports of all actors be known before hand. SDF 076 * also requires that the rates on the ports not change during execution. In 077 * addition, in some cases (namely systems with feedback) delays, which are 078 * represented by initial tokens on relations must be explicitly noted. SDF uses 079 * this rate and delay information to determine the execution sequence of the 080 * actors before execution begins. <h3>Schedule Properties</h3> 081 * <ul> 082 * <li>The number of tokens accumulated on every relation is bounded, given an 083 * infinite number of executions of the schedule. 084 * <li>Deadlock will never occur, given an infinite number of executions of the 085 * schedule. 086 * </ul> 087 * <h1>Class comments</h1> An SDFDirector is the class that controls execution 088 * of actors under the SDF domain. By default, actor scheduling is handled by 089 * the SDFScheduler class. Furthermore, the newReceiver method creates Receivers 090 * of type SDFReceiver, which extends QueueReceiver to support optimized gets 091 * and puts of arrays of tokens. 092 * <p> 093 * Actors are assumed to consume and produce exactly one token per channel on 094 * each firing. Actors that do not follow this convention should set the 095 * appropriate parameters on input and output ports to declare the number of 096 * tokens they produce or consume. See the 097 * 098 * @link ptolemy.domains.sdf.kernel.SDFScheduler for more information. The @link 099 * ptolemy.domains.sdf.lib.SampleDelay actor is usually used in a model to 100 * specify the delay across a relation. 101 * <p> 102 * The <i>allowDisconnectedGraphs</i> parameter of this director 103 * determines whether disconnected graphs are permitted. A model may have 104 * two or more graphs of actors that are not connected. The schedule can 105 * jump from one graph to another among the disconnected graphs. There is 106 * nothing to force the scheduler to finish executing all actors on one 107 * graph before firing actors on another graph. However, the order of 108 * execution within an graph should be correct. Usually, disconnected 109 * graphs in an SDF model indicates an error. The default value of the 110 * allowDisconnectedGraphs parameter is a BooleanToken with the value 111 * false. 112 * <p> 113 * The <i>iterations</i> parameter of this director corresponds to a limit 114 * on the number of times the director will fire its hierarchy before it 115 * returns false in postfire. If this number is not greater than zero, 116 * then no limit is set and postfire will always return true. The default 117 * value of the iterations parameter is an IntToken with value zero. 118 * <p> 119 * The <i>vectorizationFactor</i> parameter of this director sets the 120 * number of times that the basic schedule is executed during each firing 121 * of this director. This might allow the director to execute the model 122 * more efficiently, by combining multiple firings of each actor. The 123 * default value of the vectorizationFactor parameter is an IntToken with 124 * value one. 125 * @see ptolemy.domains.sdf.kernel.SDFScheduler 126 * @see ptolemy.domains.sdf.kernel.SDFReceiver 127 * @author Nandita Mangal 128 * @version $Id: SDF4WS.java 24234 2010-05-06 05:21:26Z welker $ 129 * @since Ptolemy II 0.2 130 * @Pt.ProposedRating Green (neuendor) 131 * @Pt.AcceptedRating Green (neuendor) 132 */ 133public class SDF4WS extends SDFDirector { 134 /** 135 * Construct a director in the default workspace with an empty string as its 136 * name. The director is added to the list of objects in the workspace. 137 * Increment the version number of the workspace. 138 * 139 * The SDFD4WS will have a default scheduler of type SDFScheduler. 140 * 141 * @exception IllegalActionException 142 * If the name has a period in it, or the director is not 143 * compatible with the specified container. 144 * @exception NameDuplicationException 145 * If the container already contains an entity with the 146 * specified name. 147 */ 148 public SDF4WS() throws IllegalActionException, NameDuplicationException { 149 150 super(); 151 // Parameters inherited from SDF Director. 152 153 } 154 155 /** 156 * Construct a director in the workspace with an empty name. The director is 157 * added to the list of objects in the workspace. Increment the version 158 * number of the workspace. The SDFDirector will have a default scheduler of 159 * type SDFScheduler. 160 * 161 * @param workspace 162 * The workspace for this object. 163 * @exception IllegalActionException 164 * If the name has a period in it, or the director is not 165 * compatible with the specified container. 166 * @exception NameDuplicationException 167 * If the container already contains an entity with the 168 * specified name. 169 */ 170 public SDF4WS(Workspace workspace) throws IllegalActionException, 171 NameDuplicationException { 172 173 super(workspace); 174 175 } 176 177 /** 178 * Construct a director in the given container with the given name. The 179 * container argument must not be null, or a NullPointerException will be 180 * thrown. If the name argument is null, then the name is set to the empty 181 * string. Increment the version number of the workspace. The SDFD4WS 182 * Director will have a default scheduler of type SDFScheduler. 183 * 184 * @param container 185 * Container of the director. 186 * @param name 187 * Name of this director. 188 * @exception IllegalActionException 189 * If the director is not compatible with the specified 190 * container. May be thrown in a derived class. 191 * @exception NameDuplicationException 192 * If the container is not a CompositeActor and the name 193 * collides with an entity in the container. 194 */ 195 public SDF4WS(CompositeEntity container, String name) 196 throws IllegalActionException, NameDuplicationException { 197 198 super(container, name); 199 } 200 201 // /////////////////////////////////////////////////////////////// 202 // // parameters //// 203 204 // all parameters extended from SDF Directors. 205 206 // ///////////////////////////////////////////////////////////////// 207 // // public methods //// 208 209 /** 210 * BASIC SDF director functionality :Calculate the current schedule, if 211 * necessary, and iterate the contained actors in the order given by the 212 * schedule. No internal state of the director is updated during fire, so it 213 * may be used with domains that require this property, such as CT. 214 * <p> 215 * Iterating an actor involves calling the actor's iterate() method, which 216 * is equivalent to calling the actor's prefire(), fire() and postfire() 217 * methods in succession. If iterate() returns NOT_READY, indicating that 218 * the actor is not ready to execute, then an IllegalActionException will be 219 * thrown. The values returned from iterate() are recorded and are used to 220 * determine the value that postfire() will return at the end of the 221 * director's iteration. 222 * <p> 223 * 224 * SDF4WS : This method overridden by web service to perform additional 225 * domain-specific operations such as three re-trials of failing web 226 * services before finally switching to another server providing the same 227 * service (if available). 228 * 229 * @exception IllegalActionException 230 * If any actor executed by this actor return false in 231 * prefire. 232 * @exception InvalidStateException 233 * If this director does not have a container. 234 */ 235 public void fire() throws IllegalActionException { 236 237 int returnValue = 0; 238 239 Scheduler scheduler = getScheduler(); 240 if (scheduler == null) { 241 throw new IllegalActionException("Attempted to fire " 242 + "system with no scheduler"); 243 } 244 // This will throw IllegalActionException if this director 245 // does not have a container. 246 Schedule schedule = scheduler.getSchedule(); 247 Iterator firings = schedule.firingIterator(); 248 249 while (firings.hasNext() && !_stopRequested) { 250 251 Firing firing = (Firing) firings.next(); 252 Actor actor = (Actor) firing.getActor(); 253 int iterationCount = firing.getIterationCount(); 254 255 if (_debugging) { 256 _debug(new FiringEvent(this, actor, FiringEvent.BEFORE_ITERATE, 257 iterationCount)); 258 } 259 260 // get the current actor in the iteration. 261 actorCurrent = actor; 262 263 // iterate the actor, catching any exceptions due to failed web 264 // service access. 265 try { 266 267 returnValue = actor.iterate(iterationCount); 268 269 } catch (Exception ex) { 270 if (actorCurrent instanceof WebService 271 && ex.getMessage().equals( 272 "\nWebService WSDL Not Responding.")) { 273 274 GraphicalMessageHandler 275 .message("\nSDF4WS re-trying web service access"); 276 277 // re-try accessing the web service three times. 278 int reTrialCount = 3; 279 boolean webServiceSuccess = _reFireWebService(3); 280 if (webServiceSuccess == false) { 281 GraphicalMessageHandler 282 .message("\nWebService WSDL failed to respond in " 283 + reTrialCount 284 + " trials." 285 + "\nSDF4WS will try to access web service via different server."); 286 287 // TO BE DONE: SDF4WS will try to access web service 288 // from another server if available. 289 290 } else { 291 GraphicalMessageHandler 292 .message("\nWebService WSDL access successfull!"); 293 returnValue = actorCurrentReturnValue; 294 295 } 296 297 } 298 } 299 300 if (returnValue == STOP_ITERATING) { 301 302 // _postfireReturns = false; 303 } else if (returnValue == NOT_READY) { 304 throw new IllegalActionException(this, (ComponentEntity) actor, 305 "Actor " + "is not ready to fire."); 306 } 307 308 if (_debugging) { 309 _debug(new FiringEvent(this, actor, FiringEvent.AFTER_ITERATE, 310 iterationCount)); 311 } 312 313 } 314 315 }// end of fire 316 317 // /////////////////////////////////////////////////////////////////////////// 318 // // private methods //// 319 320 private boolean _reFireWebService(int retrialCount) { 321 int counter = 0; 322 boolean webServiceSuccess = false; 323 for (counter = 0; counter < retrialCount; counter++) { 324 // iterate the actor retrialCount number of times. 325 try { 326 327 actorCurrent.stopFire(); 328 actorCurrent.prefire(); 329 actorCurrent.fire(); 330 // actor was iterated successfully w/o exception. 331 // get actor's return Value 332 boolean returnValue = actorCurrent.postfire(); 333 if (returnValue == false) 334 actorCurrentReturnValue = STOP_ITERATING; 335 336 webServiceSuccess = true; 337 338 return webServiceSuccess; 339 } catch (Exception e) { 340 // do nothing but try again 341 webServiceSuccess = false; 342 } 343 344 } 345 return webServiceSuccess; 346 347 } 348 349 // ///////////////////////////////////////////////////////////////// 350 // // private variables //// 351 private int _iterationCount = 0; 352 private Actor actorCurrent; 353 private int actorCurrentReturnValue = 0; 354 355}