1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.gwe.persistence.model;
18
19 import java.sql.Timestamp;
20 import java.util.Timer;
21 import java.util.TimerTask;
22
23 import javax.persistence.Entity;
24 import javax.persistence.GeneratedValue;
25 import javax.persistence.GenerationType;
26 import javax.persistence.Id;
27 import javax.persistence.Transient;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.gwe.app.daemon.domain.AgentDomain;
32 import org.hibernate.annotations.GenericGenerator;
33
34
35
36
37
38
39 @Entity
40 @GenericGenerator(name="ALLOC_SEQ", strategy="increment")
41
42 public class AllocationInfo extends BaseModelInfo<Integer> {
43
44 private static Log log = LogFactory.getLog(AgentDomain.class);
45
46 private static final int RELEASE_REASON_ERROR = 0;
47 private static final int RELEASE_REASON_TOO_LATE = 1;
48 private static final int RELEASE_REASON_TOO_IDLE = 2;
49 private static final int RELEASE_REASON_TOO_OLD = 3;
50 private static final int RELEASE_REASON_NON_RESPONSIVE = 4;
51 private static final int RELEASE_REASON_DAEMON_STOPPING = 5;
52
53 @Id
54 @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ALLOC_SEQ")
55 private int id;
56
57
58 protected String systemPid = null;
59
60
61
62 @Transient
63 private ComputeResourceInfo compResource;
64
65 private Timestamp whenScheduled = null;
66 private Timestamp whenAttained = null;
67
68 private Timestamp whenReleased = null;
69 private Timestamp whenDisposed = null;
70
71 private int releaseReason = -1;
72
73
74 @Transient private transient Object lifeControllerLock = new Object();
75 @Transient private transient JobExecutionInfo currentJobExecution = null;
76 @Transient private transient DeathDealer deathDealer;
77 @Transient private transient boolean registered = false;
78
79 public AllocationInfo() {}
80
81 public Integer getId() {
82 return id;
83 }
84
85 public void setId(int id) {
86 this.id = id;
87 }
88
89
90 public String getSystemPid() {
91 return systemPid;
92 }
93
94 public void setSystemPid(String pid) {
95 systemPid = pid;
96 whenScheduled = logEvent(EventType.ALLOCATION_SCHEDULED);
97 }
98
99 public boolean isRegistered() {
100 return registered;
101 }
102
103 public Timestamp getWhenScheduled() { return whenScheduled; }
104 public Timestamp getWhenAttained() { return whenAttained; }
105 public Timestamp getWhenReleased() { synchronized (lifeControllerLock) { return whenReleased; } }
106 public Timestamp getWhenDisposed() { synchronized (lifeControllerLock) { return whenDisposed; } }
107
108 public ComputeResourceInfo getCompResource() {
109 return compResource;
110 }
111
112 public void setCompResource(ComputeResourceInfo compRes) {
113 compResource = compRes;
114 this.registered = true;
115 whenAttained = logEvent(EventType.ALLOCATION_ATTAINED);
116 }
117
118 public DeathDealer createDeathDealer(DaemonConfigDesc config) {
119 if (deathDealer == null) deathDealer = new DeathDealer(config);
120 return deathDealer;
121 }
122
123 public DeathDealer getDeathDealer() {
124 return deathDealer;
125 }
126
127 public int getReleaseReason() {
128 return releaseReason;
129 }
130
131 public void setReleaseReason(int reason) {
132 releaseReason = reason;
133 whenReleased = logEvent(EventType.ALLOCATION_RELEASED);
134 }
135
136 public JobExecutionInfo getProcessingExecution() {
137 synchronized (lifeControllerLock) { return currentJobExecution; }
138 }
139
140 public JobExecutionInfo extractProcessingExecution() {
141 synchronized (lifeControllerLock) {
142 JobExecutionInfo result = currentJobExecution;
143 currentJobExecution = null;
144 return result;
145 }
146 }
147
148 public JobExecutionInfo getNextProcessingExecutionBlocking() {
149 synchronized (lifeControllerLock) {
150 while (currentJobExecution == null && whenReleased == null)
151 try { lifeControllerLock.wait(); } catch (InterruptedException e) {}
152
153 return currentJobExecution;
154 }
155 }
156
157 public boolean setProcessingExecution(JobExecutionInfo execution) {
158 synchronized (lifeControllerLock) {
159 if (whenReleased != null) return false;
160 this.currentJobExecution = execution;
161 execution.setAllocation(this);
162 deathDealer.cancelIdleCountdown();
163 lifeControllerLock.notifyAll();
164 return true;
165 }
166 }
167
168 public JobExecutionInfo dispose(boolean beatOverdue) {
169 synchronized (lifeControllerLock) {
170 if (whenReleased == null)
171 setReleaseReason((beatOverdue) ? RELEASE_REASON_NON_RESPONSIVE : RELEASE_REASON_ERROR);
172 whenDisposed = logEvent(EventType.ALLOCATION_DISPOSED);
173 lifeControllerLock.notifyAll();
174 return currentJobExecution;
175 }
176 }
177
178 public class DeathDealer implements Runnable {
179 private long idleDeathTime = -1;
180 private long oldDeathTime;
181 private DaemonConfigDesc config;
182
183 public DeathDealer(DaemonConfigDesc config) {
184 this.config = config;
185 this.oldDeathTime = whenAttained.getTime() + getHeadResource().getMaxHijackMillis();
186 }
187
188 public void startIdleCountdown() {
189 deathDealer.setIdleDeathTime(System.currentTimeMillis() + getHeadResource().getMaxIdleMillis());
190 }
191
192 public void cancelIdleCountdown() {
193 deathDealer.setIdleDeathTime(-1);
194 }
195
196 private void setIdleDeathTime(long time) {
197 synchronized (lifeControllerLock) {
198 idleDeathTime = time;
199 lifeControllerLock.notifyAll();
200 }
201 }
202
203 public void run() {
204
205 boolean hijack = getHeadResource().getMaxHijackMillis() > 0;
206 if (!hijack && getHeadResource().getMaxIdleMillis() <= 0) return;
207
208
209 boolean isIdleCutTime;
210 synchronized (lifeControllerLock) {
211
212 while (true) {
213 isIdleCutTime = (0 <= idleDeathTime && idleDeathTime <= oldDeathTime);
214 long remaining = (isIdleCutTime ? idleDeathTime : oldDeathTime) - System.currentTimeMillis();
215 if (remaining <= 0) break;
216 try {
217 lifeControllerLock.wait(remaining);
218 } catch (InterruptedException e) {
219
220
221 }
222 if (whenReleased != null || whenDisposed != null) break;
223 }
224
225
226 if (whenReleased == null) {
227 setReleaseReason((isIdleCutTime) ? RELEASE_REASON_TOO_IDLE : RELEASE_REASON_TOO_OLD);
228
229
230 lifeControllerLock.notifyAll();
231 }
232 }
233 }
234
235 private HeadResourceInfo getHeadResource() {
236 return config.getHeadResource();
237 }
238 }
239
240 public ModelSummary<Integer> createModelSummaryFor(EventType ev) {
241 switch (ev) {
242 case ALLOCATION_RELEASED:
243 return new ModelSummary<Integer>(this, releaseReason);
244
245 default:
246 return super.createModelSummaryFor(ev);
247 }
248 }
249
250 public String getAgentBaseFileName(String suffix) {
251 return "agent-" + getId() + suffix;
252 }
253
254 public String getAgentScriptFileName() {
255 return getAgentBaseFileName(".sh");
256 }
257
258 public String getAgentSubmitFileName() {
259 return getAgentBaseFileName(".submit");
260 }
261
262 public String toString() {
263 return "allocId:" + getId();
264 }
265
266
267
268
269
270
271 @Transient private transient Timer tooLateTimer = null;
272 @Transient private transient Boolean tooLateTimerRunning = true;
273 @Transient private transient Object tooLateTimerLock = new Object();
274
275 public void setTooLateTimerTask(TimerTask tooLateTimerTask, long delay) {
276 this.tooLateTimer = new Timer();
277 tooLateTimer.schedule(tooLateTimerTask, delay);
278 }
279
280 public boolean isTooLate() {
281 synchronized (tooLateTimerLock) {
282 cancelTooLateTimer();
283 return (releaseReason == RELEASE_REASON_TOO_LATE);
284 }
285 }
286
287 public void flagAsTooLate() {
288 synchronized (tooLateTimerLock) {
289 if (tooLateTimerRunning) {
290 setReleaseReason(RELEASE_REASON_TOO_LATE);
291 log.warn("Allocation " + id + " timeout waiting for it to be established!");
292 }
293 cancelTooLateTimer();
294 }
295 }
296
297 private void cancelTooLateTimer() {
298 if (tooLateTimer != null) {
299 tooLateTimer.cancel();
300 tooLateTimer = null;
301 }
302 tooLateTimerRunning = false;
303 }
304 }