Search in sources :

Example 1 with Versioned

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;
}
Also used : Versioned(io.atomix.utils.time.Versioned) AtomicLong(java.util.concurrent.atomic.AtomicLong) DocumentPath(io.atomix.core.tree.DocumentPath) NoSuchDocumentPathException(io.atomix.core.tree.NoSuchDocumentPathException) IllegalDocumentModificationException(io.atomix.core.tree.IllegalDocumentModificationException) NoSuchDocumentPathException(io.atomix.core.tree.NoSuchDocumentPathException) IllegalDocumentModificationException(io.atomix.core.tree.IllegalDocumentModificationException)

Example 2 with Versioned

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());
        }
    });
}
Also used : TransactionId(io.atomix.core.transaction.TransactionId) BiFunction(java.util.function.BiFunction) REMOVE_LISTENER(io.atomix.core.map.impl.ConsistentMapOperations.REMOVE_LISTENER) MapEventListener(io.atomix.core.map.MapEventListener) IS_EMPTY(io.atomix.core.map.impl.ConsistentMapOperations.IS_EMPTY) Remove(io.atomix.core.map.impl.ConsistentMapOperations.Remove) KEY_SET(io.atomix.core.map.impl.ConsistentMapOperations.KEY_SET) Duration(java.time.Duration) Map(java.util.Map) COMMIT(io.atomix.core.map.impl.ConsistentMapOperations.COMMIT) ENTRY_SET(io.atomix.core.map.impl.ConsistentMapOperations.ENTRY_SET) REPLACE_VERSION(io.atomix.core.map.impl.ConsistentMapOperations.REPLACE_VERSION) ADD_LISTENER(io.atomix.core.map.impl.ConsistentMapOperations.ADD_LISTENER) ReplaceVersion(io.atomix.core.map.impl.ConsistentMapOperations.ReplaceVersion) Predicate(java.util.function.Predicate) REMOVE(io.atomix.core.map.impl.ConsistentMapOperations.REMOVE) Collection(java.util.Collection) RemoveValue(io.atomix.core.map.impl.ConsistentMapOperations.RemoveValue) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) CONTAINS_KEY(io.atomix.core.map.impl.ConsistentMapOperations.CONTAINS_KEY) PUT_AND_GET(io.atomix.core.map.impl.ConsistentMapOperations.PUT_AND_GET) Versioned(io.atomix.utils.time.Versioned) ContainsValue(io.atomix.core.map.impl.ConsistentMapOperations.ContainsValue) CHANGE(io.atomix.core.map.impl.ConsistentMapEvents.CHANGE) List(java.util.List) GET_OR_DEFAULT(io.atomix.core.map.impl.ConsistentMapOperations.GET_OR_DEFAULT) KryoNamespaces(io.atomix.utils.serializer.KryoNamespaces) TransactionPrepare(io.atomix.core.map.impl.ConsistentMapOperations.TransactionPrepare) Entry(java.util.Map.Entry) Get(io.atomix.core.map.impl.ConsistentMapOperations.Get) Serializer(io.atomix.utils.serializer.Serializer) GET(io.atomix.core.map.impl.ConsistentMapOperations.GET) ConcurrentModificationException(java.util.ConcurrentModificationException) GET_ALL_PRESENT(io.atomix.core.map.impl.ConsistentMapOperations.GET_ALL_PRESENT) REMOVE_VALUE(io.atomix.core.map.impl.ConsistentMapOperations.REMOVE_VALUE) GetOrDefault(io.atomix.core.map.impl.ConsistentMapOperations.GetOrDefault) ConsistentMapException(io.atomix.core.map.ConsistentMapException) PUT_IF_ABSENT(io.atomix.core.map.impl.ConsistentMapOperations.PUT_IF_ABSENT) TransactionCommit(io.atomix.core.map.impl.ConsistentMapOperations.TransactionCommit) CompletableFuture(java.util.concurrent.CompletableFuture) CLEAR(io.atomix.core.map.impl.ConsistentMapOperations.CLEAR) HashSet(java.util.HashSet) AsyncConsistentMap(io.atomix.core.map.AsyncConsistentMap) ConsistentMap(io.atomix.core.map.ConsistentMap) MapEvent(io.atomix.core.map.MapEvent) Replace(io.atomix.core.map.impl.ConsistentMapOperations.Replace) KryoNamespace(io.atomix.utils.serializer.KryoNamespace) REPLACE_VALUE(io.atomix.core.map.impl.ConsistentMapOperations.REPLACE_VALUE) ROLLBACK(io.atomix.core.map.impl.ConsistentMapOperations.ROLLBACK) REMOVE_VERSION(io.atomix.core.map.impl.ConsistentMapOperations.REMOVE_VERSION) TransactionRollback(io.atomix.core.map.impl.ConsistentMapOperations.TransactionRollback) Futures(io.atomix.utils.concurrent.Futures) ContainsKey(io.atomix.core.map.impl.ConsistentMapOperations.ContainsKey) Executor(java.util.concurrent.Executor) AbstractAsyncPrimitive(io.atomix.primitive.impl.AbstractAsyncPrimitive) RemoveVersion(io.atomix.core.map.impl.ConsistentMapOperations.RemoveVersion) SIZE(io.atomix.core.map.impl.ConsistentMapOperations.SIZE) CONTAINS_VALUE(io.atomix.core.map.impl.ConsistentMapOperations.CONTAINS_VALUE) REPLACE(io.atomix.core.map.impl.ConsistentMapOperations.REPLACE) VALUES(io.atomix.core.map.impl.ConsistentMapOperations.VALUES) PREPARE(io.atomix.core.map.impl.ConsistentMapOperations.PREPARE) Put(io.atomix.core.map.impl.ConsistentMapOperations.Put) PUT(io.atomix.core.map.impl.ConsistentMapOperations.PUT) PrimitiveProxy(io.atomix.primitive.proxy.PrimitiveProxy) TransactionLog(io.atomix.core.transaction.TransactionLog) GetAllPresent(io.atomix.core.map.impl.ConsistentMapOperations.GetAllPresent) ReplaceValue(io.atomix.core.map.impl.ConsistentMapOperations.ReplaceValue) RemoveVersion(io.atomix.core.map.impl.ConsistentMapOperations.RemoveVersion) Versioned(io.atomix.utils.time.Versioned) ReplaceVersion(io.atomix.core.map.impl.ConsistentMapOperations.ReplaceVersion) ConcurrentModificationException(java.util.ConcurrentModificationException) ConsistentMapException(io.atomix.core.map.ConsistentMapException) Put(io.atomix.core.map.impl.ConsistentMapOperations.Put)

