View Javadoc

1   package org.xvsm.internal.tasks;
2   
3   import java.util.List;
4   
5   import org.apache.log4j.Logger;
6   import org.xvsm.core.ContainerRef;
7   import org.xvsm.core.Entry;
8   import org.xvsm.core.aspect.AspectContext;
9   import org.xvsm.core.aspect.LocalIPoint;
10  import org.xvsm.interfaces.ICapi;
11  import org.xvsm.interfaces.IContainerManager;
12  import org.xvsm.interfaces.container.IContainer;
13  import org.xvsm.internal.ContainerManager;
14  import org.xvsm.internal.EventProcessingPool;
15  import org.xvsm.internal.GlobalAspectManager;
16  import org.xvsm.internal.exceptions.AspectNotOkException;
17  import org.xvsm.internal.exceptions.AspectRescheduleException;
18  import org.xvsm.internal.exceptions.AspectSkipException;
19  import org.xvsm.internal.exceptions.ContainerFullException;
20  import org.xvsm.internal.exceptions.CountNotMetException;
21  import org.xvsm.internal.exceptions.FatalException;
22  import org.xvsm.internal.exceptions.InvalidContainerException;
23  import org.xvsm.internal.exceptions.InvalidTransactionException;
24  import org.xvsm.internal.exceptions.TransactionLockException;
25  import org.xvsm.selectors.Selector;
26  import org.xvsm.transactions.Transaction;
27  import org.xvsm.transactions.TransactionManager;
28  
29  /***
30   * 
31   * @author Christian Schreiber, Michael Proestler
32   * 
33   */
34  public class OperationTask extends Task {
35  
36  	/***
37  	 * Auto genereated serial version uid.
38  	 */
39  	private static final long serialVersionUID = 852362856073526398L;
40  
41  	/***
42  	 * the logger.
43  	 */
44  	private static Logger logger = Logger.getLogger(OperationTask.class);
45  
46  	/***
47  	 * @see OperationTaskType
48  	 */
49  	private OperationTaskType type;
50  
51  	/***
52  	 * the timeout of this operation.
53  	 */
54  	private long timeout;
55  
56  	/***
57  	 * the time of the last update of the timeout.
58  	 */
59  	// TODO: this only works within one virtual machine.
60  	private long lastTimeoutUpdate = System.currentTimeMillis();
61  
62  	/***
63  	 * @see ContainerRef
64  	 */
65  	private ContainerRef cref;
66  
67  	/***
68  	 * @see Transaction
69  	 */
70  	private Transaction tx;
71  
72  	/***
73  	 * @see Selector
74  	 */
75  	private List<Selector> selectors;
76  
77  	/***
78  	 * @see Entry
79  	 */
80  	private List<Entry> entries;
81  
82  	/***
83  	 * deleted entries.
84  	 */
85  	private List<Entry> deleted;
86  
87  	/***
88  	 * The retrycount of this task.
89  	 */
90  	private int retrycount = 0;
91  
92  	/***
93  	 * Constructor.
94  	 * 
95  	 * @param type
96  	 *            {@link OperationTaskType}
97  	 */
98  	public OperationTask(OperationTaskType type) {
99  		this.type = type;
100 	}
101 
102 	/***
103 	 * Constructor.
104 	 * 
105 	 * @param type
106 	 *            {@link OperationTaskType}
107 	 * @param cref
108 	 *            {@link ContainerRef}
109 	 * @param tx
110 	 *            {@link Transaction}
111 	 * @param selectors
112 	 *            {@link Selector}
113 	 * @param entries
114 	 *            List of {@link Entry}s
115 	 * @param timeout
116 	 *            the timeout of this operation.
117 	 */
118 	public OperationTask(OperationTaskType type, List<Entry> entries,
119 			ContainerRef cref, Transaction tx, List<Selector> selectors,
120 			long timeout) {
121 
122 		super();
123 		this.type = type;
124 		this.cref = cref;
125 		this.tx = tx;
126 		this.selectors = selectors;
127 		this.entries = entries;
128 		this.timeout = timeout;
129 	}
130 	
131 	/***
132 	 * Constructor
133 	 * 
134 	 * @param type
135 	 *            {@link OperationTaskType}
136 	 * @param taskID
137 	 *            the original ID of this task 
138 	 * @param cref
139 	 *            {@link ContainerRef}
140 	 * @param tx
141 	 *            {@link Transaction}
142 	 * @param selectors
143 	 *            {@link Selector}
144 	 * @param entries
145 	 *            List of {@link Entry}s
146 	 * @param timeout
147 	 *            the timeout of this operation.
148 	 */
149 	public OperationTask(OperationTaskType type, long taskID, List<Entry> entries,
150 			ContainerRef cref, Transaction tx, List<Selector> selectors,
151 			long timeout) {
152 
153 		this(type, entries, cref, tx, selectors, timeout);
154 		setTaskID(taskID);
155 	}
156 
157 	/***
158 	 * {@inheritDoc}
159 	 */
160 	public void run() {
161 		Thread.currentThread().setName(this.getClass().getName());
162 		if (logger.isDebugEnabled()) {
163 			logger.debug("run() " + this);
164 		}
165 		if (this.tx != null) {
166 			// we have to get the transaction because the extra information
167 			// (modified entries,...) is not transported over the network.
168 			try {
169 				if (tx.isUnderRollback()) {
170 					throw new InvalidTransactionException();
171 				}
172 				this.tx = TransactionManager.getInstance().getTransaction(
173 						this.tx.getId());
174 			} catch (InvalidTransactionException e) {
175 				this.setResult(e);
176 				return;
177 			}
178 		}
179 		try {
180 			IContainerManager mngr = ContainerManager.getInstance();
181 			IContainer c = mngr.getContainer(this.tx, cref);
182 			if (logger.isDebugEnabled()) {
183 				logger.debug("Received Container " + c + " cref = " + cref);
184 			}
185 			if (c == null) {
186 				if (logger.isDebugEnabled()) {
187 					logger.debug("run() Could not find the container "
188 							+ "-> UnknownContainerException");
189 				}
190 				setResult(new InvalidContainerException(cref + " is unknown."));
191 
192 				return;
193 			}
194 
195 			Object result = null;
196 
197 			AspectContext acontext = new AspectContext(null, this.cref,
198 					this.tx, this.selectors, this.entries, this.deleted,
199 					this.retrycount, this.getAspectContext());
200 			acontext.setTimeout(this.timeout);
201 			boolean skip = false;
202 			try {
203 				switch (this.type) {
204 				case READ:
205 					acontext.setLocalIPoint(LocalIPoint.PreRead);
206 					GlobalAspectManager.execute(acontext);
207 					break;
208 				case WRITE:
209 					acontext.setLocalIPoint(LocalIPoint.PreWrite);
210 					GlobalAspectManager.execute(acontext);
211 					break;
212 				case TAKE:
213 					acontext.setLocalIPoint(LocalIPoint.PreTake);
214 					GlobalAspectManager.execute(acontext);
215 					break;
216 				case SHIFT:
217 					acontext.setLocalIPoint(LocalIPoint.PreShift);
218 					GlobalAspectManager.execute(acontext);
219 					break;
220 				case DESTROY:
221 					acontext.setLocalIPoint(LocalIPoint.PreDestroy);
222 					GlobalAspectManager.execute(acontext);
223 					break;
224 				default:
225 				}
226 			} catch (AspectRescheduleException e) {
227 				EventProcessingPool.getInstance().execute(this);
228 				return;
229 			} catch (AspectNotOkException e) {
230 				
231 				if (this.tx != null) {
232 					EventProcessingPool.getInstance().execute(
233 							new TransactionTask(TransactionTaskType.ROLLBACK,
234 									this.tx));
235 				}
236 				this.setResult(e);
237 				return;
238 			} catch (AspectSkipException e) {
239 				skip = true;
240 			}
241 			try {
242 				if (!skip) {
243 					if (logger.isDebugEnabled()) {
244 						logger.debug("run() execute task in TXLayer: "
245 								+ this.type + ", " + acontext.getCref() + ", "
246 								+ acontext.getTx() + ", "
247 								+ acontext.getSelectors() + ", "
248 								+ acontext.getEntries() + ", "
249 								+ acontext.getDeleted() + ", "
250 								+ acontext.getRetrycount() + ", "
251 								+ acontext.getTimeout());
252 					}
253 
254 					this.setCref(acontext.getCref());
255 					this.setTx(acontext.getTx());
256 					this.setSelectors(acontext.getSelectors());
257 					this.setEntries(acontext.getEntries());
258 					this.setDeleted(acontext.getDeleted());
259 					this.setRetrycount(acontext.getRetrycount());
260 					this.setTimeout(acontext.getTimeout());
261 					try {
262 						result = c.execute(this);
263 					} catch (AspectRescheduleException e) {
264 						EventProcessingPool.getInstance().execute(this);
265 						return;
266 					}
267 				}
268 				try {
269 					switch (this.type) {
270 					case READ:
271 						acontext.setLocalIPoint(LocalIPoint.PostRead);
272 						GlobalAspectManager.execute(acontext);
273 						break;
274 					case WRITE:
275 						acontext.setLocalIPoint(LocalIPoint.PostWrite);
276 						GlobalAspectManager.execute(acontext);
277 						break;
278 					case TAKE:
279 						acontext.setLocalIPoint(LocalIPoint.PostTake);
280 						GlobalAspectManager.execute(acontext);
281 						break;
282 					case SHIFT:
283 						acontext.setLocalIPoint(LocalIPoint.PostShift);
284 						GlobalAspectManager.execute(acontext);
285 						break;
286 					case DESTROY:
287 						acontext.setLocalIPoint(LocalIPoint.PostDestroy);
288 						GlobalAspectManager.execute(acontext);
289 						break;
290 					default:
291 					}
292 					this.setResult(result);
293 				} catch (Exception e) {
294 					this.setResult(new FatalException(
295 							"Aspect result not allowed here. " + e));
296 				}
297 			} catch (CountNotMetException e) {
298 				// ignore
299 			} catch (TransactionLockException e) {
300 				// ignore
301 			} catch (ContainerFullException e) {
302 				// ignore
303 			}
304 		} catch (Exception e) {
305 			logger.error("run() Unexpected Exception occured:" + e);
306 			this.setResult(new FatalException(e));
307 		}
308 	}
309 
310 	/***
311 	 * Get the type of this OperationTask.
312 	 * 
313 	 * @return the type
314 	 */
315 	public OperationTaskType getType() {
316 		return type;
317 	}
318 
319 	/***
320 	 * Set the type of this OperationTask.
321 	 * 
322 	 * @param type
323 	 *            the type to set
324 	 */
325 	public void setType(OperationTaskType type) {
326 		this.type = type;
327 	}
328 
329 	/***
330 	 * Get the cref of this OperationTask.
331 	 * 
332 	 * @return the cref
333 	 */
334 	public ContainerRef getCref() {
335 		return cref;
336 	}
337 
338 	/***
339 	 * Set the cref of this OperationTask.
340 	 * 
341 	 * @param cref
342 	 *            the cref to set
343 	 */
344 	public void setCref(ContainerRef cref) {
345 		this.cref = cref;
346 	}
347 
348 	/***
349 	 * Get the tx of this OperationTask.
350 	 * 
351 	 * @return the tx
352 	 */
353 	public Transaction getTx() {
354 		return tx;
355 	}
356 
357 	/***
358 	 * Set the tx of this OperationTask.
359 	 * 
360 	 * @param tx
361 	 *            the tx to set
362 	 */
363 	public void setTx(Transaction tx) {
364 		this.tx = tx;
365 	}
366 
367 	/***
368 	 * Get the selectors of this OperationTask.
369 	 * 
370 	 * @return the selectors
371 	 */
372 	public List<Selector> getSelectors() {
373 		return selectors;
374 	}
375 
376 	/***
377 	 * Set the selectors of this OperationTask.
378 	 * 
379 	 * @param selectors
380 	 *            the selectors to set
381 	 */
382 	public void setSelectors(List<Selector> selectors) {
383 		this.selectors = selectors;
384 	}
385 
386 	/***
387 	 * Get the entries of this OperationTask.
388 	 * 
389 	 * @return the entries
390 	 */
391 	public List<Entry> getEntries() {
392 		return entries;
393 	}
394 
395 	/***
396 	 * Set the entries of this OperationTask.
397 	 * 
398 	 * @param entries
399 	 *            the entries to set
400 	 */
401 	public void setEntries(List<Entry> entries) {
402 		this.entries = entries;
403 	}
404 
405 	/***
406 	 * Get the retrycount of this OperationTask.
407 	 * 
408 	 * @return the retrycount
409 	 */
410 	public int getRetrycount() {
411 		return retrycount;
412 	}
413 
414 	/***
415 	 * Set the retrycount of this OperationTask.
416 	 * 
417 	 * @param retrycount
418 	 *            the retrycount to set
419 	 */
420 	public void setRetrycount(int retrycount) {
421 		this.retrycount = retrycount;
422 	}
423 
424 	/***
425 	 * Get the timeout of this OperationTask.
426 	 * 
427 	 * @return the timeout
428 	 */
429 	public long getTimeout() {
430 		return timeout;
431 	}
432 
433 	/***
434 	 * Set the timeout of this OperationTask.
435 	 * 
436 	 * @param timeout
437 	 *            the timeout to set
438 	 */
439 	public void setTimeout(long timeout) {
440 		this.timeout = timeout;
441 	}
442 
443 	/***
444 	 * Calculates the remaining timeout.
445 	 */
446 	public void updateTimeout() {
447 		if (this.timeout != ICapi.INFINITE_TIMEOUT) {
448 			long now = System.currentTimeMillis();
449 			long timepassed = now - this.lastTimeoutUpdate;
450 			this.timeout = timeout - timepassed;
451 			// it could happen that the timeout is now -1 (== INFINITE_TIMEOUT)
452 			// if this happens, set the timeout to 0
453 			if (this.timeout == ICapi.INFINITE_TIMEOUT) {
454 				this.timeout = 0;
455 			}
456 			this.lastTimeoutUpdate = now;
457 		}
458 	}
459 
460 	/***
461 	 * Returns <code>true</code> if the timeout of this task has been expired,
462 	 * otherwise <code>false</code>.
463 	 * 
464 	 * @return <code>true</code> if the timeout of this task has been expired.
465 	 */
466 	public boolean timeoutExpired() {
467 		if (this.timeout == ICapi.INFINITE_TIMEOUT) {
468 			return false;
469 		}
470 		return this.timeout <= 0;
471 	}
472 
473 	/***
474 	 * {@inheritDoc}
475 	 * 
476 	 * @see java.lang.Object#toString()
477 	 */
478 	public String toString() {
479 		return "[OperationTask: " + this.getType().toString() + " cref: "
480 				+ this.cref + " selectors " + this.selectors + " entries "
481 				+ this.entries + ", timeout " + this.timeout + "]";
482 	}
483 
484 	/***
485 	 * Get the deleted of this OperationTask.
486 	 * 
487 	 * @return the deleted
488 	 */
489 	public List<Entry> getDeleted() {
490 		return deleted;
491 	}
492 
493 	/***
494 	 * Set the deleted of this OperationTask.
495 	 * 
496 	 * @param deleted
497 	 *            the deleted to set
498 	 */
499 	public void setDeleted(List<Entry> deleted) {
500 		this.deleted = deleted;
501 	}
502 }