blob: 15666b289728cc4d3a9f64cf0d90b50238a4ee1c [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.
154 *
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700155 * @return Will return null, if never been set, or was not deserialized
Ray Milkey269ffb92014-04-03 14:43:30 -0700156 * @note Will not trigger deserialization
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700157 */
158 protected Map<Object, Object> getPropertyMap() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700159 return this.propertyMap;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700160 }
161
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700162 /**
163 * Replaces the user-defined object properties.
164 *
165 * @param newMap new user-defined object properties
166 * @return old user-defined object properties
167 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700168 protected Map<Object, Object> replacePropertyMap(final Map<Object, Object> newMap) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700169 Map<Object, Object> oldMap = this.propertyMap;
170 this.propertyMap = newMap;
171 return oldMap;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700172 }
173
174 /**
175 * Serialize object.
Ray Milkey269ffb92014-04-03 14:43:30 -0700176 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700177 * sub-classes should override this method to customize serialization.
178 *
179 * @return serialized byte array
180 */
181 public byte[] serialize() {
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700182 return serializePropertyMap(DEFAULT_KRYO.get(), this.propertyMap);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700183 }
184
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700185 /**
186 * Serialize user-defined object properties.
187 *
188 * @param kryo {@link Kryo} instance to use for serialization
189 * @param propMap user-defined object properties
190 * @return serialized byte array
191 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700192 protected byte[] serializePropertyMap(final Kryo kryo,
Ray Milkey269ffb92014-04-03 14:43:30 -0700193 final Map<Object, Object> propMap) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700194
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700195 // value
196 byte[] rcTemp = new byte[1024 * 1024];
197 Output output = new Output(rcTemp);
198 kryo.writeObject(output, propMap);
199 return output.toBytes();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700200 }
201
202
203 /**
204 * Deserialize using value and version stored in data store.
205 *
Ray Milkey269ffb92014-04-03 14:43:30 -0700206 * @param bytes serialized bytes
Ray Milkey5df613b2014-04-15 10:50:56 -0700207 * @param dataStoreVersion version of this {@code bytes}
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700208 * @return true if success
209 */
Ray Milkey5df613b2014-04-15 10:50:56 -0700210 public boolean deserialize(final byte[] bytes,
211 final long dataStoreVersion) {
212 version = dataStoreVersion;
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700213 return deserialize(bytes);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700214 }
215
216 /**
217 * Deserialize object.
Ray Milkey269ffb92014-04-03 14:43:30 -0700218 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700219 * sub-classes should override this method to customize deserialization.
220 *
221 * @param bytes serialized byte array
222 * @return true if success
223 */
224 protected boolean deserialize(final byte[] bytes) {
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700225 deserializePropertyMap(DEFAULT_KRYO.get(), bytes);
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700226 return true;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700227 }
228
229 /**
230 * Deserialize and set {@link propertyMap}.
Ray Milkey269ffb92014-04-03 14:43:30 -0700231 *
232 * @param kryo serializer to use
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700233 * @param bytes Kryo serialized Map object
234 * @return true if success
235 */
236 protected boolean deserializePropertyMap(final Kryo kryo, final byte[] bytes) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700237 @SuppressWarnings("unchecked")
238 Map<Object, Object> map = deserializePropertyMap(kryo, bytes, HashMap.class);
239 if (map == null) {
240 map = new HashMap<>();
241 }
242 this.propertyMap = map;
243 return true;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700244 }
245
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700246 /**
247 * Deserialize user-defined object properties.
248 *
249 * @param kryo {@link Kryo} instance to use for deserialization
250 * @param bytes serialized byte array
251 * @param type Type of user-defined object properties
252 * @return user-defined object properties
253 */
254 protected static <T extends Map<?, ?>> T deserializePropertyMap(final Kryo kryo,
Ray Milkey269ffb92014-04-03 14:43:30 -0700255 final byte[] bytes, final Class<T> type) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700256
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700257 if (bytes == null || bytes.length == 0) {
258 return null;
259 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700260
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700261 Input input = new Input(bytes);
262 T map = kryo.readObject(input, type);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700263
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700264 return map;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700265 }
266
267
268 /**
269 * Create an Object in DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700270 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700271 * Fails if the Object with same key already exists.
272 *
273 * @throws ObjectExistsException
274 */
275 public void create() throws ObjectExistsException {
276
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700277 if (this.propertyMap == null) {
278 log.warn("No object map was set. Setting empty Map.");
279 replacePropertyMap(new HashMap<Object, Object>());
280 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700281
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700282 this.version = table.create(key, this.serialize());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700283 }
284
285 public void forceCreate() {
286
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700287 if (this.propertyMap == null) {
288 log.warn("No object map was set. Setting empty Map.");
289 replacePropertyMap(new HashMap<Object, Object>());
290 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700291
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700292 this.version = table.forceCreate(key, this.serialize());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700293 }
294
295 /**
296 * Read an Object from DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700297 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700298 * Fails if the Object with the key does not exist.
299 *
300 * @throws ObjectDoesntExistException
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700301 */
302 public void read() throws ObjectDoesntExistException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700303 IKVEntry e = table.read(key);
304 deserialize(e.getValue(), e.getVersion());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700305 }
306
307 /**
308 * Update an existing Object in DataStore checking versions.
Ray Milkey269ffb92014-04-03 14:43:30 -0700309 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700310 * Fails if the Object with key does not exists, or conditional failure.
311 *
312 * @throws WrongVersionException
313 * @throws ObjectDoesntExistException
314 */
315 public void update() throws ObjectDoesntExistException,
Ray Milkey269ffb92014-04-03 14:43:30 -0700316 WrongVersionException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700317 if (this.propertyMap == null) {
318 replacePropertyMap(new HashMap<Object, Object>());
319 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700320
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700321 this.version = table.update(key, this.serialize(), version);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700322 }
323
324 /**
325 * Remove an existing Object in DataStore.
Ray Milkey269ffb92014-04-03 14:43:30 -0700326 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700327 * Fails if the Object with key does not exists.
328 *
329 * @throws ObjectDoesntExistException
330 * @throws WrongVersionException
331 */
332 public void delete() throws ObjectDoesntExistException,
Ray Milkey269ffb92014-04-03 14:43:30 -0700333 WrongVersionException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700334 this.version = table.delete(key, this.version);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700335 }
336
337 public void forceDelete() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700338 this.version = table.forceDelete(key);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700339 }
340
341 public WriteOp forceCreateOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700342 return new WriteOp(client.forceCreateOp(getTableId(), getKey(), serialize()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700343 }
344
345 public WriteOp createOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700346 return new WriteOp(client.createOp(getTableId(), getKey(), serialize()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700347 }
348
349 // this might not be needed?
350 public WriteOp readOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700351 return new WriteOp(client.readOp(getTableId(), getKey()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700352 }
353
354 public WriteOp updateOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700355 return new WriteOp(client.updateOp(getTableId(), getKey(), serialize(), getVersion()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700356 }
357
358 public WriteOp deleteOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700359 return new WriteOp(client.deleteOp(getTableId(), getKey(), serialize(), getVersion()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700360 }
361
362 public WriteOp forceDeleteOp(IKVClient client) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700363 return new WriteOp(client.forceDeleteOp(getTableId(), getKey()), this);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700364 }
365
366 /**
367 * Multi-read RCObjects.
Ray Milkey269ffb92014-04-03 14:43:30 -0700368 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700369 * If the blob value was read successfully, RCObject will deserialize them.
370 *
Ray Milkey269ffb92014-04-03 14:43:30 -0700371 * @param objects RCObjects to read
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700372 * @return true if there exist a failed read.
373 */
374 public static boolean multiRead(final List<? extends KVObject> objects) {
375
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700376 final IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700377
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700378 final ArrayList<IMultiEntryOperation> readOps = new ArrayList<>(objects.size());
379 for (KVObject o : objects) {
380 readOps.add(o.readOp(client));
381 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700382
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700383 boolean failExists = client.multiRead(readOps);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700384
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700385 for (int i = 0; i < readOps.size(); ++i) {
386 KVObject obj = objects.get(i);
387 IMultiEntryOperation entry = readOps.get(i);
Ray Milkey269ffb92014-04-03 14:43:30 -0700388 if (entry.hasSucceeded()) {
389 if (!obj.deserialize(entry.getValue(), entry.getVersion())) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700390 //deserialize return true on success
391 failExists = true;
392 log.error("MultiRead error, failed to deserialize {}, {}", obj.getTable(), obj);
393 }
394 } else {
395 log.error("MultiRead error, skipping {}, {}", obj.getTable(), obj);
Ray Milkey7531a342014-04-11 15:08:12 -0700396 obj.version = obj.getTable().getVersionNonexistant();
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700397 failExists = true;
398 }
399 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700400
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700401 return failExists;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700402 }
403
404 /**
Ray Milkeyb41100a2014-04-10 10:42:15 -0700405 * TODO Extract common interface.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700406 */
407 public static class WriteOp implements IMultiObjectOperation, IModifiableMultiEntryOperation {
408
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700409 private final IModifiableMultiEntryOperation base;
410 private final KVObject obj;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700411
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700412 public WriteOp(IMultiEntryOperation base, final KVObject obj) {
413 this.base = (IModifiableMultiEntryOperation) base;
414 this.obj = obj;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700415
Ray Milkey269ffb92014-04-03 14:43:30 -0700416 // switch (base.getOperation()) {
417 // case CREATE:
418 // case FORCE_CREATE:
419 // case UPDATE:
420 // break;
421 // default:
422 // throw new UnsupportedOperationException("Unexpected OPERATION:"+base.getOperation());
423 // }
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700424 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700425
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700426 @Override
427 public KVObject getObject() {
428 return obj;
429 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700430
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700431 @Override
432 public boolean hasSucceeded() {
433 return base.hasSucceeded();
434 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700435
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700436 @Override
437 public STATUS getStatus() {
438 return base.getStatus();
439 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700440
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700441 @Override
442 public IKVTableID getTableId() {
443 return base.getTableId();
444 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700445
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700446 @Override
447 public byte[] getKey() {
448 return base.getKey();
449 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700450
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700451 @Override
452 public byte[] getValue() {
453 return base.getValue();
454 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700455
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700456 @Override
457 public long getVersion() {
458 return base.getVersion();
459 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700460
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700461 @Override
462 public OPERATION getOperation() {
463 return base.getOperation();
464 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700465
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700466 @Override
467 public void setStatus(STATUS status) {
468 base.setStatus(status);
469 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700470
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700471 @Override
472 public void setValue(byte[] value, long version) {
473 base.setValue(value, version);
474 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700475
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700476 @Override
477 public void setVersion(long version) {
478 base.setVersion(version);
479 this.obj.version = version;
480 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700481
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700482 @Override
483 public IModifiableMultiEntryOperation getActualOperation() {
484 return base;
485 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700486 }
487
488 public static boolean multiWrite(final List<WriteOp> objects) {
489
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700490 final IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700491
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700492 final ArrayList<IMultiEntryOperation> writeOps = new ArrayList<>(objects.size());
493 for (WriteOp o : objects) {
494 writeOps.add(o);
495 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700496
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700497 return client.multiWrite(writeOps);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700498 }
499
500 public abstract static class AbstractObjectIterator<E extends KVObject> implements
Ray Milkey269ffb92014-04-03 14:43:30 -0700501 Iterator<E> {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700502
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700503 protected Iterator<IKVEntry> enumerator;
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700504 protected final String namespace;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700505
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700506 @Deprecated
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700507 public AbstractObjectIterator(final IKVTable table) {
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700508 this(table, DEFAULT_NAMESPACE);
509 }
510
511 public AbstractObjectIterator(final IKVTable table, final String namespace) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700512 this.enumerator = table.getAllEntries().iterator();
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700513 this.namespace = namespace;
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700514 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700515
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700516 @Override
517 public boolean hasNext() {
518 return enumerator.hasNext();
519 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700520
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700521 // Implement something similar to below to realize Iterator
Ray Milkey269ffb92014-04-03 14:43:30 -0700522 // @Override
523 // public E next() {
524 // IKVTable.IKVEntry o = enumerator.next();
525 // E obj = E.createFromKey(o.getKey());
526 // obj.deserialize(o.getValue(), o.getVersion());
527 // return obj;
528 // }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700529
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700530 /**
531 * Not implemented.
532 */
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700533 @Deprecated
534 @Override
535 public void remove() {
536 // TODO Not implemented, as I cannot find a use-case for it.
537 throw new UnsupportedOperationException("Not implemented yet");
538 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700539
540 }
541
542}