Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2008-2015, Hazelcast, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.map.impl.mapstore.writebehind;
import com.hazelcast.map.impl.mapstore.MapStoreContext;
import com.hazelcast.map.impl.mapstore.writebehind.entry.DelayedEntry;
import com.hazelcast.nio.serialization.Data;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static com.hazelcast.util.CollectionUtil.isNotEmpty;
/**
* Processes store operations.
*/
class DefaultWriteBehindProcessor extends AbstractWriteBehindProcessor {
private static final Comparator DELAYED_ENTRY_COMPARATOR = new Comparator() {
@Override
public int compare(DelayedEntry o1, DelayedEntry o2) {
final long s1 = o1.getStoreTime();
final long s2 = o2.getStoreTime();
return (s1 < s2) ? -1 : ((s1 == s2) ? 0 : 1);
}
};
private static final int RETRY_TIMES_OF_A_FAILED_STORE_OPERATION = 3;
private static final int RETRY_STORE_AFTER_WAIT_SECONDS = 1;
private final List storeListeners;
DefaultWriteBehindProcessor(MapStoreContext mapStoreContext) {
super(mapStoreContext);
this.storeListeners = new ArrayList(2);
}
@Override
public Map> process(List delayedEntries) {
Map> failMap;
sort(delayedEntries);
if (writeBatchSize > 1) {
failMap = doStoreUsingBatchSize(delayedEntries);
} else {
failMap = processInternal(delayedEntries);
}
return failMap;
}
private Map> processInternal(List delayedEntries) {
if (delayedEntries == null || delayedEntries.isEmpty()) {
return Collections.emptyMap();
}
final Map> failsPerPartition = new HashMap>();
final List entriesToProcess = new ArrayList();
StoreOperationType operationType = null;
StoreOperationType previousOperationType;
// process entries by preserving order.
for (final DelayedEntry entry : delayedEntries) {
previousOperationType = operationType;
if (entry.getValue() == null) {
operationType = StoreOperationType.DELETE;
} else {
operationType = StoreOperationType.WRITE;
}
if (previousOperationType != null && !previousOperationType.equals(operationType)) {
final List failures = callHandler(entriesToProcess, previousOperationType);
addToFails(failures, failsPerPartition);
entriesToProcess.clear();
}
entriesToProcess.add(entry);
}
final List failures = callHandler(entriesToProcess, operationType);
addToFails(failures, failsPerPartition);
entriesToProcess.clear();
return failsPerPartition;
}
private void addToFails(List fails, Map> failsPerPartition) {
if (fails == null || fails.isEmpty()) {
return;
}
for (DelayedEntry entry : fails) {
final int partitionId = entry.getPartitionId();
List delayedEntriesPerPartition = failsPerPartition.get(partitionId);
if (delayedEntriesPerPartition == null) {
delayedEntriesPerPartition = new ArrayList();
failsPerPartition.put(partitionId, delayedEntriesPerPartition);
}
delayedEntriesPerPartition.add(entry);
}
}
/**
* Decides how entries should be passed to handlers.
* It passes entries to handler's single or batch handling
* methods.
*
* @param delayedEntries sorted entries to be processed.
* @return failed entry list if any.
*/
private List callHandler(Collection delayedEntries, StoreOperationType operationType) {
final int size = delayedEntries.size();
if (size == 0) {
return Collections.emptyList();
}
// if we want to write all store operations on a key into the MapStore, not same as write-coalescing, we don't call
// batch processing methods e.g., MapStore{#storeAll,#deleteAll}, instead we call methods which process single entries
// e.g. MapStore{#store,#delete}. This is because MapStore#storeAll requires a Map type in its signature and Map type
// can only contain one store operation type per key, so only last update on a key can be included when batching.
// Due to that limitation it is not possible to provide a correct no-write-coalescing write-behind behavior.
// Under that limitation of current MapStore interface, we are making a workaround and persisting all
// entries one by one for no-write-coalescing write-behind map-stores and as a result not doing batching
// when writeCoalescing is false.
if (size == 1 || !writeCoalescing) {
return processEntriesOneByOne(delayedEntries, operationType);
}
final DelayedEntry[] delayedEntriesArray = delayedEntries.toArray(new DelayedEntry[delayedEntries.size()]);
final Map