/*
* Copyright (c) 2008-2017, 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.proxy;
import com.hazelcast.aggregation.Aggregator;
import com.hazelcast.config.MapConfig;
import com.hazelcast.core.EntryListener;
import com.hazelcast.core.EntryView;
import com.hazelcast.core.ExecutionCallback;
import com.hazelcast.core.HazelcastException;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.ICompletableFuture;
import com.hazelcast.core.IMap;
import com.hazelcast.map.EntryProcessor;
import com.hazelcast.map.MapInterceptor;
import com.hazelcast.map.QueryCache;
import com.hazelcast.map.impl.MapService;
import com.hazelcast.map.impl.SimpleEntryView;
import com.hazelcast.map.impl.iterator.MapPartitionIterator;
import com.hazelcast.map.impl.query.AggregationResult;
import com.hazelcast.map.impl.query.MapQueryEngine;
import com.hazelcast.map.impl.query.Query;
import com.hazelcast.map.impl.query.QueryResult;
import com.hazelcast.map.impl.query.Target;
import com.hazelcast.map.impl.querycache.QueryCacheContext;
import com.hazelcast.map.impl.querycache.subscriber.InternalQueryCache;
import com.hazelcast.map.impl.querycache.subscriber.NodeQueryCacheEndToEndConstructor;
import com.hazelcast.map.impl.querycache.subscriber.QueryCacheEndToEndProvider;
import com.hazelcast.map.impl.querycache.subscriber.QueryCacheRequest;
import com.hazelcast.map.impl.querycache.subscriber.SubscriberContext;
import com.hazelcast.map.listener.MapListener;
import com.hazelcast.map.listener.MapPartitionLostListener;
import com.hazelcast.mapreduce.Collator;
import com.hazelcast.mapreduce.CombinerFactory;
import com.hazelcast.mapreduce.Job;
import com.hazelcast.mapreduce.JobTracker;
import com.hazelcast.mapreduce.KeyValueSource;
import com.hazelcast.mapreduce.Mapper;
import com.hazelcast.mapreduce.MappingJob;
import com.hazelcast.mapreduce.ReducerFactory;
import com.hazelcast.mapreduce.ReducingSubmittableJob;
import com.hazelcast.mapreduce.aggregation.Aggregation;
import com.hazelcast.mapreduce.aggregation.Supplier;
import com.hazelcast.nio.serialization.Data;
import com.hazelcast.projection.Projection;
import com.hazelcast.query.PagingPredicate;
import com.hazelcast.query.PartitionPredicate;
import com.hazelcast.query.Predicate;
import com.hazelcast.query.TruePredicate;
import com.hazelcast.spi.InternalCompletableFuture;
import com.hazelcast.spi.NodeEngine;
import com.hazelcast.spi.Operation;
import com.hazelcast.util.CollectionUtil;
import com.hazelcast.util.ConstructorFunction;
import com.hazelcast.util.IterationType;
import com.hazelcast.util.UuidUtil;
import com.hazelcast.util.executor.DelegatingFuture;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static com.hazelcast.config.InMemoryFormat.NATIVE;
import static com.hazelcast.map.impl.MapService.SERVICE_NAME;
import static com.hazelcast.map.impl.query.QueryResultUtils.transformToSet;
import static com.hazelcast.map.impl.querycache.subscriber.QueryCacheRequests.newQueryCacheRequest;
import static com.hazelcast.util.MapUtil.createHashMap;
import static com.hazelcast.util.Preconditions.checkNotInstanceOf;
import static com.hazelcast.util.Preconditions.checkNotNull;
import static com.hazelcast.util.Preconditions.checkPositive;
import static com.hazelcast.util.Preconditions.checkTrue;
import static com.hazelcast.util.Preconditions.isNotNull;
import static java.util.Collections.emptyMap;
/**
* Proxy implementation of {@link com.hazelcast.core.IMap} interface.
*
* @param <K> the key type of map.
* @param <V> the value type of map.
*/
@SuppressWarnings("checkstyle:classfanoutcomplexity")
public class MapProxyImpl<K, V> extends MapProxySupport<K, V> {
public MapProxyImpl(String name, MapService mapService, NodeEngine nodeEngine, MapConfig mapConfig) {
super(name, mapService, nodeEngine, mapConfig);
}
@Override
public V get(Object key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return toObject(getInternal(keyData));
}
@Override
public V put(K key, V value) {
return put(key, value, -1, TimeUnit.MILLISECONDS);
}
@Override
public V put(K key, V value, long ttl, TimeUnit timeunit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
Data result = putInternal(keyData, valueData, ttl, timeunit);
return toObject(result);
}
@Override
public boolean tryPut(K key, V value, long timeout, TimeUnit timeunit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
return tryPutInternal(keyData, valueData, timeout, timeunit);
}
@Override
public V putIfAbsent(K key, V value) {
return putIfAbsent(key, value, -1, TimeUnit.MILLISECONDS);
}
@Override
public V putIfAbsent(K key, V value, long ttl, TimeUnit timeunit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
Data result = putIfAbsentInternal(keyData, valueData, ttl, timeunit);
return toObject(result);
}
@Override
public void putTransient(K key, V value, long ttl, TimeUnit timeunit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
putTransientInternal(keyData, valueData, ttl, timeunit);
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(oldValue, NULL_VALUE_IS_NOT_ALLOWED);
checkNotNull(newValue, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data oldValueData = toData(oldValue);
Data newValueData = toData(newValue);
return replaceInternal(keyData, oldValueData, newValueData);
}
@Override
public V replace(K key, V value) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
return toObject(replaceInternal(keyData, valueData));
}
@Override
public void set(K key, V value) {
set(key, value, -1, TimeUnit.MILLISECONDS);
}
@Override
public void set(K key, V value, long ttl, TimeUnit timeunit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
setInternal(keyData, valueData, ttl, timeunit);
}
@Override
public V remove(Object key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data result = removeInternal(keyData);
return toObject(result);
}
@Override
public boolean remove(Object key, Object value) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
return removeInternal(keyData, valueData);
}
@Override
public void removeAll(Predicate<K, V> predicate) {
checkNotNull(predicate, "predicate cannot be null");
removeAllInternal(predicate);
}
@Override
public void delete(Object key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
deleteInternal(keyData);
}
@Override
public boolean containsKey(Object key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return containsKeyInternal(keyData);
}
@Override
public boolean containsValue(Object value) {
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data valueData = toData(value);
return containsValueInternal(valueData);
}
@Override
public void lock(K key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
lockSupport.lock(getNodeEngine(), keyData);
}
@Override
public void lock(Object key, long leaseTime, TimeUnit timeUnit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkPositive(leaseTime, "leaseTime should be positive");
Data keyData = toDataWithStrategy(key);
lockSupport.lock(getNodeEngine(), keyData, timeUnit.toMillis(leaseTime));
}
@Override
public void unlock(K key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
lockSupport.unlock(getNodeEngine(), keyData);
}
@Override
public boolean tryRemove(K key, long timeout, TimeUnit timeunit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return tryRemoveInternal(keyData, timeout, timeunit);
}
@Override
public ICompletableFuture<V> getAsync(K key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return new DelegatingFuture<V>(getAsyncInternal(keyData), serializationService);
}
@Override
public boolean isLocked(K key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return lockSupport.isLocked(getNodeEngine(), keyData);
}
@Override
public ICompletableFuture<V> putAsync(K key, V value) {
return putAsync(key, value, -1, TimeUnit.MILLISECONDS);
}
@Override
public ICompletableFuture<V> putAsync(K key, V value, long ttl, TimeUnit timeunit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
return new DelegatingFuture<V>(putAsyncInternal(keyData, valueData, ttl, timeunit), serializationService);
}
@Override
public ICompletableFuture<Void> setAsync(K key, V value) {
return setAsync(key, value, -1, TimeUnit.MILLISECONDS);
}
@Override
public ICompletableFuture<Void> setAsync(K key, V value, long ttl, TimeUnit timeunit) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
Data valueData = toData(value);
return new DelegatingFuture<Void>(setAsyncInternal(keyData, valueData, ttl, timeunit), serializationService);
}
@Override
public ICompletableFuture<V> removeAsync(K key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return new DelegatingFuture<V>(removeAsyncInternal(keyData), serializationService);
}
@Override
public Map<K, V> getAll(Set<K> keys) {
if (CollectionUtil.isEmpty(keys)) {
return emptyMap();
}
List<Data> requestedKeys = new ArrayList<Data>(keys.size());
for (K key : keys) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
requestedKeys.add(keyData);
}
List<Object> resultingKeyValuePairs = new ArrayList<Object>(2 * keys.size());
getAllObjectInternal(requestedKeys, resultingKeyValuePairs);
Map<K, V> result = createHashMap(keys.size());
for (int i = 0; i < resultingKeyValuePairs.size(); ) {
K key = toObject(resultingKeyValuePairs.get(i++));
V value = toObject(resultingKeyValuePairs.get(i++));
result.put(key, value);
}
return result;
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
putAllInternal(map);
}
@Override
public boolean tryLock(K key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return lockSupport.tryLock(getNodeEngine(), keyData);
}
@Override
public boolean tryLock(K key, long time, TimeUnit timeunit) throws InterruptedException {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return lockSupport.tryLock(getNodeEngine(), keyData, time, timeunit);
}
@Override
public boolean tryLock(K key, long time, TimeUnit timeunit, long leaseTime, TimeUnit leaseTimeUnit)
throws InterruptedException {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return lockSupport.tryLock(getNodeEngine(), keyData, time, timeunit, leaseTime, leaseTimeUnit);
}
@Override
public void forceUnlock(K key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
lockSupport.forceUnlock(getNodeEngine(), keyData);
}
@Override
public String addInterceptor(MapInterceptor interceptor) {
checkNotNull(interceptor, "Interceptor should not be null!");
return addMapInterceptorInternal(interceptor);
}
@Override
public void removeInterceptor(String id) {
checkNotNull(id, "Interceptor id should not be null!");
removeMapInterceptorInternal(id);
}
@Override
public String addLocalEntryListener(MapListener listener) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
return addLocalEntryListenerInternal(listener);
}
@Override
public String addLocalEntryListener(EntryListener listener) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
return addLocalEntryListenerInternal(listener);
}
@Override
public String addLocalEntryListener(MapListener listener, Predicate<K, V> predicate, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
return addLocalEntryListenerInternal(listener, predicate, null, includeValue);
}
@Override
public String addLocalEntryListener(EntryListener listener, Predicate<K, V> predicate, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
return addLocalEntryListenerInternal(listener, predicate, null, includeValue);
}
@Override
public String addLocalEntryListener(MapListener listener, Predicate<K, V> predicate, K key, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return addLocalEntryListenerInternal(listener, predicate, keyData, includeValue);
}
@Override
public String addLocalEntryListener(EntryListener listener, Predicate<K, V> predicate, K key, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
return addLocalEntryListenerInternal(listener, predicate, keyData, includeValue);
}
@Override
public String addEntryListener(MapListener listener, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
return addEntryListenerInternal(listener, null, includeValue);
}
@Override
public String addEntryListener(EntryListener listener, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
return addEntryListenerInternal(listener, null, includeValue);
}
@Override
public String addEntryListener(MapListener listener, K key, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
return addEntryListenerInternal(listener, toDataWithStrategy(key), includeValue);
}
@Override
public String addEntryListener(EntryListener listener, K key, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
return addEntryListenerInternal(listener, toDataWithStrategy(key), includeValue);
}
@Override
public String addEntryListener(MapListener listener, Predicate<K, V> predicate, K key, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
return addEntryListenerInternal(listener, predicate, toDataWithStrategy(key), includeValue);
}
@Override
public String addEntryListener(EntryListener listener, Predicate<K, V> predicate, K key, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
return addEntryListenerInternal(listener, predicate, toDataWithStrategy(key), includeValue);
}
@Override
public String addEntryListener(MapListener listener, Predicate<K, V> predicate, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
return addEntryListenerInternal(listener, predicate, null, includeValue);
}
@Override
public String addEntryListener(EntryListener listener, Predicate<K, V> predicate, boolean includeValue) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
return addEntryListenerInternal(listener, predicate, null, includeValue);
}
@Override
public boolean removeEntryListener(String id) {
checkNotNull(id, "Listener id should not be null!");
return removeEntryListenerInternal(id);
}
@Override
public String addPartitionLostListener(MapPartitionLostListener listener) {
checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED);
return addPartitionLostListenerInternal(listener);
}
@Override
public boolean removePartitionLostListener(String id) {
checkNotNull(id, "Listener id should not be null!");
return removePartitionLostListenerInternal(id);
}
@Override
@SuppressWarnings("unchecked")
public EntryView<K, V> getEntryView(K key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
SimpleEntryView<K, V> entryViewInternal = (SimpleEntryView<K, V>) getEntryViewInternal(toDataWithStrategy(key));
if (entryViewInternal == null) {
return null;
}
Data value = (Data) entryViewInternal.getValue();
entryViewInternal.setKey(key);
entryViewInternal.setValue((V) toObject(value));
return entryViewInternal;
}
@Override
public boolean evict(Object key) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
return evictInternal(toDataWithStrategy(key));
}
@Override
public void evictAll() {
evictAllInternal();
}
@Override
public void loadAll(boolean replaceExistingValues) {
checkTrue(isMapStoreEnabled(), "First you should configure a map store");
loadAllInternal(replaceExistingValues);
}
@Override
public void loadAll(Set<K> keys, boolean replaceExistingValues) {
checkTrue(isMapStoreEnabled(), "First you should configure a map store");
checkNotNull(keys, "Parameter keys should not be null.");
loadInternal(convertToData(keys), replaceExistingValues);
}
/**
* This method clears the map and calls deleteAll on MapStore which if connected to a database,
* will delete the records from that database.
* <p>
* If you wish to clear the map only without calling deleteAll, use #clearMapOnly.
*
* @see #clearMapOnly
*/
@Override
public void clear() {
clearInternal();
}
/**
* This method clears the map. It does not invoke deleteAll on any associated MapStore.
*
* @see #clear
*/
//TODO: why is this not tested?
//TODO: how come the implementation is the same as clear? I think this code is broken
//TODO: This method also isn't part of the IMap API
public void clearMapOnly() {
// TODO: need a different method here that does not call deleteAll()
clearInternal();
}
@Override
public Set<K> keySet() {
return keySet(TruePredicate.INSTANCE);
}
@Override
@SuppressWarnings("unchecked")
public Set<K> keySet(Predicate predicate) {
return executePredicate(predicate, IterationType.KEY, true);
}
@Override
public Set entrySet() {
return entrySet(TruePredicate.INSTANCE);
}
@Override
public Set entrySet(Predicate predicate) {
return executePredicate(predicate, IterationType.ENTRY, true);
}
@Override
public Collection<V> values() {
return values(TruePredicate.INSTANCE);
}
@Override
@SuppressWarnings("unchecked")
public Collection<V> values(Predicate predicate) {
return executePredicate(predicate, IterationType.VALUE, false);
}
private Set executePredicate(Predicate predicate, IterationType iterationType, boolean uniqueResult) {
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
MapQueryEngine queryEngine = getMapQueryEngine();
QueryResult result;
if (predicate instanceof PartitionPredicate) {
PartitionPredicate partitionPredicate = (PartitionPredicate) predicate;
Data key = toData(partitionPredicate.getPartitionKey());
int partitionId = partitionService.getPartitionId(key);
Query query = Query.of()
.mapName(getName())
.predicate(partitionPredicate.getTarget())
.iterationType(iterationType)
.build();
result = queryEngine.execute(query, Target.of().partitionOwner(partitionId).build());
} else {
Query query = Query.of()
.mapName(getName())
.predicate(predicate)
.iterationType(iterationType)
.build();
result = queryEngine.execute(query, Target.ALL_NODES);
}
return transformToSet(serializationService, result, predicate, iterationType, uniqueResult);
}
@Override
public Set<K> localKeySet() {
return localKeySet(TruePredicate.INSTANCE);
}
@Override
@SuppressWarnings("unchecked")
public Set<K> localKeySet(Predicate predicate) {
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
MapQueryEngine queryEngine = getMapQueryEngine();
Query query = Query.of()
.mapName(getName())
.predicate(predicate)
.iterationType(IterationType.KEY)
.build();
QueryResult result = queryEngine.execute(query, Target.LOCAL_NODE);
return transformToSet(serializationService, result, predicate, IterationType.KEY, false);
}
@Override
public Object executeOnKey(K key, EntryProcessor entryProcessor) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data result = executeOnKeyInternal(toDataWithStrategy(key), entryProcessor);
return toObject(result);
}
@Override
public Map<K, Object> executeOnKeys(Set<K> keys, EntryProcessor entryProcessor) {
if (keys == null || keys.contains(null)) {
throw new NullPointerException(NULL_KEY_IS_NOT_ALLOWED);
}
if (keys.isEmpty()) {
return emptyMap();
}
Set<Data> dataKeys = new HashSet<Data>(keys.size());
for (K key : keys) {
dataKeys.add(toDataWithStrategy(key));
}
return executeOnKeysInternal(dataKeys, entryProcessor);
}
@Override
public void submitToKey(K key, EntryProcessor entryProcessor, ExecutionCallback callback) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
executeOnKeyInternal(keyData, entryProcessor, callback);
}
@Override
public ICompletableFuture submitToKey(K key, EntryProcessor entryProcessor) {
checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED);
Data keyData = toDataWithStrategy(key);
InternalCompletableFuture future = executeOnKeyInternal(keyData, entryProcessor, null);
return new DelegatingFuture(future, serializationService);
}
@Override
public Map<K, Object> executeOnEntries(EntryProcessor entryProcessor) {
return executeOnEntries(entryProcessor, TruePredicate.INSTANCE);
}
@Override
public Map<K, Object> executeOnEntries(EntryProcessor entryProcessor, Predicate predicate) {
List<Data> result = new ArrayList<Data>();
executeOnEntriesInternal(entryProcessor, predicate, result);
if (result.isEmpty()) {
return emptyMap();
}
Map<K, Object> resultingMap = createHashMap(result.size() / 2);
for (int i = 0; i < result.size(); ) {
Data key = result.get(i++);
Data value = result.get(i++);
resultingMap.put((K) toObject(key), toObject(value));
}
return resultingMap;
}
@Override
public <R> R aggregate(Aggregator<Map.Entry<K, V>, R> aggregator) {
checkNotNull(aggregator, NULL_AGGREGATOR_IS_NOT_ALLOWED);
MapQueryEngine queryEngine = getMapQueryEngine();
aggregator = serializationService.toObject(serializationService.toData(aggregator));
Query query = Query.of()
.mapName(getName())
.predicate(TruePredicate.INSTANCE)
.iterationType(IterationType.ENTRY)
.aggregator(aggregator)
.build();
AggregationResult result = queryEngine.execute(query, Target.ALL_NODES);
return result.<R>getAggregator().aggregate();
}
@Override
public <R> R aggregate(Aggregator<Map.Entry<K, V>, R> aggregator, Predicate<K, V> predicate) {
checkNotNull(aggregator, NULL_AGGREGATOR_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
aggregator = serializationService.toObject(serializationService.toData(aggregator));
MapQueryEngine queryEngine = getMapQueryEngine();
if (predicate instanceof PagingPredicate) {
throw new IllegalArgumentException("PagingPredicate now allowed with EntryAggregator.");
}
Query query = Query.of()
.mapName(getName())
.predicate(predicate)
.iterationType(IterationType.ENTRY)
.aggregator(aggregator)
.build();
AggregationResult result = queryEngine.execute(query, Target.ALL_NODES);
return result.<R>getAggregator().aggregate();
}
@Override
public <R> Collection<R> project(Projection<Map.Entry<K, V>, R> projection) {
checkNotNull(projection, NULL_PROJECTION_IS_NOT_ALLOWED);
MapQueryEngine queryEngine = getMapQueryEngine();
projection = serializationService.toObject(serializationService.toData(projection));
Query query = Query.of()
.mapName(getName())
.predicate(TruePredicate.INSTANCE)
.iterationType(IterationType.VALUE)
.projection(projection)
.build();
QueryResult result = queryEngine.execute(query, Target.ALL_NODES);
return transformToSet(serializationService, result, TruePredicate.INSTANCE, IterationType.VALUE, false);
}
@Override
public <R> Collection<R> project(Projection<Map.Entry<K, V>, R> projection, Predicate<K, V> predicate) {
checkNotNull(projection, NULL_PROJECTION_IS_NOT_ALLOWED);
checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED);
projection = serializationService.toObject(serializationService.toData(projection));
MapQueryEngine queryEngine = getMapQueryEngine();
Query query = Query.of()
.mapName(getName())
.predicate(predicate)
.iterationType(IterationType.VALUE)
.projection(projection)
.build();
queryEngine.execute(query, Target.ALL_NODES);
QueryResult result = queryEngine.execute(query, Target.ALL_NODES);
return transformToSet(serializationService, result, predicate, IterationType.VALUE, false);
}
@Override
public <SuppliedValue, Result> Result aggregate(Supplier<K, V, SuppliedValue> supplier,
Aggregation<K, SuppliedValue, Result> aggregation) {
checkTrue(NATIVE != mapConfig.getInMemoryFormat(), "NATIVE storage format is not supported for MapReduce");
HazelcastInstance hazelcastInstance = getNodeEngine().getHazelcastInstance();
JobTracker jobTracker = hazelcastInstance.getJobTracker("hz::aggregation-map-" + getName());
return aggregate(supplier, aggregation, jobTracker);
}
@Override
public <SuppliedValue, Result> Result aggregate(Supplier<K, V, SuppliedValue> supplier,
Aggregation<K, SuppliedValue, Result> aggregation,
JobTracker jobTracker) {
checkTrue(NATIVE != mapConfig.getInMemoryFormat(), "NATIVE storage format is not supported for MapReduce");
try {
isNotNull(jobTracker, "jobTracker");
KeyValueSource<K, V> keyValueSource = KeyValueSource.fromMap(this);
Job<K, V> job = jobTracker.newJob(keyValueSource);
Mapper mapper = aggregation.getMapper(supplier);
CombinerFactory combinerFactory = aggregation.getCombinerFactory();
ReducerFactory reducerFactory = aggregation.getReducerFactory();
Collator collator = aggregation.getCollator();
MappingJob mappingJob = job.mapper(mapper);
ReducingSubmittableJob reducingJob;
if (combinerFactory == null) {
reducingJob = mappingJob.reducer(reducerFactory);
} else {
reducingJob = mappingJob.combiner(combinerFactory).reducer(reducerFactory);
}
ICompletableFuture<Result> future = reducingJob.submit(collator);
return future.get();
} catch (Exception e) {
// TODO: not what we want, because it can lead to wrapping of HazelcastException
throw new HazelcastException(e);
}
}
protected Object invoke(Operation operation, int partitionId) throws Throwable {
Future future = operationService.invokeOnPartition(SERVICE_NAME, operation, partitionId);
Object response = future.get();
Object result = toObject(response);
if (result instanceof Throwable) {
throw (Throwable) result;
}
return result;
}
public Iterator<Entry<K, V>> iterator(int fetchSize, int partitionId, boolean prefetchValues) {
return new MapPartitionIterator<K, V>(this, fetchSize, partitionId, prefetchValues);
}
@Override
public String toString() {
return "IMap{name='" + name + '\'' + '}';
}
@Override
public QueryCache<K, V> getQueryCache(String name) {
checkNotNull(name, "name cannot be null");
return getQueryCacheInternal(name, null, null, null, this);
}
@Override
public QueryCache<K, V> getQueryCache(String name, Predicate<K, V> predicate, boolean includeValue) {
checkNotNull(name, "name cannot be null");
checkNotNull(predicate, "predicate cannot be null");
checkNotInstanceOf(PagingPredicate.class, predicate, "predicate");
return getQueryCacheInternal(name, null, predicate, includeValue, this);
}
@Override
public QueryCache<K, V> getQueryCache(String name, MapListener listener, Predicate<K, V> predicate, boolean includeValue) {
checkNotNull(name, "name cannot be null");
checkNotNull(predicate, "predicate cannot be null");
checkNotInstanceOf(PagingPredicate.class, predicate, "predicate");
return getQueryCacheInternal(name, listener, predicate, includeValue, this);
}
private QueryCache<K, V> getQueryCacheInternal(String name, MapListener listener, Predicate<K, V> predicate,
Boolean includeValue, IMap<K, V> map) {
QueryCacheContext queryCacheContext = mapServiceContext.getQueryCacheContext();
QueryCacheRequest request = newQueryCacheRequest()
.forMap(map)
.withCacheName(UuidUtil.newUnsecureUuidString())
.withUserGivenCacheName(name)
.withListener(listener)
.withPredicate(predicate)
.withIncludeValue(includeValue)
.withContext(queryCacheContext);
return createQueryCache(request);
}
private QueryCache<K, V> createQueryCache(QueryCacheRequest request) {
ConstructorFunction<String, InternalQueryCache> constructorFunction = new NodeQueryCacheEndToEndConstructor(request);
QueryCacheContext queryCacheContext = request.getContext();
SubscriberContext subscriberContext = queryCacheContext.getSubscriberContext();
QueryCacheEndToEndProvider queryCacheEndToEndProvider = subscriberContext.getEndToEndQueryCacheProvider();
return queryCacheEndToEndProvider.getOrCreateQueryCache(request.getMapName(), request.getUserGivenCacheName(),
constructorFunction);
}
}