use of com.hazelcast.spi.impl.InternalCompletableFuture in project hazelcast by hazelcast.
the class InvalidationMetaDataFetcher method fetchMetadata.
public final void fetchMetadata(ConcurrentMap<String, RepairingHandler> handlers) {
if (handlers.isEmpty()) {
return;
}
List<String> dataStructureNames = getDataStructureNames(handlers);
Map<Member, InternalCompletableFuture> futureByMember = fetchMembersMetadataFor(dataStructureNames);
for (Map.Entry<Member, InternalCompletableFuture> entry : futureByMember.entrySet()) {
Member member = entry.getKey();
InternalCompletableFuture future = entry.getValue();
processMemberMetadata(member, future, handlers);
}
}
use of com.hazelcast.spi.impl.InternalCompletableFuture in project hazelcast by hazelcast.
the class InvalidationMetaDataFetcher method fetchMembersMetadataFor.
private Map<Member, InternalCompletableFuture> fetchMembersMetadataFor(List<String> names) {
Collection<Member> members = getDataMembers();
if (members.isEmpty()) {
return Collections.emptyMap();
}
Map<Member, InternalCompletableFuture> futureByMember = createHashMap(members.size());
for (Member member : members) {
Address address = member.getAddress();
try {
futureByMember.put(member, fetchMetadataOf(member, names));
} catch (Exception e) {
handleExceptionWhileProcessingMetadata(member, e);
}
}
return futureByMember;
}
use of com.hazelcast.spi.impl.InternalCompletableFuture in project hazelcast by hazelcast.
the class MasterContext method invokeOnParticipant.
private void invokeOnParticipant(MemberInfo memberInfo, Supplier<Operation> operationSupplier, @Nullable Consumer<Collection<Map.Entry<MemberInfo, Object>>> completionCallback, @Nullable BiConsumer<Address, Object> individualCallback, boolean retryOnTimeoutException, ConcurrentMap<MemberInfo, Object> collectedResponses, AtomicInteger remainingCount) {
Operation operation = operationSupplier.get();
InternalCompletableFuture<Object> future = nodeEngine.getOperationService().createInvocationBuilder(JetServiceBackend.SERVICE_NAME, operation, memberInfo.getAddress()).invoke();
future.whenCompleteAsync(withTryCatch(logger, (r, throwable) -> {
Object response = r != null ? r : throwable != null ? peel(throwable) : NULL_OBJECT;
if (retryOnTimeoutException && throwable instanceof OperationTimeoutException) {
logger.warning("Retrying " + operation.getClass().getName() + " that failed with " + OperationTimeoutException.class.getSimpleName() + " in " + jobIdString());
invokeOnParticipant(memberInfo, operationSupplier, completionCallback, individualCallback, retryOnTimeoutException, collectedResponses, remainingCount);
return;
}
if (individualCallback != null) {
individualCallback.accept(memberInfo.getAddress(), throwable != null ? peel(throwable) : r);
}
Object oldResponse = collectedResponses.put(memberInfo, response);
assert oldResponse == null : "Duplicate response for " + memberInfo.getAddress() + ". Old=" + oldResponse + ", new=" + response;
if (remainingCount.decrementAndGet() == 0 && completionCallback != null) {
completionCallback.accept(collectedResponses.entrySet().stream().map(e -> e.getValue() == NULL_OBJECT ? entry(e.getKey(), null) : e).collect(Collectors.toList()));
}
}));
}
use of com.hazelcast.spi.impl.InternalCompletableFuture in project hazelcast by hazelcast.
the class InvocationUtil method invokeOnStableClusterSerial.
/**
* Invoke operation on all cluster members.
*
* The invocation is serial: It iterates over all members starting from the oldest member to the youngest one.
* If there is a cluster membership change while invoking then it will restart invocations on all members. This
* implies the operation should be idempotent.
*
* If there is an exception - other than {@link com.hazelcast.core.MemberLeftException} or
* {@link com.hazelcast.spi.exception.TargetNotMemberException} while invoking then the iteration
* is interrupted and the exception is propagated to the caller.
*/
public static <V> InternalCompletableFuture<V> invokeOnStableClusterSerial(NodeEngine nodeEngine, Supplier<? extends Operation> operationSupplier, int maxRetries) {
ClusterService clusterService = nodeEngine.getClusterService();
if (!clusterService.isJoined()) {
return newCompletedFuture(null);
}
RestartingMemberIterator memberIterator = new RestartingMemberIterator(clusterService, maxRetries);
// we are going to iterate over all members and invoke an operation on each of them
InvokeOnMemberFunction invokeOnMemberFunction = new InvokeOnMemberFunction(operationSupplier, nodeEngine, memberIterator);
Iterator<InternalCompletableFuture<Object>> invocationIterator = map(memberIterator, invokeOnMemberFunction);
// the future itself completes only when the last invocation completes (or if there is an error)
return new ChainingFuture(invocationIterator, memberIterator);
}
use of com.hazelcast.spi.impl.InternalCompletableFuture in project hazelcast by hazelcast.
the class MapProxySupport method putAllInternal.
/**
* This method will group all entries per partition and send one operation
* per member. If there are e.g. five keys for a single member, even if
* they are from different partitions, there will only be a single remote
* invocation instead of five.
* <p>
* There is also an optional support for batching to send smaller packages.
* Takes care about {@code null} checks for keys and values.
*
* @param future iff not-null, execute asynchronously by completing this future.
* Batching is not supported in async mode
*/
@SuppressWarnings({ "checkstyle:MethodLength", "checkstyle:CyclomaticComplexity", "checkstyle:NPathComplexity" })
protected void putAllInternal(Map<? extends K, ? extends V> map, @Nullable InternalCompletableFuture<Void> future, boolean triggerMapLoader) {
try {
int mapSize = map.size();
if (mapSize == 0) {
if (future != null) {
future.complete(null);
}
return;
}
boolean useBatching = future == null && isPutAllUseBatching(mapSize);
int partitionCount = partitionService.getPartitionCount();
int initialSize = getPutAllInitialSize(useBatching, mapSize, partitionCount);
Map<Address, List<Integer>> memberPartitionsMap = partitionService.getMemberPartitionsMap();
// init counters for batching
MutableLong[] counterPerMember = null;
Address[] addresses = null;
if (useBatching) {
counterPerMember = new MutableLong[partitionCount];
addresses = new Address[partitionCount];
for (Entry<Address, List<Integer>> addressListEntry : memberPartitionsMap.entrySet()) {
MutableLong counter = new MutableLong();
Address address = addressListEntry.getKey();
for (int partitionId : addressListEntry.getValue()) {
counterPerMember[partitionId] = counter;
addresses[partitionId] = address;
}
}
}
// fill entriesPerPartition
MapEntries[] entriesPerPartition = new MapEntries[partitionCount];
for (Entry entry : map.entrySet()) {
checkNotNull(entry.getKey(), NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(entry.getValue(), NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(entry.getKey());
int partitionId = partitionService.getPartitionId(keyData);
MapEntries entries = entriesPerPartition[partitionId];
if (entries == null) {
entries = new MapEntries(initialSize);
entriesPerPartition[partitionId] = entries;
}
entries.add(keyData, toData(entry.getValue()));
if (useBatching) {
long currentSize = ++counterPerMember[partitionId].value;
if (currentSize % putAllBatchSize == 0) {
List<Integer> partitions = memberPartitionsMap.get(addresses[partitionId]);
invokePutAllOperation(addresses[partitionId], partitions, entriesPerPartition, triggerMapLoader).get();
}
}
}
// invoke operations for entriesPerPartition
AtomicInteger counter = new AtomicInteger(memberPartitionsMap.size());
InternalCompletableFuture<Void> resultFuture = future != null ? future : new InternalCompletableFuture<>();
BiConsumer<Void, Throwable> callback = (response, t) -> {
if (t != null) {
resultFuture.completeExceptionally(t);
}
if (counter.decrementAndGet() == 0) {
try {
// don't ignore errors here, see https://github.com/hazelcast/hazelcast-jet/issues/3046
finalizePutAll(map);
} catch (Throwable e) {
resultFuture.completeExceptionally(e);
return;
}
if (!resultFuture.isDone()) {
resultFuture.complete(null);
}
}
};
for (Entry<Address, List<Integer>> entry : memberPartitionsMap.entrySet()) {
invokePutAllOperation(entry.getKey(), entry.getValue(), entriesPerPartition, triggerMapLoader).whenCompleteAsync(callback);
}
// if executing in sync mode, block for the responses
if (future == null) {
resultFuture.get();
}
} catch (Throwable e) {
throw rethrow(e);
}
}
Aggregations