package org.infinispan.client.hotrod.impl.operations;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.infinispan.client.hotrod.CacheTopologyInfo;
import org.infinispan.client.hotrod.Flag;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ClientIntelligence;
import org.infinispan.client.hotrod.event.ClientListenerNotifier;
import org.infinispan.client.hotrod.impl.iteration.KeyTracker;
import org.infinispan.client.hotrod.impl.protocol.Codec;
import org.infinispan.client.hotrod.impl.protocol.HotRodConstants;
import org.infinispan.client.hotrod.impl.query.RemoteQuery;
import org.infinispan.client.hotrod.impl.transport.Transport;
import org.infinispan.client.hotrod.impl.transport.TransportFactory;
import net.jcip.annotations.Immutable;
/**
* Factory for {@link org.infinispan.client.hotrod.impl.operations.HotRodOperation} objects.
*
* @author Mircea.Markus@jboss.com
* @since 4.1
*/
@Immutable
public class OperationsFactory implements HotRodConstants {
private final ThreadLocal<Integer> flagsMap = new ThreadLocal<>();
private final TransportFactory transportFactory;
private final byte[] cacheNameBytes;
private final AtomicInteger topologyId;
private final boolean forceReturnValue;
private final Codec codec;
private final ClientListenerNotifier listenerNotifier;
private final String cacheName;
private final ExecutorService executorService;
private final ClientIntelligence clientIntelligence;
public OperationsFactory(TransportFactory transportFactory, String cacheName, boolean forceReturnValue, Codec
codec, ClientListenerNotifier listenerNotifier, ExecutorService executorService, ClientIntelligence clientIntelligence) {
this.transportFactory = transportFactory;
this.executorService = executorService;
this.cacheNameBytes = RemoteCacheManager.cacheNameBytes(cacheName);
this.cacheName = cacheName;
this.topologyId = transportFactory != null
? transportFactory.createTopologyId(cacheNameBytes)
: new AtomicInteger(-1);
this.forceReturnValue = forceReturnValue;
this.codec = codec;
this.listenerNotifier = listenerNotifier;
this.clientIntelligence = clientIntelligence;
}
public ClientListenerNotifier getListenerNotifier() {
return listenerNotifier;
}
public byte[] getCacheName() {
return cacheNameBytes;
}
public <V> GetOperation<V> newGetKeyOperation(Object key, byte[] keyBytes) {
return new GetOperation<>(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public <K, V> GetAllParallelOperation<K, V> newGetAllOperation(Set<byte[]> keys) {
return new GetAllParallelOperation<>(codec, transportFactory, keys, cacheNameBytes, topologyId, flags(),
clientIntelligence, executorService);
}
public <V> RemoveOperation<V> newRemoveOperation(Object key, byte[] keyBytes) {
return new RemoveOperation<>(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public <V> RemoveIfUnmodifiedOperation<V> newRemoveIfUnmodifiedOperation(Object key, byte[] keyBytes, long version) {
return new RemoveIfUnmodifiedOperation<>(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence, version);
}
public ReplaceIfUnmodifiedOperation newReplaceIfUnmodifiedOperation(Object key, byte[] keyBytes,
byte[] value, long lifespan, TimeUnit lifespanTimeUnit, long maxIdle, TimeUnit maxIdleTimeUnit, long version) {
return new ReplaceIfUnmodifiedOperation(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(lifespan, maxIdle),
clientIntelligence, value, lifespan, lifespanTimeUnit, maxIdle, maxIdleTimeUnit, version);
}
public <V> GetWithVersionOperation<V> newGetWithVersionOperation(Object key, byte[] keyBytes) {
return new GetWithVersionOperation<>(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public <V> GetWithMetadataOperation<V> newGetWithMetadataOperation(Object key, byte[] keyBytes) {
return new GetWithMetadataOperation<>(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public StatsOperation newStatsOperation() {
return new StatsOperation(
codec, transportFactory, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public <V> PutOperation<V> newPutKeyValueOperation(Object key, byte[] keyBytes, byte[] value,
long lifespan, TimeUnit lifespanTimeUnit, long maxIdle, TimeUnit maxIdleTimeUnit) {
return new PutOperation<>(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(lifespan, maxIdle),
clientIntelligence, value, lifespan, lifespanTimeUnit, maxIdle, maxIdleTimeUnit);
}
public PutAllParallelOperation newPutAllOperation(Map<byte[], byte[]> map,
long lifespan, TimeUnit lifespanTimeUnit, long maxIdle, TimeUnit maxIdleTimeUnit) {
return new PutAllParallelOperation(
codec, transportFactory, map, cacheNameBytes, topologyId, flags(lifespan, maxIdle), clientIntelligence,
lifespan, lifespanTimeUnit, maxIdle, maxIdleTimeUnit, executorService);
}
public <V> PutIfAbsentOperation<V> newPutIfAbsentOperation(Object key, byte[] keyBytes, byte[] value,
long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) {
return new PutIfAbsentOperation<>(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(lifespan, maxIdleTime),
clientIntelligence, value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit);
}
public <V> ReplaceOperation<V> newReplaceOperation(Object key, byte[] keyBytes, byte[] values,
long lifespan, TimeUnit lifespanTimeUnit, long maxIdle, TimeUnit maxIdleTimeUnit) {
return new ReplaceOperation<>(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(lifespan, maxIdle),
clientIntelligence, values, lifespan, lifespanTimeUnit, maxIdle, maxIdleTimeUnit);
}
public ContainsKeyOperation newContainsKeyOperation(Object key, byte[] keyBytes) {
return new ContainsKeyOperation(
codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public ClearOperation newClearOperation() {
return new ClearOperation(
codec, transportFactory, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public <K, V> BulkGetOperation<K, V> newBulkGetOperation(int size) {
return new BulkGetOperation(
codec, transportFactory, cacheNameBytes, topologyId, flags(), clientIntelligence, size);
}
public <K> BulkGetKeysOperation<K> newBulkGetKeysOperation(int scope) {
return new BulkGetKeysOperation<>(
codec, transportFactory, cacheNameBytes, topologyId, flags(), clientIntelligence, scope);
}
public AddClientListenerOperation newAddClientListenerOperation(Object listener) {
return new AddClientListenerOperation(codec, transportFactory,
cacheName, topologyId, flags(), clientIntelligence, listenerNotifier,
listener, null, null);
}
public AddClientListenerOperation newAddClientListenerOperation(
Object listener, byte[][] filterFactoryParams, byte[][] converterFactoryParams) {
return new AddClientListenerOperation(codec, transportFactory,
cacheName, topologyId, flags(), clientIntelligence, listenerNotifier,
listener, filterFactoryParams, converterFactoryParams);
}
public RemoveClientListenerOperation newRemoveClientListenerOperation(Object listener) {
return new RemoveClientListenerOperation(codec, transportFactory,
cacheNameBytes, topologyId, flags(), clientIntelligence, listenerNotifier, listener);
}
/**
* Construct a ping request directed to a particular node.
*
* @param transport represents the node to which the operation is directed
* @return a ping operation for a particular node
*/
public PingOperation newPingOperation(Transport transport) {
return new PingOperation(codec, topologyId, clientIntelligence, transport, cacheNameBytes);
}
/**
* Construct a fault tolerant ping request. This operation should be capable
* to deal with nodes being down, so it will find the first node successful
* node to respond to the ping.
*
* @return a ping operation for the cluster
*/
public FaultTolerantPingOperation newFaultTolerantPingOperation() {
return new FaultTolerantPingOperation(
codec, transportFactory, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public QueryOperation newQueryOperation(RemoteQuery remoteQuery) {
return new QueryOperation(
codec, transportFactory, cacheNameBytes, topologyId, flags(), clientIntelligence, remoteQuery);
}
public SizeOperation newSizeOperation() {
return new SizeOperation(codec, transportFactory, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public <T> ExecuteOperation<T> newExecuteOperation(String taskName, Map<String, byte[]> marshalledParams) {
return new ExecuteOperation<>(codec, transportFactory, cacheNameBytes, topologyId, flags(), clientIntelligence, taskName, marshalledParams);
}
private int flags(long lifespan, long maxIdle) {
int intFlags = flags();
if (lifespan == 0) {
intFlags |= Flag.DEFAULT_LIFESPAN.getFlagInt();
}
if (maxIdle == 0) {
intFlags |= Flag.DEFAULT_MAXIDLE.getFlagInt();
}
return intFlags;
}
public int flags() {
Integer threadLocalFlags = this.flagsMap.get();
this.flagsMap.remove();
int intFlags = 0;
if (threadLocalFlags != null) {
intFlags |= threadLocalFlags.intValue();
}
if (forceReturnValue) {
intFlags |= Flag.FORCE_RETURN_VALUE.getFlagInt();
}
return intFlags;
}
public void setFlags(Flag[] flags) {
int intFlags = 0;
for(Flag flag : flags)
intFlags |= flag.getFlagInt();
this.flagsMap.set(intFlags);
}
public void setFlags(int intFlags) {
this.flagsMap.set(intFlags);
}
public boolean hasFlag(Flag flag) {
Integer threadLocalFlags = this.flagsMap.get();
return threadLocalFlags != null && (threadLocalFlags & flag.getFlagInt()) != 0;
}
public CacheTopologyInfo getCacheTopologyInfo() {
return transportFactory.getCacheTopologyInfo(cacheNameBytes);
}
public IterationStartOperation newIterationStartOperation(String filterConverterFactory, byte[][] filterParameters, Set<Integer> segments, int batchSize, boolean metadata) {
return new IterationStartOperation(codec, flags(), clientIntelligence, cacheNameBytes, topologyId, filterConverterFactory, filterParameters, segments, batchSize, transportFactory, metadata);
}
public IterationEndOperation newIterationEndOperation(String iterationId, Transport transport) {
return new IterationEndOperation(codec, flags(), clientIntelligence, cacheNameBytes, topologyId, iterationId, transportFactory, transport);
}
public <K, V> IterationNextOperation newIterationNextOperation(String iterationId, Transport transport, KeyTracker segmentKeyTracker) {
return new IterationNextOperation(codec, flags(), clientIntelligence, cacheNameBytes, topologyId, iterationId, transport, segmentKeyTracker);
}
public <K> GetStreamOperation newGetStreamOperation(K key, byte[] keyBytes, int offset) {
return new GetStreamOperation(codec, transportFactory, key, keyBytes, offset, cacheNameBytes, topologyId, flags(), clientIntelligence);
}
public <K> PutStreamOperation newPutStreamOperation(K key, byte[] keyBytes, long version, long lifespan, TimeUnit lifespanUnit, long maxIdle, TimeUnit maxIdleUnit) {
return new PutStreamOperation(codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence, version, lifespan, lifespanUnit, maxIdle, maxIdleUnit);
}
public <K> PutStreamOperation newPutStreamOperation(K key, byte[] keyBytes, long lifespan, TimeUnit lifespanUnit, long maxIdle, TimeUnit maxIdleUnit) {
return new PutStreamOperation(codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence, PutStreamOperation.VERSION_PUT, lifespan, lifespanUnit, maxIdle, maxIdleUnit);
}
public <K> PutStreamOperation newPutIfAbsentStreamOperation(K key, byte[] keyBytes, long lifespan, TimeUnit lifespanUnit, long maxIdle, TimeUnit maxIdleUnit) {
return new PutStreamOperation(codec, transportFactory, key, keyBytes, cacheNameBytes, topologyId, flags(), clientIntelligence, PutStreamOperation.VERSION_PUT_IF_ABSENT, lifespan, lifespanUnit, maxIdle, maxIdleUnit);
}
}