blob: 41d5853af8e14d7682acc4c13dbca0564e8ae4e7 [file] [log] [blame]
Jonathan Hart6df90172014-04-03 10:13:11 -07001package net.onrc.onos.core.datastore.hazelcast;
Yuta HIGUCHI6a643132014-03-18 22:39:27 -07002
3import java.io.FileNotFoundException;
4import java.util.Collection;
5import java.util.List;
6
Jonathan Hart6df90172014-04-03 10:13:11 -07007import net.onrc.onos.core.datastore.IKVClient;
8import net.onrc.onos.core.datastore.IKVTable;
Jonathan Harta99ec672014-04-03 11:30:34 -07009import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
Jonathan Hart6df90172014-04-03 10:13:11 -070010import net.onrc.onos.core.datastore.IKVTableID;
11import net.onrc.onos.core.datastore.IMultiEntryOperation;
Jonathan Harta99ec672014-04-03 11:30:34 -070012import net.onrc.onos.core.datastore.IMultiEntryOperation.OPERATION;
13import net.onrc.onos.core.datastore.IMultiEntryOperation.STATUS;
Jonathan Hart6df90172014-04-03 10:13:11 -070014import net.onrc.onos.core.datastore.ObjectDoesntExistException;
15import net.onrc.onos.core.datastore.ObjectExistsException;
16import net.onrc.onos.core.datastore.WrongVersionException;
Jonathan Hart6df90172014-04-03 10:13:11 -070017import net.onrc.onos.core.datastore.hazelcast.HZTable.VersionedValue;
18import net.onrc.onos.core.datastore.internal.IModifiableMultiEntryOperation;
Yuta HIGUCHId47eac32014-04-07 13:44:47 -070019import net.onrc.onos.core.datastore.utils.ByteArrayUtil;
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070020
21import org.slf4j.Logger;
22import org.slf4j.LoggerFactory;
23
24import com.hazelcast.client.HazelcastClient;
25import com.hazelcast.client.config.ClientConfig;
26import com.hazelcast.config.Config;
27import com.hazelcast.config.FileSystemXmlConfig;
28import com.hazelcast.config.MapConfig;
29import com.hazelcast.config.SerializationConfig;
30import com.hazelcast.core.Hazelcast;
31import com.hazelcast.core.HazelcastInstance;
Yuta HIGUCHId47eac32014-04-07 13:44:47 -070032import com.hazelcast.core.IAtomicLong;
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070033import com.hazelcast.core.IMap;
34
Ray Milkey1584ec82014-04-10 11:58:30 -070035public final class HZClient implements IKVClient {
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070036 private static final Logger log = LoggerFactory.getLogger(HZClient.class);
37
38 static final long VERSION_NONEXISTENT = 0L;
39
40 private static final String MAP_PREFIX = "datastore://";
41
42 // make this path configurable
Jonathan Hart6df90172014-04-03 10:13:11 -070043 private static final String BASE_CONFIG_FILENAME = System.getProperty("net.onrc.onos.core.datastore.hazelcast.baseConfig", "conf/hazelcast.xml");
Yuta HIGUCHI3ebc9482014-05-08 16:28:28 -070044 private static final String HAZELCAST_DEFAULT_XML = "conf/hazelcast.default.xml";
Jonathan Hart6df90172014-04-03 10:13:11 -070045 private static boolean useClientMode = Boolean.parseBoolean(System.getProperty("net.onrc.onos.core.datastore.hazelcast.clientMode", "true"));
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070046
47 // Note: xml configuration will overwrite this value if present
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -070048 private static int backupCount = Integer.parseInt(System.getProperty("net.onrc.onos.core.datastore.hazelcast.backupCount", "3"));
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070049
50 private final HazelcastInstance hazelcastInstance;
51
52 private static final HZClient THE_INSTANCE = new HZClient();
53
54 public static HZClient getClient() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070055 return THE_INSTANCE;
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070056 }
57
58 private HZClient() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070059 hazelcastInstance = getHZinstance(BASE_CONFIG_FILENAME);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070060 }
61
62 private static HazelcastInstance getHZinstance(final String hazelcastConfigFileName) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070063 Config baseHzConfig = null;
64 try {
65 baseHzConfig = new FileSystemXmlConfig(hazelcastConfigFileName);
66 } catch (FileNotFoundException e) {
67 log.error("Error opening Hazelcast XML configuration. File not found: " + hazelcastConfigFileName, e);
Yuta HIGUCHI3ebc9482014-05-08 16:28:28 -070068 // Fallback mechanism to support running unit test without setup.
69 log.error("Falling back to default Hazelcast XML {}", HAZELCAST_DEFAULT_XML);
70 try {
71 baseHzConfig = new FileSystemXmlConfig(HAZELCAST_DEFAULT_XML);
72 } catch (FileNotFoundException e2) {
73 log.error("Error opening fall back Hazelcast XML configuration. "
74 + "File not found: " + HAZELCAST_DEFAULT_XML, e2);
75
76 // intentionally throwing Exception "e" thrown from non-fallback
77 // Hazelcast configuration loading.
78 throw new Error("Cannot find Hazelcast configuration: " + hazelcastConfigFileName, e);
79 }
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070080 }
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070081
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070082 // use xml config if present, if not use System.property
83 MapConfig mapConfig = baseHzConfig.getMapConfigs().get(MAP_PREFIX + "*");
84 if (mapConfig != null) {
85 backupCount = mapConfig.getBackupCount();
86 }
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070087
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070088 HazelcastInstance instance = null;
89 if (useClientMode) {
90 log.info("Configuring Hazelcast datastore as Client mode");
91 ClientConfig clientConfig = new ClientConfig();
92 final int port = baseHzConfig.getNetworkConfig().getPort();
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070093
Jonathan Hart6df90172014-04-03 10:13:11 -070094 String server = System.getProperty("net.onrc.onos.core.datastore.hazelcast.client.server", "localhost");
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070095 clientConfig.addAddress(server + ":" + port);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -070096
Yuta HIGUCHIceb21b62014-04-17 15:46:05 -070097 // client mode connection limit.
98 // set to 0 for fast fall back to Instance mode.
99 String sAttempts = System.getProperty("net.onrc.onos.core.datastore.hazelcast.client.attemptLimit");
100 if (sAttempts != null) {
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -0700101 clientConfig.setConnectionAttemptLimit(Integer.parseInt(sAttempts));
Yuta HIGUCHIceb21b62014-04-17 15:46:05 -0700102 }
103
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700104 // copy group config from base Hazelcast configuration
105 clientConfig.getGroupConfig().setName(baseHzConfig.getGroupConfig().getName());
106 clientConfig.getGroupConfig().setPassword(baseHzConfig.getGroupConfig().getPassword());
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700107
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700108 // TODO We probably need to figure out what else need to be
109 // derived from baseConfig
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700110
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700111 registerSerializer(clientConfig.getSerializationConfig());
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700112
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700113 log.info("Starting Hazelcast datastore client for [{}]", clientConfig.getAddressList());
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700114
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700115 try {
116 instance = HazelcastClient.newHazelcastClient(clientConfig);
117 if (!instance.getCluster().getMembers().isEmpty()) {
118 log.debug("Members in cluster: " + instance.getCluster().getMembers());
119 return instance;
120 }
121 log.info("Failed to find cluster member, falling back to Instance mode");
122 } catch (IllegalStateException e) {
123 log.info("Failed to initialize HazelcastClient, falling back to Instance mode");
124 }
125 useClientMode = false;
126 instance = null;
127 }
128 log.info("Configuring Hazelcast datastore as Instance mode");
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700129
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700130 // To run 2 Hazelcast instance in 1 JVM,
131 // we probably need to something like below
132 //int port = hazelcastConfig.getNetworkConfig().getPort();
133 //hazelcastConfig.getNetworkConfig().setPort(port+1);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700134
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700135 registerSerializer(baseHzConfig.getSerializationConfig());
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700136
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700137 return Hazelcast.newHazelcastInstance(baseHzConfig);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700138 }
139
140 /**
141 * Register serializer for VersionedValue class used to imitate value version.
Ray Milkey269ffb92014-04-03 14:43:30 -0700142 *
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700143 * @param config
144 */
145 private static void registerSerializer(final SerializationConfig config) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700146 config.addDataSerializableFactoryClass(
147 VersionedValueSerializableFactory.FACTORY_ID,
148 VersionedValueSerializableFactory.class);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700149 }
150
151 @Override
152 public IKVTable getTable(final String tableName) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700153 IMap<byte[], VersionedValue> map = hazelcastInstance.getMap(MAP_PREFIX + tableName);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700154
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700155 if (!useClientMode) {
156 // config only available in Instance Mode
157 // Client Mode must rely on hazelcast.xml to be properly configured.
158 MapConfig config = hazelcastInstance.getConfig().getMapConfig(MAP_PREFIX + tableName);
159 // config for this map to be strong consistent
160 if (config.isReadBackupData()) {
161 config.setReadBackupData(false);
162 }
163 if (config.isNearCacheEnabled()) {
164 config.getNearCacheConfig().setMaxSize(0);
165 }
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700166
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700167 if (config.getBackupCount() != backupCount) {
168 config.setAsyncBackupCount(0);
169 config.setBackupCount(backupCount);
170 }
171 }
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700172
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700173 return new HZTable(tableName, map);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700174 }
175
176 @Override
177 public void dropTable(final IKVTable table) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700178 ((HZTable) table).getBackendMap().clear();
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700179 }
180
181 @Override
182 public long create(final IKVTableID tableId, final byte[] key, final byte[] value)
183 throws ObjectExistsException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700184 IKVTable table = (IKVTable) tableId;
185 return table.create(key, value);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700186 }
187
188 @Override
189 public long forceCreate(final IKVTableID tableId, final byte[] key, final byte[] value) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700190 IKVTable table = (IKVTable) tableId;
191 return table.forceCreate(key, value);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700192 }
193
194 @Override
195 public IKVEntry read(final IKVTableID tableId, final byte[] key)
196 throws ObjectDoesntExistException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700197 IKVTable table = (IKVTable) tableId;
198 return table.read(key);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700199 }
200
201 @Override
202 public long update(final IKVTableID tableId, final byte[] key, final byte[] value,
Ray Milkey269ffb92014-04-03 14:43:30 -0700203 final long version) throws ObjectDoesntExistException,
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700204 WrongVersionException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700205 IKVTable table = (IKVTable) tableId;
206 return table.update(key, value, version);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700207 }
208
209 @Override
210 public long update(final IKVTableID tableId, final byte[] key, final byte[] value)
211 throws ObjectDoesntExistException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700212 IKVTable table = (IKVTable) tableId;
213 return table.update(key, value);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700214 }
215
216 @Override
217 public long delete(final IKVTableID tableId, final byte[] key, final long version)
218 throws ObjectDoesntExistException, WrongVersionException {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700219 IKVTable table = (IKVTable) tableId;
220 return table.delete(key, version);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700221 }
222
223 @Override
224 public long forceDelete(final IKVTableID tableId, final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700225 IKVTable table = (IKVTable) tableId;
226 return table.forceDelete(key);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700227 }
228
229 @Override
230 public Iterable<IKVEntry> getAllEntries(final IKVTableID tableId) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700231 IKVTable table = (IKVTable) tableId;
232 return table.getAllEntries();
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700233 }
234
235 @Override
236 public IMultiEntryOperation createOp(final IKVTableID tableId, final byte[] key,
Ray Milkey269ffb92014-04-03 14:43:30 -0700237 final byte[] value) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700238 return new HZMultiEntryOperation((HZTable) tableId, key, value, HZClient.VERSION_NONEXISTENT, OPERATION.CREATE);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700239 }
240
241 @Override
242 public IMultiEntryOperation forceCreateOp(final IKVTableID tableId, final byte[] key,
Ray Milkey269ffb92014-04-03 14:43:30 -0700243 final byte[] value) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700244 return new HZMultiEntryOperation((HZTable) tableId, key, value, HZClient.VERSION_NONEXISTENT, OPERATION.FORCE_CREATE);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700245 }
246
247 @Override
248 public IMultiEntryOperation readOp(final IKVTableID tableId, final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700249 return new HZMultiEntryOperation((HZTable) tableId, key, OPERATION.READ);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700250 }
251
252 @Override
253 public IMultiEntryOperation updateOp(final IKVTableID tableId, final byte[] key,
Ray Milkey269ffb92014-04-03 14:43:30 -0700254 final byte[] value, final long version) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700255 return new HZMultiEntryOperation((HZTable) tableId, key, value, version, OPERATION.UPDATE);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700256 }
257
258 @Override
259 public IMultiEntryOperation deleteOp(final IKVTableID tableId, final byte[] key,
Ray Milkey269ffb92014-04-03 14:43:30 -0700260 final byte[] value, final long version) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700261 return new HZMultiEntryOperation((HZTable) tableId, key, value, version, OPERATION.DELETE);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700262 }
263
264 @Override
265 public IMultiEntryOperation forceDeleteOp(final IKVTableID tableId, final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700266 return new HZMultiEntryOperation((HZTable) tableId, key, OPERATION.FORCE_DELETE);
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700267 }
268
269 @Override
270 public boolean multiDelete(final Collection<IMultiEntryOperation> ops) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700271 boolean failExists = false;
272 for (IMultiEntryOperation op : ops) {
273 HZMultiEntryOperation mop = (HZMultiEntryOperation) op;
274 switch (mop.getOperation()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700275 case DELETE:
276 try {
277 final long version = delete(mop.getTableId(), mop.getKey(), mop.getVersion());
278 mop.setVersion(version);
279 mop.setStatus(STATUS.SUCCESS);
280 } catch (ObjectDoesntExistException | WrongVersionException e) {
281 log.error(mop + " failed.", e);
282 mop.setStatus(STATUS.FAILED);
283 failExists = true;
284 }
285 break;
286 case FORCE_DELETE:
287 final long version = forceDelete(mop.getTableId(), mop.getKey());
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700288 mop.setVersion(version);
289 mop.setStatus(STATUS.SUCCESS);
Ray Milkey269ffb92014-04-03 14:43:30 -0700290 break;
291 default:
292 throw new UnsupportedOperationException(mop.toString());
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700293 }
294 }
295 return failExists;
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700296 }
297
298 @Override
299 public boolean multiWrite(final List<IMultiEntryOperation> ops) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700300 // there may be room to batch to improve performance
301 boolean failExists = false;
302 for (IMultiEntryOperation op : ops) {
303 IModifiableMultiEntryOperation mop = (IModifiableMultiEntryOperation) op;
304 switch (mop.getOperation()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700305 case CREATE:
306 try {
307 long version = create(mop.getTableId(), mop.getKey(), mop.getValue());
308 mop.setVersion(version);
309 mop.setStatus(STATUS.SUCCESS);
310 } catch (ObjectExistsException e) {
311 log.error(mop + " failed.", e);
312 mop.setStatus(STATUS.FAILED);
313 failExists = true;
314 }
315 break;
316 case FORCE_CREATE: {
317 final long version = forceCreate(mop.getTableId(), mop.getKey(), mop.getValue());
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700318 mop.setVersion(version);
319 mop.setStatus(STATUS.SUCCESS);
Ray Milkey269ffb92014-04-03 14:43:30 -0700320 break;
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700321 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700322 case UPDATE:
323 try {
324 long version = update(mop.getTableId(), mop.getKey(), mop.getValue(), mop.getVersion());
325 mop.setVersion(version);
326 mop.setStatus(STATUS.SUCCESS);
327 } catch (ObjectDoesntExistException | WrongVersionException e) {
328 log.error(mop + " failed.", e);
329 mop.setStatus(STATUS.FAILED);
330 failExists = true;
331 }
332 break;
333 default:
334 throw new UnsupportedOperationException(mop.toString());
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700335 }
336 }
337 return failExists;
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700338 }
339
340 @Override
341 public boolean multiRead(final Collection<IMultiEntryOperation> ops) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700342 boolean failExists = false;
343 for (IMultiEntryOperation op : ops) {
344 IModifiableMultiEntryOperation mop = (IModifiableMultiEntryOperation) op;
345 HZTable table = (HZTable) op.getTableId();
346 ((HZMultiEntryOperation) mop.getActualOperation()).setFuture(table.getBackendMap().getAsync(op.getKey()));
347 }
348 for (IMultiEntryOperation op : ops) {
349 IModifiableMultiEntryOperation mop = (IModifiableMultiEntryOperation) op;
Ray Milkey1aa71f82014-04-08 16:23:24 -0700350 if (!mop.hasSucceeded()) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700351 failExists = true;
352 }
353 }
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700354
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700355 return failExists;
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700356 }
357
358 @Override
Ray Milkey7531a342014-04-11 15:08:12 -0700359 public long getVersionNonexistant() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700360 return VERSION_NONEXISTENT;
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700361 }
362
Yuta HIGUCHId47eac32014-04-07 13:44:47 -0700363 private String getCounterName(final IKVTableID tableId, final byte[] key) {
Yuta HIGUCHI805bc8f2014-04-16 11:51:43 -0700364 StringBuilder buf = new StringBuilder(tableId.getTableName());
Yuta HIGUCHId47eac32014-04-07 13:44:47 -0700365 buf.append('@');
Yuta HIGUCHI805bc8f2014-04-16 11:51:43 -0700366 ByteArrayUtil.toHexStringBuilder(key, ":", buf);
Yuta HIGUCHId47eac32014-04-07 13:44:47 -0700367 return buf.toString();
368 }
369
370 private IAtomicLong getAtomicLong(final IKVTableID tableId, final byte[] key) {
371 // TODO we probably want to implement some sort of caching
372 return hazelcastInstance.getAtomicLong(getCounterName(tableId, key));
373 }
374
375 /**
376 * {@inheritDoc}
377 * <p />
378 * Warning: The counter is a different object from {@code key} entry on
379 * IKVTable with {@code tableId}. You cannot use table API to read/write
380 * counters.
381 *
382 * @param tableId Only getTableName() will be used.
383 * @param key tableId + key will be used as Counter name
384 */
385 @Override
386 public void createCounter(final IKVTableID tableId,
387 final byte[] key, final long initialValue)
388 throws ObjectExistsException {
389
390 IAtomicLong counter = getAtomicLong(tableId, key);
391 // Assumption here is that AtomicLong is initialized to 0L
392 final boolean success = counter.compareAndSet(0L, initialValue);
393 if (!success) {
394 throw new ObjectExistsException("Atomic counter "
395 + getCounterName(tableId, key)
396 + " already exist with value:" + counter.get());
397 }
398 }
399
400 @Override
401 public void setCounter(final IKVTableID tableId,
402 final byte[] key, final long value) {
403
404 IAtomicLong counter = getAtomicLong(tableId, key);
405 counter.set(value);
406 }
407
408 @Override
409 public long incrementCounter(final IKVTableID tableId,
410 final byte[] key, final long incrementValue) {
411
412 IAtomicLong counter = getAtomicLong(tableId, key);
413 return counter.addAndGet(incrementValue);
414 }
415
416 @Override
417 public void destroyCounter(final IKVTableID tableId, final byte[] key) {
418 IAtomicLong counter = getAtomicLong(tableId, key);
419 counter.destroy();
420
421 }
422
423 @Override
424 public long getCounter(final IKVTableID tableId, final byte[] key)
425 throws ObjectDoesntExistException {
426
427 IAtomicLong counter = getAtomicLong(tableId, key);
428 return counter.get();
429 }
Yuta HIGUCHI6a643132014-03-18 22:39:27 -0700430
431}