use of com.hazelcast.internal.util.MutableLong 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