blob: a3bb975b4de560efe2186c5d002724a205b999c7 [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
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070047 /**
48 * Default namespace name for KVObject.
49 */
50 public static final String DEFAULT_NAMESPACE = "G";
51
52 private final String namespace;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070053 private final IKVTable table;
54 private final byte[] key;
55
56 /**
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070057 * Serialized-value version stored on data store or
58 * {@link IKVTable.getVersionNonexistant()} if it is a new object.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070059 */
60 private long version;
61
62 /**
Ray Milkeyb41100a2014-04-10 10:42:15 -070063 * Map to store user-defined properties.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070064 */
65 private Map<Object, Object> propertyMap;
66
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070067 /**
68 * KVObject constructor without value secified for specified namespace.
69 *
70 * @param table table where this object resides
71 * @param key Key or ID of this object
72 * @param namespace namespace where this object resides
73 */
74 public KVObject(final IKVTable table, final byte[] key, final String namespace) {
75 this(table, key, null, table.getVersionNonexistant(), namespace);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070076 }
77
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070078 /**
79 * KVObject constructor for specified namespace.
80 *
81 * @param table table where this object resides
82 * @param key Key or ID of this object
83 * @param value Value blob representation of this object
84 * @param version version of this Value blob
85 * @param namespace namespace where this object resides
86 */
87 public KVObject(final IKVTable table, final byte[] key,
88 final byte[] value, final long version,
89 final String namespace) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070090 if (table == null) {
91 throw new IllegalArgumentException("table cannot be null");
92 }
93 if (key == null) {
94 throw new IllegalArgumentException("key cannot be null");
95 }
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070096 this.namespace = namespace;
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070097 this.table = table;
Yuta HIGUCHIce7e7f82014-04-15 21:37:38 -070098 this.key = key.clone();
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070099 this.version = version;
100 this.propertyMap = new HashMap<Object, Object>();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700101
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700102 if (value != null) {
103 deserialize(value);
104 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700105 }
106
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700107 /**
108 * Gets the namespace which this object reside.
109 *
110 * @return the namespace which this object reside
111 */
112 public String getNamespace() {
113 return namespace;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700114 }
115
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700116 /**
117 * Gets the table where this object resides.
118 *
119 * @return table where this object resides
120 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700121 public IKVTable getTable() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700122 return table;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700123 }
124
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700125 /**
126 * Gets the table ID of the table where this object resides.
127 *
128 * @return the table ID of the table where this object resides
129 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700130 public IKVTableID getTableId() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700131 return table.getTableId();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700132 }
133
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700134 /**
135 * Gets the Key or ID of this object.
136 *
137 * @return Key or ID of this object
138 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700139 public byte[] getKey() {
Yuta HIGUCHIce7e7f82014-04-15 21:37:38 -0700140 return key.clone();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700141 }
142
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700143 /**
144 * Gets the version of this objects value blob.
145 *
146 * @return version of this objects value blob
147 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700148 public long getVersion() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700149 return version;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700150 }
151
152 /**
153 * Return user-defined object properties.
Jonathan Hart99ff20a2014-06-15 16:53:00 -0700154 * <p/>
155 * Note: Will not trigger deserialization.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700156 *
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700157 * @return Will return null, if never been set, or was not deserialized
158 */
159 protected Map<Object, Object> getPropertyMap() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700160 return this.propertyMap;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700161 }
162
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700163 /**
164 * Replaces the user-defined object properties.
165 *
166 * @param newMap new user-defined object properties
167 * @return old user-defined object properties
168 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700169 protected Map<Object, Object> replacePropertyMap(final Map<Object, Object> newMap) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700170 Map<Object, Object> oldMap = this.propertyMap;
171 this.propertyMap = newMap;
172 return oldMap;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700173 }
174
175 /**
176 * Serialize object.
Ray Milkey269ffb92014-04-03 14:43:30 -0700177 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700178 * sub-classes should override this method to customize serialization.
179 *
180 * @return serialized byte array
181 */
182 public byte[] serialize() {
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700183 return serializePropertyMap(DEFAULT_KRYO.get(), this.propertyMap);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700184 }
185
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700186 /**
187 * Serialize user-defined object properties.
188 *
189 * @param kryo {@link Kryo} instance to use for serialization
190 * @param propMap user-defined object properties
191 * @return serialized byte array
192 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700193 protected byte[] serializePropertyMap(final Kryo kryo,
Ray Milkey269ffb92014-04-03 14:43:30 -0700194 final Map<Object, Object> propMap) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700195
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700196 // value
197 byte[] rcTemp = new byte[1024 * 1024];
198 Output output = new Output(rcTemp);
199 kryo.writeObject(output, propMap);
200 return output.toBytes();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700201 }
202
203
204 /**
205 * Deserialize using value and version stored in data store.
206 *
Ray Milkey269ffb92014-04-03 14:43:30 -0700207 * @param bytes serialized bytes
Ray Milkey5df613b2014-04-15 10:50:56 -0700208 * @param dataStoreVersion version of this {@code bytes}
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700209 * @return true if success
210 */
Ray Milkey5df613b2014-04-15 10:50:56 -0700211 public boolean deserialize(final byte[] bytes,
212 final long dataStoreVersion) {
213 version = dataStoreVersion;
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700214 return deserialize(bytes);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700215 }
216
217 /**
218 * Deserialize object.
Ray Milkey269ffb92014-04-03 14:43:30 -0700219 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700220 * sub-classes should override this method to customize deserialization.
221 *
222 * @param bytes serialized byte array
223 * @return true if success
224 */
225 protected boolean deserialize(final byte[] bytes) {
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700226 deserializePropertyMap(DEFAULT_KRYO.get(), bytes);
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700227 return true;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700228 }
229
230 /**
Jonathan Hart99ff20a2014-06-15 16:53:00 -0700231 * Deserialize and set {@link #propertyMap}.
Ray Milkey269ffb92014-04-03 14:43:30 -0700232 *
233 * @param kryo serializer to use
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700234 * @param bytes Kryo serialized Map object
235 * @return true if success
236 */
237 protected boolean deserializePropertyMap(final Kryo kryo, final byte[] bytes) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700238 @SuppressWarnings("unchecked")
239 Map<Object, Object> map = deserializePropertyMap(kryo, bytes, HashMap.class);
240 if (map == null) {
241 map = new HashMap<>();
242 }
243 this.propertyMap = map;
244 return true;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700245 }
246
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700247 /**
248 * Deserialize user-defined object properties.
249 *
250 * @param kryo {@link Kryo} instance to use for deserialization
251 * @param bytes serialized byte array
252 * @param type Type of user-defined object properties
253 * @return user-defined object properties
254 */
255 protected static <T extends Map<?, ?>> T deserializePropertyMap(final Kryo kryo,
Ray Milkey269ffb92014-04-03 14:43:30 -0700256 final byte[] bytes, final Class<T> type) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700257
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700258 if (bytes == null || bytes.length == 0) {
259 return null;
260 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700261
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700262 Input input = new Input(bytes);
263 T map = kryo.readObject(input, type);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700264
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700265 return map;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700266 }
267
268
269 /**
270 * Create an Object in DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700271 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700272 * Fails if the Object with same key already exists.
273 *
274 * @throws ObjectExistsException
275 */
276 public void create() throws ObjectExistsException {
277
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700278 if (this.propertyMap == null) {
279 log.warn("No object map was set. Setting empty Map.");
280 replacePropertyMap(new HashMap<Object, Object>());
281 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700282
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700283 this.version = table.create(key, this.serialize());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700284 }
285
286 public void forceCreate() {
287
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700288 if (this.propertyMap == null) {
289 log.warn("No object map was set. Setting empty Map.");
290 replacePropertyMap(new HashMap<Object, Object>());
291 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700292
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700293 this.version = table.forceCreate(key, this.serialize());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700294 }
295
296 /**
297 * Read an Object from DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700298 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700299 * Fails if the Object with the key does not exist.
300 *
301 * @throws ObjectDoesntExistException
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700302 */
303 public void read() throws ObjectDoesntExistException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700304 IKVEntry e = table.read(key);
305 deserialize(e.getValue(), e.getVersion());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700306 }
307
308 /**
309 * Update an existing Object in DataStore checking versions.
Ray Milkey269ffb92014-04-03 14:43:30 -0700310 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700311 * Fails if the Object with key does not exists, or conditional failure.
312 *
313 * @throws WrongVersionException
314 * @throws ObjectDoesntExistException
315 */
316 public void update() throws ObjectDoesntExistException,
Ray Milkey269ffb92014-04-03 14:43:30 -0700317 WrongVersionException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700318 if (this.propertyMap == null) {
319 replacePropertyMap(new HashMap<Object, Object>());
320 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700321
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700322 this.version = table.update(key, this.serialize(), version);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700323 }
324
325 /**
326 * Remove an existing Object in DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700327 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700328 * Fails if the Object with key does not exists.
329 *
330 * @throws ObjectDoesntExistException
331 * @throws WrongVersionException
332 */
333 public void delete() throws ObjectDoesntExistException,
Ray Milkey269ffb92014-04-03 14:43:30 -0700334 WrongVersionException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700335 this.version = table.delete(key, this.version);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700336 }
337
338 public void forceDelete() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700339 this.version = table.forceDelete(key);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700340 }
341
342 public WriteOp forceCreateOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700343 return new WriteOp(client.forceCreateOp(getTableId(), getKey(), serialize()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700344 }
345
346 public WriteOp createOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700347 return new WriteOp(client.createOp(getTableId(), getKey(), serialize()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700348 }
349
350 // this might not be needed?
351 public WriteOp readOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700352 return new WriteOp(client.readOp(getTableId(), getKey()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700353 }
354
355 public WriteOp updateOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700356 return new WriteOp(client.updateOp(getTableId(), getKey(), serialize(), getVersion()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700357 }
358
359 public WriteOp deleteOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700360 return new WriteOp(client.deleteOp(getTableId(), getKey(), serialize(), getVersion()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700361 }
362
363 public WriteOp forceDeleteOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700364 return new WriteOp(client.forceDeleteOp(getTableId(), getKey()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700365 }
366
367 /**
368 * Multi-read RCObjects.
Ray Milkey269ffb92014-04-03 14:43:30 -0700369 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700370 * If the blob value was read successfully, RCObject will deserialize them.
371 *
Ray Milkey269ffb92014-04-03 14:43:30 -0700372 * @param objects RCObjects to read
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700373 * @return true if there exist a failed read.
374 */
375 public static boolean multiRead(final List<? extends KVObject> objects) {
376
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700377 final IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700378
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700379 final ArrayList<IMultiEntryOperation> readOps = new ArrayList<>(objects.size());
380 for (KVObject o : objects) {
381 readOps.add(o.readOp(client));
382 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700383
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700384 boolean failExists = client.multiRead(readOps);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700385
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700386 for (int i = 0; i < readOps.size(); ++i) {
387 KVObject obj = objects.get(i);
388 IMultiEntryOperation entry = readOps.get(i);
Ray Milkey269ffb92014-04-03 14:43:30 -0700389 if (entry.hasSucceeded()) {
390 if (!obj.deserialize(entry.getValue(), entry.getVersion())) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700391 //deserialize return true on success
392 failExists = true;
393 log.error("MultiRead error, failed to deserialize {}, {}", obj.getTable(), obj);
394 }
395 } else {
396 log.error("MultiRead error, skipping {}, {}", obj.getTable(), obj);
Ray Milkey7531a342014-04-11 15:08:12 -0700397 obj.version = obj.getTable().getVersionNonexistant();
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700398 failExists = true;
399 }
400 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700401
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700402 return failExists;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700403 }
404
405 /**
Ray Milkeyb41100a2014-04-10 10:42:15 -0700406 * TODO Extract common interface.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700407 */
408 public static class WriteOp implements IMultiObjectOperation, IModifiableMultiEntryOperation {
409
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700410 private final IModifiableMultiEntryOperation base;
411 private final KVObject obj;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700412
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700413 public WriteOp(IMultiEntryOperation base, final KVObject obj) {
414 this.base = (IModifiableMultiEntryOperation) base;
415 this.obj = obj;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700416
Ray Milkey269ffb92014-04-03 14:43:30 -0700417 // switch (base.getOperation()) {
418 // case CREATE:
419 // case FORCE_CREATE:
420 // case UPDATE:
421 // break;
422 // default:
423 // throw new UnsupportedOperationException("Unexpected OPERATION:"+base.getOperation());
424 // }
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700425 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700426
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700427 @Override
428 public KVObject getObject() {
429 return obj;
430 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700431
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700432 @Override
433 public boolean hasSucceeded() {
434 return base.hasSucceeded();
435 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700436
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700437 @Override
438 public STATUS getStatus() {
439 return base.getStatus();
440 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700441
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700442 @Override
443 public IKVTableID getTableId() {
444 return base.getTableId();
445 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700446
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700447 @Override
448 public byte[] getKey() {
449 return base.getKey();
450 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700451
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700452 @Override
453 public byte[] getValue() {
454 return base.getValue();
455 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700456
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700457 @Override
458 public long getVersion() {
459 return base.getVersion();
460 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700461
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700462 @Override
463 public OPERATION getOperation() {
464 return base.getOperation();
465 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700466
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700467 @Override
468 public void setStatus(STATUS status) {
469 base.setStatus(status);
470 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700471
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700472 @Override
473 public void setValue(byte[] value, long version) {
474 base.setValue(value, version);
475 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700476
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700477 @Override
478 public void setVersion(long version) {
479 base.setVersion(version);
480 this.obj.version = version;
481 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700482
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700483 @Override
484 public IModifiableMultiEntryOperation getActualOperation() {
485 return base;
486 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700487 }
488
489 public static boolean multiWrite(final List<WriteOp> objects) {
490
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700491 final IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700492
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700493 final ArrayList<IMultiEntryOperation> writeOps = new ArrayList<>(objects.size());
494 for (WriteOp o : objects) {
495 writeOps.add(o);
496 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700497
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700498 return client.multiWrite(writeOps);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700499 }
500
501 public abstract static class AbstractObjectIterator<E extends KVObject> implements
Ray Milkey269ffb92014-04-03 14:43:30 -0700502 Iterator<E> {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700503
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700504 protected Iterator<IKVEntry> enumerator;
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700505 protected final String namespace;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700506
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700507 @Deprecated
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700508 public AbstractObjectIterator(final IKVTable table) {
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700509 this(table, DEFAULT_NAMESPACE);
510 }
511
512 public AbstractObjectIterator(final IKVTable table, final String namespace) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700513 this.enumerator = table.getAllEntries().iterator();
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700514 this.namespace = namespace;
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700515 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700516
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700517 @Override
518 public boolean hasNext() {
519 return enumerator.hasNext();
520 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700521
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700522 // Implement something similar to below to realize Iterator
Ray Milkey269ffb92014-04-03 14:43:30 -0700523 // @Override
524 // public E next() {
525 // IKVTable.IKVEntry o = enumerator.next();
526 // E obj = E.createFromKey(o.getKey());
527 // obj.deserialize(o.getValue(), o.getVersion());
528 // return obj;
529 // }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700530
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700531 /**
532 * Not implemented.
533 */
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700534 @Deprecated
535 @Override
536 public void remove() {
537 // TODO Not implemented, as I cannot find a use-case for it.
538 throw new UnsupportedOperationException("Not implemented yet");
539 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700540
541 }
542
543}