blob: 568cfc73a9b26fa7f1863269bfd9c264a9129969 [file] [log] [blame]
Jonathan Hart6df90172014-04-03 10:13:11 -07001package net.onrc.onos.core.datastore.utils;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -07002
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.Iterator;
6import java.util.List;
7import java.util.Map;
8
Jonathan Hart6df90172014-04-03 10:13:11 -07009import net.onrc.onos.core.datastore.DataStoreClient;
10import net.onrc.onos.core.datastore.IKVClient;
11import net.onrc.onos.core.datastore.IKVTable;
Jonathan Harta99ec672014-04-03 11:30:34 -070012import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
Jonathan Hart6df90172014-04-03 10:13:11 -070013import net.onrc.onos.core.datastore.IKVTableID;
14import net.onrc.onos.core.datastore.IMultiEntryOperation;
15import net.onrc.onos.core.datastore.IMultiObjectOperation;
16import net.onrc.onos.core.datastore.ObjectDoesntExistException;
17import net.onrc.onos.core.datastore.ObjectExistsException;
18import net.onrc.onos.core.datastore.WrongVersionException;
Jonathan Hart6df90172014-04-03 10:13:11 -070019import net.onrc.onos.core.datastore.internal.IModifiableMultiEntryOperation;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070020
21import org.slf4j.Logger;
22import org.slf4j.LoggerFactory;
23
24import com.esotericsoftware.kryo.Kryo;
25import com.esotericsoftware.kryo.io.Input;
26import com.esotericsoftware.kryo.io.Output;
27
28/**
29 * Class to represent an Object represented as a single K-V pair Value blob.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070030 */
31public class KVObject {
32 private static final Logger log = LoggerFactory.getLogger(KVObject.class);
33
34 // Default Kryo serializer.
35 // each sub-class should prepare their own serializer, which has required
36 // objects registered for better performance.
Ray Milkey5c9f2db2014-04-09 10:31:21 -070037 private static final ThreadLocal<Kryo> DEFAULT_KRYO = new ThreadLocal<Kryo>() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070038 @Override
39 protected Kryo initialValue() {
40 Kryo kryo = new Kryo();
41 // kryo.setRegistrationRequired(true);
42 // kryo.setReferences(false);
43 return kryo;
44 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070045 };
46
47 private final IKVTable table;
48 private final byte[] key;
49
50 /**
51 * serialized value version stored on data store or
52 * {@link IKVTable.VERSION_NONEXISTENT()} if is a new object.
53 */
54 private long version;
55
56 /**
Ray Milkeyb41100a2014-04-10 10:42:15 -070057 * Map to store user-defined properties.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070058 */
59 private Map<Object, Object> propertyMap;
60
61 public KVObject(final IKVTable table, final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070062 this(table, key, null, table.VERSION_NONEXISTENT());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070063 }
64
65 public KVObject(final IKVTable table, final byte[] key, final byte[] value, final long version) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070066 if (table == null) {
67 throw new IllegalArgumentException("table cannot be null");
68 }
69 if (key == null) {
70 throw new IllegalArgumentException("key cannot be null");
71 }
72 this.table = table;
73 this.key = key;
74 this.version = version;
75 this.propertyMap = new HashMap<Object, Object>();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070076
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070077 if (value != null) {
78 deserialize(value);
79 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070080 }
81
82 protected static KVObject createFromKey(final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070083 // Equivalent of this method is expected to be implemented by SubClasses
84 throw new UnsupportedOperationException(
85 "createFromKey() is not expected to be called for RCObject");
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070086 }
87
88 public IKVTable getTable() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070089 return table;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070090 }
91
92 public IKVTableID getTableId() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070093 return table.getTableId();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070094 }
95
96 public byte[] getKey() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070097 return key;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070098 }
99
100 public long getVersion() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700101 return version;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700102 }
103
104 /**
105 * Return user-defined object properties.
106 *
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700107 * @return Will return null, if never been set, or was not deserialized
Ray Milkey269ffb92014-04-03 14:43:30 -0700108 * @note Will not trigger deserialization
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700109 */
110 protected Map<Object, Object> getPropertyMap() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700111 return this.propertyMap;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700112 }
113
114 protected Map<Object, Object> replacePropertyMap(final Map<Object, Object> newMap) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700115 Map<Object, Object> oldMap = this.propertyMap;
116 this.propertyMap = newMap;
117 return oldMap;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700118 }
119
120 /**
121 * Serialize object.
Ray Milkey269ffb92014-04-03 14:43:30 -0700122 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700123 * sub-classes should override this method to customize serialization.
124 *
125 * @return serialized byte array
126 */
127 public byte[] serialize() {
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700128 return serializePropertyMap(DEFAULT_KRYO.get(), this.propertyMap);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700129 }
130
131 protected byte[] serializePropertyMap(final Kryo kryo,
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 final Map<Object, Object> propMap) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700133
134
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700135 // value
136 byte[] rcTemp = new byte[1024 * 1024];
137 Output output = new Output(rcTemp);
138 kryo.writeObject(output, propMap);
139 return output.toBytes();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700140 }
141
142
143 /**
144 * Deserialize using value and version stored in data store.
145 *
Ray Milkey269ffb92014-04-03 14:43:30 -0700146 * @param bytes serialized bytes
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700147 * @param version version of this {@code bytes}
148 * @return true if success
149 */
150 public boolean deserialize(final byte[] bytes, final long version) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700151 this.version = version;
152 return deserialize(bytes);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700153 }
154
155 /**
156 * Deserialize object.
Ray Milkey269ffb92014-04-03 14:43:30 -0700157 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700158 * sub-classes should override this method to customize deserialization.
159 *
160 * @param bytes serialized byte array
161 * @return true if success
162 */
163 protected boolean deserialize(final byte[] bytes) {
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700164 deserializePropertyMap(DEFAULT_KRYO.get(), bytes);
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700165 return true;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700166 }
167
168 /**
169 * Deserialize and set {@link propertyMap}.
Ray Milkey269ffb92014-04-03 14:43:30 -0700170 *
171 * @param kryo serializer to use
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700172 * @param bytes Kryo serialized Map object
173 * @return true if success
174 */
175 protected boolean deserializePropertyMap(final Kryo kryo, final byte[] bytes) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700176 @SuppressWarnings("unchecked")
177 Map<Object, Object> map = deserializePropertyMap(kryo, bytes, HashMap.class);
178 if (map == null) {
179 map = new HashMap<>();
180 }
181 this.propertyMap = map;
182 return true;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700183 }
184
185 protected <T extends Map<?, ?>> T deserializePropertyMap(final Kryo kryo,
Ray Milkey269ffb92014-04-03 14:43:30 -0700186 final byte[] bytes, final Class<T> type) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700187
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700188 if (bytes == null || bytes.length == 0) {
189 return null;
190 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700191
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700192 Input input = new Input(bytes);
193 T map = kryo.readObject(input, type);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700194
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700195 return map;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700196 }
197
198
199 /**
200 * Create an Object in DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700201 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700202 * Fails if the Object with same key already exists.
203 *
204 * @throws ObjectExistsException
205 */
206 public void create() throws ObjectExistsException {
207
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700208 if (this.propertyMap == null) {
209 log.warn("No object map was set. Setting empty Map.");
210 replacePropertyMap(new HashMap<Object, Object>());
211 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700212
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700213 this.version = table.create(key, this.serialize());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700214 }
215
216 public void forceCreate() {
217
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700218 if (this.propertyMap == null) {
219 log.warn("No object map was set. Setting empty Map.");
220 replacePropertyMap(new HashMap<Object, Object>());
221 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700222
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700223 this.version = table.forceCreate(key, this.serialize());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700224 }
225
226 /**
227 * Read an Object from DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700228 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700229 * Fails if the Object with the key does not exist.
230 *
231 * @throws ObjectDoesntExistException
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700232 */
233 public void read() throws ObjectDoesntExistException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700234 IKVEntry e = table.read(key);
235 deserialize(e.getValue(), e.getVersion());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700236 }
237
238 /**
239 * Update an existing Object in DataStore checking versions.
Ray Milkey269ffb92014-04-03 14:43:30 -0700240 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700241 * Fails if the Object with key does not exists, or conditional failure.
242 *
243 * @throws WrongVersionException
244 * @throws ObjectDoesntExistException
245 */
246 public void update() throws ObjectDoesntExistException,
Ray Milkey269ffb92014-04-03 14:43:30 -0700247 WrongVersionException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700248 if (this.propertyMap == null) {
249 replacePropertyMap(new HashMap<Object, Object>());
250 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700251
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700252 this.version = table.update(key, this.serialize(), version);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700253 }
254
255 /**
256 * Remove an existing Object in DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700257 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700258 * Fails if the Object with key does not exists.
259 *
260 * @throws ObjectDoesntExistException
261 * @throws WrongVersionException
262 */
263 public void delete() throws ObjectDoesntExistException,
Ray Milkey269ffb92014-04-03 14:43:30 -0700264 WrongVersionException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700265 this.version = table.delete(key, this.version);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700266 }
267
268 public void forceDelete() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700269 this.version = table.forceDelete(key);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700270 }
271
272 public WriteOp forceCreateOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700273 return new WriteOp(client.forceCreateOp(getTableId(), getKey(), serialize()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700274 }
275
276 public WriteOp createOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700277 return new WriteOp(client.createOp(getTableId(), getKey(), serialize()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700278 }
279
280 // this might not be needed?
281 public WriteOp readOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700282 return new WriteOp(client.readOp(getTableId(), getKey()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700283 }
284
285 public WriteOp updateOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700286 return new WriteOp(client.updateOp(getTableId(), getKey(), serialize(), getVersion()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700287 }
288
289 public WriteOp deleteOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700290 return new WriteOp(client.deleteOp(getTableId(), getKey(), serialize(), getVersion()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700291 }
292
293 public WriteOp forceDeleteOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700294 return new WriteOp(client.forceDeleteOp(getTableId(), getKey()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700295 }
296
297 /**
298 * Multi-read RCObjects.
Ray Milkey269ffb92014-04-03 14:43:30 -0700299 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700300 * If the blob value was read successfully, RCObject will deserialize them.
301 *
Ray Milkey269ffb92014-04-03 14:43:30 -0700302 * @param objects RCObjects to read
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700303 * @return true if there exist a failed read.
304 */
305 public static boolean multiRead(final List<? extends KVObject> objects) {
306
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700307 final IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700308
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700309 final ArrayList<IMultiEntryOperation> readOps = new ArrayList<>(objects.size());
310 for (KVObject o : objects) {
311 readOps.add(o.readOp(client));
312 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700313
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700314 boolean failExists = client.multiRead(readOps);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700315
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700316 for (int i = 0; i < readOps.size(); ++i) {
317 KVObject obj = objects.get(i);
318 IMultiEntryOperation entry = readOps.get(i);
Ray Milkey269ffb92014-04-03 14:43:30 -0700319 if (entry.hasSucceeded()) {
320 if (!obj.deserialize(entry.getValue(), entry.getVersion())) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700321 //deserialize return true on success
322 failExists = true;
323 log.error("MultiRead error, failed to deserialize {}, {}", obj.getTable(), obj);
324 }
325 } else {
326 log.error("MultiRead error, skipping {}, {}", obj.getTable(), obj);
327 obj.version = obj.getTable().VERSION_NONEXISTENT();
328 failExists = true;
329 }
330 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700331
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700332 return failExists;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700333 }
334
335 /**
Ray Milkeyb41100a2014-04-10 10:42:15 -0700336 * TODO Extract common interface.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700337 */
338 public static class WriteOp implements IMultiObjectOperation, IModifiableMultiEntryOperation {
339
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700340 private final IModifiableMultiEntryOperation base;
341 private final KVObject obj;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700342
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700343 public WriteOp(IMultiEntryOperation base, final KVObject obj) {
344 this.base = (IModifiableMultiEntryOperation) base;
345 this.obj = obj;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700346
Ray Milkey269ffb92014-04-03 14:43:30 -0700347 // switch (base.getOperation()) {
348 // case CREATE:
349 // case FORCE_CREATE:
350 // case UPDATE:
351 // break;
352 // default:
353 // throw new UnsupportedOperationException("Unexpected OPERATION:"+base.getOperation());
354 // }
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700355 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700356
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700357 @Override
358 public KVObject getObject() {
359 return obj;
360 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700361
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700362 @Deprecated
363 public OPERATION getOp() {
364 return this.getOperation();
365 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700366
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700367 @Override
368 public boolean hasSucceeded() {
369 return base.hasSucceeded();
370 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700371
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700372 @Override
373 public STATUS getStatus() {
374 return base.getStatus();
375 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700376
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700377 @Override
378 public IKVTableID getTableId() {
379 return base.getTableId();
380 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700381
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700382 @Override
383 public byte[] getKey() {
384 return base.getKey();
385 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700386
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700387 @Override
388 public byte[] getValue() {
389 return base.getValue();
390 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700391
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700392 @Override
393 public long getVersion() {
394 return base.getVersion();
395 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700396
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700397 @Override
398 public OPERATION getOperation() {
399 return base.getOperation();
400 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700401
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700402 @Override
403 public void setStatus(STATUS status) {
404 base.setStatus(status);
405 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700406
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700407 @Override
408 public void setValue(byte[] value, long version) {
409 base.setValue(value, version);
410 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700411
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700412 @Override
413 public void setVersion(long version) {
414 base.setVersion(version);
415 this.obj.version = version;
416 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700417
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700418 @Override
419 public IModifiableMultiEntryOperation getActualOperation() {
420 return base;
421 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700422 }
423
424 public static boolean multiWrite(final List<WriteOp> objects) {
425
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700426 final IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700427
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700428 final ArrayList<IMultiEntryOperation> writeOps = new ArrayList<>(objects.size());
429 for (WriteOp o : objects) {
430 writeOps.add(o);
431 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700432
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700433 return client.multiWrite(writeOps);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700434 }
435
436 public abstract static class AbstractObjectIterator<E extends KVObject> implements
Ray Milkey269ffb92014-04-03 14:43:30 -0700437 Iterator<E> {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700438
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700439 protected Iterator<IKVEntry> enumerator;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700440
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700441 public AbstractObjectIterator(final IKVTable table) {
442 this.enumerator = table.getAllEntries().iterator();
443 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700444
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700445 @Override
446 public boolean hasNext() {
447 return enumerator.hasNext();
448 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700449
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700450 // Implement something similar to below to realize Iterator
Ray Milkey269ffb92014-04-03 14:43:30 -0700451 // @Override
452 // public E next() {
453 // IKVTable.IKVEntry o = enumerator.next();
454 // E obj = E.createFromKey(o.getKey());
455 // obj.deserialize(o.getValue(), o.getVersion());
456 // return obj;
457 // }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700458
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700459 @Deprecated
460 @Override
461 public void remove() {
462 // TODO Not implemented, as I cannot find a use-case for it.
463 throw new UnsupportedOperationException("Not implemented yet");
464 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700465
466 }
467
468}