View Javadoc

1   package org.xvsm.coordinators;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.List;
6   import java.util.Random;
7   
8   import org.apache.log4j.Logger;
9   import org.xvsm.core.Entry;
10  import org.xvsm.interfaces.IExplicitCoordinator;
11  import org.xvsm.interfaces.container.IContainer;
12  import org.xvsm.internal.exceptions.CannotShiftException;
13  import org.xvsm.internal.exceptions.ContainerFullException;
14  import org.xvsm.internal.exceptions.CountNotMetException;
15  import org.xvsm.internal.exceptions.TransactionLockException;
16  import org.xvsm.selectors.Selector;
17  import org.xvsm.selectors.VectorSelector;
18  import org.xvsm.transactions.Transaction;
19  
20  /***
21   * 
22   * @author Christian Schreiber, Michael Proestler
23   * 
24   */
25  public class VectorCoordinator extends IExplicitCoordinator {
26  
27  	private static Logger logger = Logger.getLogger(VectorCoordinator.class);
28  	/***
29  	 * The SerialVersionUID of this Class.
30  	 */
31  	private static final long serialVersionUID = -2474815951120951066L;
32  
33  	/***
34  	 * Entries managed by this coordinator. They are stored in fifo order in
35  	 * this list.
36  	 */
37  	private List<Entry> entries = new ArrayList<Entry>();
38  
39  	/***
40  	 * The maximum size of the container where this VectorCoordinator belongs
41  	 * to.
42  	 */
43  	private int maxSize;
44  
45  	/***
46  	 * Default Constructor.
47  	 */
48  	public VectorCoordinator() {
49  
50  	}
51  
52  	/***
53  	 * {@inheritDoc}
54  	 */
55  	@Override
56  	public void commit(Transaction tx) throws TransactionLockException {
57  
58  		for (Entry e : tx.getModifiedEntries(this.getCref())) {
59  			if (e.hasDeleteLock(tx)) {
60  				if (logger.isDebugEnabled()) {
61  
62  					logger.debug("commit() remove entry: " + e);
63  				}
64  
65  				// remove the entries which are masked as removed under this tx.
66  				// OPTIMIZE remove(Object) Runtime
67  				this.entries.remove(e);
68  			}
69  		}
70  
71  		super.commitLocks(tx);
72  	}
73  
74  	/***
75  	 * {@inheritDoc}
76  	 * 
77  	 * @throws TransactionLockException
78  	 */
79  	@Override
80  	public void commitSubTransaction(Transaction tx)
81  			throws TransactionLockException {
82  		super.commitLocks(tx);
83  	}
84  
85  	/***
86  	 * {@inheritDoc}
87  	 */
88  	@Override
89  	public void delete(Transaction tx, Entry e) throws TransactionLockException {
90  		super.aquireLock(true, tx);
91  		// super.deleteLockEntry(e, tx);
92  		// TODO Auto-generated method stub
93  
94  	}
95  
96  	/***
97  	 * {@inheritDoc}
98  	 */
99  	@Override
100 	public List<Entry> read(Transaction tx, Selector selector,
101 			List<Entry> centries) throws TransactionLockException,
102 			CountNotMetException {
103 		super.aquireLock(false, tx);
104 		int index = ((VectorSelector) selector).getIndex();
105 		if (index == VectorSelector.APPEND) {
106 			index = 0;
107 		}
108 		int count = selector.getCount();
109 
110 		List<Entry> result = new ArrayList<Entry>();
111 
112 		if (centries == null) { // Operate on all entries
113 
114 			if (this.entries.size() < index + count) {
115 				throw new CountNotMetException(
116 						"Not enough matching entries in the container");
117 			}
118 
119 			for (int i = index; i < this.entries.size(); i++) {
120 				if (!this.entries.get(i).hasDeleteLock(tx)) {
121 					// super.readLockEntry(this.entries.get(i), tx);
122 					result.add(this.entries.get(i));
123 					if (result.size() == count) {
124 						break;
125 					}
126 				}
127 			}
128 
129 			if (count != Selector.CNT_ALL && result.size() != count) {
130 				throw new CountNotMetException(
131 						"Not enough matching entries in the container");
132 			}
133 			if (logger.isDebugEnabled()) {
134 				logger.debug("Read returns: " + result);
135 				logger.debug("Entries: " + this.entries);
136 			}
137 			return result;
138 		} else { // Operate on given entries
139 			if (centries.size() < count) {
140 				throw new CountNotMetException(
141 						"Not enough matching entries in the container");
142 			}
143 
144 			List<Integer> posEntries = new ArrayList<Integer>();
145 			for (Entry e : centries) {
146 				// OPTIMIZE
147 				if (!e.hasDeleteLock(tx)) {
148 					// Entry should never have a
149 					// deleteLock. The Coordinator that
150 					// was executed before should never
151 					// have an entry with a deleteLock
152 					// in its output.
153 					int ind = this.entries.indexOf(e);
154 					if (ind >= index) {
155 						posEntries.add(ind);
156 					}
157 				}
158 			}
159 
160 			if (!posEntries.contains(index)) {
161 				throw new CountNotMetException(
162 						"Not enough matching entries in the container");
163 			}
164 			Collections.sort(posEntries);
165 
166 			for (int i = 0; i < count; i++) {
167 				if (posEntries.get(i) == null) {
168 					throw new CountNotMetException(
169 							"Not enough matching entries in the container");
170 				}
171 				if (posEntries.get(i) != (index + i)) {
172 					throw new CountNotMetException(
173 							"Not enough matching entries in the container");
174 				}
175 				// super.readLockEntry(this.entries.get(posEntries.get(i)), tx);
176 				result.add(this.entries.get(posEntries.get(i)));
177 			}
178 
179 			return result;
180 		}
181 
182 	}
183 
184 	/***
185 	 * {@inheritDoc}
186 	 */
187 	@Override
188 	public void rollback(Transaction tx) throws TransactionLockException {
189 		// the commented code does not work because we would jump over some
190 		// entries ...
191 		// for (int i = 0; i < this.entries.size(); i++) {
192 		// Entry e = this.entries.get(i);
193 		// if (e.hasWriteLock(tx)) {
194 		// this.entries.remove(i);
195 		// }
196 		// }
197 		// OPTIMIZE avoid the copy ... the code above does not work.
198 		for (Entry e : new ArrayList<Entry>(this.entries)) {
199 			if (e.hasWriteLock(tx)) {
200 				this.entries.remove(e);
201 			}
202 		}
203 		super.rollbackLocks(tx);
204 	}
205 
206 	/***
207 	 * {@inheritDoc}
208 	 */
209 	@Override
210 	public void setMaxContainerSize(int size) {
211 		this.maxSize = size;
212 	}
213 
214 	/***
215 	 * {@inheritDoc}
216 	 */
217 	@Override
218 	public Entry shift(Entry e, Transaction tx, Selector s)
219 			throws TransactionLockException, CannotShiftException {
220 		super.aquireLock(true, tx);
221 		int index;
222 		if (s == null) {
223 			index = VectorSelector.APPEND;
224 		} else {
225 			index = ((VectorSelector) s).getIndex();
226 		}
227 
228 		int shiftIndex = index;
229 		Entry shifted = null;
230 		if (this.entries.size() == this.maxSize) {
231 			if (index == VectorSelector.APPEND) {
232 				Random r = new Random();
233 				shiftIndex = r.nextInt(this.entries.size());
234 			}
235 
236 			shifted = this.entries.remove(shiftIndex);
237 			// super.deleteLockEntry(shifted, tx);
238 		}
239 
240 		// super.writeLockEntry(e, tx);
241 		if (shiftIndex == VectorSelector.APPEND) {
242 			this.entries.add(e);
243 		} else {
244 			this.entries.add(shiftIndex, e);
245 		}
246 
247 		return shifted;
248 	}
249 
250 	/***
251 	 * {@inheritDoc}
252 	 */
253 	@Override
254 	public void write(Entry e, Transaction tx, Selector s)
255 			throws ContainerFullException, TransactionLockException {
256 		super.aquireLock(true, tx);
257 		int index;
258 
259 		if (s == null) {
260 			index = VectorSelector.APPEND;
261 		} else {
262 			index = ((VectorSelector) s).getIndex();
263 		}
264 
265 		// is there place left?
266 		if (this.maxSize != IContainer.INFINITE_SIZE
267 				&& this.entries.size() >= this.maxSize) {
268 			throw new ContainerFullException();
269 		}
270 
271 		// super.writeLockEntry(e, tx);
272 		if (index == VectorSelector.APPEND) {
273 			this.entries.add(e);
274 		} else {
275 			this.entries.add(index, e);
276 		}
277 	}
278 
279 	/***
280 	 * {@inheritDoc}.
281 	 */
282 	@Override
283 	public Class<? extends Selector> getDefaultSelector() {
284 		return VectorSelector.class;
285 	}
286 
287 }