Example 3 with Versioned

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);
        }
    }
}
Also used : Versioned(io.atomix.utils.time.Versioned) DocumentPath(io.atomix.core.tree.DocumentPath)

Example 4 with Versioned

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");
}
Also used : Transaction(io.atomix.core.transaction.Transaction) Versioned(io.atomix.utils.time.Versioned) Test(org.junit.Test) AbstractPrimitiveTest(io.atomix.core.AbstractPrimitiveTest)

Aggregations

Versioned (io.atomix.utils.time.Versioned)4 AbstractPrimitiveTest (io.atomix.core.AbstractPrimitiveTest)1 AsyncConsistentMap (io.atomix.core.map.AsyncConsistentMap)1 ConsistentMap (io.atomix.core.map.ConsistentMap)1 ConsistentMapException (io.atomix.core.map.ConsistentMapException)1 MapEvent (io.atomix.core.map.MapEvent)1 MapEventListener (io.atomix.core.map.MapEventListener)1 CHANGE (io.atomix.core.map.impl.ConsistentMapEvents.CHANGE)1 ADD_LISTENER (io.atomix.core.map.impl.ConsistentMapOperations.ADD_LISTENER)1 CLEAR (io.atomix.core.map.impl.ConsistentMapOperations.CLEAR)1 COMMIT (io.atomix.core.map.impl.ConsistentMapOperations.COMMIT)1 CONTAINS_KEY (io.atomix.core.map.impl.ConsistentMapOperations.CONTAINS_KEY)1 CONTAINS_VALUE (io.atomix.core.map.impl.ConsistentMapOperations.CONTAINS_VALUE)1 ContainsKey (io.atomix.core.map.impl.ConsistentMapOperations.ContainsKey)1 ContainsValue (io.atomix.core.map.impl.ConsistentMapOperations.ContainsValue)1 ENTRY_SET (io.atomix.core.map.impl.ConsistentMapOperations.ENTRY_SET)1 GET (io.atomix.core.map.impl.ConsistentMapOperations.GET)1 GET_ALL_PRESENT (io.atomix.core.map.impl.ConsistentMapOperations.GET_ALL_PRESENT)1 GET_OR_DEFAULT (io.atomix.core.map.impl.ConsistentMapOperations.GET_OR_DEFAULT)1 Get (io.atomix.core.map.impl.ConsistentMapOperations.Get)1