public VectorClock getNewIncrementedVectorClock() { VectorClock vectorClock = new VectorClock(); vectorClock.incrementVersion(this.nodeId, System.currentTimeMillis()); return vectorClock; }
/** * Create a clone of this Versioned object such that the object pointed to * is the same, but the VectorClock and Versioned wrapper is a shallow copy. */ public Versioned<T> cloneVersioned() { return new Versioned<T>(this.getValue(), this.version.clone()); }
/** * Remove all non replica clock entries from the list of versioned values * provided * * @param vals list of versioned values to prune replicas from * @param keyReplicas list of current replicas for the given key * @param didPrune flag to mark if we did actually prune something * @return pruned list */ public static List<Versioned<byte[]>> pruneNonReplicaEntries(List<Versioned<byte[]>> vals, List<Integer> keyReplicas, MutableBoolean didPrune) { List<Versioned<byte[]>> prunedVals = new ArrayList<Versioned<byte[]>>(vals.size()); for(Versioned<byte[]> val: vals) { VectorClock clock = (VectorClock) val.getVersion(); List<ClockEntry> clockEntries = new ArrayList<ClockEntry>(); for(ClockEntry clockEntry: clock.getEntries()) { if(keyReplicas.contains((int) clockEntry.getNodeId())) { clockEntries.add(clockEntry); } else { didPrune.setValue(true); } } prunedVals.add(new Versioned<byte[]>(val.getValue(), new VectorClock(clockEntries, clock.getTimestamp()))); } return prunedVals; }
/** * Get new vector clock based on this clock but incremented on index nodeId * * @param nodeId The id of the node to increment * @return A vector clock equal on each element execept that indexed by * nodeId */ public VectorClock incremented(int nodeId, long time) { VectorClock copyClock = this.clone(); copyClock.incrementVersion(nodeId, time); return copyClock; }
public byte[] toBytes() { byte[] serialized = new byte[sizeInBytes()]; toBytes(serialized, 0); return serialized; }
public VectorClockWrapper(VectorClock vc) { this.versions = vc.getEntries(); this.setTimestamp(vc.getTimestamp()); }
@Override @Test public void testPutVersioned() { VectorClock vc = new VectorClock(); vc.incrementVersion(this.nodeId, System.currentTimeMillis()); VectorClock initialVC = vc.clone(); client.put("k", new Versioned<String>("v", vc)); Versioned<String> v = client.get("k"); assertEquals("GET should return the version set by PUT.", "v", v.getValue()); VectorClock expected = initialVC.clone(); expected.incrementVersion(this.nodeId, System.currentTimeMillis()); assertEquals("The version should be incremented after a put.", expected.getEntries(), ((VectorClock) v.getVersion()).getEntries()); try { client.put("k", new Versioned<String>("v", initialVC)); 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()); }
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); } }
@Test public void testPutIncrementsVersionZZZ() throws Exception { Store<ByteArray, byte[], byte[]> store = getZonedStore(); VectorClock clock = new VectorClock(); VectorClock copy = clock.clone(); store.put(aKey, new Versioned<byte[]>(getValue(), clock), aTransform); List<Versioned<byte[]>> found = store.get(aKey, aTransform); assertEquals("Invalid number of items found.", 1, found.size()); assertEquals("Version not incremented properly", Occurred.BEFORE, copy.compare(found.get(0).getVersion())); }
private VectorClock getVectorClock(byte[] bytes) { if(bytes[0] >= 0) return new VectorClock(bytes); return null; }
@Test public void testIncrementAndSerialize() { int node = 1; VectorClock vc = getClock(node); assertEquals(node, vc.getMaxVersion()); int increments = 3000; for(int i = 0; i < increments; i++) { vc.incrementVersion(node, 45); // serialize vc = new VectorClock(vc.toBytes()); } assertEquals(increments + 1, vc.getMaxVersion()); }
@Override @Test public void testPutIfNotObsolete() { VectorClock vc = new VectorClock(); vc.incrementVersion(this.nodeId, System.currentTimeMillis()); VectorClock initialVC = vc.clone(); client.putIfNotObsolete("k", new Versioned<String>("v", vc)); assertEquals("PUT of non-obsolete version should succeed.", "v", client.getValue("k")); assertFalse(client.putIfNotObsolete("k", new Versioned<String>("v2", initialVC))); assertEquals("Failed PUT should not change the value stored.", "v", client.getValue("k")); }
@Test public void testSerializationWraps() { VectorClock clock = getClock(1, 1, 2, 3, 3, 6); for(int i = 0; i < 300; i++) clock.incrementVersion(2, System.currentTimeMillis()); assertEquals("Clock does not serialize to itself.", clock, new VectorClock(clock.toBytes())); }
@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()); }
@Test public void testSerialization() { assertEquals("The empty clock serializes incorrectly.", getClock(), new VectorClock(getClock().toBytes())); VectorClock clock = getClock(1, 1, 2, 3, 4, 4, 6); assertEquals("This clock does not serialize to itself.", clock, new VectorClock(clock.toBytes())); }
/** * Pre-condition: timestamp is ignored in determine vector clock equality */ @Test public void testDeserializationBackwardCompatibility() { assertEquals("The empty clock serializes incorrectly.", getClock(), new VectorClock(getClock().toBytes())); VectorClock clock = getClock(1, 1, 2, 3, 4, 4, 6); // Old Vector Clock would serialize to this: // 0 5; 1; 0 1, 2; 0 2, 1; 0 3, 1; 0 4, 2; 0 6, 1; [timestamp=random] byte[] knownSerialized = { 0, 5, 1, 0, 1, 2, 0, 2, 1, 0, 3, 1, 0, 4, 2, 0, 6, 1, 0, 0, 1, 0x3e, 0x7b, (byte) 0x8c, (byte) 0x9d, 0x19 }; assertEquals("vector clock does not deserialize correctly on given byte array", clock, new VectorClock(knownSerialized)); DataInputStream ds = new DataInputStream(new ByteArrayInputStream(knownSerialized)); VectorClock clock2 = VectorClock.createVectorClock(ds); assertEquals("vector clock does not deserialize correctly on given input stream", clock, clock2); }
/** * A test for comparing vector clocks that nodes of clock entries are not * sorted In case people insert clock entries without using increment we * need to test although it has been deprecated */ @Test public void testNodeClockEntryDeprecate() { VectorClock vc1 = new VectorClock(); try { vc1.getEntries().add(new ClockEntry((short) 2, 2)); fail("Did not throw UnsupportedOperationException"); } catch(UnsupportedOperationException e) { } }
/** * See github issue #25: Incorrect coercion of version to short before * passing to ClockEntry constructor */ @Test public void testMergeWithLargeVersion() { VectorClock clock1 = getClock(1); VectorClock clock2 = new VectorClock(Lists.newArrayList(new ClockEntry((short) 1, Short.MAX_VALUE + 1)), System.currentTimeMillis()); VectorClock mergedClock = clock1.merge(clock2); assertEquals(mergedClock.getMaxVersion(), Short.MAX_VALUE + 1); }
/** * Test the new put that returns the new version */ @Test public void testPutReturnVersion() { Version baseVersion = new VectorClock(); Version oldVersion = null; Version newVersion = null; Versioned<String> getVersioned = null; String oldValue = null; String newValue = null; for(int i = 0; i < 5; i++) { oldValue = "value" + i; newValue = "value" + (i + 1); oldVersion = storeClient.put("key1", Versioned.value(oldValue, baseVersion)); newVersion = storeClient.put("key1", Versioned.value(newValue, ((VectorClock) oldVersion).clone())); getVersioned = storeClient.get("key1"); baseVersion = newVersion; verifyResults(oldVersion, newVersion, getVersioned, newValue); } }
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))); }