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
66
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
92
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) {
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
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 {
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
147 if (!e.hasDeleteLock(tx)) {
148
149
150
151
152
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
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
190
191
192
193
194
195
196
197
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
238 }
239
240
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
266 if (this.maxSize != IContainer.INFINITE_SIZE
267 && this.entries.size() >= this.maxSize) {
268 throw new ContainerFullException();
269 }
270
271
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 }