1 | package de.uka.ipd.sdq.simucomframework; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.List; |
5 | import java.util.concurrent.atomic.AtomicLong; |
6 | |
7 | import org.apache.log4j.Logger; |
8 | |
9 | import de.uka.ipd.sdq.probespec.framework.RequestContext; |
10 | import de.uka.ipd.sdq.reliability.core.FailureStatistics; |
11 | import de.uka.ipd.sdq.scheduler.IActiveResource; |
12 | import de.uka.ipd.sdq.scheduler.ISchedulableProcess; |
13 | import de.uka.ipd.sdq.scheduler.LoggingWrapper; |
14 | import de.uka.ipd.sdq.scheduler.resources.active.SimDelayResource; |
15 | import de.uka.ipd.sdq.simucomframework.exceptions.FailureException; |
16 | import de.uka.ipd.sdq.simucomframework.model.SimuComModel; |
17 | import de.uka.ipd.sdq.simucomframework.simucomstatus.Process; |
18 | import de.uka.ipd.sdq.simucomframework.simucomstatus.SimucomstatusFactory; |
19 | import de.uka.ipd.sdq.simulation.SimulationResult; |
20 | import de.uka.ipd.sdq.simulation.abstractsimengine.AbstractSimProcessDelegator; |
21 | import de.uka.ipd.sdq.simulation.abstractsimengine.ISimProcess; |
22 | import de.uka.ipd.sdq.simulation.abstractsimengine.ISimProcessListener; |
23 | |
24 | public abstract class SimuComSimProcess extends AbstractSimProcessDelegator implements ISchedulableProcess, |
25 | ISimProcessListener { |
26 | |
27 | private static AtomicLong sessionID = new AtomicLong(0); |
28 | /** Logger for this class. */ |
29 | protected static Logger logger = Logger.getLogger(SimuComSimProcess.class.getName()); |
30 | |
31 | private Process processStatus = null; |
32 | private SimDelayResource delayResource = null; |
33 | |
34 | private boolean isDebug; |
35 | |
36 | private List<IActiveResource> removedObservers = new ArrayList<IActiveResource>();; |
37 | |
38 | private RequestContext requestContext; |
39 | |
40 | private ArrayList<IActiveResource> terminatedObservers = new ArrayList<IActiveResource>(); |
41 | |
42 | protected long currentSessionId; |
43 | |
44 | private boolean isTimeoutFailure = false; |
45 | |
46 | private String timeoutFailureTypeId = null; |
47 | |
48 | protected SimuComSimProcess(SimuComModel model, String name) { |
49 | this(model, name, null); |
50 | } |
51 | |
52 | protected SimuComSimProcess(SimuComModel model, String name, RequestContext parentRequestContext) { |
53 | super(model, name); |
54 | this.isDebug = model.getConfiguration().isDebug(); |
55 | this.delayResource = new SimDelayResource(model, name + "_thinktime", name + "_thinktime"); |
56 | requestContext = new RequestContext(Long.valueOf(getRawId()).toString(), parentRequestContext); |
57 | |
58 | // add a process listener in order to get notified when this process is about to be |
59 | // suspended or resumed again. |
60 | this.addProcessListener(this); |
61 | |
62 | logger.debug("Create SimuComSimProcess with id " + getRawId()); |
63 | } |
64 | |
65 | public void activate() { |
66 | this.scheduleAt(0); |
67 | } |
68 | |
69 | /* |
70 | * (non-Javadoc) |
71 | * |
72 | * @see |
73 | * de.uka.ipd.sdq.scheduler.ISchedulableProcess#timeout(java.lang.String) |
74 | */ |
75 | public void timeout(String timeoutFailureTypeId) { |
76 | this.isTimeoutFailure = true; |
77 | this.timeoutFailureTypeId = timeoutFailureTypeId; |
78 | activate(); |
79 | }; |
80 | |
81 | /** |
82 | * Clients may override default behaviour, e.g., PassiveResource |
83 | */ |
84 | protected void addProcessToSimStatus() { |
85 | logger.debug("Starting simulation process " + this.getName()); |
86 | |
87 | if (isDebug) { |
88 | processStatus = SimucomstatusFactory.eINSTANCE.createProcess(); |
89 | this.getModel().getSimulationStatus().getProcessStatus() |
90 | .getProcesses().add(processStatus); |
91 | processStatus.setId(this.getName()); |
92 | processStatus.setProcessStartTime(this.getModel() |
93 | .getSimulationControl().getCurrentSimulationTime()); |
94 | } |
95 | } |
96 | |
97 | public void addTerminatedObserver(IActiveResource r) { |
98 | if (!terminatedObservers.contains(r)){ |
99 | terminatedObservers.add(r); |
100 | } |
101 | } |
102 | |
103 | public void fireTerminated() { |
104 | LoggingWrapper.log("Process " + this.getId() + " terminated."); |
105 | for (IActiveResource o : terminatedObservers) |
106 | o.notifyTerminated(this); |
107 | terminatedObservers.removeAll(removedObservers); |
108 | removedObservers.clear(); |
109 | } |
110 | |
111 | // Strategy dependent methods |
112 | |
113 | public long getCurrentSessionId() { |
114 | return currentSessionId; |
115 | } |
116 | |
117 | /** |
118 | * Returns the {@link RequestContext} in which this simulated process is |
119 | * executed. |
120 | * |
121 | * @return the request context |
122 | */ |
123 | public RequestContext getRequestContext() { |
124 | return requestContext; |
125 | } |
126 | |
127 | public ISchedulableProcess getRootProcess(){ |
128 | // TODO: What is expected here? |
129 | return null; |
130 | } |
131 | |
132 | public Process getSimProcessStatus() { |
133 | return this.processStatus; |
134 | } |
135 | |
136 | public void hold(double d) { |
137 | delayResource.process(this, 1, d); |
138 | } |
139 | |
140 | protected abstract void internalLifeCycle(); |
141 | |
142 | public boolean isFinished() { |
143 | return isTerminated(); |
144 | } |
145 | |
146 | /* |
147 | * (non-Javadoc) |
148 | * |
149 | * @see |
150 | * de.uka.ipd.sdq.simulation.abstractsimengine.ISimProcessDelegate |
151 | * #lifeCycle() |
152 | */ |
153 | public final void lifeCycle() { |
154 | addProcessToSimStatus(); |
155 | try { |
156 | this.internalLifeCycle(); |
157 | this.fireTerminated(); |
158 | } catch (Exception e) { |
159 | e.printStackTrace(); |
160 | String message = e.getMessage(); |
161 | message = message == null ? "" : message; |
162 | if (e instanceof IllegalArgumentException && message.contains("Cannot schedule in the past")){ |
163 | logger.warn( |
164 | "Simulation caused an exception because it scheduled in the past. Check your models that you do not have any negative demands, arrival times, or similar", |
165 | e); |
166 | } |
167 | else { |
168 | logger.warn( |
169 | "Simulation caused an exception. Caught it in SimProcess Lifecycle Method", |
170 | e); |
171 | } |
172 | ((SimuComModel) getModel()).setStatus(SimulationResult.ERROR, e); |
173 | logger.debug("Trying to stop simulation now..."); |
174 | this.getModel().getSimulationControl().stop(); |
175 | } |
176 | removeProcessFromSimStatus(); |
177 | } |
178 | |
179 | /** |
180 | * |
181 | */ |
182 | protected void removeProcessFromSimStatus() { |
183 | logger.debug("Terminating SimuComSimProcess " + this.getName()); |
184 | if (isDebug) { |
185 | this.getModel().getSimulationStatus().getProcessStatus() |
186 | .getProcesses().remove(processStatus); |
187 | } |
188 | } |
189 | |
190 | public void removeTerminatedObserver(IActiveResource r) { |
191 | removedObservers.remove(r); |
192 | } |
193 | |
194 | protected void updateNewSessionID() { |
195 | currentSessionId = sessionID.incrementAndGet(); |
196 | } |
197 | |
198 | @Override |
199 | public void notifyResuming(ISimProcess process) { |
200 | // the process is about to resume again. Check for the timeout |
201 | // failure condition: |
202 | if (this.isTimeoutFailure) { |
203 | // reset timeout failure |
204 | this.isTimeoutFailure = false; |
205 | FailureException.raise(FailureStatistics.getInstance().getFailureType(timeoutFailureTypeId)); |
206 | } |
207 | } |
208 | |
209 | @Override |
210 | public void notifySuspending(ISimProcess process) { |
211 | // nothing to do here |
212 | } |
213 | |
214 | @Override |
215 | public SimuComModel getModel() { |
216 | return (SimuComModel) super.getModel(); |
217 | } |
218 | |
219 | } |