1 package org.xvsm.coordinators;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.List;
6
7 import org.apache.log4j.Logger;
8 import org.xvsm.core.Entry;
9 import org.xvsm.interfaces.IImplicitCoordinator;
10 import org.xvsm.interfaces.container.IContainer;
11 import org.xvsm.internal.exceptions.ContainerFullException;
12 import org.xvsm.internal.exceptions.CountNotMetException;
13 import org.xvsm.internal.exceptions.FatalException;
14 import org.xvsm.internal.exceptions.TransactionLockException;
15 import org.xvsm.selectors.FifoSelector;
16 import org.xvsm.selectors.Selector;
17 import org.xvsm.transactions.Transaction;
18
19 /***
20 * @author Christian Schreiber, Michael Proestler
21 *
22 */
23 public class FifoCoordinator extends IImplicitCoordinator {
24
25 /***
26 * The Logger for this Class.
27 */
28 private static Logger logger = Logger.getLogger(FifoCoordinator.class);
29
30 /***
31 * The SerialVersionUID of this class.
32 */
33 private static final long serialVersionUID = -795071041584329339L;
34
35 /***
36 * Entries managed by this coordinator. They are stored in fifo order in
37 * this list.
38 */
39 protected List<Entry> entries = new ArrayList<Entry>();
40
41 /***
42 * The maximum size of the container where this FifoCoordinator belongs to.
43 */
44 private int size;
45
46 /***
47 * {@inheritDoc}.
48 */
49 @Override
50 public void commit(Transaction tx) throws TransactionLockException {
51 if (logger.isDebugEnabled()) {
52 logger
53 .debug("commit() transaction: " + tx + " modified "
54 + tx.getModifiedEntries(this.getCref()).size()
55 + " entries");
56 for (Entry e : tx.getModifiedEntries(this.getCref())) {
57 logger.debug("commit() entry: " + e + " hasDeleteLock? "
58 + e.hasDeleteLock(tx));
59 }
60 }
61 for (Entry e : tx.getModifiedEntries(this.getCref())) {
62 if (e.hasDeleteLock(tx)) {
63 if (logger.isDebugEnabled()) {
64 logger.debug("commit() remove entry: " + e);
65 }
66
67
68 this.entries.remove(e);
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 if (logger.isDebugEnabled()) {
83 logger.debug("commitSubTransaction() " + tx);
84 }
85 super.commitLocks(tx);
86
87 }
88
89 /***
90 * {@inheritDoc}.
91 */
92 @Override
93 public void delete(Transaction tx, Entry e) throws TransactionLockException {
94
95
96 }
97
98 /***
99 * {@inheritDoc}.
100 */
101 @Override
102 public List<Entry> read(Transaction tx, Selector selector,
103 List<Entry> centries) throws TransactionLockException,
104 CountNotMetException {
105 this.aquireLock(false, tx);
106
107 if (centries == null) {
108 if (this.entries.size() < selector.getCount()) {
109
110 throw new CountNotMetException(
111 "Not enough matching entries in the fifo container. needed:"
112 + selector.getCount() + " available "
113 + this.entries.size());
114
115 }
116
117
118 List<Entry> ourEntries = new ArrayList<Entry>();
119 for (Entry e : this.entries) {
120 if (e.canBeRead(tx)) {
121
122
123
124 ourEntries.add(e);
125 }
126 if (selector.getCount() != Selector.CNT_ALL) {
127 if (ourEntries.size() == selector.getCount()) {
128
129 break;
130 }
131 }
132 }
133
134 if (ourEntries.size() < selector.getCount()) {
135 throw new CountNotMetException(
136 "Not enough matching entries in the container. Needed "
137 + selector.getCount() + " but only have "
138 + ourEntries.size());
139 }
140 if (logger.isDebugEnabled()) {
141 logger.debug("Read returns: " + ourEntries);
142 }
143 return ourEntries;
144
145 } else {
146 if (centries.size() < selector.getCount()) {
147 throw new CountNotMetException(
148 "Not enough matching entries in the fifo container");
149 }
150
151 List<Integer> posEntries = new ArrayList<Integer>();
152 for (Entry e : centries) {
153 if (e.canBeRead(tx)) {
154
155
156
157
158
159 posEntries.add(this.entries.indexOf(e));
160 }
161 }
162 Collections.sort(posEntries);
163 List<Entry> result = new ArrayList<Entry>();
164 int count = 0;
165 for (Integer pos : posEntries) {
166 result.add(this.entries.get(pos));
167 count++;
168 if (count == selector.getCount()) {
169
170 break;
171 }
172
173 }
174 return result;
175 }
176 }
177
178 /***
179 * {@inheritDoc}.
180 */
181 @Override
182 public void rollback(Transaction tx) throws TransactionLockException {
183
184
185 for (Entry e : new ArrayList<Entry>(this.entries)) {
186
187 if (e != null && e.removeOnRollback(tx)) {
188 if (tx.getFather() != null) {
189
190 } else {
191 this.entries.remove(e);
192 }
193 }
194 }
195 super.rollbackLocks(tx);
196 }
197
198 /***
199 * {@inheritDoc}.
200 */
201 @Override
202 public void setMaxContainerSize(int maxSize) {
203 this.size = maxSize;
204 }
205
206 /***
207 * {@inheritDoc}.
208 */
209 @Override
210 public Entry shift(Entry e, Transaction tx, Selector s)
211 throws TransactionLockException {
212
213 this.aquireLock(true, tx);
214
215 Entry shifted = null;
216
217 if (this.size != IContainer.INFINITE_SIZE
218 && this.entries.size() >= this.size) {
219
220 for (int i = 0; i < this.entries.size(); i++) {
221
222 shifted = this.entries.get(i);
223
224
225 Transaction dlock = shifted.getDeleteLock();
226 if (dlock != null) {
227 if (dlock.equals(tx)) {
228
229
230 continue;
231 } else {
232
233 throw new TransactionLockException(dlock);
234 }
235 }
236
237
238
239 this.entries.remove(i);
240 break;
241 }
242 }
243
244 try {
245 this.write(e, tx, s);
246 } catch (ContainerFullException e1) {
247
248 throw new FatalException();
249 }
250
251 return shifted;
252 }
253
254 /***
255 * {@inheritDoc}.
256 */
257 @Override
258 public void write(Entry e, Transaction tx, Selector s)
259 throws ContainerFullException, TransactionLockException {
260 this.aquireLock(true, tx);
261
262 this.entries.add(e);
263 if (logger.isDebugEnabled()) {
264 logger.debug(this.entries);
265 }
266 }
267
268 /***
269 * {@inheritDoc}.
270 */
271 @Override
272 public Class<? extends Selector> getDefaultSelector() {
273 return FifoSelector.class;
274 }
275
276 }