View Javadoc

1   package org.xvsm.internal;
2   
3   import java.net.URI;
4   import java.util.ArrayList;
5   import java.util.List;
6   import java.util.Properties;
7   
8   import org.apache.log4j.Logger;
9   import org.xvsm.core.ContainerRef;
10  import org.xvsm.core.Entry;
11  import org.xvsm.core.aspect.AspectContext;
12  import org.xvsm.core.aspect.IAspect;
13  import org.xvsm.core.aspect.IPoint;
14  import org.xvsm.core.aspect.LocalIPoint;
15  import org.xvsm.interfaces.ICapi;
16  import org.xvsm.interfaces.ICoordinator;
17  import org.xvsm.interfaces.container.IContainerEngine;
18  import org.xvsm.interfaces.container.ITransactionLayer;
19  import org.xvsm.internal.exceptions.AspectNotOkException;
20  import org.xvsm.internal.exceptions.AspectRescheduleException;
21  import org.xvsm.internal.exceptions.AspectSkipException;
22  import org.xvsm.internal.exceptions.ContainerFullException;
23  import org.xvsm.internal.exceptions.CountNotMetException;
24  import org.xvsm.internal.exceptions.FatalException;
25  import org.xvsm.internal.exceptions.InvalidContainerException;
26  import org.xvsm.internal.exceptions.InvalidTransactionException;
27  import org.xvsm.internal.exceptions.NoSuchCoordinationTypeException;
28  import org.xvsm.internal.exceptions.TransactionLockException;
29  import org.xvsm.internal.exceptions.XCoreException;
30  import org.xvsm.internal.tasks.TransactionTask;
31  import org.xvsm.internal.tasks.TransactionTaskType;
32  import org.xvsm.selectors.Selector;
33  import org.xvsm.transactions.Transaction;
34  import org.xvsm.transactions.TransactionManager;
35  
36  /***
37   * Static class used to manage {@link Transaction}s.
38   * 
39   * @author Christian Schreiber, Michael Proestler
40   * 
41   */
42  public class TransactionLayer implements ITransactionLayer {
43  
44  	/***
45  	 * The logger for this class.
46  	 */
47  	private static Logger logger = Logger.getLogger(ITransactionLayer.class);
48  
49  	/***
50  	 * The container for this transaction manager.
51  	 */
52  	private IContainerEngine c;
53  
54  	/***
55  	 * The aspect manager for this container.
56  	 */
57  	private AspectManager aspectManager = new AspectManager();
58  
59  	/***
60  	 * Default constructor.
61  	 */
62  	public TransactionLayer() {
63  		c = new ContainerEngine();
64  	}
65  
66  	/***
67  	 * Default constructor.
68  	 * 
69  	 * @param size
70  	 *            the size of the container.
71  	 */
72  	public TransactionLayer(int size) {
73  		c = new ContainerEngine(size);
74  	}
75  
76  	/***
77  	 * Commits a sub transaction and updates the locks (sets the lock to
78  	 * tx.getFather()). The commit method of the container is called too.
79  	 * 
80  	 * @param tx
81  	 *            the transaction to commit.
82  	 * @throws TransactionLockException
83  	 *             thrown if a lock cannot be aquired.
84  	 */
85  	private void commitSubtransaction(Transaction tx)
86  			throws TransactionLockException {
87  		if (logger.isDebugEnabled()) {
88  			logger.debug("commitSubtransaction(" + tx + ") -- "
89  					+ this.getCref());
90  		}
91  
92  		Transaction father = tx.getFather();
93  		// if (father == null) {
94  		// throw new IllegalArgumentException(tx
95  		// + " has not a child transaction");
96  		// }
97  
98  		c.commitSubTransaction(tx);
99  
100 		// copy the information from the child to the father.
101 		for (ContainerRef cref : tx.getModifiedContainers()) {
102 			father.addContainerRef(cref);
103 		}
104 		for (ICoordinator coord : tx.getModifiedCoordinators()) {
105 			father.addCoordinator(coord);
106 		}
107 		TransactionManager.getInstance().removeTransaction(tx);
108 
109 		if (logger.isDebugEnabled()) {
110 			logger.debug("commitSubtransaction() transaction commited -- "
111 					+ this.getCref());
112 		}
113 	}
114 
115 	/***
116 	 * Rolls back a sub transaction.
117 	 * 
118 	 * @param tx
119 	 *            The transaction to roll back.
120 	 * @throws TransactionLockException
121 	 *             thrown if a lock cannot be aquired.
122 	 */
123 	private void rollbackSubtransaction(Transaction tx)
124 			throws TransactionLockException {
125 		if (logger.isDebugEnabled()) {
126 			logger.debug("rollbackSubtransaction(" + tx + ") -- "
127 					+ this.getCref());
128 		}
129 
130 		// if (tx.getFather() == null) {
131 		// throw new IllegalArgumentException(tx
132 		// + " has not a child transaction");
133 		// }
134 
135 		c.rollback(tx);
136 		TransactionManager.getInstance().removeTransaction(tx);
137 		if (logger.isDebugEnabled()) {
138 			logger.debug("rollbackSubtransaction() transaction rolled back -- "
139 					+ this.getCref());
140 		}
141 	}
142 
143 	/***
144 	 * {@inheritDoc}.
145 	 */
146 	public void commit(Transaction tx) throws TransactionLockException,
147 			InvalidTransactionException, AspectRescheduleException,
148 			AspectNotOkException {
149 		if (logger.isDebugEnabled()) {
150 			logger.debug("commit(" + tx + ") -- " + this.getCref());
151 		}
152 
153 		if (tx == null) {
154 			throw new IllegalArgumentException("Can not commit transaction "
155 					+ tx);
156 		}
157 		if (tx.getFather() != null) {
158 			throw new IllegalArgumentException(
159 					"Can not commit a child transaction.");
160 		}
161 		tx = this.initTransaction(tx);
162 		// this.acquireContainerLock(tx);
163 
164 		this.c.commit(tx);
165 
166 		// remove this container from the transaction.
167 		tx.removeContainerRef(this.getCref());
168 
169 		// TransactionManager.getInstance().removeTransaction(tx);
170 		if (logger.isDebugEnabled()) {
171 			logger.debug("commit() transaction commited -- " + this.getCref());
172 		}
173 	}
174 
175 	/***
176 	 * {@inheritDoc}.
177 	 */
178 	public void rollback(Transaction tx) throws InvalidTransactionException,
179 			TransactionLockException, AspectRescheduleException,
180 			AspectNotOkException {
181 		if (logger.isDebugEnabled()) {
182 			logger.debug("rollback(" + tx + ") -- " + this.getCref());
183 		}
184 		if (tx == null) {
185 			throw new IllegalArgumentException("Can not rollback transaction "
186 					+ tx);
187 		}
188 		if (tx.getFather() != null) {
189 			throw new IllegalArgumentException(
190 					"Can not commit a child transaction.");
191 		}
192 		tx = this.initTransaction(tx);
193 		// this.acquireContainerLock(tx);
194 
195 		c.rollback(tx);
196 
197 		// remove this container from the transaction.
198 		tx.removeContainerRef(this.getCref());
199 
200 		if (logger.isDebugEnabled()) {
201 			logger.debug("rollback() transaction rolled back -- "
202 					+ this.getCref());
203 		}
204 	}
205 
206 	/***
207 	 * {@inheritDoc}.
208 	 */
209 	public ICoordinator getCoordTypefromSelector(Class<? extends Selector> s)
210 			throws NoSuchCoordinationTypeException {
211 		return c.getCoordTypefromSelector(s);
212 	}
213 
214 	/***
215 	 * {@inheritDoc}.
216 	 */
217 	public int getSize() {
218 		return c.getSize();
219 	}
220 
221 	/***
222 	 * {@inheritDoc}.
223 	 */
224 	public List<Entry> read(Transaction tx, List<Selector> selectors,
225 			int retrycount, Properties aspectContext)
226 			throws NoSuchCoordinationTypeException, CountNotMetException,
227 			InvalidTransactionException, TransactionLockException,
228 			AspectRescheduleException, AspectNotOkException {
229 
230 		if (logger.isDebugEnabled()) {
231 			logger.debug("read(" + tx + ", " + selectors + "," + retrycount
232 					+ ", " + aspectContext + ") -- " + this.getCref());
233 		}
234 		Transaction stx = null;
235 		try {
236 			// Check if the Transaction is valid, or create an implicit one.
237 			tx = this.initTransaction(tx);
238 
239 			boolean skip = false;
240 			AspectContext acontext = new AspectContext(LocalIPoint.PreRead,
241 					this.getCref(), tx, selectors, null, null, retrycount,
242 					aspectContext);
243 			try { // PreRead
244 				this.executeAspect(acontext);
245 			} catch (AspectRescheduleException e) {
246 				this.rollbackSubtransaction(acontext.getTx());
247 				throw e;
248 			} catch (AspectNotOkException e) {
249 				try {
250 					TransactionManager.getInstance().rollbackTransaction(
251 							acontext.getTx());
252 				} catch (XCoreException e1) {
253 					throw new FatalException(e1);
254 				}
255 				throw e;
256 			} catch (AspectSkipException e) {
257 				skip = true;
258 			}
259 			// the arguments could have been modified in the aspect.
260 			tx = acontext.getTx();
261 
262 			stx = TransactionManager.getInstance().createSubTransaction(tx);
263 
264 			selectors = acontext.getSelectors();
265 			retrycount = acontext.getRetrycount();
266 
267 			List<Entry> result = new ArrayList<Entry>();
268 			if (!skip) {
269 				result = c.read(stx, selectors);
270 
271 				// Set the locks.
272 				for (Entry e : result) {
273 					for (Selector s : e.getSelectors()) {
274 						tx.addCoordinator(c.getCoordTypefromSelector(s
275 								.getClass()));
276 					}
277 				}
278 
279 			}
280 			try { // PostRead
281 				acontext.setLocalIPoint(LocalIPoint.PostRead);
282 				acontext.setEntries(result);
283 				this.executeAspect(acontext);
284 			} catch (AspectRescheduleException e) {
285 				this.rollbackSubtransaction(stx);
286 				throw e;
287 			} catch (AspectNotOkException e) {
288 				try {
289 					TransactionManager.getInstance().rollbackTransaction(
290 							acontext.getTx());
291 				} catch (XCoreException e1) {
292 					throw new FatalException(e1);
293 				}
294 				throw e;
295 			} catch (AspectSkipException e) {
296 				try {
297 					TransactionManager.getInstance().rollbackTransaction(
298 							acontext.getTx());
299 				} catch (XCoreException e1) {
300 					throw new FatalException(e1);
301 				}
302 				throw new FatalException(
303 						"SKIP not allowed as answer of a post aspect.");
304 			}
305 			this.commitSubtransaction(stx);
306 			tx = acontext.getTx();
307 			// commit if we used an implicit transaction.
308 			if (tx.isImplicit()) {
309 				try {
310 					TransactionManager.getInstance().commitTransaction(tx);
311 				} catch (XCoreException e) {
312 					throw new FatalException(e);
313 				}
314 			}
315 
316 			if (logger.isDebugEnabled()) {
317 				logger.debug("read() entries read: " + acontext.getEntries()
318 						+ " -- " + this.getCref());
319 			}
320 
321 			return acontext.getEntries();
322 		} catch (CountNotMetException e) {
323 			if (logger.isDebugEnabled()) {
324 				logger.debug("read() CountNotMetException was thrown " + e
325 						+ " -- " + this.getCref());
326 			}
327 			this.rollbackSubtransaction(stx);
328 			throw e;
329 		} catch (TransactionLockException e) {
330 			if (logger.isDebugEnabled()) {
331 				logger.debug("read() TransactionLockException " + e + " -- "
332 						+ this.getCref());
333 			}
334 			this.rollbackSubtransaction(stx);
335 			throw e;
336 		}
337 	}
338 
339 	/***
340 	 * {@inheritDoc}.
341 	 */
342 	public List<Entry> shift(List<Entry> entries, Transaction tx,
343 			Properties aspectContext) throws NoSuchCoordinationTypeException,
344 			InvalidTransactionException, TransactionLockException,
345 			AspectRescheduleException, AspectNotOkException {
346 		if (logger.isDebugEnabled()) {
347 			logger.debug("shift(" + entries + ", " + tx + ", " + aspectContext
348 					+ ") -- " + this.getCref());
349 		}
350 		Transaction stx = null;
351 		try {
352 			// Check if the Transaction is valid, or create an implicit one.
353 			tx = this.initTransaction(tx);
354 
355 			AspectContext acontext = new AspectContext(LocalIPoint.PreShift,
356 					this.getCref(), tx, null, entries, null, 0, aspectContext);
357 			boolean skip = false;
358 			try { // PreShift
359 				this.executeAspect(acontext);
360 			} catch (AspectRescheduleException e) {
361 				this.rollbackSubtransaction(acontext.getTx());
362 				throw e;
363 			} catch (AspectNotOkException e) {
364 				try {
365 					TransactionManager.getInstance().rollbackTransaction(
366 							acontext.getTx());
367 				} catch (XCoreException e1) {
368 					throw new FatalException(e1);
369 				}
370 				throw e;
371 			} catch (AspectSkipException e) {
372 				skip = true;
373 			}
374 			entries = acontext.getEntries();
375 			tx = acontext.getTx();
376 
377 			stx = TransactionManager.getInstance().createSubTransaction(tx);
378 
379 			List<Entry> shifted = null;
380 			if (!skip) {
381 				shifted = new ArrayList<Entry>();
382 				for (Entry e : entries) {
383 
384 					shifted.addAll(this.c.shift(e, stx));
385 
386 					for (Selector s : e.getSelectors()) {
387 						stx.addCoordinator(c.getCoordTypefromSelector(s
388 								.getClass()));
389 					}
390 				}
391 
392 				// Set the locks on the deleted entries.
393 				for (Entry en : shifted) {
394 					for (Selector s : en.getSelectors()) {
395 						stx.addCoordinator(c.getCoordTypefromSelector(s
396 								.getClass()));
397 					}
398 				}
399 			}
400 			acontext.setDeleted(shifted);
401 
402 			try { // PostShift
403 				acontext.setLocalIPoint(LocalIPoint.PostShift);
404 				this.executeAspect(acontext);
405 			} catch (AspectRescheduleException e) {
406 				this.rollbackSubtransaction(stx);
407 				throw e;
408 			} catch (AspectNotOkException e) {
409 				try {
410 					TransactionManager.getInstance().rollbackTransaction(
411 							acontext.getTx());
412 				} catch (XCoreException e1) {
413 					throw new FatalException(e1);
414 				}
415 				throw e;
416 			} catch (AspectSkipException e) {
417 				try {
418 					TransactionManager.getInstance().rollbackTransaction(
419 							acontext.getTx());
420 				} catch (XCoreException e1) {
421 					throw new FatalException(e1);
422 				}
423 				throw new FatalException(
424 						"SKIP not allowed as answer of a post aspect.");
425 			}
426 			this.commitSubtransaction(stx);
427 			tx = acontext.getTx();
428 			// commit if we used an implicit transaction.
429 			if (tx.isImplicit()) {
430 				try {
431 					TransactionManager.getInstance().commitTransaction(tx);
432 				} catch (XCoreException e) {
433 					throw new FatalException(e);
434 				}
435 			}
436 
437 			if (logger.isDebugEnabled()) {
438 				logger.debug("shift() entries shifted: "
439 						+ acontext.getDeleted());
440 			}
441 			return acontext.getDeleted();
442 		} catch (TransactionLockException e) {
443 			if (logger.isDebugEnabled()) {
444 				logger.debug("shift() TransactionLockException " + e + " -- "
445 						+ this.getCref());
446 			}
447 			this.rollbackSubtransaction(stx);
448 			throw e;
449 		}
450 
451 	}
452 
453 	/***
454 	 * {@inheritDoc}.
455 	 */
456 	public List<Entry> take(boolean isDelete, Transaction tx,
457 			List<Selector> selectors, int retrycount, Properties aspectContext)
458 			throws NoSuchCoordinationTypeException, CountNotMetException,
459 			InvalidTransactionException, TransactionLockException,
460 			AspectRescheduleException, AspectNotOkException {
461 		if (logger.isDebugEnabled()) {
462 			logger.debug("take(" + isDelete + ", " + tx + ", " + selectors
463 					+ ", " + retrycount + ", " + aspectContext + ") -- "
464 					+ this.getCref());
465 		}
466 
467 		Transaction stx = null;
468 		try {
469 			tx = this.initTransaction(tx);
470 
471 			AspectContext acontext = new AspectContext(
472 					isDelete ? LocalIPoint.PreDestroy : LocalIPoint.PreTake,
473 					this.getCref(), tx, selectors, null, null, retrycount,
474 					aspectContext);
475 			boolean skip = false;
476 			try { // PreTake, PreDelete
477 				this.executeAspect(acontext);
478 			} catch (AspectRescheduleException e) {
479 				this.rollbackSubtransaction(acontext.getTx());
480 				throw e;
481 			} catch (AspectNotOkException e) {
482 				try {
483 					TransactionManager.getInstance().rollbackTransaction(
484 							acontext.getTx());
485 				} catch (XCoreException e1) {
486 					throw new FatalException(e1);
487 				}
488 				throw e;
489 			} catch (AspectSkipException e) {
490 				skip = true;
491 			}
492 			tx = acontext.getTx();
493 			stx = TransactionManager.getInstance().createSubTransaction(tx);
494 			selectors = acontext.getSelectors();
495 			retrycount = acontext.getRetrycount();
496 
497 			List<Entry> entries = null;
498 			if (!skip) {
499 				// Get the list of entries.
500 				entries = c.take(stx, selectors);
501 				// Set the locks.
502 				for (Entry e : entries) {
503 					for (Selector s : e.getSelectors()) {
504 						stx.addCoordinator(c.getCoordTypefromSelector(s
505 								.getClass()));
506 					}
507 				}
508 			}
509 			acontext.setDeleted(entries);
510 			try { // PostTake, PostDelete
511 				acontext.setLocalIPoint(isDelete ? LocalIPoint.PostDestroy
512 						: LocalIPoint.PostTake);
513 				this.executeAspect(acontext);
514 			} catch (AspectRescheduleException e) {
515 				this.rollbackSubtransaction(stx);
516 				throw e;
517 			} catch (AspectNotOkException e) {
518 				try {
519 					TransactionManager.getInstance().rollbackTransaction(
520 							acontext.getTx());
521 				} catch (XCoreException e1) {
522 					throw new FatalException(e1);
523 				}
524 				throw e;
525 			} catch (AspectSkipException e) {
526 				try {
527 					TransactionManager.getInstance().rollbackTransaction(
528 							acontext.getTx());
529 				} catch (XCoreException e1) {
530 					throw new FatalException(e1);
531 				}
532 				throw new FatalException(
533 						"SKIP not allowed as answer of a post aspect.");
534 			}
535 			this.commitSubtransaction(stx);
536 			tx = acontext.getTx();
537 			// commit if we used an implicit transaction.
538 			if (tx.isImplicit()) {
539 				try {
540 					TransactionManager.getInstance().commitTransaction(tx);
541 				} catch (XCoreException e) {
542 					throw new FatalException(e);
543 				}
544 			}
545 
546 			if (logger.isDebugEnabled()) {
547 				logger.debug("take() entries taken: " + acontext.getDeleted()
548 						+ " -- " + this.getCref());
549 			}
550 
551 			return acontext.getDeleted();
552 		} catch (CountNotMetException e) {
553 			if (logger.isDebugEnabled()) {
554 				logger.debug("take() CountNotMetException was thrown: " + e
555 						+ " -- " + this.getCref());
556 			}
557 			this.rollbackSubtransaction(stx);
558 			throw e;
559 		} catch (TransactionLockException e) {
560 			if (logger.isDebugEnabled()) {
561 				logger.debug("take() TransactionLockException " + e + " -- "
562 						+ this.getCref());
563 			}
564 			this.rollbackSubtransaction(stx);
565 			throw e;
566 		}
567 	}
568 
569 	/***
570 	 * Writes one Entry. The method uses a sub transaction for writing the entry
571 	 * to ensure the all coordinators a rolled back if one coordinator can not
572 	 * write the entry.
573 	 * 
574 	 * @param e
575 	 *            the entry to write.
576 	 * @param tx
577 	 *            the transaction for the operation.
578 	 * @throws ContainerFullException
579 	 *             thrown when the entry can not be written because there is no
580 	 *             free place for it (e.g. full bounded container, vector
581 	 *             position already used, key already present).
582 	 * @throws NoSuchCoordinationTypeException
583 	 *             thrown when there is a selector which needs a coordination
584 	 *             type which has not been activated on the container
585 	 * @throws TransactionLockException
586 	 *             if an entry or container is locked by another transaction.
587 	 */
588 	private void write(Entry e, Transaction tx) throws ContainerFullException,
589 			TransactionLockException, NoSuchCoordinationTypeException {
590 		if (logger.isDebugEnabled()) {
591 			logger.debug("write(" + e + ", " + tx + ") -- " + this.getCref());
592 		}
593 
594 		// Every entry has to be written under one child tx.
595 		// otherwise we could not roll back coordinators if one coordinator can
596 		// not write.
597 		Transaction stx = TransactionManager.getInstance()
598 				.createSubTransaction(tx);
599 
600 		try {
601 			c.write(e, stx);
602 		} catch (ContainerFullException e1) {
603 			this.rollbackSubtransaction(stx);
604 			throw e1;
605 		} catch (TransactionLockException e1) {
606 			this.rollbackSubtransaction(stx);
607 			throw e1;
608 		} catch (NoSuchCoordinationTypeException e1) {
609 			this.rollbackSubtransaction(stx);
610 			throw e1;
611 		}
612 
613 		for (Selector s : e.getSelectors()) {
614 			stx.addCoordinator(c.getCoordTypefromSelector(s.getClass()));
615 		}
616 
617 		this.commitSubtransaction(stx);
618 
619 		if (logger.isDebugEnabled()) {
620 			logger.debug("write() entry written -- " + this.getCref());
621 		}
622 
623 	}
624 
625 	/***
626 	 * {@inheritDoc}.
627 	 */
628 	public void write(List<Entry> entries, Transaction tx, int retrycount,
629 			Properties aspectContext) throws ContainerFullException,
630 			TransactionLockException, NoSuchCoordinationTypeException,
631 			InvalidTransactionException, AspectRescheduleException,
632 			AspectNotOkException {
633 		if (logger.isDebugEnabled()) {
634 			logger.debug("write(" + entries + ", " + tx + ", " + retrycount
635 					+ ", " + aspectContext + ") -- " + this.getCref());
636 		}
637 
638 		// Check if the Transaction is valid, or create an implicit one.
639 		tx = this.initTransaction(tx);
640 		Transaction stx = null;
641 		try {
642 			AspectContext acontext = new AspectContext(LocalIPoint.PreWrite,
643 					this.getCref(), tx, null, entries, null, retrycount,
644 					aspectContext);
645 			boolean skip = false;
646 			try { // PreWrite
647 				this.executeAspect(acontext);
648 			} catch (AspectRescheduleException e) {
649 				this.rollbackSubtransaction(acontext.getTx());
650 				throw e;
651 			} catch (AspectNotOkException e) {
652 				try {
653 					TransactionManager.getInstance().rollbackTransaction(
654 							acontext.getTx());
655 				} catch (XCoreException e1) {
656 					throw new FatalException(e1);
657 				}
658 				throw e;
659 			} catch (AspectSkipException e) {
660 				skip = true;
661 			}
662 			tx = acontext.getTx();
663 			entries = acontext.getEntries();
664 			retrycount = acontext.getRetrycount();
665 			// A bulk operation has to be performed under ONE child
666 			// transaction.
667 			stx = TransactionManager.getInstance().createSubTransaction(tx);
668 
669 			if (!skip) {
670 				for (Entry e : entries) {
671 					this.write(e, stx);
672 				}
673 			}
674 			try { // PostWrite
675 				acontext.setLocalIPoint(LocalIPoint.PostWrite);
676 				this.executeAspect(acontext);
677 			} catch (AspectRescheduleException e) {
678 				this.rollbackSubtransaction(stx);
679 				throw e;
680 			} catch (AspectNotOkException e) {
681 				try {
682 					TransactionManager.getInstance().rollbackTransaction(
683 							acontext.getTx());
684 				} catch (XCoreException e1) {
685 					throw new FatalException(e1);
686 				}
687 				throw e;
688 			} catch (AspectSkipException e) {
689 				// FIXME: what is to do here??
690 				try {
691 					TransactionManager.getInstance().rollbackTransaction(
692 							acontext.getTx());
693 				} catch (XCoreException e1) {
694 					throw new FatalException(e1);
695 				}
696 				throw new FatalException(
697 						"SKIP not allowed as answer of a post aspect.");
698 			}
699 			tx = acontext.getTx();
700 			// commit the subtransaction.
701 			this.commitSubtransaction(stx);
702 
703 			if (tx.isImplicit()) {
704 				try {
705 					TransactionManager.getInstance().commitTransaction(tx);
706 				} catch (XCoreException e) {
707 					throw new FatalException(e);
708 				}
709 			}
710 		} catch (ContainerFullException e1) {
711 			if (logger.isDebugEnabled()) {
712 				logger.debug("write() NoPlaceLeftException was thrown: " + e1
713 						+ " -- " + this.getCref());
714 			}
715 			this.rollbackSubtransaction(stx);
716 			if (tx.isImplicit()) {
717 				try {
718 					TransactionManager.getInstance().rollbackTransaction(tx);
719 				} catch (XCoreException e) {
720 					throw new FatalException(e);
721 				}
722 			}
723 			throw e1;
724 		} catch (TransactionLockException e) {
725 			if (logger.isDebugEnabled()) {
726 				logger.debug("write() TransactionLockException " + e + " -- "
727 						+ this.getCref() + " Reason: " + e.getReason());
728 			}
729 			this.rollbackSubtransaction(stx);
730 			throw e;
731 		}
732 
733 		if (logger.isDebugEnabled()) {
734 			logger.debug("write() entries written -- " + this.getCref());
735 		}
736 
737 	}
738 
739 	/***
740 	 * Checks if the transaction is valid. If tx is <code>null</code> a new
741 	 * implicit transaction will be created and returned.<br>
742 	 * The returned transaction has to be used for the work.
743 	 * 
744 	 * @param tx
745 	 *            the transaction to check.
746 	 * @return the transaction which has to be used.
747 	 * @throws InvalidTransactionException
748 	 *             if tx is invalid
749 	 */
750 	private Transaction initTransaction(Transaction tx)
751 			throws InvalidTransactionException {
752 		// check if we have to use an implicit transaction.
753 		if (tx == null) {
754 			tx = TransactionManager.getInstance().createImplicitTransaction(
755 					ICapi.INFINITE_TIMEOUT);
756 		}
757 
758 		// is this a valid transaction?
759 		if (!TransactionManager.getInstance().isValid(tx)) {
760 			throw new InvalidTransactionException("Unknown Transaction: " + tx);
761 
762 		}
763 
764 		tx.addContainerRef(this.getCref());
765 
766 		return tx;
767 	}
768 
769 	/***
770 	 * {@inheritDoc}.
771 	 */
772 	public ContainerRef getCref() {
773 		return c.getCref();
774 	}
775 
776 	/***
777 	 * {@inheritDoc}.
778 	 */
779 	public void setCref(ContainerRef cref) {
780 		c.setCref(cref);
781 	}
782 
783 	/***
784 	 * Creates an AspectContext and executes the aspects.
785 	 * 
786 	 * @param context
787 	 *            the aspect context.
788 	 * @throws AspectNotOkException
789 	 *             thrown if the operation has to be rescheduled.
790 	 * @throws AspectRescheduleException
791 	 *             thrown if the operation has to be undone and the transaction
792 	 *             has to be rolled back.
793 	 * @throws AspectSkipException
794 	 *             thrown if the operation shall be skiped.
795 	 */
796 	private void executeAspect(AspectContext context)
797 			throws AspectNotOkException, AspectRescheduleException,
798 			AspectSkipException {
799 		// remember the tx.
800 		Transaction tx = context.getTx();
801                 
802 		// give the aspect the "highest" transaction and make sure that it is
803 		// not implicit (it would be committed when it is used to write into a
804 		// container).
805 		Transaction ntx = context.getTx();
806 		while (ntx.getFather() != null) {
807 			ntx = ntx.getFather();
808 		}
809 		boolean implicit = tx.isImplicit();
810 		ntx.setImplicit(false);
811 		context.setTx(ntx);
812 
813                 // put the originall Transaction into the AspectContext
814                 Properties aspectContext = context.getAspectContext();
815             
816                 if (aspectContext == null) {
817                     aspectContext = new Properties();
818                     context.setAspectContext(aspectContext);
819                 }
820                 
821                 aspectContext.put("Transaction", tx);
822                 aspectContext.put("TxnIsImplicit", new Boolean(implicit));
823                 
824 
825                 try {
826 			this.aspectManager.execute(context);
827 		} finally {
828 			// if the tx has not been modified in the aspect
829 			//if (!context.getTx().equals(ntx)) {
830 				// reset the tx in the context.
831 				context.setTx(tx);
832 			//}
833                         
834 			// reset implicit
835 			tx.setImplicit(implicit);
836                         
837             // remove the Transaction again from the AspectContext
838             context.getAspectContext().remove("Transaction");
839             context.getAspectContext().remove("TxnIsImplicit");
840 		}
841 	}
842 
843 	/***
844 	 * 
845 	 * {@inheritDoc}.
846 	 */
847 	// @Override
848 	public String addAspects(List<IPoint> points, IAspect aspect,
849 			Properties aspectContext) {
850 		AspectContext acontext = new AspectContext(LocalIPoint.PreAddAspect,
851 				points, aspect, aspectContext);
852 		boolean skip = false;
853 		String id = null;
854 		try {
855 			this.aspectManager.execute(acontext);
856 		} catch (AspectNotOkException e) {
857 			// TODO realy have to throw the exception?
858 			throw new FatalException(
859 					"Aspect is not allowed to answer NotOk here.");
860 		} catch (AspectRescheduleException e) {
861 			throw new FatalException(
862 					"Aspect is not allowed to answer Delay here.");
863 		} catch (AspectSkipException e) {
864 			skip = true;
865 		}
866 		if (!skip) {
867 			for (IPoint p : acontext.getIpoints()) {
868 				id = this.aspectManager.addAspect(p, acontext.getAspect());
869 			}
870 		}
871 		acontext.setLocalIPoint(LocalIPoint.PostAddAspect);
872 		try {
873 			this.aspectManager.execute(acontext);
874 		} catch (Exception e) {
875 			throw new FatalException(
876 					"Aspect is not allowed to answer with something else then OK!");
877 		}
878 		return id;
879 	}
880 
881 	/***
882 	 * 
883 	 * {@inheritDoc}.
884 	 */
885 	// @Override
886 	public void removeAspect(IPoint p, URI uri, Properties aspectContext) {
887 		AspectContext acontext = new AspectContext(LocalIPoint.PreRemoveAspect,
888 				java.util.Arrays.asList(new IPoint[] { p }), uri, aspectContext);
889 		boolean skip = false;
890 		try {
891 			this.aspectManager.execute(acontext);
892 		} catch (AspectNotOkException e) {
893 			// TODO really have to throw the exception?
894 			throw new FatalException(
895 					"Aspect is not allowed to answer NotOk here.");
896 		} catch (AspectRescheduleException e) {
897 			throw new FatalException(
898 					"Aspect is not allowed to answer Delay here.");
899 		} catch (AspectSkipException e) {
900 			skip = true;
901 		}
902 		if (!skip) {
903 			for (IPoint pp : acontext.getIpoints()) {
904 				this.aspectManager.removeAspect(pp, acontext.getAspectURI());
905 			}
906 		}
907 		try {
908 			acontext.setLocalIPoint(LocalIPoint.PostRemoveAspect);
909 			this.aspectManager.execute(acontext);
910 		} catch (Exception e) {
911 			// TODO realy have to throw the exception?
912 
913 			throw new FatalException(
914 					"Aspect is not allowed to answer with something else then OK!");
915 		}
916 	}
917 
918 	/***
919 	 * {@inheritDoc}
920 	 */
921 	// @Override
922 	public void addCoordinator(Class<? extends Selector> s, ICoordinator coord) {
923 		this.c.addCoordinator(s, coord);
924 	}
925 
926 	/***
927 	 * {@inheritDoc}
928 	 */
929 	// @Override
930 	public List<ICoordinator> getCoordinators() {
931 		// TODO Auto-generated method stub
932 		return null;
933 	}
934 
935 	/***
936 	 * {@inheritDoc}
937 	 */
938 	public int currentSize() {
939 		return c.currentSize();
940 	}
941 }