use of com.hazelcast.spi.impl.operationservice.Operation 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);
}
}
use of com.hazelcast.spi.impl.operationservice.Operation in project hazelcast by hazelcast.
the class MapProxySupport method clearInternal.
public void clearInternal() {
try {
Operation clearOperation = operationProvider.createClearOperation(name);
clearOperation.setServiceName(SERVICE_NAME);
BinaryOperationFactory factory = new BinaryOperationFactory(clearOperation, getNodeEngine());
Map<Integer, Object> resultMap = operationService.invokeOnAllPartitions(SERVICE_NAME, factory);
int clearedCount = 0;
for (Object object : resultMap.values()) {
clearedCount += (Integer) object;
}
if (clearedCount > 0) {
publishMapEvent(clearedCount, CLEAR_ALL);
}
incrementOtherOperationsStat();
} catch (Throwable t) {
throw rethrow(t);
}
}
use of com.hazelcast.spi.impl.operationservice.Operation in project hazelcast by hazelcast.
the class MapProxySupport method waitUntilLoaded.
public void waitUntilLoaded() {
try {
int mapNamesPartitionId = partitionService.getPartitionId(name);
// first we have to check if key-load finished - otherwise
// the loading on other partitions might not have started.
// In this case we can't invoke IsPartitionLoadedOperation
// -> they will return "true", but it won't be correct
int sleepDurationMillis = INITIAL_WAIT_LOAD_SLEEP_MILLIS;
while (true) {
Operation op = new IsKeyLoadFinishedOperation(name);
Future<Boolean> loadingFuture = operationService.invokeOnPartition(SERVICE_NAME, op, mapNamesPartitionId);
if (loadingFuture.get()) {
break;
}
// sleep with some back-off
TimeUnit.MILLISECONDS.sleep(sleepDurationMillis);
sleepDurationMillis = (sleepDurationMillis * 2 < MAXIMAL_WAIT_LOAD_SLEEP_MILLIS) ? sleepDurationMillis * 2 : MAXIMAL_WAIT_LOAD_SLEEP_MILLIS;
}
OperationFactory opFactory = new IsPartitionLoadedOperationFactory(name);
Map<Integer, Object> results = operationService.invokeOnAllPartitions(SERVICE_NAME, opFactory);
// wait for all the data to be loaded on all partitions - wait forever
waitAllTrue(results, opFactory);
} catch (Throwable t) {
throw rethrow(t);
}
}
use of com.hazelcast.spi.impl.operationservice.Operation in project hazelcast by hazelcast.
the class QueryEngineImpl method dispatchFullQueryOnLocalMemberOnQueryThread.
private List<Future<Result>> dispatchFullQueryOnLocalMemberOnQueryThread(Query query) {
Operation operation = mapServiceContext.getMapOperationProvider(query.getMapName()).createQueryOperation(query);
Future<Result> result = operationService.invokeOnTarget(MapService.SERVICE_NAME, operation, nodeEngine.getThisAddress());
return singletonList(result);
}
use of com.hazelcast.spi.impl.operationservice.Operation in project hazelcast by hazelcast.
the class QueryEngineImpl method dispatchFullQueryOnAllMembersOnQueryThread.
private List<Future<Result>> dispatchFullQueryOnAllMembersOnQueryThread(Query query) {
Collection<Address> members;
if (query.getPartitionIdSet().size() == partitionService.getPartitionCount()) {
members = clusterService.getMembers(DATA_MEMBER_SELECTOR).stream().map(m -> m.getAddress()).collect(Collectors.toList());
} else {
members = new HashSet<>();
for (PrimitiveIterator.OfInt iterator = query.getPartitionIdSet().intIterator(); iterator.hasNext(); ) {
members.add(partitionService.getPartitionOwnerOrWait(iterator.next()));
}
}
List<Future<Result>> futures = new ArrayList<>(members.size());
for (Address address : members) {
Operation operation = createQueryOperation(query);
Future<Result> future = operationService.invokeOnTarget(MapService.SERVICE_NAME, operation, address);
futures.add(future);
}
return futures;
}
Aggregations