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);
}
}
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();
}
}
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());
}
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());
}
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;
}
Aggregations