public synchronized void fetchAndUpdateRemoteMetadata(int nodeId, String key, String value) { VectorClock currentClock = (VectorClock) getRemoteMetadata(nodeId, key).getVersion(); updateRemoteMetadata(nodeId, key, new Versioned<String>(Boolean.toString(false), currentClock.incremented(nodeId, 1))); }
/** * helper function to read current version and put() after incrementing it * for local node. * * @param key * @param value */ public void put(String key, Object value) { // acquire write lock writeLock.lock(); try { if(METADATA_KEYS.contains(key)) { VectorClock version = (VectorClock) get(key, null).get(0).getVersion(); put(key, new Versioned<Object>(value, version.incremented(getNodeId(), System.currentTimeMillis()))); } else { throw new VoldemortException("Unhandled Key:" + key + " for MetadataStore put()"); } } finally { writeLock.unlock(); } }
private Versioned<byte[]> incremented(Versioned<byte[]> versioned, int nodeId) { return new Versioned<byte[]>(versioned.getValue(), ((VectorClock) versioned.getVersion()).incremented(nodeId, time.getMilliseconds())); }
/** * Sets metadata. * * @param nodeIds Node ids to set metadata * @param key Metadata key to set * @param value Metadata value to set */ public void updateRemoteMetadata(Collection<Integer> nodeIds, String key, String value) { VectorClock updatedVersion = null; for(Integer nodeId: nodeIds) { if(updatedVersion == null) { updatedVersion = (VectorClock) metadataMgmtOps.getRemoteMetadata(nodeId, key) .getVersion(); } else { updatedVersion = updatedVersion.merge((VectorClock) metadataMgmtOps.getRemoteMetadata(nodeId, key) .getVersion()); } // Bump up version on first node updatedVersion = updatedVersion.incremented(nodeIds.iterator().next(), System.currentTimeMillis()); } metadataMgmtOps.updateRemoteMetadata(nodeIds, key, Versioned.value(value, updatedVersion)); }
/** * helper function to auto update version and put() * * @param key * @param value */ private void incrementVersionAndPut(MetadataStore metadataStore, String keyString, Object value) { ByteArray key = new ByteArray(ByteUtils.getBytes(keyString, "UTF-8")); VectorClock current = (VectorClock) metadataStore.getVersions(key).get(0); metadataStore.put(keyString, new Versioned<Object>(value, current.incremented(0, System.currentTimeMillis()))); } }
private void put(String... items) { for(String item: items) { VectorClock clock = null; List<Versioned<byte[]>> found = engine.get(new ByteArray(item.getBytes()), null); if(found.size() == 0) { clock = new VectorClock(time.getMilliseconds()); } else if(found.size() == 1) { VectorClock oldClock = (VectorClock) found.get(0).getVersion(); clock = oldClock.incremented(0, time.getMilliseconds()); } else { fail("Found multiple versions."); } engine.put(new ByteArray(item.getBytes()), new Versioned<byte[]>(item.getBytes(), clock), null); } }
public void testPutWithTransforms() { Integer[] values1 = { 9, 90, 10, 15, 25, 106 }; Integer[] filter1 = { 1, 10 }; Versioned<List<Integer>> values = Versioned.value(Arrays.asList(values1)); VectorClock clock = (VectorClock) values.getVersion(); clock.incrementVersion(0, System.currentTimeMillis()); view.put(1, Versioned.value(values.getValue(), clock), Arrays.asList(filter1)); assertEquals(10, view.get(1, Arrays.asList(filter1)).get(0).getValue().size()); Integer[] filter2 = { 5, 10 }; assertEquals(6, view.get(1, Arrays.asList(filter2)).get(0).getValue().size()); Version updatedVersion = view.get(1, Arrays.asList(filter2)).get(0).getVersion(); Integer[] filter3 = { 1, 50 }; Integer[] values2 = { 90, 15, 25, 106 }; clock = (VectorClock) updatedVersion; VectorClock clock1 = clock.incremented(0, System.currentTimeMillis()); view.put(1, Versioned.value(Arrays.asList(values2), clock1), Arrays.asList(filter3)); assertEquals(12, view.get(1, Arrays.asList(filter3)).get(0).getValue().size()); }
@Override @Test public void testGetAll() throws Exception { Store<ByteArray, byte[], byte[]> store = getStore(); int putCount = 10; List<ByteArray> keys = getKeys(putCount); List<byte[]> values = getValues(putCount); assertEquals(putCount, values.size()); VectorClock clock = new VectorClock(); for(int i = 0; i < putCount; i++) { store.put(keys.get(i), new Versioned<byte[]>(values.get(i), clock), null); clock = clock.incremented(0, System.currentTimeMillis()); } int countForGet = putCount / 2; List<ByteArray> keysForGet = keys.subList(0, countForGet); List<byte[]> valuesForGet = values.subList(0, countForGet); Map<ByteArray, List<Versioned<byte[]>>> result = store.getAll(keysForGet, null); assertGetAllValues(keysForGet, valuesForGet, result); }
private void checkServerSideRouting(VoldemortServer server0, VoldemortServer server1) { // create bunch of key-value pairs HashMap<ByteArray, byte[]> entryMap = ServerTestUtils.createRandomKeyValuePairs(TEST_VALUES_SIZE); // populate all entries in server1 Store<ByteArray, byte[], byte[]> store = server1.getStoreRepository() .getRoutedStore(testStoreName); for(Entry<ByteArray, byte[]> entry: entryMap.entrySet()) { store.put(entry.getKey(), Versioned.value(entry.getValue(), new VectorClock().incremented(0, System.currentTimeMillis())), null); } // try fetching them from server0 store = server0.getStoreRepository().getLocalStore(testStoreName); RoutingStrategy routing = server0.getMetadataStore().getRoutingStrategy(testStoreName); for(Entry<ByteArray, byte[]> entry: entryMap.entrySet()) { List<Node> nodes = routing.routeRequest(entry.getKey().get()); if(hasNode(nodes, 0)) { assertTrue("ServerSideRouting should return keys from other nodes.", ByteUtils.compare(entry.getValue(), store.get(entry.getKey(), null) .get(0) .getValue()) == 0); } } }
@Test public void testSynchronousPut() { for(int i = 0; i <= TEST_RUNS; i++) { ByteArray key = getValidKey(); VectorClock clock = (VectorClock) metadataStore.get(key, null).get(0).getVersion(); Versioned<byte[]> value1 = new Versioned<byte[]>(getValidValue(key), clock.incremented(1, 1)); Versioned<byte[]> value2 = new Versioned<byte[]>(getValidValue(key), clock.incremented(2, 1)); metadataStore.put(key, value1, null); metadataStore.put(key, value2, null); assertEquals("Only one metadata value should return", 1, metadataStore.get(key, null) .size()); checkValues(value2, metadataStore.get(key, null), key); } }
@Test public void testSimpleGetAndPut() { for(int i = 0; i <= TEST_RUNS; i++) { ByteArray key = getValidKey(); VectorClock clock = (VectorClock) metadataStore.get(key, null).get(0).getVersion(); Versioned<byte[]> value = new Versioned<byte[]>(getValidValue(key), clock.incremented(0, 1)); metadataStore.put(key, value, null); checkValues(value, metadataStore.get(key, null), key); } }
@Test public void testRepeatedPuts() { for(int i = 0; i <= TEST_RUNS; i++) { for(int j = 0; j <= 5; j++) { ByteArray key = getValidKey(); VectorClock clock = (VectorClock) metadataStore.get(key, null).get(0).getVersion(); Versioned<byte[]> value = new Versioned<byte[]>(getValidValue(key), clock.incremented(0, 1)); metadataStore.put(key, value, null); checkValues(value, metadataStore.get(key, null), key); } } }
@Override public void update(StoreClient<Object, Object> storeClient) { long startNs = System.nanoTime(); Versioned<Object> vs = storeClient.get(key); boolean noCurrentValue = (vs == null); if (localMode) { VectorClock clock = (vs == null) ? new VectorClock() : (VectorClock) vs.getVersion(); clock = clock.incremented(1, System.currentTimeMillis()); Versioned<Object> versionedNewValue = new Versioned<Object>(newValue, clock); ((DefaultStoreClient<Object, Object>) storeClient).put(key, versionedNewValue, transforms); } else { storeClient.put(key, newValue, transforms); } long endNs = System.nanoTime(); measurement.recordLatency(Operations.Mixed.getOpString(), (int) ((endNs - startNs) / Time.NS_PER_MS)); if (noCurrentValue) { measurement.recordWarningCode(Operations.Mixed.getOpString(), WarningCode.NO_CURRENT_VALUE.ordinal()); } } });
@Test public void testObsoletePut() { for(int i = 0; i <= TEST_RUNS; i++) { ByteArray key = getValidKey(); VectorClock clock = (VectorClock) metadataStore.get(key, null).get(0).getVersion(); Versioned<byte[]> value = new Versioned<byte[]>(getValidValue(key), clock.incremented(0, 1)); try { metadataStore.put(key, value, null); assertTrue(true); metadataStore.put(key, value, null); fail(); } catch(ObsoleteVersionException e) { // expected ObsoleteVersionException } } }
@Override @Test public void testDeleteVersion() { VectorClock vc = new VectorClock(); vc.incrementVersion(this.nodeId, System.currentTimeMillis()); VectorClock initialVC = vc.clone(); assertFalse("Delete of non-existant key should be false.", client.delete("k", vc)); client.put("k", new Versioned<String>("v", vc)); assertFalse("Delete of a lesser version should be false.", client.delete("k", initialVC)); assertNotNull("After failed delete, value should still be there.", client.get("k")); assertTrue("Delete of k, with the current version should succeed.", client.delete("k", initialVC.incremented(this.nodeId, time.getMilliseconds()))); assertNull("After a successful delete(k), get(k) should return null.", client.get("k")); } }
@Test public void testUpdateClusterMetadata() { Cluster updatedCluster = ServerTestUtils.getLocalCluster(4); AdminClient client = getAdminClient(); for(int i = 0; i < NUM_RUNS; i++) { VectorClock existingClock = ((VectorClock) client.metadataMgmtOps.getRemoteCluster(0) .getVersion()); VectorClock clock = existingClock.incremented(0, System.currentTimeMillis()); client.metadataMgmtOps.updateRemoteCluster(0, updatedCluster, clock); assertEquals("Cluster should match", updatedCluster, getVoldemortServer(0).getMetadataStore().getCluster()); assertEquals("AdminClient.getMetdata() should match", client.metadataMgmtOps.getRemoteCluster(0).getValue(), updatedCluster); // version should match assertEquals("versions should match as well.", clock, client.metadataMgmtOps.getRemoteCluster(0).getVersion()); } }
@Test public void testDeleteVersion() { assertFalse("Delete of non-existant key should be false.", client.delete("k", new VectorClock())); client.put("k", new Versioned<String>("v")); assertFalse("Delete of a lesser version should be false.", client.delete("k", new VectorClock())); assertNotNull("After failed delete, value should still be there.", client.get("k")); assertTrue("Delete of k, with the current version should succeed.", client.delete("k", new VectorClock().incremented(nodeId, time.getMilliseconds()))); assertNull("After a successful delete(k), get(k) should return null.", client.get("k")); }
@Test public void testPutVersioned() { client.put("k", Versioned.value("v")); Versioned<String> v = client.get("k"); assertEquals("GET should return the version set by PUT.", "v", v.getValue()); VectorClock expected = new VectorClock(); expected.incrementVersion(nodeId, time.getMilliseconds()); assertEquals("The version should be incremented after a put.", expected, v.getVersion()); try { client.put("k", Versioned.value("v")); fail("Put of obsolete version should throw exception."); } catch(ObsoleteVersionException e) { // this is good } // PUT of a concurrent version should succeed client.put("k", new Versioned<String>("v2", new VectorClock().incremented(nodeId + 1, time.getMilliseconds()))); assertEquals("GET should return the new value set by PUT.", "v2", client.getValue("k")); assertEquals("GET should return the new version set by PUT.", expected.incremented(nodeId + 1, time.getMilliseconds()), client.get("k").getVersion()); }
@Override @Test public void testGetWithDefault() { assertEquals("GET of missing key should return default.", new Versioned<String>("v"), client.get("k", new Versioned<String>("v"))); assertEquals("null should be an acceptable default value.", null, client.getValue("k", null)); client.put("k", "v"); VectorClock expectedVC = new VectorClock().incremented(nodeId, time.getMilliseconds()); assertEquals("If there is a value for k, get(k) should return it.", "v", client.get("k", new Versioned<String>("v2")).getValue()); assertNotNull(client.get("k").getVersion()); }
@Test public void testGetWithDefault() { assertEquals("GET of missing key should return default.", new Versioned<String>("v"), client.get("k", new Versioned<String>("v"))); assertEquals("null should be an acceptable default value.", null, client.getValue("k", null)); client.put("k", "v"); assertEquals("If there is a value for k, get(k) should return it.", new Versioned<String>("v", new VectorClock().incremented(nodeId, time.getMilliseconds())), client.get("k", new Versioned<String>("v2"))); assertNotNull(client.get("k").getVersion()); }