/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.ignite.internal.processors.cache;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.configuration.CacheEntryListenerConfiguration;
import javax.cache.configuration.Configuration;
import javax.cache.expiry.ExpiryPolicy;
import javax.cache.integration.CompletionListener;
import javax.cache.processor.EntryProcessor;
import javax.cache.processor.EntryProcessorException;
import javax.cache.processor.EntryProcessorResult;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.cache.CacheEntry;
import org.apache.ignite.cache.CacheEntryProcessor;
import org.apache.ignite.cache.CacheManager;
import org.apache.ignite.cache.CacheMetrics;
import org.apache.ignite.cache.CachePeekMode;
import org.apache.ignite.cache.query.ContinuousQuery;
import org.apache.ignite.cache.query.Query;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.QueryDetailMetrics;
import org.apache.ignite.cache.query.QueryMetrics;
import org.apache.ignite.cache.query.ScanQuery;
import org.apache.ignite.cache.query.SpiQuery;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.SqlQuery;
import org.apache.ignite.cache.query.TextQuery;
import org.apache.ignite.cluster.ClusterGroup;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.AsyncSupportAdapter;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.query.CacheQuery;
import org.apache.ignite.internal.processors.cache.query.CacheQueryFuture;
import org.apache.ignite.internal.processors.cache.query.GridCacheQueryType;
import org.apache.ignite.internal.processors.query.QueryUtils;
import org.apache.ignite.internal.util.GridCloseableIteratorAdapter;
import org.apache.ignite.internal.util.GridEmptyIterator;
import org.apache.ignite.internal.util.future.IgniteFinishedFutureImpl;
import org.apache.ignite.internal.util.future.IgniteFutureImpl;
import org.apache.ignite.internal.util.lang.GridCloseableIterator;
import org.apache.ignite.internal.util.lang.GridClosureException;
import org.apache.ignite.internal.util.lang.IgniteOutClosureX;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.CI1;
import org.apache.ignite.internal.util.typedef.CX1;
import org.apache.ignite.internal.util.typedef.internal.A;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiPredicate;
import org.apache.ignite.lang.IgniteClosure;
import org.apache.ignite.lang.IgniteFuture;
import org.apache.ignite.mxbean.CacheMetricsMXBean;
import org.apache.ignite.plugin.security.SecurityPermission;
import org.jetbrains.annotations.Nullable;
/**
* Cache proxy.
*/
@SuppressWarnings("unchecked")
public class IgniteCacheProxy<K, V> extends AsyncSupportAdapter<IgniteCache<K, V>>
implements IgniteCache<K, V>, Externalizable {
/** */
private static final long serialVersionUID = 0L;
/** Context. */
private GridCacheContext<K, V> ctx;
/** Gateway. */
private GridCacheGateway<K, V> gate;
/** Delegate. */
@GridToStringInclude
private IgniteInternalCache<K, V> delegate;
/** Operation context. */
private CacheOperationContext opCtx;
/** */
@GridToStringExclude
private GridCacheProxyImpl<K, V> internalProxy;
/** */
@GridToStringExclude
private CacheManager cacheMgr;
/** If {@code false} does not acquire read lock on gateway enter. */
@GridToStringExclude
private boolean lock;
/**
* Empty constructor required for {@link Externalizable}.
*/
public IgniteCacheProxy() {
// No-op.
}
/**
* @param ctx Context.
* @param delegate Delegate.
* @param opCtx Operation context.
* @param async Async support flag.
*/
public IgniteCacheProxy(
GridCacheContext<K, V> ctx,
IgniteInternalCache<K, V> delegate,
CacheOperationContext opCtx,
boolean async
) {
this(ctx, delegate, opCtx, async, true);
}
/**
* @param ctx Context.
* @param delegate Delegate.
* @param opCtx Operation context.
* @param async Async support flag.
* @param lock If {@code false} does not acquire read lock on gateway enter.
*/
private IgniteCacheProxy(
GridCacheContext<K, V> ctx,
IgniteInternalCache<K, V> delegate,
@Nullable CacheOperationContext opCtx,
boolean async,
boolean lock
) {
super(async);
assert ctx != null;
assert delegate != null;
this.ctx = ctx;
this.delegate = delegate;
this.opCtx = opCtx;
gate = ctx.gate();
internalProxy = new GridCacheProxyImpl<>(ctx, delegate, opCtx);
this.lock = lock;
}
/**
* @return Operation context.
*/
@Nullable public CacheOperationContext operationContext() {
return opCtx;
}
/**
* Gets cache proxy which does not acquire read lock on gateway enter, should be used only if grid read lock is
* externally acquired.
*
* @return Ignite cache proxy with simple gate.
*/
public IgniteCacheProxy<K, V> cacheNoGate() {
return new IgniteCacheProxy<>(ctx, delegate, opCtx, isAsync(), false);
}
/**
* @return Context.
*/
public GridCacheContext<K, V> context() {
return ctx;
}
/**
* @return Gateway.
*/
public GridCacheGateway<K, V> gate() {
return gate;
}
/** {@inheritDoc} */
@Override public CacheMetrics metrics() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return ctx.cache().clusterMetrics();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public CacheMetrics metrics(ClusterGroup grp) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return ctx.cache().clusterMetrics(grp);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public CacheMetrics localMetrics() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return ctx.cache().localMetrics();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public CacheMetricsMXBean mxBean() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return ctx.cache().clusterMxBean();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public CacheMetricsMXBean localMxBean() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return ctx.cache().localMxBean();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public <C extends Configuration<K, V>> C getConfiguration(Class<C> clazz) {
CacheConfiguration cfg = ctx.config();
if (!clazz.isAssignableFrom(cfg.getClass()))
throw new IllegalArgumentException();
return clazz.cast(cfg);
}
/** {@inheritDoc} */
@Override public IgniteCache<K, V> withExpiryPolicy(ExpiryPolicy plc) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
CacheOperationContext prj0 = opCtx != null ? opCtx.withExpiryPolicy(plc) :
new CacheOperationContext(false, null, false, plc, false, null, false);
return new IgniteCacheProxy<>(ctx, delegate, prj0, isAsync(), lock);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteCache<K, V> withSkipStore() {
return skipStore();
}
/** {@inheritDoc} */
@Override public <K1, V1> IgniteCache<K1, V1> withKeepBinary() {
return keepBinary();
}
/** {@inheritDoc} */
@Override public IgniteCache<K, V> withNoRetries() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
boolean noRetries = opCtx != null && opCtx.noRetries();
if (noRetries)
return this;
CacheOperationContext opCtx0 = opCtx != null ? opCtx.setNoRetries(true) :
new CacheOperationContext(false, null, false, null, true, null, false);
return new IgniteCacheProxy<>(ctx,
delegate,
opCtx0,
isAsync(),
lock);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteCache<K, V> withPartitionRecover() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
boolean recovery = opCtx != null && opCtx.recovery();
if (recovery)
return this;
CacheOperationContext opCtx0 = opCtx != null ? opCtx.setRecovery(true) :
new CacheOperationContext(false, null, false, null, false, null, true);
return new IgniteCacheProxy<>(ctx,
delegate,
opCtx0,
isAsync(),
lock);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void loadCache(@Nullable IgniteBiPredicate<K, V> p, @Nullable Object... args) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
if (ctx.cache().isLocal())
setFuture(ctx.cache().localLoadCacheAsync(p, args));
else
setFuture(ctx.cache().globalLoadCacheAsync(p, args));
}
else {
if (ctx.cache().isLocal())
ctx.cache().localLoadCache(p, args);
else
ctx.cache().globalLoadCache(p, args);
}
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> loadCacheAsync(@Nullable IgniteBiPredicate<K, V> p,
@Nullable Object... args) throws CacheException {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (ctx.cache().isLocal())
return (IgniteFuture<Void>)createFuture(ctx.cache().localLoadCacheAsync(p, args));
else
return (IgniteFuture<Void>)createFuture(ctx.cache().globalLoadCacheAsync(p, args));
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public void localLoadCache(@Nullable IgniteBiPredicate<K, V> p, @Nullable Object... args) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
setFuture(delegate.localLoadCacheAsync(p, args));
else
delegate.localLoadCache(p, args);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> localLoadCacheAsync(@Nullable IgniteBiPredicate<K, V> p,
@Nullable Object... args) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return (IgniteFuture<Void>)createFuture(delegate.localLoadCacheAsync(p, args));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Nullable @Override public V getAndPutIfAbsent(K key, V val) throws CacheException {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getAndPutIfAbsentAsync(key, val));
return null;
}
else
return delegate.getAndPutIfAbsent(key, val);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<V> getAndPutIfAbsentAsync(K key, V val) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getAndPutIfAbsentAsync(key, val));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public Lock lock(K key) throws CacheException {
return lockAll(Collections.singleton(key));
}
/** {@inheritDoc} */
@Override public Lock lockAll(final Collection<? extends K> keys) {
return new CacheLockImpl<>(gate, delegate, opCtx, keys);
}
/** {@inheritDoc} */
@Override public boolean isLocalLocked(K key, boolean byCurrThread) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return byCurrThread ? delegate.isLockedByThread(key) : delegate.isLocked(key);
}
finally {
onLeave(gate, prev);
}
}
/**
* @param scanQry ScanQry.
* @param transformer Transformer
* @param grp Optional cluster group.
* @return Cursor.
* @throws IgniteCheckedException If failed.
*/
@SuppressWarnings("unchecked")
private <T, R> QueryCursor<R> query(
final ScanQuery scanQry,
@Nullable final IgniteClosure<T, R> transformer,
@Nullable ClusterGroup grp)
throws IgniteCheckedException {
final CacheQuery<R> qry;
boolean isKeepBinary = opCtx != null && opCtx.isKeepBinary();
IgniteBiPredicate<K, V> p = scanQry.getFilter();
qry = ctx.queries().createScanQuery(p, transformer, scanQry.getPartition(), isKeepBinary);
if (scanQry.getPageSize() > 0)
qry.pageSize(scanQry.getPageSize());
if (grp != null)
qry.projection(grp);
final GridCloseableIterator<R> iter = ctx.kernalContext().query().executeQuery(GridCacheQueryType.SCAN,
ctx.name(), ctx, new IgniteOutClosureX<GridCloseableIterator<R>>() {
@Override public GridCloseableIterator<R> applyx() throws IgniteCheckedException {
final GridCloseableIterator iter0 = qry.executeScanQuery();
final boolean needToConvert = transformer == null;
return new GridCloseableIteratorAdapter<R>() {
@Override protected R onNext() throws IgniteCheckedException {
Object next = iter0.nextX();
if (needToConvert) {
Map.Entry<K, V> entry = (Map.Entry<K, V>)next;
return (R) new CacheEntryImpl<>(entry.getKey(), entry.getValue());
}
return (R)next;
}
@Override protected boolean onHasNext() throws IgniteCheckedException {
return iter0.hasNextX();
}
@Override protected void onClose() throws IgniteCheckedException {
iter0.close();
}
};
}
}, true);
return new QueryCursorImpl<>(iter);
}
/**
* @param filter Filter.
* @param grp Optional cluster group.
* @return Cursor.
* @throws IgniteCheckedException If failed.
*/
@SuppressWarnings("unchecked")
private QueryCursor<Cache.Entry<K, V>> query(final Query filter, @Nullable ClusterGroup grp)
throws IgniteCheckedException {
final CacheQuery qry;
boolean isKeepBinary = opCtx != null && opCtx.isKeepBinary();
final CacheQueryFuture fut;
if (filter instanceof TextQuery) {
TextQuery p = (TextQuery)filter;
qry = ctx.queries().createFullTextQuery(p.getType(), p.getText(), isKeepBinary);
if (grp != null)
qry.projection(grp);
fut = ctx.kernalContext().query().executeQuery(GridCacheQueryType.TEXT, p.getText(), ctx,
new IgniteOutClosureX<CacheQueryFuture<Map.Entry<K, V>>>() {
@Override public CacheQueryFuture<Map.Entry<K, V>> applyx() {
return qry.execute();
}
}, false);
}
else if (filter instanceof SpiQuery) {
qry = ctx.queries().createSpiQuery(isKeepBinary);
if (grp != null)
qry.projection(grp);
fut = ctx.kernalContext().query().executeQuery(GridCacheQueryType.SPI, filter.getClass().getSimpleName(),
ctx, new IgniteOutClosureX<CacheQueryFuture<Map.Entry<K, V>>>() {
@Override public CacheQueryFuture<Map.Entry<K, V>> applyx() {
return qry.execute(((SpiQuery)filter).getArgs());
}
}, false);
}
else {
if (filter instanceof SqlFieldsQuery)
throw new CacheException("Use methods 'queryFields' and 'localQueryFields' for " +
SqlFieldsQuery.class.getSimpleName() + ".");
throw new CacheException("Unsupported query type: " + filter);
}
return new QueryCursorImpl<>(new GridCloseableIteratorAdapter<Entry<K, V>>() {
/** */
private Cache.Entry<K, V> cur;
@Override protected Entry<K, V> onNext() throws IgniteCheckedException {
if (!onHasNext())
throw new NoSuchElementException();
Cache.Entry<K, V> e = cur;
cur = null;
return e;
}
@Override protected boolean onHasNext() throws IgniteCheckedException {
if (cur != null)
return true;
Object next = fut.next();
// Workaround a bug: if IndexingSpi is configured future represents Iterator<Cache.Entry>
// instead of Iterator<Map.Entry> due to IndexingSpi interface.
if (next == null)
return false;
if (next instanceof Cache.Entry)
cur = (Cache.Entry)next;
else {
Map.Entry e = (Map.Entry)next;
cur = new CacheEntryImpl(e.getKey(), e.getValue());
}
return true;
}
@Override protected void onClose() throws IgniteCheckedException {
fut.cancel();
}
});
}
/**
* @param loc Enforce local.
* @return Local node cluster group.
*/
private ClusterGroup projection(boolean loc) {
if (loc || ctx.isLocal() || ctx.isReplicatedAffinityNode())
return ctx.kernalContext().grid().cluster().forLocal();
if (ctx.isReplicated())
return ctx.kernalContext().grid().cluster().forDataNodes(ctx.name()).forRandom();
return null;
}
/**
* Executes continuous query.
*
* @param qry Query.
* @param loc Local flag.
* @param keepBinary Keep binary flag.
* @return Initial iteration cursor.
*/
@SuppressWarnings("unchecked")
private QueryCursor<Cache.Entry<K, V>> queryContinuous(ContinuousQuery qry, boolean loc, boolean keepBinary) {
if (qry.getInitialQuery() instanceof ContinuousQuery)
throw new IgniteException("Initial predicate for continuous query can't be an instance of another " +
"continuous query. Use SCAN or SQL query for initial iteration.");
if (qry.getLocalListener() == null)
throw new IgniteException("Mandatory local listener is not set for the query: " + qry);
if (qry.getRemoteFilter() != null && qry.getRemoteFilterFactory() != null)
throw new IgniteException("Should be used either RemoterFilter or RemoteFilterFactory.");
try {
final UUID routineId = ctx.continuousQueries().executeQuery(
qry.getLocalListener(),
qry.getRemoteFilter(),
qry.getRemoteFilterFactory(),
qry.getPageSize(),
qry.getTimeInterval(),
qry.isAutoUnsubscribe(),
loc,
keepBinary,
qry.isIncludeExpired());
final QueryCursor<Cache.Entry<K, V>> cur =
qry.getInitialQuery() != null ? query(qry.getInitialQuery()) : null;
return new QueryCursor<Cache.Entry<K, V>>() {
@Override public Iterator<Cache.Entry<K, V>> iterator() {
return cur != null ? cur.iterator() : new GridEmptyIterator<Cache.Entry<K, V>>();
}
@Override public List<Cache.Entry<K, V>> getAll() {
return cur != null ? cur.getAll() : Collections.<Cache.Entry<K, V>>emptyList();
}
@Override public void close() {
if (cur != null)
cur.close();
try {
ctx.kernalContext().continuous().stopRoutine(routineId).get();
}
catch (IgniteCheckedException e) {
throw U.convertException(e);
}
}
};
}
catch (IgniteCheckedException e) {
throw U.convertException(e);
}
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <R> QueryCursor<R> query(Query<R> qry) {
A.notNull(qry, "qry");
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
ctx.checkSecurity(SecurityPermission.CACHE_READ);
validate(qry);
convertToBinary(qry);
final CacheOperationContext opCtxCall = ctx.operationContextPerCall();
if (qry instanceof ContinuousQuery)
return (QueryCursor<R>)queryContinuous((ContinuousQuery<K, V>)qry, qry.isLocal(),
opCtxCall != null && opCtxCall.isKeepBinary());
if (qry instanceof SqlQuery) {
boolean keepBinary = opCtxCall != null && opCtxCall.isKeepBinary();
return (QueryCursor<R>)ctx.kernalContext().query().querySql(ctx, (SqlQuery)qry, keepBinary);
}
if (qry instanceof SqlFieldsQuery)
return (QueryCursor<R>)ctx.kernalContext().query().querySqlFields(ctx, (SqlFieldsQuery)qry);
if (qry instanceof ScanQuery)
return query((ScanQuery)qry, null, projection(qry.isLocal()));
return (QueryCursor<R>)query(qry, projection(qry.isLocal()));
}
catch (Exception e) {
if (e instanceof CacheException)
throw (CacheException)e;
throw new CacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public <T, R> QueryCursor<R> query(Query<T> qry, IgniteClosure<T, R> transformer) {
A.notNull(qry, "qry");
A.notNull(transformer, "transformer");
if (!(qry instanceof ScanQuery))
throw new UnsupportedOperationException("Transformers are supported only for SCAN queries.");
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
ctx.checkSecurity(SecurityPermission.CACHE_READ);
validate(qry);
return query((ScanQuery<K, V>)qry, transformer, projection(qry.isLocal()));
}
catch (Exception e) {
if (e instanceof CacheException)
throw (CacheException)e;
throw new CacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/**
* Convert query arguments to BinaryObjects if binary marshaller used.
*
* @param qry Query.
*/
private void convertToBinary(final Query qry) {
if (ctx.binaryMarshaller()) {
if (qry instanceof SqlQuery) {
final SqlQuery sqlQry = (SqlQuery) qry;
convertToBinary(sqlQry.getArgs());
}
else if (qry instanceof SpiQuery) {
final SpiQuery spiQry = (SpiQuery) qry;
convertToBinary(spiQry.getArgs());
}
else if (qry instanceof SqlFieldsQuery) {
final SqlFieldsQuery fieldsQry = (SqlFieldsQuery) qry;
convertToBinary(fieldsQry.getArgs());
}
}
}
/**
* Converts query arguments to BinaryObjects if binary marshaller used.
*
* @param args Arguments.
*/
private void convertToBinary(final Object[] args) {
if (args == null)
return;
for (int i = 0; i < args.length; i++)
args[i] = ctx.cacheObjects().binary().toBinary(args[i]);
}
/**
* Checks query.
*
* @param qry Query
* @throws CacheException If query indexing disabled for sql query.
*/
private void validate(Query qry) {
if (!QueryUtils.isEnabled(ctx.config()) && !(qry instanceof ScanQuery) &&
!(qry instanceof ContinuousQuery) && !(qry instanceof SpiQuery))
throw new CacheException("Indexing is disabled for cache: " + ctx.cache().name() +
". Use setIndexedTypes or setTypeMetadata methods on CacheConfiguration to enable.");
if (!ctx.kernalContext().query().moduleEnabled() &&
(qry instanceof SqlQuery || qry instanceof SqlFieldsQuery || qry instanceof TextQuery))
throw new CacheException("Failed to execute query. Add module 'ignite-indexing' to the classpath " +
"of all Ignite nodes.");
}
/** {@inheritDoc} */
@Override public Iterable<Cache.Entry<K, V>> localEntries(CachePeekMode... peekModes) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.localEntries(peekModes);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public QueryMetrics queryMetrics() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.context().queries().metrics();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void resetQueryMetrics() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
delegate.context().queries().resetMetrics();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public Collection<? extends QueryDetailMetrics> queryDetailMetrics() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.context().queries().detailMetrics();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void resetQueryDetailMetrics() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
delegate.context().queries().resetDetailMetrics();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void localEvict(Collection<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
delegate.evictAll(keys);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Nullable @Override public V localPeek(K key, CachePeekMode... peekModes) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.localPeek(key, peekModes, null);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public int size(CachePeekMode... peekModes) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.sizeAsync(peekModes));
return 0;
}
else
return delegate.size(peekModes);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Integer> sizeAsync(CachePeekMode... peekModes) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.sizeAsync(peekModes));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public long sizeLong(CachePeekMode... peekModes) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.sizeLongAsync(peekModes));
return 0;
}
else
return delegate.sizeLong(peekModes);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Long> sizeLongAsync(CachePeekMode... peekModes) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.sizeLongAsync(peekModes));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public long sizeLong(int part, CachePeekMode... peekModes) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.sizeLongAsync(part, peekModes));
return 0;
}
else
return delegate.sizeLong(part, peekModes);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Long> sizeLongAsync(int part, CachePeekMode... peekModes) throws CacheException {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.sizeLongAsync(part, peekModes));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public int localSize(CachePeekMode... peekModes) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.localSize(peekModes);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public long localSizeLong(CachePeekMode... peekModes) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.localSizeLong(peekModes);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public long localSizeLong(int part, CachePeekMode... peekModes) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.localSizeLong(part, peekModes);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public V get(K key) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getAsync(key));
return null;
}
else
return delegate.get(key);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<V> getAsync(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getAsync(key));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public CacheEntry<K, V> getEntry(K key) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getEntryAsync(key));
return null;
}
else
return delegate.getEntry(key);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<CacheEntry<K, V>> getEntryAsync(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getEntryAsync(key));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public Map<K, V> getAll(Set<? extends K> keys) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getAllAsync(keys));
return null;
}
else
return delegate.getAll(keys);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Map<K, V>> getAllAsync(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getAllAsync(keys));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public Collection<CacheEntry<K, V>> getEntries(Set<? extends K> keys) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getEntriesAsync(keys));
return null;
}
else
return delegate.getEntries(keys);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Collection<CacheEntry<K, V>>> getEntriesAsync(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getEntriesAsync(keys));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public Map<K, V> getAllOutTx(Set<? extends K> keys) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getAllOutTxAsync(keys));
return null;
}
else
return delegate.getAllOutTx(keys);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Map<K, V>> getAllOutTxAsync(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getAllOutTxAsync(keys));
}
finally {
onLeave(gate, prev);
}
}
/**
* @param keys Keys.
* @return Values map.
*/
public Map<K, V> getAll(Collection<? extends K> keys) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getAllAsync(keys));
return null;
}
else
return delegate.getAll(keys);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public boolean containsKey(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.containsKeyAsync(key));
return false;
}
else
return delegate.containsKey(key);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Boolean> containsKeyAsync(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.containsKeyAsync(key));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public boolean containsKeys(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.containsKeysAsync(keys));
return false;
}
else
return delegate.containsKeys(keys);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Boolean> containsKeysAsync(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.containsKeysAsync(keys));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void loadAll(
Set<? extends K> keys,
boolean replaceExisting,
@Nullable final CompletionListener completionLsnr
) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
IgniteInternalFuture<?> fut = ctx.cache().loadAll(keys, replaceExisting);
if (completionLsnr != null) {
fut.listen(new CI1<IgniteInternalFuture<?>>() {
@Override public void apply(IgniteInternalFuture<?> fut) {
try {
fut.get();
completionLsnr.onCompletion();
}
catch (IgniteCheckedException e) {
completionLsnr.onException(cacheException(e));
}
}
});
}
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void put(K key, V val) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
setFuture(putAsync0(key, val));
else
delegate.put(key, val);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> putAsync(K key, V val) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(putAsync0(key, val));
}
finally {
onLeave(gate, prev);
}
}
/**
* Put async internal operation implementation.
*
* @param key Key.
* @param val Value.
* @return Internal future.
*/
private IgniteInternalFuture<Void> putAsync0(K key, V val) {
IgniteInternalFuture<Boolean> fut = delegate.putAsync(key, val);
return fut.chain(new CX1<IgniteInternalFuture<Boolean>, Void>() {
@Override public Void applyx(IgniteInternalFuture<Boolean> fut1) throws IgniteCheckedException {
try {
fut1.get();
}
catch (RuntimeException e) {
throw new GridClosureException(e);
}
return null;
}
});
}
/** {@inheritDoc} */
@Override public V getAndPut(K key, V val) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getAndPutAsync(key, val));
return null;
}
else
return delegate.getAndPut(key, val);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<V> getAndPutAsync(K key, V val) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getAndPutAsync(key, val));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void putAll(Map<? extends K, ? extends V> map) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
setFuture(delegate.putAllAsync(map));
else
delegate.putAll(map);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> putAllAsync(Map<? extends K, ? extends V> map) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return (IgniteFuture<Void>)createFuture(delegate.putAllAsync(map));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public boolean putIfAbsent(K key, V val) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.putIfAbsentAsync(key, val));
return false;
}
else
return delegate.putIfAbsent(key, val);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Boolean> putIfAbsentAsync(K key, V val) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.putIfAbsentAsync(key, val));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public boolean remove(K key) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.removeAsync(key));
return false;
}
else
return delegate.remove(key);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Boolean> removeAsync(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.removeAsync(key));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public boolean remove(K key, V oldVal) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.removeAsync(key, oldVal));
return false;
}
else
return delegate.remove(key, oldVal);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Boolean> removeAsync(K key, V oldVal) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.removeAsync(key, oldVal));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public V getAndRemove(K key) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getAndRemoveAsync(key));
return null;
}
else
return delegate.getAndRemove(key);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<V> getAndRemoveAsync(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getAndRemoveAsync(key));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public boolean replace(K key, V oldVal, V newVal) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.replaceAsync(key, oldVal, newVal));
return false;
}
else
return delegate.replace(key, oldVal, newVal);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Boolean> replaceAsync(K key, V oldVal, V newVal) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.replaceAsync(key, oldVal, newVal));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public boolean replace(K key, V val) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.replaceAsync(key, val));
return false;
}
else
return delegate.replace(key, val);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Boolean> replaceAsync(K key, V val) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.replaceAsync(key, val));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public V getAndReplace(K key, V val) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.getAndReplaceAsync(key, val));
return null;
}
else
return delegate.getAndReplace(key, val);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<V> getAndReplaceAsync(K key, V val) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.getAndReplaceAsync(key, val));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void removeAll(Set<? extends K> keys) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
setFuture(delegate.removeAllAsync(keys));
else
delegate.removeAll(keys);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> removeAllAsync(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return (IgniteFuture<Void>)createFuture(delegate.removeAllAsync(keys));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void removeAll() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
setFuture(delegate.removeAllAsync());
else
delegate.removeAll();
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> removeAllAsync() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return (IgniteFuture<Void>)createFuture(delegate.removeAllAsync());
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void clear(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
setFuture(delegate.clearAsync(key));
else
delegate.clear(key);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> clearAsync(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return (IgniteFuture<Void>)createFuture(delegate.clearAsync(key));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void clearAll(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
setFuture(delegate.clearAllAsync(keys));
else
delegate.clearAll(keys);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> clearAllAsync(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return (IgniteFuture<Void>)createFuture(delegate.clearAllAsync(keys));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void clear() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
setFuture(delegate.clearAsync());
else
delegate.clear();
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public IgniteFuture<Void> clearAsync() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return (IgniteFuture<Void>)createFuture(delegate.clearAsync());
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void localClear(K key) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
delegate.clearLocally(key);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void localClearAll(Set<? extends K> keys) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
for (K key : keys)
delegate.clearLocally(key);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public <T> T invoke(K key, EntryProcessor<K, V, T> entryProcessor, Object... args)
throws EntryProcessorException {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(invokeAsync0(key, entryProcessor, args));
return null;
}
else {
EntryProcessorResult<T> res = delegate.invoke(key, entryProcessor, args);
return res != null ? res.get() : null;
}
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public <T> IgniteFuture<T> invokeAsync(K key, EntryProcessor<K, V, T> entryProcessor,
Object... args) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(invokeAsync0(key, entryProcessor, args));
}
finally {
onLeave(gate, prev);
}
}
/**
* Invoke async operation internal implementation.
*
* @param key Key.
* @param entryProcessor Processor.
* @param args Arguments.
* @return Internal future.
*/
private <T> IgniteInternalFuture<T> invokeAsync0(K key, EntryProcessor<K, V, T> entryProcessor, Object[] args) {
IgniteInternalFuture<EntryProcessorResult<T>> fut = delegate.invokeAsync(key, entryProcessor, args);
return fut.chain(new CX1<IgniteInternalFuture<EntryProcessorResult<T>>, T>() {
@Override public T applyx(IgniteInternalFuture<EntryProcessorResult<T>> fut1)
throws IgniteCheckedException {
try {
EntryProcessorResult<T> res = fut1.get();
return res != null ? res.get() : null;
}
catch (RuntimeException e) {
throw new GridClosureException(e);
}
}
});
}
/** {@inheritDoc} */
@Override public <T> T invoke(K key, CacheEntryProcessor<K, V, T> entryProcessor, Object... args)
throws EntryProcessorException {
return invoke(key, (EntryProcessor<K, V, T>)entryProcessor, args);
}
/** {@inheritDoc} */
@Override public <T> IgniteFuture<T> invokeAsync(K key, CacheEntryProcessor<K, V, T> entryProcessor,
Object... args) {
return invokeAsync(key, (EntryProcessor<K, V, T>)entryProcessor, args);
}
/**
* @param topVer Locked topology version.
* @param key Key.
* @param entryProcessor Entry processor.
* @param args Arguments.
* @return Invoke result.
*/
public <T> T invoke(@Nullable AffinityTopologyVersion topVer,
K key,
EntryProcessor<K, V, T> entryProcessor,
Object... args) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync())
throw new UnsupportedOperationException();
else {
EntryProcessorResult<T> res = delegate.invoke(topVer, key, entryProcessor, args);
return res != null ? res.get() : null;
}
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public <T> Map<K, EntryProcessorResult<T>> invokeAll(Set<? extends K> keys,
EntryProcessor<K, V, T> entryProcessor,
Object... args) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.invokeAllAsync(keys, entryProcessor, args));
return null;
}
else
return delegate.invokeAll(keys, entryProcessor, args);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public <T> IgniteFuture<Map<K, EntryProcessorResult<T>>> invokeAllAsync(Set<? extends K> keys,
EntryProcessor<K, V, T> entryProcessor, Object... args) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.invokeAllAsync(keys, entryProcessor, args));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public <T> Map<K, EntryProcessorResult<T>> invokeAll(Set<? extends K> keys,
CacheEntryProcessor<K, V, T> entryProcessor,
Object... args) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.invokeAllAsync(keys, entryProcessor, args));
return null;
}
else
return delegate.invokeAll(keys, entryProcessor, args);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public <T> IgniteFuture<Map<K, EntryProcessorResult<T>>> invokeAllAsync(Set<? extends K> keys,
CacheEntryProcessor<K, V, T> entryProcessor, Object... args) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.invokeAllAsync(keys, entryProcessor, args));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public <T> Map<K, EntryProcessorResult<T>> invokeAll(
Map<? extends K, ? extends EntryProcessor<K, V, T>> map,
Object... args) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
if (isAsync()) {
setFuture(delegate.invokeAllAsync(map, args));
return null;
}
else
return delegate.invokeAll(map, args);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public <T> IgniteFuture<Map<K, EntryProcessorResult<T>>> invokeAllAsync(
Map<? extends K, ? extends EntryProcessor<K, V, T>> map, Object... args) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return createFuture(delegate.invokeAllAsync(map, args));
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public String getName() {
return delegate.name();
}
/** {@inheritDoc} */
@Override public CacheManager getCacheManager() {
return cacheMgr;
}
/**
* @param cacheMgr Cache manager.
*/
public void setCacheManager(CacheManager cacheMgr) {
this.cacheMgr = cacheMgr;
}
/** {@inheritDoc} */
@Override public void destroy() {
GridCacheGateway<K, V> gate = this.gate;
if (!onEnterIfNoStop(gate))
return;
IgniteInternalFuture<?> fut;
try {
fut = ctx.kernalContext().cache().dynamicDestroyCache(ctx.name(), true);
}
finally {
onLeave(gate);
}
try {
fut.get();
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public void close() {
GridCacheGateway<K, V> gate = this.gate;
if (!onEnterIfNoStop(gate))
return;
IgniteInternalFuture<?> fut;
try {
fut = ctx.kernalContext().cache().dynamicCloseCache(ctx.name());
}
finally {
onLeave(gate);
}
try {
fut.get();
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public boolean isClosed() {
GridCacheGateway<K, V> gate = this.gate;
if (!onEnterIfNoStop(gate))
return true;
try {
return ctx.kernalContext().cache().context().closed(ctx);
}
finally {
onLeave(gate);
}
}
/**
* @return Proxy delegate.
*/
public IgniteInternalCache delegate() {
return delegate;
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <T> T unwrap(Class<T> clazz) {
if (clazz.isAssignableFrom(getClass()))
return (T)this;
else if (clazz.isAssignableFrom(IgniteEx.class))
return (T)ctx.grid();
throw new IllegalArgumentException("Unwrapping to class is not supported: " + clazz);
}
/** {@inheritDoc} */
@Override public void registerCacheEntryListener(CacheEntryListenerConfiguration<K, V> lsnrCfg) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
CacheOperationContext opCtx = ctx.operationContextPerCall();
ctx.continuousQueries().executeJCacheQuery(lsnrCfg, false, opCtx != null && opCtx.isKeepBinary());
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void deregisterCacheEntryListener(CacheEntryListenerConfiguration<K, V> lsnrCfg) {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
ctx.continuousQueries().cancelJCacheQuery(lsnrCfg);
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public Iterator<Cache.Entry<K, V>> iterator() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return ctx.cache().igniteIterator();
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override protected IgniteCache<K, V> createAsyncInstance() {
return new IgniteCacheProxy<>(ctx, delegate, opCtx, true, lock);
}
/**
* Creates projection that will operate with binary objects. <p> Projection returned by this method will force
* cache not to deserialize binary objects, so keys and values will be returned from cache API methods without
* changes. Therefore, signature of the projection can contain only following types: <ul> <li>{@code BinaryObject}
* for binary classes</li> <li>All primitives (byte, int, ...) and there boxed versions (Byte, Integer, ...)</li>
* <li>Arrays of primitives (byte[], int[], ...)</li> <li>{@link String} and array of {@link String}s</li>
* <li>{@link UUID} and array of {@link UUID}s</li> <li>{@link Date} and array of {@link Date}s</li> <li>{@link
* java.sql.Timestamp} and array of {@link java.sql.Timestamp}s</li> <li>Enums and array of enums</li> <li> Maps,
* collections and array of objects (but objects inside them will still be converted if they are binary) </li>
* </ul> <p> For example, if you use {@link Integer} as a key and {@code Value} class as a value (which will be
* stored in binary format), you should acquire following projection to avoid deserialization:
* <pre>
* IgniteInternalCache<Integer, GridBinaryObject> prj = cache.keepBinary();
*
* // Value is not deserialized and returned in binary format.
* GridBinaryObject po = prj.get(1);
* </pre>
* <p> Note that this method makes sense only if cache is working in binary mode ({@code
* CacheConfiguration#isBinaryEnabled()} returns {@code true}. If not, this method is no-op and will return
* current projection.
*
* @return Projection for binary objects.
*/
@SuppressWarnings("unchecked")
public <K1, V1> IgniteCache<K1, V1> keepBinary() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
CacheOperationContext opCtx0 =
new CacheOperationContext(
opCtx != null && opCtx.skipStore(),
opCtx != null ? opCtx.subjectId() : null,
true,
opCtx != null ? opCtx.expiry() : null,
opCtx != null && opCtx.noRetries(),
opCtx != null ? opCtx.dataCenterId() : null,
opCtx != null && opCtx.recovery());
return new IgniteCacheProxy<>((GridCacheContext<K1, V1>)ctx,
(IgniteInternalCache<K1, V1>)delegate,
opCtx0,
isAsync(),
lock);
}
finally {
onLeave(gate, prev);
}
}
/**
* @param dataCenterId Data center ID.
* @return Projection for data center id.
*/
@SuppressWarnings("unchecked")
public IgniteCache<K, V> withDataCenterId(byte dataCenterId) {
CacheOperationContext prev = onEnter(gate, opCtx);
try {
Byte prevDataCenterId = opCtx != null ? opCtx.dataCenterId() : null;
if (prevDataCenterId != null && dataCenterId == prevDataCenterId)
return this;
CacheOperationContext opCtx0 =
new CacheOperationContext(
opCtx != null && opCtx.skipStore(),
opCtx != null ? opCtx.subjectId() : null,
opCtx != null && opCtx.isKeepBinary(),
opCtx != null ? opCtx.expiry() : null,
opCtx != null && opCtx.noRetries(),
dataCenterId,
opCtx != null && opCtx.recovery());
return new IgniteCacheProxy<>(ctx,
delegate,
opCtx0,
isAsync(),
lock);
}
finally {
onLeave(gate, prev);
}
}
/**
* @return Cache with skip store enabled.
*/
public IgniteCache<K, V> skipStore() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
boolean skip = opCtx != null && opCtx.skipStore();
if (skip)
return this;
CacheOperationContext opCtx0 =
new CacheOperationContext(true,
opCtx != null ? opCtx.subjectId() : null,
opCtx != null && opCtx.isKeepBinary(),
opCtx != null ? opCtx.expiry() : null,
opCtx != null && opCtx.noRetries(),
opCtx != null ? opCtx.dataCenterId() : null,
opCtx != null && opCtx.recovery());
return new IgniteCacheProxy<>(ctx,
delegate,
opCtx0,
isAsync(),
lock);
}
finally {
onLeave(gate, prev);
}
}
/**
* @param e Checked exception.
* @return Cache exception.
*/
private RuntimeException cacheException(IgniteCheckedException e) {
return CU.convertToCacheException(e);
}
/**
* @param fut Future for async operation.
*/
private <R> void setFuture(IgniteInternalFuture<R> fut) {
curFut.set(createFuture(fut));
}
/** {@inheritDoc} */
@Override protected <R> IgniteFuture<R> createFuture(IgniteInternalFuture<R> fut) {
return new IgniteCacheFutureImpl<>(fut);
}
/**
* @return Internal proxy.
*/
public GridCacheProxyImpl<K, V> internalProxy() {
return internalProxy;
}
/**
* @return {@code True} if proxy was closed.
*/
public boolean proxyClosed() {
return !gate.getClass().equals(GridCacheGateway.class);
}
/**
* Closes this proxy instance.
*/
public void closeProxy() {
gate = new GridCacheGateway<K, V>(ctx) {
@Override public void enter() {
throw new IllegalStateException("Cache has been closed: " + ctx.name());
}
@Override public boolean enterIfNotStopped() {
return false;
}
@Override public boolean enterIfNotStoppedNoLock() {
return false;
}
@Override public void leaveNoLock() {
assert false;
}
@Override public void leave() {
assert false;
}
@Nullable @Override public CacheOperationContext enter(@Nullable CacheOperationContext opCtx) {
throw new IllegalStateException("Cache has been closed: " + ctx.name());
}
@Nullable @Override public CacheOperationContext enterNoLock(@Nullable CacheOperationContext opCtx) {
throw new IllegalStateException("Cache has been closed: " + ctx.name());
}
@Override public void leave(CacheOperationContext prev) {
assert false;
}
@Override public void leaveNoLock(CacheOperationContext prev) {
assert false;
}
@Override public void stopped() {
// No-op.
}
@Override public void onStopped() {
// No-op.
}
};
}
/**
* @param gate Cache gateway.
* @param opCtx Cache operation context to guard.
* @return Previous projection set on this thread.
*/
private CacheOperationContext onEnter(GridCacheGateway<K, V> gate, CacheOperationContext opCtx) {
return lock ? gate.enter(opCtx) : gate.enterNoLock(opCtx);
}
/**
* @param gate Cache gateway.
* @return {@code True} if enter successful.
*/
private boolean onEnterIfNoStop(GridCacheGateway<K, V> gate) {
return lock ? gate.enterIfNotStopped() : gate.enterIfNotStoppedNoLock();
}
/**
* @param gate Cache gateway.
* @param opCtx Operation context to guard.
*/
private void onLeave(GridCacheGateway<K, V> gate, CacheOperationContext opCtx) {
if (lock)
gate.leave(opCtx);
else
gate.leaveNoLock(opCtx);
}
/**
* @param gate Cache gateway.
*/
private void onLeave(GridCacheGateway<K, V> gate) {
if (lock)
gate.leave();
else
gate.leaveNoLock();
}
/** {@inheritDoc} */
@Override public Collection<Integer> lostPartitions() {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.lostPartitions();
}
finally {
onLeave(gate, prev);
}
}
/** {@inheritDoc} */
@Override public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(ctx);
out.writeObject(delegate);
out.writeObject(opCtx);
out.writeBoolean(lock);
}
/** {@inheritDoc} */
@SuppressWarnings({"unchecked"})
@Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
ctx = (GridCacheContext<K, V>)in.readObject();
delegate = (IgniteInternalCache<K, V>)in.readObject();
opCtx = (CacheOperationContext)in.readObject();
gate = ctx.gate();
lock = in.readBoolean();
}
/** {@inheritDoc} */
@Override public IgniteFuture<?> rebalance() {
return new IgniteFutureImpl<>(ctx.preloader().forceRebalance());
}
/** {@inheritDoc} */
@Override public IgniteFuture<?> indexReadyFuture() {
IgniteInternalFuture fut = ctx.shared().database().indexRebuildFuture(ctx.cacheId());
if (fut == null)
return new IgniteFinishedFutureImpl<>();
return new IgniteFutureImpl<>(fut);
}
/**
* Gets value without waiting for toplogy changes.
*
* @param key Key.
* @return Value.
*/
public V getTopologySafe(K key) {
try {
GridCacheGateway<K, V> gate = this.gate;
CacheOperationContext prev = onEnter(gate, opCtx);
try {
return delegate.getTopologySafe(key);
}
finally {
onLeave(gate, prev);
}
}
catch (IgniteCheckedException e) {
throw cacheException(e);
}
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(IgniteCacheProxy.class, this);
}
}