Search in sources :

Example 1 with CRDTTimestampedLong

use of com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong in project hazelcast by hazelcast.

the class PNCounterProxy method invokeInternal.

/**
 * Invokes the {@code operation} recursively on viable replica addresses
 * until successful or the list of viable replicas is exhausted.
 * Replicas with addresses contained in the {@code excludedAddresses} are
 * skipped. If there are no viable replicas, this method will throw the
 * {@code lastException} if not {@code null} or a
 * {@link NoDataMemberInClusterException} if the {@code lastException} is
 * {@code null}.
 *
 * @param operation         the operation to invoke on a CRDT replica
 * @param excludedAddresses the addresses to exclude when choosing a replica
 *                          address, must not be {@code null}
 * @param lastException     the exception thrown from the last invocation of
 *                          the {@code operation} on a replica, may be {@code null}
 * @return the result of the operation invocation on a replica
 * @throws NoDataMemberInClusterException if there are no replicas and the
 *                                        {@code lastException} is {@code null}
 */
private long invokeInternal(Operation operation, List<Address> excludedAddresses, HazelcastException lastException) {
    final Address target = getCRDTOperationTarget(excludedAddresses);
    if (target == null) {
        throw lastException != null ? lastException : new NoDataMemberInClusterException("Cannot invoke operations on a CRDT because the cluster does not contain any data members");
    }
    try {
        final InvocationBuilder builder = getNodeEngine().getOperationService().createInvocationBuilder(SERVICE_NAME, operation, target);
        if (operationTryCount > 0) {
            builder.setTryCount(operationTryCount);
        }
        final InvocationFuture<CRDTTimestampedLong> future = builder.invoke();
        final CRDTTimestampedLong result = future.joinInternal();
        updateObservedReplicaTimestamps(result.getVectorClock());
        return result.getValue();
    } catch (HazelcastException e) {
        logger.fine("Exception occurred while invoking operation on target " + target + ", choosing different target", e);
        if (excludedAddresses == EMPTY_ADDRESS_LIST) {
            excludedAddresses = new ArrayList<Address>();
        }
        excludedAddresses.add(target);
        return invokeInternal(operation, excludedAddresses, e);
    }
}
Also used : HazelcastException(com.hazelcast.core.HazelcastException) Address(com.hazelcast.cluster.Address) ArrayList(java.util.ArrayList) InvocationBuilder(com.hazelcast.spi.impl.operationservice.InvocationBuilder) NoDataMemberInClusterException(com.hazelcast.partition.NoDataMemberInClusterException) CRDTTimestampedLong(com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong)

Example 2 with CRDTTimestampedLong

use of com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong in project hazelcast by hazelcast.

the class PNCounterImpl method get.

/**
 * Returns the current value of the counter.
 * <p>
 * The method can throw a {@link ConsistencyLostException} when the state
 * of this CRDT is not causally related to the observed timestamps. This
 * means that it cannot provide the session guarantees of RYW (read your
 * writes) and monotonic read.
 *
 * @param observedTimestamps the vector clock last observed by the client of
 *                           this counter
 * @return the current counter value with the current counter vector clock
 * @throws ConsistencyLostException if this replica cannot provide the
 *                                  session guarantees
 */
public CRDTTimestampedLong get(VectorClock observedTimestamps) {
    checkSessionConsistency(observedTimestamps);
    stateReadLock.lock();
    try {
        long value = 0;
        for (long[] pnValue : state.values()) {
            value += pnValue[0];
            value -= pnValue[1];
        }
        return new CRDTTimestampedLong(value, new VectorClock(stateVectorClock));
    } finally {
        stateReadLock.unlock();
    }
}
Also used : VectorClock(com.hazelcast.cluster.impl.VectorClock) CRDTTimestampedLong(com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong)

Example 3 with CRDTTimestampedLong

use of com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong in project hazelcast by hazelcast.

the class PNCounterAddMessageTask method encodeResponse.

@Override
protected ClientMessage encodeResponse(Object response) {
    final CRDTTimestampedLong resp = (CRDTTimestampedLong) response;
    final PNCounterConfig counterConfig = nodeEngine.getConfig().findPNCounterConfig(parameters.name);
    return PNCounterAddCodec.encodeResponse(resp.getValue(), resp.getVectorClock().entrySet(), counterConfig.getReplicaCount());
}
Also used : CRDTTimestampedLong(com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong) PNCounterConfig(com.hazelcast.config.PNCounterConfig)

Example 4 with CRDTTimestampedLong

use of com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong in project hazelcast by hazelcast.

the class PNCounterGetMessageTask method encodeResponse.

@Override
protected ClientMessage encodeResponse(Object response) {
    final CRDTTimestampedLong resp = (CRDTTimestampedLong) response;
    final PNCounterConfig counterConfig = nodeEngine.getConfig().findPNCounterConfig(parameters.name);
    return PNCounterGetCodec.encodeResponse(resp.getValue(), resp.getVectorClock().entrySet(), counterConfig.getReplicaCount());
}
Also used : CRDTTimestampedLong(com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong) PNCounterConfig(com.hazelcast.config.PNCounterConfig)

Example 5 with CRDTTimestampedLong

use of com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong in project hazelcast by hazelcast.

the class PNCounterImpl method getAndUpdate.

/**
 * Updates the PN counter state for this replica and returns the value before
 * the update.
 * The {@code delta} parameter must be greater than or equal to 0.
 * The {@code isAddition} parameter determines if this is an addition or a
 * subtraction.
 *
 * @param delta              the delta to be applied to the current value,
 *                           must be greater than or equal to 0
 * @param observedTimestamps the last observed timestamp by the client
 * @param isAddition         if the {@code delta} should be added to or
 *                           subtracted from the current value
 * @return the PN counter value before the update
 */
private CRDTTimestampedLong getAndUpdate(long delta, VectorClock observedTimestamps, boolean isAddition) {
    if (delta < 0) {
        throw new IllegalArgumentException("Delta must be greater than or equal to 0");
    }
    final long nextTimestamp = stateVectorClock.getTimestampForReplica(localReplicaId) + 1;
    final long[] pnValues = state.containsKey(localReplicaId) ? state.get(localReplicaId) : new long[] { 0, 0 };
    pnValues[isAddition ? 0 : 1] += delta;
    state.put(localReplicaId, pnValues);
    stateVectorClock.setReplicaTimestamp(localReplicaId, nextTimestamp);
    final CRDTTimestampedLong current = get(observedTimestamps);
    current.setValue(isAddition ? current.getValue() - delta : current.getValue() + delta);
    return current;
}
Also used : CRDTTimestampedLong(com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong)

Aggregations

CRDTTimestampedLong (com.hazelcast.internal.crdt.pncounter.operations.CRDTTimestampedLong)5 PNCounterConfig (com.hazelcast.config.PNCounterConfig)2 Address (com.hazelcast.cluster.Address)1 VectorClock (com.hazelcast.cluster.impl.VectorClock)1 HazelcastException (com.hazelcast.core.HazelcastException)1 NoDataMemberInClusterException (com.hazelcast.partition.NoDataMemberInClusterException)1 InvocationBuilder (com.hazelcast.spi.impl.operationservice.InvocationBuilder)1 ArrayList (java.util.ArrayList)1