use of io.atomix.utils.time.Versioned in project atomix by atomix.
the class DocumentTreeService method update.
protected DocumentTreeResult<Versioned<byte[]>> update(Commit<? extends Update> commit) {
DocumentTreeResult<Versioned<byte[]>> result = null;
DocumentPath path = commit.value().path();
// If the path is locked by a transaction, return a WRITE_LOCK error.
if (isLocked(path)) {
return DocumentTreeResult.writeLock();
}
Versioned<byte[]> currentValue = docTree.get(path);
try {
Match<Long> versionMatch = commit.value().versionMatch();
Match<byte[]> valueMatch = commit.value().valueMatch();
if (versionMatch.matches(currentValue == null ? null : currentValue.version()) && valueMatch.matches(currentValue == null ? null : currentValue.value())) {
if (commit.value().value() == null) {
Versioned<byte[]> oldValue = docTree.removeNode(path);
result = new DocumentTreeResult<>(Status.OK, oldValue);
if (oldValue != null) {
notifyListeners(new DocumentTreeEvent<>(path, Type.DELETED, Optional.empty(), Optional.of(oldValue)));
}
} else {
Versioned<byte[]> oldValue = docTree.set(path, commit.value().value().orElse(null));
Versioned<byte[]> newValue = docTree.get(path);
result = new DocumentTreeResult<>(Status.OK, newValue);
if (oldValue == null) {
notifyListeners(new DocumentTreeEvent<>(path, Type.CREATED, Optional.of(newValue), Optional.empty()));
} else {
notifyListeners(new DocumentTreeEvent<>(path, Type.UPDATED, Optional.of(newValue), Optional.of(oldValue)));
}
}
} else {
result = new DocumentTreeResult<>(commit.value().value() == null ? Status.INVALID_PATH : Status.NOOP, currentValue);
}
} catch (IllegalDocumentModificationException e) {
result = DocumentTreeResult.illegalModification();
} catch (NoSuchDocumentPathException e) {
result = DocumentTreeResult.invalidPath();
} catch (Exception e) {
getLogger().error("Failed to apply {} to state machine", commit.value(), e);
throw Throwables.propagate(e);
}
return result;
}
use of io.atomix.utils.time.Versioned in project atomix by atomix.
the class ConsistentMapProxy method computeIf.
@Override
@SuppressWarnings("unchecked")
public CompletableFuture<Versioned<byte[]>> computeIf(String key, Predicate<? super byte[]> condition, BiFunction<? super String, ? super byte[], ? extends byte[]> remappingFunction) {
return get(key).thenCompose(r1 -> {
byte[] existingValue = r1 == null ? null : r1.value();
// if the condition evaluates to false, return existing value.
if (!condition.test(existingValue)) {
return CompletableFuture.completedFuture(r1);
}
byte[] computedValue;
try {
computedValue = remappingFunction.apply(key, existingValue);
} catch (Exception e) {
return Futures.exceptionalFuture(e);
}
if (computedValue == null && r1 == null) {
return CompletableFuture.completedFuture(null);
}
if (r1 == null) {
return proxy.<Put, MapEntryUpdateResult<String, byte[]>>invoke(PUT_IF_ABSENT, serializer()::encode, new Put(key, computedValue, 0), serializer()::decode).whenComplete((r, e) -> throwIfLocked(r)).thenCompose(r -> checkLocked(r)).thenApply(result -> new Versioned<>(computedValue, result.version()));
} else if (computedValue == null) {
return proxy.<RemoveVersion, MapEntryUpdateResult<String, byte[]>>invoke(REMOVE_VERSION, serializer()::encode, new RemoveVersion(key, r1.version()), serializer()::decode).whenComplete((r, e) -> throwIfLocked(r)).thenCompose(r -> checkLocked(r)).thenApply(v -> null);
} else {
return proxy.<ReplaceVersion, MapEntryUpdateResult<String, byte[]>>invoke(REPLACE_VERSION, serializer()::encode, new ReplaceVersion(key, r1.version(), computedValue), serializer()::decode).whenComplete((r, e) -> throwIfLocked(r)).thenCompose(r -> checkLocked(r)).thenApply(result -> result.status() == MapEntryUpdateResult.Status.OK ? new Versioned(computedValue, result.version()) : result.result());
}
});
}
use of io.atomix.utils.time.Versioned in project atomix by atomix.
the class DocumentTreeService method clear.
protected void clear(Commit<Void> commit) {
Queue<DocumentPath> toClearQueue = Queues.newArrayDeque();
Map<String, Versioned<byte[]>> topLevelChildren = docTree.getChildren(DocumentPath.from("root"));
toClearQueue.addAll(topLevelChildren.keySet().stream().map(name -> new DocumentPath(name, DocumentPath.from("root"))).collect(Collectors.toList()));
while (!toClearQueue.isEmpty()) {
DocumentPath path = toClearQueue.remove();
Map<String, Versioned<byte[]>> children = docTree.getChildren(path);
if (children.size() == 0) {
docTree.removeNode(path);
} else {
children.keySet().forEach(name -> toClearQueue.add(new DocumentPath(name, path)));
toClearQueue.add(path);
}
}
}
use of io.atomix.utils.time.Versioned in project atomix by atomix.
the class ConsistentMapTest method testTransaction.
@Test
public void testTransaction() throws Throwable {
Transaction transaction1 = atomix().transactionBuilder().withIsolation(Isolation.READ_COMMITTED).build();
transaction1.begin();
TransactionalMap<String, String> map1 = transaction1.<String, String>mapBuilder("test-transactional-map", protocol()).build();
Transaction transaction2 = atomix().transactionBuilder().withIsolation(Isolation.REPEATABLE_READS).build();
transaction2.begin();
TransactionalMap<String, String> map2 = transaction2.<String, String>mapBuilder("test-transactional-map", protocol()).build();
assertNull(map1.get("foo"));
assertFalse(map1.containsKey("foo"));
assertNull(map2.get("foo"));
assertFalse(map2.containsKey("foo"));
map1.put("foo", "bar");
map1.put("bar", "baz");
assertNull(map1.get("foo"));
assertEquals(transaction1.commit(), CommitStatus.SUCCESS);
assertNull(map2.get("foo"));
assertEquals(map2.get("bar"), "baz");
map2.put("foo", "bar");
assertEquals(map2.get("foo"), "bar");
map2.remove("foo");
assertFalse(map2.containsKey("foo"));
map2.put("foo", "baz");
assertEquals(transaction2.commit(), CommitStatus.FAILURE);
Transaction transaction3 = atomix().transactionBuilder().withIsolation(Isolation.REPEATABLE_READS).build();
transaction3.begin();
TransactionalMap<String, String> map3 = transaction3.<String, String>mapBuilder("test-transactional-map", protocol()).build();
assertEquals(map3.get("foo"), "bar");
map3.put("foo", "baz");
assertEquals(map3.get("foo"), "baz");
assertEquals(transaction3.commit(), CommitStatus.SUCCESS);
ConsistentMap<String, String> map = atomix().<String, String>consistentMapBuilder("test-transactional-map", protocol()).build();
assertEquals(map.get("foo").value(), "baz");
assertEquals(map.get("bar").value(), "baz");
Map<String, Versioned<String>> result = map.getAllPresent(Collections.singleton("foo"));
assertNotNull(result);
assertTrue(result.size() == 1);
assertEquals(result.get("foo").value(), "baz");
}
Aggregations