/* * 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.client.proxy; import com.hazelcast.aggregation.Aggregator; import com.hazelcast.client.impl.ClientLockReferenceIdGenerator; import com.hazelcast.client.impl.ClientMessageDecoder; import com.hazelcast.client.impl.protocol.ClientMessage; import com.hazelcast.client.impl.protocol.codec.MapAddEntryListenerCodec; import com.hazelcast.client.impl.protocol.codec.MapAddEntryListenerToKeyCodec; import com.hazelcast.client.impl.protocol.codec.MapAddEntryListenerToKeyWithPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapAddEntryListenerWithPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapAddIndexCodec; import com.hazelcast.client.impl.protocol.codec.MapAddInterceptorCodec; import com.hazelcast.client.impl.protocol.codec.MapAddPartitionLostListenerCodec; import com.hazelcast.client.impl.protocol.codec.MapAggregateCodec; import com.hazelcast.client.impl.protocol.codec.MapAggregateWithPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapClearCodec; import com.hazelcast.client.impl.protocol.codec.MapContainsKeyCodec; import com.hazelcast.client.impl.protocol.codec.MapContainsValueCodec; import com.hazelcast.client.impl.protocol.codec.MapDeleteCodec; import com.hazelcast.client.impl.protocol.codec.MapEntriesWithPagingPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapEntriesWithPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapEntrySetCodec; import com.hazelcast.client.impl.protocol.codec.MapEvictAllCodec; import com.hazelcast.client.impl.protocol.codec.MapEvictCodec; import com.hazelcast.client.impl.protocol.codec.MapExecuteOnAllKeysCodec; import com.hazelcast.client.impl.protocol.codec.MapExecuteOnKeyCodec; import com.hazelcast.client.impl.protocol.codec.MapExecuteOnKeysCodec; import com.hazelcast.client.impl.protocol.codec.MapExecuteWithPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapFlushCodec; import com.hazelcast.client.impl.protocol.codec.MapForceUnlockCodec; import com.hazelcast.client.impl.protocol.codec.MapGetAllCodec; import com.hazelcast.client.impl.protocol.codec.MapGetCodec; import com.hazelcast.client.impl.protocol.codec.MapGetEntryViewCodec; import com.hazelcast.client.impl.protocol.codec.MapIsEmptyCodec; import com.hazelcast.client.impl.protocol.codec.MapIsLockedCodec; import com.hazelcast.client.impl.protocol.codec.MapKeySetCodec; import com.hazelcast.client.impl.protocol.codec.MapKeySetWithPagingPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapKeySetWithPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapLoadAllCodec; import com.hazelcast.client.impl.protocol.codec.MapLoadGivenKeysCodec; import com.hazelcast.client.impl.protocol.codec.MapLockCodec; import com.hazelcast.client.impl.protocol.codec.MapProjectCodec; import com.hazelcast.client.impl.protocol.codec.MapProjectWithPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapPutAllCodec; import com.hazelcast.client.impl.protocol.codec.MapPutCodec; import com.hazelcast.client.impl.protocol.codec.MapPutIfAbsentCodec; import com.hazelcast.client.impl.protocol.codec.MapPutTransientCodec; import com.hazelcast.client.impl.protocol.codec.MapRemoveAllCodec; import com.hazelcast.client.impl.protocol.codec.MapRemoveCodec; import com.hazelcast.client.impl.protocol.codec.MapRemoveEntryListenerCodec; import com.hazelcast.client.impl.protocol.codec.MapRemoveIfSameCodec; import com.hazelcast.client.impl.protocol.codec.MapRemoveInterceptorCodec; import com.hazelcast.client.impl.protocol.codec.MapRemovePartitionLostListenerCodec; import com.hazelcast.client.impl.protocol.codec.MapReplaceCodec; import com.hazelcast.client.impl.protocol.codec.MapReplaceIfSameCodec; import com.hazelcast.client.impl.protocol.codec.MapSetCodec; import com.hazelcast.client.impl.protocol.codec.MapSizeCodec; import com.hazelcast.client.impl.protocol.codec.MapSubmitToKeyCodec; import com.hazelcast.client.impl.protocol.codec.MapTryLockCodec; import com.hazelcast.client.impl.protocol.codec.MapTryPutCodec; import com.hazelcast.client.impl.protocol.codec.MapTryRemoveCodec; import com.hazelcast.client.impl.protocol.codec.MapUnlockCodec; import com.hazelcast.client.impl.protocol.codec.MapValuesCodec; import com.hazelcast.client.impl.protocol.codec.MapValuesWithPagingPredicateCodec; import com.hazelcast.client.impl.protocol.codec.MapValuesWithPredicateCodec; import com.hazelcast.client.impl.querycache.ClientQueryCacheContext; import com.hazelcast.client.impl.querycache.subscriber.ClientQueryCacheEndToEndConstructor; import com.hazelcast.client.map.impl.ClientMapPartitionIterator; import com.hazelcast.client.spi.ClientContext; import com.hazelcast.client.spi.ClientPartitionService; import com.hazelcast.client.spi.ClientProxy; import com.hazelcast.client.spi.EventHandler; import com.hazelcast.client.spi.impl.ClientInvocation; import com.hazelcast.client.spi.impl.ClientInvocationFuture; import com.hazelcast.client.spi.impl.ListenerMessageCodec; import com.hazelcast.client.util.ClientDelegatingFuture; import com.hazelcast.core.EntryEvent; import com.hazelcast.core.EntryEventType; import com.hazelcast.core.EntryListener; import com.hazelcast.core.EntryView; import com.hazelcast.core.ExecutionCallback; import com.hazelcast.core.HazelcastException; import com.hazelcast.core.ICompletableFuture; import com.hazelcast.core.IMap; import com.hazelcast.core.IMapEvent; import com.hazelcast.core.MapEvent; import com.hazelcast.core.Member; import com.hazelcast.core.ReadOnly; import com.hazelcast.internal.serialization.InternalSerializationService; import com.hazelcast.map.EntryBackupProcessor; import com.hazelcast.map.EntryProcessor; import com.hazelcast.map.MapInterceptor; import com.hazelcast.map.MapPartitionLostEvent; import com.hazelcast.map.QueryCache; import com.hazelcast.map.impl.DataAwareEntryEvent; import com.hazelcast.map.impl.LazyMapEntry; import com.hazelcast.map.impl.ListenerAdapter; import com.hazelcast.map.impl.SimpleEntryView; import com.hazelcast.map.impl.querycache.subscriber.InternalQueryCache; 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.monitor.LocalMapStats; import com.hazelcast.monitor.impl.LocalMapStatsImpl; import com.hazelcast.nio.serialization.Data; import com.hazelcast.projection.Projection; import com.hazelcast.query.PagingPredicate; import com.hazelcast.query.Predicate; import com.hazelcast.spi.impl.UnmodifiableLazyList; import com.hazelcast.util.CollectionUtil; import com.hazelcast.util.ConstructorFunction; import com.hazelcast.util.IterationType; import com.hazelcast.util.MapUtil; import com.hazelcast.util.Preconditions; import com.hazelcast.util.UuidUtil; import com.hazelcast.util.collection.InflatableSet; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; 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.map.impl.ListenerAdapters.createListenerAdapter; import static com.hazelcast.map.impl.MapListenerFlagOperator.setAndGetListenerFlags; import static com.hazelcast.map.impl.querycache.subscriber.QueryCacheRequests.newQueryCacheRequest; import static com.hazelcast.util.CollectionUtil.objectToDataCollection; import static com.hazelcast.util.ExceptionUtil.rethrow; import static com.hazelcast.util.Preconditions.checkNotInstanceOf; import static com.hazelcast.util.Preconditions.checkNotNull; import static com.hazelcast.util.SortingUtil.getSortedQueryResultSet; import static com.hazelcast.util.ThreadUtil.getThreadId; import static java.util.Collections.emptyMap; /** * Proxy implementation of {@link IMap}. * * @param <K> key * @param <V> value */ @SuppressWarnings("checkstyle:classdataabstractioncoupling") public class ClientMapProxy<K, V> extends ClientProxy implements IMap<K, V> { protected static final String NULL_LISTENER_IS_NOT_ALLOWED = "Null listener is not allowed!"; protected static final String NULL_KEY_IS_NOT_ALLOWED = "Null key is not allowed!"; protected static final String NULL_VALUE_IS_NOT_ALLOWED = "Null value is not allowed!"; protected static final String NULL_PREDICATE_IS_NOT_ALLOWED = "Predicate should not be null!"; protected static final String NULL_AGGREGATOR_IS_NOT_ALLOWED = "Aggregator should not be null!"; @SuppressWarnings("unchecked") private static final ClientMessageDecoder GET_ASYNC_RESPONSE_DECODER = new ClientMessageDecoder() { @Override public <T> T decodeClientMessage(ClientMessage clientMessage) { return (T) MapGetCodec.decodeResponse(clientMessage).response; } }; @SuppressWarnings("unchecked") private static final ClientMessageDecoder PUT_ASYNC_RESPONSE_DECODER = new ClientMessageDecoder() { @Override public <T> T decodeClientMessage(ClientMessage clientMessage) { return (T) MapPutCodec.decodeResponse(clientMessage).response; } }; @SuppressWarnings("unchecked") private static final ClientMessageDecoder SET_ASYNC_RESPONSE_DECODER = new ClientMessageDecoder() { @Override public <T> T decodeClientMessage(ClientMessage clientMessage) { return null; } }; @SuppressWarnings("unchecked") private static final ClientMessageDecoder REMOVE_ASYNC_RESPONSE_DECODER = new ClientMessageDecoder() { @Override public <T> T decodeClientMessage(ClientMessage clientMessage) { return (T) MapRemoveCodec.decodeResponse(clientMessage).response; } }; @SuppressWarnings("unchecked") private static final ClientMessageDecoder SUBMIT_TO_KEY_RESPONSE_DECODER = new ClientMessageDecoder() { @Override public <T> T decodeClientMessage(ClientMessage clientMessage) { return (T) MapSubmitToKeyCodec.decodeResponse(clientMessage).response; } }; private ClientLockReferenceIdGenerator lockReferenceIdGenerator; private ClientQueryCacheContext queryCacheContext; public ClientMapProxy(String serviceName, String name, ClientContext context) { super(serviceName, name, context); } @Override protected void onInitialize() { super.onInitialize(); lockReferenceIdGenerator = getClient().getLockReferenceIdGenerator(); queryCacheContext = getContext().getQueryCacheContext(); } @Override public boolean containsKey(Object key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); return containsKeyInternal(keyData); } protected boolean containsKeyInternal(Data keyData) { ClientMessage message = MapContainsKeyCodec.encodeRequest(name, keyData, getThreadId()); ClientMessage result = invoke(message, keyData); MapContainsKeyCodec.ResponseParameters resultParameters = MapContainsKeyCodec.decodeResponse(result); return resultParameters.response; } @Override public boolean containsValue(Object value) { checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED); Data valueData = toData(value); ClientMessage request = MapContainsValueCodec.encodeRequest(name, valueData); ClientMessage response = invoke(request); MapContainsValueCodec.ResponseParameters resultParameters = MapContainsValueCodec.decodeResponse(response); return resultParameters.response; } @Override public V get(Object key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); return toObject(getInternal(keyData)); } protected Object getInternal(Data keyData) { ClientMessage request = MapGetCodec.encodeRequest(name, keyData, getThreadId()); ClientMessage response = invoke(request, keyData); MapGetCodec.ResponseParameters resultParameters = MapGetCodec.decodeResponse(response); return resultParameters.response; } @Override public V put(K key, V value) { return put(key, value, -1, TimeUnit.MILLISECONDS); } @Override public V remove(Object key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); MapRemoveCodec.ResponseParameters resultParameters = removeInternal(keyData); return toObject(resultParameters.response); } protected MapRemoveCodec.ResponseParameters removeInternal(Data keyData) { ClientMessage request = MapRemoveCodec.encodeRequest(name, keyData, getThreadId()); ClientMessage response = invoke(request, keyData); return MapRemoveCodec.decodeResponse(response); } @Override public boolean remove(Object key, Object value) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED); Data keyData = toData(key); Data valueData = toData(value); return removeInternal(keyData, valueData); } protected boolean removeInternal(Data keyData, Data valueData) { ClientMessage request = MapRemoveIfSameCodec.encodeRequest(name, keyData, valueData, getThreadId()); ClientMessage response = invoke(request, keyData); MapRemoveIfSameCodec.ResponseParameters resultParameters = MapRemoveIfSameCodec.decodeResponse(response); return resultParameters.response; } @Override public void removeAll(Predicate<K, V> predicate) { checkNotNull(predicate, "predicate cannot be null"); removeAllInternal(predicate); } protected void removeAllInternal(Predicate predicate) { ClientMessage request = MapRemoveAllCodec.encodeRequest(name, toData(predicate)); invoke(request); } @Override public void delete(Object key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); deleteInternal(keyData); } protected void deleteInternal(Data keyData) { ClientMessage request = MapDeleteCodec.encodeRequest(name, keyData, getThreadId()); invoke(request, keyData); } @Override public void flush() { ClientMessage request = MapFlushCodec.encodeRequest(name); invoke(request); } @Override public ICompletableFuture<V> getAsync(K key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); return getAsyncInternal(keyData); } protected ICompletableFuture<V> getAsyncInternal(Data keyData) { try { ClientMessage request = MapGetCodec.encodeRequest(name, keyData, getThreadId()); ClientInvocationFuture future = invokeOnKeyOwner(request, keyData); return new ClientDelegatingFuture<V>(future, getSerializationService(), GET_ASYNC_RESPONSE_DECODER); } catch (Exception e) { throw rethrow(e); } } private ClientInvocationFuture invokeOnKeyOwner(ClientMessage request, Data keyData) { int partitionId = getContext().getPartitionService().getPartitionId(keyData); ClientInvocation clientInvocation = new ClientInvocation(getClient(), request, partitionId); return clientInvocation.invoke(); } @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 = toData(key); Data valueData = toData(value); return putAsyncInternal(ttl, timeunit, keyData, valueData); } protected ICompletableFuture<V> putAsyncInternal(long ttl, TimeUnit timeunit, Data keyData, Data valueData) { try { long ttlMillis = getTimeInMillis(ttl, timeunit); ClientMessage request = MapPutCodec.encodeRequest(name, keyData, valueData, getThreadId(), ttlMillis); ClientInvocationFuture future = invokeOnKeyOwner(request, keyData); return new ClientDelegatingFuture<V>(future, getSerializationService(), PUT_ASYNC_RESPONSE_DECODER); } catch (Exception e) { throw rethrow(e); } } @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 = toData(key); Data valueData = toData(value); return setAsyncInternal(ttl, timeunit, keyData, valueData); } protected ICompletableFuture<Void> setAsyncInternal(long ttl, TimeUnit timeunit, Data keyData, Data valueData) { try { long ttlMillis = getTimeInMillis(ttl, timeunit); ClientMessage request = MapSetCodec.encodeRequest(name, keyData, valueData, getThreadId(), ttlMillis); ClientInvocationFuture future = invokeOnKeyOwner(request, keyData); return new ClientDelegatingFuture<Void>(future, getSerializationService(), SET_ASYNC_RESPONSE_DECODER); } catch (Exception e) { throw rethrow(e); } } @Override public ICompletableFuture<V> removeAsync(K key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); return removeAsyncInternal(keyData); } protected ICompletableFuture<V> removeAsyncInternal(Data keyData) { try { ClientMessage request = MapRemoveCodec.encodeRequest(name, keyData, getThreadId()); ClientInvocationFuture future = invokeOnKeyOwner(request, keyData); return new ClientDelegatingFuture<V>(future, getSerializationService(), REMOVE_ASYNC_RESPONSE_DECODER); } catch (Exception e) { throw rethrow(e); } } @Override public boolean tryRemove(K key, long timeout, TimeUnit timeunit) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); return tryRemoveInternal(timeout, timeunit, keyData); } protected boolean tryRemoveInternal(long timeout, TimeUnit timeunit, Data keyData) { ClientMessage request = MapTryRemoveCodec.encodeRequest(name, keyData, getThreadId(), timeunit.toMillis(timeout)); ClientMessage response = invoke(request, keyData); MapTryRemoveCodec.ResponseParameters resultParameters = MapTryRemoveCodec.decodeResponse(response); return resultParameters.response; } @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 = toData(key); Data valueData = toData(value); return tryPutInternal(timeout, timeunit, keyData, valueData); } protected boolean tryPutInternal(long timeout, TimeUnit timeunit, Data keyData, Data valueData) { long timeoutMillis = getTimeInMillis(timeout, timeunit); ClientMessage request = MapTryPutCodec.encodeRequest(name, keyData, valueData, getThreadId(), timeoutMillis); ClientMessage response = invoke(request, keyData); MapTryPutCodec.ResponseParameters resultParameters = MapTryPutCodec.decodeResponse(response); return resultParameters.response; } @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 = toData(key); Data valueData = toData(value); return putInternal(ttl, timeunit, keyData, valueData); } protected V putInternal(long ttl, TimeUnit timeunit, Data keyData, Data valueData) { long ttlMillis = getTimeInMillis(ttl, timeunit); ClientMessage request = MapPutCodec.encodeRequest(name, keyData, valueData, getThreadId(), ttlMillis); ClientMessage response = invoke(request, keyData); MapPutCodec.ResponseParameters resultParameters = MapPutCodec.decodeResponse(response); return toObject(resultParameters.response); } @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 = toData(key); Data valueData = toData(value); putTransientInternal(ttl, timeunit, keyData, valueData); } protected void putTransientInternal(long ttl, TimeUnit timeunit, Data keyData, Data valueData) { long ttlMillis = getTimeInMillis(ttl, timeunit); ClientMessage request = MapPutTransientCodec.encodeRequest(name, keyData, valueData, getThreadId(), ttlMillis); invoke(request, keyData); } @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 = toData(key); Data valueData = toData(value); return putIfAbsentInternal(ttl, timeunit, keyData, valueData); } protected V putIfAbsentInternal(long ttl, TimeUnit timeunit, Data keyData, Data valueData) { long ttlMillis = getTimeInMillis(ttl, timeunit); ClientMessage request = MapPutIfAbsentCodec.encodeRequest(name, keyData, valueData, getThreadId(), ttlMillis); ClientMessage result = invoke(request, keyData); MapPutIfAbsentCodec.ResponseParameters resultParameters = MapPutIfAbsentCodec.decodeResponse(result); return toObject(resultParameters.response); } @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 = toData(key); Data oldValueData = toData(oldValue); Data newValueData = toData(newValue); return replaceIfSameInternal(keyData, oldValueData, newValueData); } protected boolean replaceIfSameInternal(Data keyData, Data oldValueData, Data newValueData) { ClientMessage request = MapReplaceIfSameCodec.encodeRequest(name, keyData, oldValueData, newValueData, getThreadId()); ClientMessage response = invoke(request, keyData); MapReplaceIfSameCodec.ResponseParameters resultParameters = MapReplaceIfSameCodec.decodeResponse(response); return resultParameters.response; } @Override public V replace(K key, V value) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); checkNotNull(value, NULL_VALUE_IS_NOT_ALLOWED); Data keyData = toData(key); Data valueData = toData(value); return replaceInternal(keyData, valueData); } protected V replaceInternal(Data keyData, Data valueData) { ClientMessage request = MapReplaceCodec.encodeRequest(name, keyData, valueData, getThreadId()); ClientMessage response = invoke(request, keyData); MapReplaceCodec.ResponseParameters resultParameters = MapReplaceCodec.decodeResponse(response); return toObject(resultParameters.response); } @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 = toData(key); Data valueData = toData(value); setInternal(ttl, timeunit, keyData, valueData); } protected void setInternal(long ttl, TimeUnit timeunit, Data keyData, Data valueData) { long ttlMillis = getTimeInMillis(ttl, timeunit); ClientMessage request = MapSetCodec.encodeRequest(name, keyData, valueData, getThreadId(), ttlMillis); invoke(request, keyData); } @Override public void lock(K key) { lock(key, -1, TimeUnit.MILLISECONDS); } @Override public void lock(K key, long leaseTime, TimeUnit timeUnit) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); ClientMessage request = MapLockCodec.encodeRequest(name, keyData, getThreadId(), getTimeInMillis(leaseTime, timeUnit), lockReferenceIdGenerator.getNextReferenceId()); invoke(request, keyData); } @Override public boolean isLocked(K key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); ClientMessage request = MapIsLockedCodec.encodeRequest(name, keyData); ClientMessage response = invoke(request, keyData); MapIsLockedCodec.ResponseParameters resultParameters = MapIsLockedCodec.decodeResponse(response); return resultParameters.response; } @Override public boolean tryLock(K key) { try { return tryLock(key, 0, null); } catch (InterruptedException e) { return false; } } @Override public boolean tryLock(K key, long time, TimeUnit timeunit) throws InterruptedException { return tryLock(key, time, timeunit, Long.MAX_VALUE, null); } @Override public boolean tryLock(K key, long time, TimeUnit timeunit, long leaseTime, TimeUnit leaseUnit) throws InterruptedException { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); long leaseTimeMillis = getTimeInMillis(leaseTime, leaseUnit); long timeoutMillis = getTimeInMillis(time, timeunit); ClientMessage request = MapTryLockCodec.encodeRequest(name, keyData, getThreadId(), leaseTimeMillis, timeoutMillis, lockReferenceIdGenerator.getNextReferenceId()); ClientMessage response = invoke(request, keyData); MapTryLockCodec.ResponseParameters resultParameters = MapTryLockCodec.decodeResponse(response); return resultParameters.response; } @Override public void unlock(K key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); ClientMessage request = MapUnlockCodec.encodeRequest(name, keyData, getThreadId(), lockReferenceIdGenerator.getNextReferenceId()); invoke(request, keyData); } @Override public void forceUnlock(K key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); ClientMessage request = MapForceUnlockCodec.encodeRequest(name, keyData, lockReferenceIdGenerator.getNextReferenceId()); invoke(request, keyData); } @Override public String addLocalEntryListener(MapListener listener) { throw new UnsupportedOperationException("Locality is ambiguous for client!"); } @Override public String addLocalEntryListener(EntryListener listener) { throw new UnsupportedOperationException("Locality is ambiguous for client!"); } @Override public String addLocalEntryListener(MapListener listener, Predicate<K, V> predicate, boolean includeValue) { throw new UnsupportedOperationException("Locality is ambiguous for client!"); } @Override public String addLocalEntryListener(EntryListener listener, Predicate<K, V> predicate, boolean includeValue) { throw new UnsupportedOperationException("Locality is ambiguous for client!"); } @Override public String addLocalEntryListener(MapListener listener, Predicate<K, V> predicate, K key, boolean includeValue) { throw new UnsupportedOperationException("Locality is ambiguous for client!"); } @Override public String addLocalEntryListener(EntryListener listener, Predicate<K, V> predicate, K key, boolean includeValue) { throw new UnsupportedOperationException("Locality is ambiguous for client!"); } @Override public String addInterceptor(MapInterceptor interceptor) { Data data = toData(interceptor); ClientMessage request = MapAddInterceptorCodec.encodeRequest(name, data); ClientMessage response = invoke(request); MapAddInterceptorCodec.ResponseParameters resultParameters = MapAddInterceptorCodec.decodeResponse(response); return resultParameters.response; } @Override public void removeInterceptor(String id) { ClientMessage request = MapRemoveInterceptorCodec.encodeRequest(name, id); invoke(request); } @Override public String addEntryListener(MapListener listener, boolean includeValue) { checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED); ListenerAdapter<IMapEvent> listenerAdaptor = createListenerAdapter(listener); return addEntryListenerInternal(listenerAdaptor, includeValue); } @Override public String addEntryListener(EntryListener listener, boolean includeValue) { checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED); ListenerAdapter<IMapEvent> listenerAdaptor = createListenerAdapter(listener); return addEntryListenerInternal(listenerAdaptor, includeValue); } private String addEntryListenerInternal(ListenerAdapter<IMapEvent> listenerAdaptor, boolean includeValue) { int listenerFlags = setAndGetListenerFlags(listenerAdaptor); EventHandler<ClientMessage> handler = createHandler(listenerAdaptor); return registerListener(createMapEntryListenerCodec(includeValue, listenerFlags), handler); } private ListenerMessageCodec createMapEntryListenerCodec(final boolean includeValue, final int listenerFlags) { return new ListenerMessageCodec() { @Override public ClientMessage encodeAddRequest(boolean localOnly) { return MapAddEntryListenerCodec.encodeRequest(name, includeValue, listenerFlags, localOnly); } @Override public String decodeAddResponse(ClientMessage clientMessage) { return MapAddEntryListenerCodec.decodeResponse(clientMessage).response; } @Override public ClientMessage encodeRemoveRequest(String realRegistrationId) { return MapRemoveEntryListenerCodec.encodeRequest(name, realRegistrationId); } @Override public boolean decodeRemoveResponse(ClientMessage clientMessage) { return MapRemoveEntryListenerCodec.decodeResponse(clientMessage).response; } }; } @Override public boolean removeEntryListener(String registrationId) { return deregisterListener(registrationId); } @Override public String addPartitionLostListener(MapPartitionLostListener listener) { checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED); EventHandler<ClientMessage> handler = new ClientMapPartitionLostEventHandler(listener); return registerListener(createMapPartitionListenerCodec(), handler); } private ListenerMessageCodec createMapPartitionListenerCodec() { return new ListenerMessageCodec() { @Override public ClientMessage encodeAddRequest(boolean localOnly) { return MapAddPartitionLostListenerCodec.encodeRequest(name, localOnly); } @Override public String decodeAddResponse(ClientMessage clientMessage) { return MapAddPartitionLostListenerCodec.decodeResponse(clientMessage).response; } @Override public ClientMessage encodeRemoveRequest(String realRegistrationId) { return MapRemovePartitionLostListenerCodec.encodeRequest(name, realRegistrationId); } @Override public boolean decodeRemoveResponse(ClientMessage clientMessage) { return MapRemovePartitionLostListenerCodec.decodeResponse(clientMessage).response; } }; } @Override public boolean removePartitionLostListener(String registrationId) { return deregisterListener(registrationId); } @Override public String addEntryListener(MapListener listener, K key, boolean includeValue) { checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED); checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); ListenerAdapter<IMapEvent> listenerAdaptor = createListenerAdapter(listener); return addEntryListenerInternal(listenerAdaptor, 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); ListenerAdapter<IMapEvent> listenerAdaptor = createListenerAdapter(listener); return addEntryListenerInternal(listenerAdaptor, key, includeValue); } private String addEntryListenerInternal(ListenerAdapter<IMapEvent> listenerAdaptor, K key, boolean includeValue) { int listenerFlags = setAndGetListenerFlags(listenerAdaptor); Data keyData = toData(key); EventHandler<ClientMessage> handler = createHandler(listenerAdaptor); return registerListener(createMapEntryListenerToKeyCodec(includeValue, listenerFlags, keyData), handler); } private ListenerMessageCodec createMapEntryListenerToKeyCodec(final boolean includeValue, final int listenerFlags, final Data keyData) { return new ListenerMessageCodec() { @Override public ClientMessage encodeAddRequest(boolean localOnly) { return MapAddEntryListenerToKeyCodec.encodeRequest(name, keyData, includeValue, listenerFlags, localOnly); } @Override public String decodeAddResponse(ClientMessage clientMessage) { return MapAddEntryListenerToKeyCodec.decodeResponse(clientMessage).response; } @Override public ClientMessage encodeRemoveRequest(String realRegistrationId) { return MapRemoveEntryListenerCodec.encodeRequest(name, realRegistrationId); } @Override public boolean decodeRemoveResponse(ClientMessage clientMessage) { return MapRemoveEntryListenerCodec.decodeResponse(clientMessage).response; } }; } @Override public String addEntryListener(MapListener listener, Predicate<K, V> predicate, K key, boolean includeValue) { checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED); checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); ListenerAdapter<IMapEvent> listenerAdaptor = createListenerAdapter(listener); return addEntryListenerInternal(listenerAdaptor, predicate, key, includeValue); } @Override public String addEntryListener(EntryListener listener, Predicate<K, V> predicate, K key, boolean includeValue) { checkNotNull(listener, NULL_LISTENER_IS_NOT_ALLOWED); checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); ListenerAdapter<IMapEvent> listenerAdaptor = createListenerAdapter(listener); return addEntryListenerInternal(listenerAdaptor, predicate, key, includeValue); } private String addEntryListenerInternal(ListenerAdapter<IMapEvent> listenerAdaptor, Predicate<K, V> predicate, K key, boolean includeValue) { int listenerFlags = setAndGetListenerFlags(listenerAdaptor); Data keyData = toData(key); Data predicateData = toData(predicate); EventHandler<ClientMessage> handler = createHandler(listenerAdaptor); ListenerMessageCodec codec = createEntryListenerToKeyWithPredicateCodec(includeValue, listenerFlags, keyData, predicateData); return registerListener(codec, handler); } private ListenerMessageCodec createEntryListenerToKeyWithPredicateCodec(final boolean includeValue, final int listenerFlags, final Data keyData, final Data predicateData) { return new ListenerMessageCodec() { @Override public ClientMessage encodeAddRequest(boolean localOnly) { return MapAddEntryListenerToKeyWithPredicateCodec.encodeRequest(name, keyData, predicateData, includeValue, listenerFlags, localOnly); } @Override public String decodeAddResponse(ClientMessage clientMessage) { return MapAddEntryListenerToKeyWithPredicateCodec.decodeResponse(clientMessage).response; } @Override public ClientMessage encodeRemoveRequest(String realRegistrationId) { return MapRemoveEntryListenerCodec.encodeRequest(name, realRegistrationId); } @Override public boolean decodeRemoveResponse(ClientMessage clientMessage) { return MapRemoveEntryListenerCodec.decodeResponse(clientMessage).response; } }; } @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); ListenerAdapter<IMapEvent> listenerAdaptor = createListenerAdapter(listener); return addEntryListenerInternal(listenerAdaptor, predicate, 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); ListenerAdapter<IMapEvent> listenerAdaptor = createListenerAdapter(listener); return addEntryListenerInternal(listenerAdaptor, predicate, includeValue); } private String addEntryListenerInternal(ListenerAdapter<IMapEvent> listenerAdaptor, Predicate<K, V> predicate, boolean includeValue) { int listenerFlags = setAndGetListenerFlags(listenerAdaptor); Data predicateData = toData(predicate); EventHandler<ClientMessage> handler = createHandler(listenerAdaptor); return registerListener(createEntryListenerWithPredicateCodec(includeValue, listenerFlags, predicateData), handler); } private ListenerMessageCodec createEntryListenerWithPredicateCodec(final boolean includeValue, final int listenerFlags, final Data predicateData) { return new ListenerMessageCodec() { @Override public ClientMessage encodeAddRequest(boolean localOnly) { return MapAddEntryListenerWithPredicateCodec.encodeRequest(name, predicateData, includeValue, listenerFlags, localOnly); } @Override public String decodeAddResponse(ClientMessage clientMessage) { return MapAddEntryListenerWithPredicateCodec.decodeResponse(clientMessage).response; } @Override public ClientMessage encodeRemoveRequest(String realRegistrationId) { return MapRemoveEntryListenerCodec.encodeRequest(name, realRegistrationId); } @Override public boolean decodeRemoveResponse(ClientMessage clientMessage) { return MapRemoveEntryListenerCodec.decodeResponse(clientMessage).response; } }; } @Override @SuppressWarnings("unchecked") public EntryView<K, V> getEntryView(K key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); ClientMessage request = MapGetEntryViewCodec.encodeRequest(name, keyData, getThreadId()); ClientMessage response = invoke(request, keyData); MapGetEntryViewCodec.ResponseParameters parameters = MapGetEntryViewCodec.decodeResponse(response); SimpleEntryView<K, V> entryView = new SimpleEntryView<K, V>(); SimpleEntryView<Data, Data> dataEntryView = parameters.response; if (dataEntryView == null) { return null; } entryView.setKey((K) toObject(dataEntryView.getKey())); entryView.setValue((V) toObject(dataEntryView.getValue())); entryView.setCost(dataEntryView.getCost()); entryView.setCreationTime(dataEntryView.getCreationTime()); entryView.setExpirationTime(dataEntryView.getExpirationTime()); entryView.setHits(dataEntryView.getHits()); entryView.setLastAccessTime(dataEntryView.getLastAccessTime()); entryView.setLastStoredTime(dataEntryView.getLastStoredTime()); entryView.setLastUpdateTime(dataEntryView.getLastUpdateTime()); entryView.setVersion(dataEntryView.getVersion()); entryView.setHits(dataEntryView.getHits()); entryView.setTtl(dataEntryView.getTtl()); // TODO: putCache return entryView; } @Override public boolean evict(K key) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); return evictInternal(keyData); } protected boolean evictInternal(Data keyData) { ClientMessage request = MapEvictCodec.encodeRequest(name, keyData, getThreadId()); ClientMessage response = invoke(request, keyData); MapEvictCodec.ResponseParameters resultParameters = MapEvictCodec.decodeResponse(response); return resultParameters.response; } @Override public void evictAll() { ClientMessage request = MapEvictAllCodec.encodeRequest(name); invoke(request); } @Override public void loadAll(boolean replaceExistingValues) { ClientMessage request = MapLoadAllCodec.encodeRequest(name, replaceExistingValues); invoke(request); } @Override public void loadAll(Set<K> keys, boolean replaceExistingValues) { checkNotNull(keys, "Parameter keys should not be null."); if (keys.isEmpty()) { return; } Collection<Data> dataKeys = objectToDataCollection(keys, getSerializationService()); loadAllInternal(replaceExistingValues, dataKeys); } protected void loadAllInternal(boolean replaceExistingValues, Collection<Data> dataKeys) { ClientMessage request = MapLoadGivenKeysCodec.encodeRequest(name, dataKeys, replaceExistingValues); invoke(request); } @Override public Set<K> keySet() { ClientMessage request = MapKeySetCodec.encodeRequest(name); ClientMessage response = invoke(request); MapKeySetCodec.ResponseParameters resultParameters = MapKeySetCodec.decodeResponse(response); InflatableSet.Builder<K> setBuilder = InflatableSet.newBuilder(resultParameters.response.size()); for (Data data : resultParameters.response) { K key = toObject(data); setBuilder.add(key); } return setBuilder.build(); } @Override public Map<K, V> getAll(Set<K> keys) { if (CollectionUtil.isEmpty(keys)) { return emptyMap(); } Map<Integer, List<Data>> partitionToKeyData = new HashMap<Integer, List<Data>>(); ClientPartitionService partitionService = getContext().getPartitionService(); for (Object key : keys) { Data keyData = toData(key); int partitionId = partitionService.getPartitionId(keyData); List<Data> keyList = partitionToKeyData.get(partitionId); if (keyList == null) { keyList = new ArrayList<Data>(); partitionToKeyData.put(partitionId, keyList); } keyList.add(keyData); } Map<K, V> result = new HashMap<K, V>(); getAllInternal(partitionToKeyData, result); return result; } protected List<MapGetAllCodec.ResponseParameters> getAllInternal(Map<Integer, List<Data>> partitionToKeyData, Map<K, V> result) { List<Future<ClientMessage>> futures = new ArrayList<Future<ClientMessage>>(partitionToKeyData.size()); List<MapGetAllCodec.ResponseParameters> responses = new ArrayList<MapGetAllCodec.ResponseParameters>( partitionToKeyData.size()); for (Map.Entry<Integer, List<Data>> entry : partitionToKeyData.entrySet()) { int partitionId = entry.getKey(); List<Data> keyList = entry.getValue(); if (!keyList.isEmpty()) { ClientMessage request = MapGetAllCodec.encodeRequest(name, keyList); futures.add(new ClientInvocation(getClient(), request, partitionId).invoke()); } } for (Future<ClientMessage> future : futures) { try { ClientMessage response = future.get(); MapGetAllCodec.ResponseParameters resultParameters = MapGetAllCodec.decodeResponse(response); for (Entry<Data, Data> entry : resultParameters.response) { V value = toObject(entry.getValue()); K key = toObject(entry.getKey()); result.put(key, value); } responses.add(resultParameters); } catch (Exception e) { throw rethrow(e); } } return responses; } @Override public Collection<V> values() { ClientMessage request = MapValuesCodec.encodeRequest(name); ClientMessage response = invoke(request); MapValuesCodec.ResponseParameters resultParameters = MapValuesCodec.decodeResponse(response); return new UnmodifiableLazyList<V>(resultParameters.response, getSerializationService()); } @Override public Set<Entry<K, V>> entrySet() { ClientMessage request = MapEntrySetCodec.encodeRequest(name); ClientMessage response = invoke(request); MapEntrySetCodec.ResponseParameters resultParameters = MapEntrySetCodec.decodeResponse(response); InflatableSet.Builder<Entry<K, V>> setBuilder = InflatableSet.newBuilder(resultParameters.response.size()); InternalSerializationService serializationService = ((InternalSerializationService) getContext() .getSerializationService()); for (Entry<Data, Data> row : resultParameters.response) { LazyMapEntry<K, V> entry = new LazyMapEntry<K, V>(row.getKey(), row.getValue(), serializationService); setBuilder.add(entry); } return setBuilder.build(); } @Override public Set<K> keySet(Predicate predicate) { checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED); if (predicate instanceof PagingPredicate) { return keySetWithPagingPredicate((PagingPredicate) predicate); } ClientMessage request = MapKeySetWithPredicateCodec.encodeRequest(name, toData(predicate)); ClientMessage response = invoke(request); MapKeySetWithPredicateCodec.ResponseParameters resultParameters = MapKeySetWithPredicateCodec.decodeResponse(response); InflatableSet.Builder<K> setBuilder = InflatableSet.newBuilder(resultParameters.response.size()); for (Data data : resultParameters.response) { K key = toObject(data); setBuilder.add(key); } return setBuilder.build(); } @SuppressWarnings("unchecked") private Set<K> keySetWithPagingPredicate(PagingPredicate pagingPredicate) { pagingPredicate.setIterationType(IterationType.KEY); ClientMessage request = MapKeySetWithPagingPredicateCodec.encodeRequest(name, toData(pagingPredicate)); ClientMessage response = invoke(request); MapKeySetWithPagingPredicateCodec.ResponseParameters resultParameters = MapKeySetWithPagingPredicateCodec .decodeResponse(response); ArrayList<Map.Entry> resultList = new ArrayList<Map.Entry>(); for (Data keyData : resultParameters.response) { K key = toObject(keyData); resultList.add(new AbstractMap.SimpleImmutableEntry<K, V>(key, null)); } return (Set<K>) getSortedQueryResultSet(resultList, pagingPredicate, IterationType.KEY); } @Override public Set<Entry<K, V>> entrySet(Predicate predicate) { if (predicate instanceof PagingPredicate) { return entrySetWithPagingPredicate((PagingPredicate) predicate); } ClientMessage request = MapEntriesWithPredicateCodec.encodeRequest(name, toData(predicate)); ClientMessage response = invoke(request); MapEntriesWithPredicateCodec.ResponseParameters resultParameters = MapEntriesWithPredicateCodec.decodeResponse(response); InflatableSet.Builder<Entry<K, V>> setBuilder = InflatableSet.newBuilder(resultParameters.response.size()); InternalSerializationService serializationService = ((InternalSerializationService) getContext() .getSerializationService()); for (Entry<Data, Data> row : resultParameters.response) { LazyMapEntry<K, V> entry = new LazyMapEntry<K, V>(row.getKey(), row.getValue(), serializationService); setBuilder.add(entry); } return setBuilder.build(); } @SuppressWarnings("unchecked") private Set<Entry<K, V>> entrySetWithPagingPredicate(PagingPredicate pagingPredicate) { pagingPredicate.setIterationType(IterationType.ENTRY); ClientMessage request = MapEntriesWithPagingPredicateCodec.encodeRequest(name, toData(pagingPredicate)); ClientMessage response = invoke(request); MapEntriesWithPagingPredicateCodec.ResponseParameters resultParameters = MapEntriesWithPagingPredicateCodec .decodeResponse(response); ArrayList<Map.Entry> resultList = new ArrayList<Map.Entry>(); for (Entry<Data, Data> entry : resultParameters.response) { K key = toObject(entry.getKey()); V value = toObject(entry.getValue()); resultList.add(new AbstractMap.SimpleEntry<K, V>(key, value)); } return (Set<Entry<K, V>>) getSortedQueryResultSet(resultList, pagingPredicate, IterationType.ENTRY); } @Override public Collection<V> values(Predicate predicate) { checkNotNull(predicate, NULL_PREDICATE_IS_NOT_ALLOWED); if (predicate instanceof PagingPredicate) { return valuesForPagingPredicate((PagingPredicate) predicate); } ClientMessage request = MapValuesWithPredicateCodec.encodeRequest(name, toData(predicate)); ClientMessage response = invoke(request); MapValuesWithPredicateCodec.ResponseParameters resultParameters = MapValuesWithPredicateCodec.decodeResponse(response); return new UnmodifiableLazyList<V>(resultParameters.response, getSerializationService()); } @SuppressWarnings("unchecked") private Collection<V> valuesForPagingPredicate(PagingPredicate pagingPredicate) { pagingPredicate.setIterationType(IterationType.VALUE); ClientMessage request = MapValuesWithPagingPredicateCodec.encodeRequest(name, toData(pagingPredicate)); ClientMessage response = invoke(request); MapValuesWithPagingPredicateCodec.ResponseParameters resultParameters = MapValuesWithPagingPredicateCodec .decodeResponse(response); List<Entry> resultList = new ArrayList<Entry>(resultParameters.response.size()); for (Entry<Data, Data> entry : resultParameters.response) { K key = toObject(entry.getKey()); V value = toObject(entry.getValue()); resultList.add(new AbstractMap.SimpleImmutableEntry<K, V>(key, value)); } return (Collection<V>) getSortedQueryResultSet(resultList, pagingPredicate, IterationType.VALUE); } @Override public Set<K> localKeySet() { throw new UnsupportedOperationException("Locality is ambiguous for client!"); } @Override public Set<K> localKeySet(Predicate predicate) { throw new UnsupportedOperationException("Locality is ambiguous for client!"); } @Override public void addIndex(String attribute, boolean ordered) { ClientMessage request = MapAddIndexCodec.encodeRequest(name, attribute, ordered); invoke(request); } @Override public LocalMapStats getLocalMapStats() { return new LocalMapStatsImpl(); } @Override public Object executeOnKey(K key, EntryProcessor entryProcessor) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); return executeOnKeyInternal(keyData, entryProcessor); } public Object executeOnKeyInternal(Data keyData, EntryProcessor entryProcessor) { validateEntryProcessorForSingleKeyProcessing(entryProcessor); ClientMessage request = MapExecuteOnKeyCodec.encodeRequest(name, toData(entryProcessor), keyData, getThreadId()); ClientMessage response = invoke(request, keyData); MapExecuteOnKeyCodec.ResponseParameters resultParameters = MapExecuteOnKeyCodec.decodeResponse(response); return toObject(resultParameters.response); } @Override public void submitToKey(K key, EntryProcessor entryProcessor, ExecutionCallback callback) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); submitToKeyInternal(keyData, entryProcessor, callback); } @SuppressWarnings("unchecked") public void submitToKeyInternal(Data keyData, EntryProcessor entryProcessor, ExecutionCallback callback) { ClientMessage request = MapSubmitToKeyCodec.encodeRequest(name, toData(entryProcessor), keyData, getThreadId()); try { ClientInvocationFuture future = invokeOnKeyOwner(request, keyData); new ClientDelegatingFuture(future, getSerializationService(), SUBMIT_TO_KEY_RESPONSE_DECODER) .andThen(callback); } catch (Exception e) { throw rethrow(e); } } @Override public ICompletableFuture submitToKey(K key, EntryProcessor entryProcessor) { checkNotNull(key, NULL_KEY_IS_NOT_ALLOWED); Data keyData = toData(key); return submitToKeyInternal(keyData, entryProcessor); } public ICompletableFuture submitToKeyInternal(Data keyData, EntryProcessor entryProcessor) { ClientMessage request = MapSubmitToKeyCodec.encodeRequest(name, toData(entryProcessor), keyData, getThreadId()); try { ClientInvocationFuture future = invokeOnKeyOwner(request, keyData); return new ClientDelegatingFuture(future, getSerializationService(), SUBMIT_TO_KEY_RESPONSE_DECODER); } catch (Exception e) { throw rethrow(e); } } @Override public Map<K, Object> executeOnEntries(EntryProcessor entryProcessor) { ClientMessage request = MapExecuteOnAllKeysCodec.encodeRequest(name, toData(entryProcessor)); ClientMessage response = invoke(request); MapExecuteOnAllKeysCodec.ResponseParameters resultParameters = MapExecuteOnAllKeysCodec.decodeResponse(response); return prepareResult(resultParameters.response); } protected Map<K, Object> prepareResult(Collection<Entry<Data, Data>> entries) { if (CollectionUtil.isEmpty(entries)) { return emptyMap(); } Map<K, Object> result = MapUtil.createHashMap(entries.size()); for (Entry<Data, Data> entry : entries) { K key = toObject(entry.getKey()); result.put(key, toObject(entry.getValue())); } return result; } @Override public Map<K, Object> executeOnEntries(EntryProcessor entryProcessor, Predicate predicate) { ClientMessage request = MapExecuteWithPredicateCodec.encodeRequest(name, toData(entryProcessor), toData(predicate)); ClientMessage response = invoke(request); MapExecuteWithPredicateCodec.ResponseParameters resultParameters = MapExecuteWithPredicateCodec.decodeResponse(response); return prepareResult(resultParameters.response); } @Override public <R> R aggregate(Aggregator<Map.Entry<K, V>, R> aggregator) { checkNotNull(aggregator, NULL_AGGREGATOR_IS_NOT_ALLOWED); ClientMessage request = MapAggregateCodec.encodeRequest(name, toData(aggregator)); ClientMessage response = invoke(request); MapAggregateCodec.ResponseParameters resultParameters = MapAggregateCodec.decodeResponse(response); return toObject(resultParameters.response); } @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); ClientMessage request = MapAggregateWithPredicateCodec.encodeRequest(name, toData(aggregator), toData(predicate)); ClientMessage response = invoke(request); MapAggregateWithPredicateCodec.ResponseParameters resultParameters = MapAggregateWithPredicateCodec.decodeResponse(response); return toObject(resultParameters.response); } @Override public <R> Collection<R> project(Projection<Entry<K, V>, R> projection) { ClientMessage request = MapProjectCodec.encodeRequest(name, toData(projection)); ClientMessage response = invoke(request); MapProjectCodec.ResponseParameters resultParameters = MapProjectCodec.decodeResponse(response); return new UnmodifiableLazyList<R>(resultParameters.response, getSerializationService()); } @Override public <R> Collection<R> project(Projection<Entry<K, V>, R> projection, Predicate<K, V> predicate) { ClientMessage request = MapProjectWithPredicateCodec.encodeRequest(name, toData(projection), toData(predicate)); ClientMessage response = invoke(request); MapProjectWithPredicateCodec.ResponseParameters resultParameters = MapProjectWithPredicateCodec.decodeResponse(response); return new UnmodifiableLazyList<R>(resultParameters.response, getSerializationService()); } @Override @SuppressWarnings({"deprecation"}) public <SuppliedValue, Result> Result aggregate(Supplier<K, V, SuppliedValue> supplier, Aggregation<K, SuppliedValue, Result> aggregation) { JobTracker jobTracker = getClient().getJobTracker("hz::aggregation-map-" + name); return aggregate(supplier, aggregation, jobTracker); } @Override @SuppressWarnings({"deprecation", "unchecked"}) public <SuppliedValue, Result> Result aggregate(Supplier<K, V, SuppliedValue> supplier, Aggregation<K, SuppliedValue, Result> aggregation, JobTracker jobTracker) { try { Preconditions.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.combiner(combinerFactory).reducer(reducerFactory); } else { reducingJob = mappingJob.reducer(reducerFactory); } ICompletableFuture<Result> future = reducingJob.submit(collator); return future.get(); } catch (Exception e) { throw new HazelcastException(e); } } @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 predicate, Boolean includeValue, IMap map) { QueryCacheRequest request = newQueryCacheRequest() .withUserGivenCacheName(name) .withCacheName(UuidUtil.newUnsecureUuidString()) .withListener(listener) .withPredicate(predicate) .withIncludeValue(includeValue) .forMap(map) .withContext(queryCacheContext); return createQueryCache(request); } @SuppressWarnings("unchecked") private QueryCache<K, V> createQueryCache(QueryCacheRequest request) { ConstructorFunction<String, InternalQueryCache> constructorFunction = new ClientQueryCacheEndToEndConstructor(request); SubscriberContext subscriberContext = queryCacheContext.getSubscriberContext(); QueryCacheEndToEndProvider queryCacheEndToEndProvider = subscriberContext.getEndToEndQueryCacheProvider(); return queryCacheEndToEndProvider.getOrCreateQueryCache(request.getMapName(), request.getUserGivenCacheName(), constructorFunction); } @Override public Map<K, Object> executeOnKeys(Set<K> keys, EntryProcessor entryProcessor) { checkNotNull(keys, NULL_KEY_IS_NOT_ALLOWED); if (keys.isEmpty()) { return emptyMap(); } Collection<Data> dataCollection = objectToDataCollection(keys, getSerializationService()); ClientMessage request = MapExecuteOnKeysCodec.encodeRequest(name, toData(entryProcessor), dataCollection); ClientMessage response = invoke(request); MapExecuteOnKeysCodec.ResponseParameters resultParameters = MapExecuteOnKeysCodec.decodeResponse(response); return prepareResult(resultParameters.response); } @Override public void set(K key, V value) { set(key, value, -1, TimeUnit.MILLISECONDS); } @Override public int size() { ClientMessage request = MapSizeCodec.encodeRequest(name); ClientMessage response = invoke(request); MapSizeCodec.ResponseParameters resultParameters = MapSizeCodec.decodeResponse(response); return resultParameters.response; } @Override public boolean isEmpty() { ClientMessage request = MapIsEmptyCodec.encodeRequest(name); ClientMessage response = invoke(request); MapIsEmptyCodec.ResponseParameters resultParameters = MapIsEmptyCodec.decodeResponse(response); return resultParameters.response; } @Override public void putAll(Map<? extends K, ? extends V> m) { ClientPartitionService partitionService = getContext().getPartitionService(); int partitionCount = partitionService.getPartitionCount(); Map<Integer, List<Map.Entry<Data, Data>>> entryMap = new HashMap<Integer, List<Map.Entry<Data, Data>>>(partitionCount); for (Entry<? extends K, ? extends V> entry : m.entrySet()) { checkNotNull(entry.getKey(), NULL_KEY_IS_NOT_ALLOWED); checkNotNull(entry.getValue(), NULL_VALUE_IS_NOT_ALLOWED); Data keyData = toData(entry.getKey()); int partitionId = partitionService.getPartitionId(keyData); List<Map.Entry<Data, Data>> partition = entryMap.get(partitionId); if (partition == null) { partition = new ArrayList<Map.Entry<Data, Data>>(); entryMap.put(partitionId, partition); } partition.add(new AbstractMap.SimpleEntry<Data, Data>(keyData, toData(entry.getValue()))); } putAllInternal(entryMap); } protected void putAllInternal(Map<Integer, List<Map.Entry<Data, Data>>> entryMap) throws RuntimeException { List<Future<?>> futures = new ArrayList<Future<?>>(entryMap.size()); for (Entry<Integer, List<Map.Entry<Data, Data>>> entry : entryMap.entrySet()) { Integer partitionId = entry.getKey(); // if there is only one entry, consider how we can use MapPutRequest // without having to get back the return value ClientMessage request = MapPutAllCodec.encodeRequest(name, entry.getValue()); futures.add(new ClientInvocation(getClient(), request, partitionId).invoke()); } try { for (Future<?> future : futures) { future.get(); } } catch (Exception e) { throw rethrow(e); } } @Override public void clear() { ClientMessage request = MapClearCodec.encodeRequest(name); invoke(request); } @Override public String toString() { return "IMap{" + "name='" + name + '\'' + '}'; } // used for testing public Iterator<Entry<K, V>> iterator(int fetchSize, int partitionId, boolean prefetchValues) { return new ClientMapPartitionIterator<K, V>(this, getContext(), fetchSize, partitionId, prefetchValues); } // used for testing public ClientQueryCacheContext getQueryCacheContext() { return queryCacheContext; } private long getTimeInMillis(long time, TimeUnit timeunit) { return timeunit != null ? timeunit.toMillis(time) : time; } private EventHandler<ClientMessage> createHandler(ListenerAdapter<IMapEvent> listenerAdapter) { return new ClientMapEventHandler(listenerAdapter); } private static void validateEntryProcessorForSingleKeyProcessing(EntryProcessor entryProcessor) { if (entryProcessor instanceof ReadOnly) { EntryBackupProcessor backupProcessor = entryProcessor.getBackupProcessor(); if (backupProcessor != null) { throw new IllegalArgumentException( "EntryProcessor.getBackupProcessor() should be null for a read-only EntryProcessor"); } } } private class ClientMapEventHandler extends MapAddEntryListenerCodec.AbstractEventHandler implements EventHandler<ClientMessage> { private ListenerAdapter<IMapEvent> listenerAdapter; ClientMapEventHandler(ListenerAdapter<IMapEvent> listenerAdapter) { this.listenerAdapter = listenerAdapter; } @Override public void handle(Data key, Data value, Data oldValue, Data mergingValue, int eventType, String uuid, int numberOfAffectedEntries) { Member member = getContext().getClusterService().getMember(uuid); listenerAdapter.onEvent(createIMapEvent(key, value, oldValue, mergingValue, eventType, numberOfAffectedEntries, member)); } private IMapEvent createIMapEvent(Data key, Data value, Data oldValue, Data mergingValue, int eventType, int numberOfAffectedEntries, Member member) { EntryEventType entryEventType = EntryEventType.getByType(eventType); checkNotNull(entryEventType, "Unknown eventType: " + eventType); switch (entryEventType) { case ADDED: case REMOVED: case UPDATED: case EVICTED: case EXPIRED: case MERGED: return createEntryEvent(key, value, oldValue, mergingValue, eventType, member); case EVICT_ALL: case CLEAR_ALL: return createMapEvent(eventType, numberOfAffectedEntries, member); default: throw new IllegalArgumentException("Not a known event type: " + entryEventType); } } private MapEvent createMapEvent(int eventType, int numberOfAffectedEntries, Member member) { return new MapEvent(name, member, eventType, numberOfAffectedEntries); } private EntryEvent<K, V> createEntryEvent(Data keyData, Data valueData, Data oldValueData, Data mergingValueData, int eventType, Member member) { return new DataAwareEntryEvent<K, V>(member, eventType, name, keyData, valueData, oldValueData, mergingValueData, getSerializationService()); } @Override public void beforeListenerRegister() { } @Override public void onListenerRegister() { } } private class ClientMapPartitionLostEventHandler extends MapAddPartitionLostListenerCodec.AbstractEventHandler implements EventHandler<ClientMessage> { private MapPartitionLostListener listener; ClientMapPartitionLostEventHandler(MapPartitionLostListener listener) { this.listener = listener; } @Override public void beforeListenerRegister() { } @Override public void onListenerRegister() { } @Override public void handle(int partitionId, String uuid) { Member member = getContext().getClusterService().getMember(uuid); listener.partitionLost(new MapPartitionLostEvent(name, member, -1, partitionId)); } } }