/* * 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.platform.cache; import org.apache.ignite.IgniteCache; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.binary.BinaryRawReader; import org.apache.ignite.binary.BinaryRawWriter; import org.apache.ignite.cache.CacheEntryProcessor; import org.apache.ignite.cache.CacheMetrics; import org.apache.ignite.cache.CachePartialUpdateException; import org.apache.ignite.cache.CachePeekMode; import org.apache.ignite.cache.query.Query; import org.apache.ignite.cache.query.ScanQuery; 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.configuration.CacheConfiguration; import org.apache.ignite.internal.binary.BinaryRawReaderEx; import org.apache.ignite.internal.binary.BinaryRawWriterEx; import org.apache.ignite.internal.processors.cache.CacheOperationContext; import org.apache.ignite.internal.processors.cache.CachePartialUpdateCheckedException; import org.apache.ignite.internal.processors.cache.IgniteCacheProxy; import org.apache.ignite.internal.processors.cache.query.QueryCursorEx; import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget; import org.apache.ignite.internal.processors.platform.PlatformContext; import org.apache.ignite.internal.processors.platform.PlatformNativeException; import org.apache.ignite.internal.processors.platform.cache.expiry.PlatformExpiryPolicy; import org.apache.ignite.internal.processors.platform.PlatformTarget; import org.apache.ignite.internal.processors.platform.cache.query.PlatformContinuousQuery; import org.apache.ignite.internal.processors.platform.cache.query.PlatformContinuousQueryProxy; import org.apache.ignite.internal.processors.platform.cache.query.PlatformFieldsQueryCursor; import org.apache.ignite.internal.processors.platform.cache.query.PlatformQueryCursor; import org.apache.ignite.internal.processors.platform.memory.PlatformMemory; import org.apache.ignite.internal.processors.platform.memory.PlatformOutputStream; import org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils; import org.apache.ignite.internal.processors.platform.utils.PlatformFutureUtils; import org.apache.ignite.internal.processors.platform.utils.PlatformListenable; import org.apache.ignite.internal.processors.platform.utils.PlatformUtils; import org.apache.ignite.internal.processors.platform.utils.PlatformWriterClosure; import org.apache.ignite.internal.util.GridConcurrentFactory; import org.apache.ignite.internal.util.typedef.C1; import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.lang.IgniteBiInClosure; import org.apache.ignite.lang.IgniteFuture; import org.apache.ignite.transactions.TransactionDeadlockException; import org.apache.ignite.transactions.TransactionTimeoutException; import org.jetbrains.annotations.Nullable; import javax.cache.Cache; import javax.cache.integration.CompletionListener; import javax.cache.processor.EntryProcessorException; import javax.cache.processor.EntryProcessorResult; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; /** * Native cache wrapper implementation. */ @SuppressWarnings({"unchecked", "UnusedDeclaration", "TryFinallyCanBeTryWithResources", "TypeMayBeWeakened", "WeakerAccess"}) public class PlatformCache extends PlatformAbstractTarget { /** */ public static final int OP_CLEAR = 1; /** */ public static final int OP_CLEAR_ALL = 2; /** */ public static final int OP_CONTAINS_KEY = 3; /** */ public static final int OP_CONTAINS_KEYS = 4; /** */ public static final int OP_GET = 5; /** */ public static final int OP_GET_ALL = 6; /** */ public static final int OP_GET_AND_PUT = 7; /** */ public static final int OP_GET_AND_PUT_IF_ABSENT = 8; /** */ public static final int OP_GET_AND_REMOVE = 9; /** */ public static final int OP_GET_AND_REPLACE = 10; /** */ public static final int OP_GET_NAME = 11; /** */ public static final int OP_INVOKE = 12; /** */ public static final int OP_INVOKE_ALL = 13; /** */ public static final int OP_IS_LOCAL_LOCKED = 14; /** */ public static final int OP_LOAD_CACHE = 15; /** */ public static final int OP_LOC_EVICT = 16; /** */ public static final int OP_LOC_LOAD_CACHE = 17; /** */ public static final int OP_LOCAL_CLEAR = 20; /** */ public static final int OP_LOCAL_CLEAR_ALL = 21; /** */ public static final int OP_LOCK = 22; /** */ public static final int OP_LOCK_ALL = 23; /** */ public static final int OP_LOCAL_METRICS = 24; /** */ private static final int OP_PEEK = 25; /** */ private static final int OP_PUT = 26; /** */ private static final int OP_PUT_ALL = 27; /** */ public static final int OP_PUT_IF_ABSENT = 28; /** */ public static final int OP_QRY_CONTINUOUS = 29; /** */ public static final int OP_QRY_SCAN = 30; /** */ public static final int OP_QRY_SQL = 31; /** */ public static final int OP_QRY_SQL_FIELDS = 32; /** */ public static final int OP_QRY_TXT = 33; /** */ public static final int OP_REMOVE_ALL = 34; /** */ public static final int OP_REMOVE_BOOL = 35; /** */ public static final int OP_REMOVE_OBJ = 36; /** */ public static final int OP_REPLACE_2 = 37; /** */ public static final int OP_REPLACE_3 = 38; /** */ public static final int OP_GET_CONFIG = 39; /** */ public static final int OP_LOAD_ALL = 40; /** */ public static final int OP_CLEAR_CACHE = 41; /** */ public static final int OP_WITH_PARTITION_RECOVER = 42; /** */ public static final int OP_REMOVE_ALL2 = 43; /** */ public static final int OP_WITH_KEEP_BINARY = 44; /** */ public static final int OP_WITH_EXPIRY_POLICY = 45; /** */ public static final int OP_WITH_NO_RETRIES = 46; /** */ public static final int OP_WITH_SKIP_STORE = 47; /** */ public static final int OP_SIZE = 48; /** */ public static final int OP_ITERATOR = 49; /** */ public static final int OP_LOC_ITERATOR = 50; /** */ public static final int OP_ENTER_LOCK = 51; /** */ public static final int OP_EXIT_LOCK = 52; /** */ public static final int OP_TRY_ENTER_LOCK = 53; /** */ public static final int OP_CLOSE_LOCK = 54; /** */ public static final int OP_REBALANCE = 55; /** */ public static final int OP_SIZE_LOC = 56; /** */ public static final int OP_PUT_ASYNC = 57; /** */ public static final int OP_CLEAR_CACHE_ASYNC = 58; /** */ public static final int OP_CLEAR_ALL_ASYNC = 59; /** */ public static final int OP_REMOVE_ALL2_ASYNC = 60; /** */ public static final int OP_SIZE_ASYNC = 61; /** */ public static final int OP_CLEAR_ASYNC = 62; /** */ public static final int OP_LOAD_CACHE_ASYNC = 63; /** */ public static final int OP_LOC_LOAD_CACHE_ASYNC = 64; /** */ public static final int OP_PUT_ALL_ASYNC = 65; /** */ public static final int OP_REMOVE_ALL_ASYNC = 66; /** */ public static final int OP_GET_ASYNC = 67; /** */ public static final int OP_CONTAINS_KEY_ASYNC = 68; /** */ public static final int OP_CONTAINS_KEYS_ASYNC = 69; /** */ public static final int OP_REMOVE_BOOL_ASYNC = 70; /** */ public static final int OP_REMOVE_OBJ_ASYNC = 71; /** */ public static final int OP_GET_ALL_ASYNC = 72; /** */ public static final int OP_GET_AND_PUT_ASYNC = 73; /** */ public static final int OP_GET_AND_PUT_IF_ABSENT_ASYNC = 74; /** */ public static final int OP_GET_AND_REMOVE_ASYNC = 75; /** */ public static final int OP_GET_AND_REPLACE_ASYNC = 76; /** */ public static final int OP_REPLACE_2_ASYNC = 77; /** */ public static final int OP_REPLACE_3_ASYNC = 78; /** */ public static final int OP_INVOKE_ASYNC = 79; /** */ public static final int OP_INVOKE_ALL_ASYNC = 80; /** */ public static final int OP_PUT_IF_ABSENT_ASYNC = 81; /** */ public static final int OP_EXTENSION = 82; /** */ public static final int OP_GLOBAL_METRICS = 83; /** */ public static final int OP_GET_LOST_PARTITIONS = 84; /** Underlying JCache in binary mode. */ private final IgniteCacheProxy cache; /** Initial JCache (not in binary mode). */ private final IgniteCache rawCache; /** Whether this cache is created with "keepBinary" flag on the other side. */ private final boolean keepBinary; /** */ private static final PlatformFutureUtils.Writer WRITER_GET_ALL = new GetAllWriter(); /** */ private static final PlatformFutureUtils.Writer WRITER_INVOKE = new EntryProcessorInvokeWriter(); /** */ private static final PlatformFutureUtils.Writer WRITER_INVOKE_ALL = new EntryProcessorInvokeAllWriter(); /** Map with currently active locks. */ private final ConcurrentMap<Long, Lock> lockMap = GridConcurrentFactory.newMap(); /** Lock ID sequence. */ private static final AtomicLong LOCK_ID_GEN = new AtomicLong(); /** Extensions. */ private final PlatformCacheExtension[] exts; /** * Constructor. * * @param platformCtx Context. * @param cache Underlying cache. * @param keepBinary Keep binary flag. */ @SuppressWarnings("ZeroLengthArrayAllocation") public PlatformCache(PlatformContext platformCtx, IgniteCache cache, boolean keepBinary) { this(platformCtx, cache, keepBinary, new PlatformCacheExtension[0]); } /** * Constructor. * * @param platformCtx Context. * @param cache Underlying cache. * @param keepBinary Keep binary flag. * @param exts Extensions. */ public PlatformCache(PlatformContext platformCtx, IgniteCache cache, boolean keepBinary, PlatformCacheExtension[] exts) { super(platformCtx); assert cache != null; assert exts != null; rawCache = cache; IgniteCache binCache = cache.withKeepBinary(); this.cache = (IgniteCacheProxy)binCache; this.keepBinary = keepBinary; this.exts = exts; } /** * @return Raw cache. */ public IgniteCache rawCache() { return rawCache; } /** {@inheritDoc} */ @Override public long processInStreamOutLong(int type, BinaryRawReaderEx reader, PlatformMemory mem) throws IgniteCheckedException { try { switch (type) { case OP_PUT: cache.put(reader.readObjectDetached(), reader.readObjectDetached()); return TRUE; case OP_GET: return writeResult(mem, cache.get(reader.readObjectDetached())); case OP_REMOVE_BOOL: return cache.remove(reader.readObjectDetached(), reader.readObjectDetached()) ? TRUE : FALSE; case OP_REMOVE_ALL: cache.removeAll(PlatformUtils.readSet(reader)); return TRUE; case OP_PUT_ALL: cache.putAll(PlatformUtils.readMap(reader)); return TRUE; case OP_LOC_EVICT: cache.localEvict(PlatformUtils.readCollection(reader)); return TRUE; case OP_CONTAINS_KEY: return cache.containsKey(reader.readObjectDetached()) ? TRUE : FALSE; case OP_CONTAINS_KEYS: return cache.containsKeys(PlatformUtils.readSet(reader)) ? TRUE : FALSE; case OP_REPLACE_3: return cache.replace(reader.readObjectDetached(), reader.readObjectDetached(), reader.readObjectDetached()) ? TRUE : FALSE; case OP_LOC_LOAD_CACHE: loadCache0(reader, true); return TRUE; case OP_LOAD_CACHE: loadCache0(reader, false); return TRUE; case OP_CLEAR: cache.clear(reader.readObjectDetached()); return TRUE; case OP_CLEAR_ALL: cache.clearAll(PlatformUtils.readSet(reader)); return TRUE; case OP_LOCAL_CLEAR: cache.localClear(reader.readObjectDetached()); return TRUE; case OP_LOCAL_CLEAR_ALL: cache.localClearAll(PlatformUtils.readSet(reader)); return TRUE; case OP_PUT_IF_ABSENT: return cache.putIfAbsent(reader.readObjectDetached(), reader.readObjectDetached()) ? TRUE : FALSE; case OP_REPLACE_2: return cache.replace(reader.readObjectDetached(), reader.readObjectDetached()) ? TRUE : FALSE; case OP_REMOVE_OBJ: return cache.remove(reader.readObjectDetached()) ? TRUE : FALSE; case OP_IS_LOCAL_LOCKED: return cache.isLocalLocked(reader.readObjectDetached(), reader.readBoolean()) ? TRUE : FALSE; case OP_LOAD_ALL: { boolean replaceExisting = reader.readBoolean(); Set<Object> keys = PlatformUtils.readSet(reader); long futId = reader.readLong(); int futTyp = reader.readInt(); CompletionListenable fut = new CompletionListenable(); PlatformFutureUtils.listen(platformCtx, fut, futId, futTyp, null, this); cache.loadAll(keys, replaceExisting, fut); return TRUE; } case OP_GET_AND_PUT: return writeResult(mem, cache.getAndPut(reader.readObjectDetached(), reader.readObjectDetached())); case OP_GET_AND_REPLACE: return writeResult(mem, cache.getAndReplace(reader.readObjectDetached(), reader.readObjectDetached())); case OP_GET_AND_REMOVE: return writeResult(mem, cache.getAndRemove(reader.readObjectDetached())); case OP_GET_AND_PUT_IF_ABSENT: return writeResult(mem, cache.getAndPutIfAbsent(reader.readObjectDetached(), reader.readObjectDetached())); case OP_PEEK: { Object key = reader.readObjectDetached(); CachePeekMode[] modes = PlatformUtils.decodeCachePeekModes(reader.readInt()); return writeResult(mem, cache.localPeek(key, modes)); } case OP_TRY_ENTER_LOCK: { try { long id = reader.readLong(); long timeout = reader.readLong(); boolean res = timeout == -1 ? lock(id).tryLock() : lock(id).tryLock(timeout, TimeUnit.MILLISECONDS); return res ? TRUE : FALSE; } catch (InterruptedException e) { throw new IgniteCheckedException(e); } } case OP_GET_ALL: { Set keys = PlatformUtils.readSet(reader); Map entries = cache.getAll(keys); return writeResult(mem, entries, new PlatformWriterClosure<Map>() { @Override public void write(BinaryRawWriterEx writer, Map val) { PlatformUtils.writeNullableMap(writer, val); } }); } case OP_PUT_ASYNC: { readAndListenFuture(reader, cache.putAsync(reader.readObjectDetached(), reader.readObjectDetached())); return TRUE; } case OP_CLEAR_CACHE_ASYNC: { readAndListenFuture(reader, cache.clearAsync()); return TRUE; } case OP_CLEAR_ALL_ASYNC: { readAndListenFuture(reader, cache.clearAllAsync(PlatformUtils.readSet(reader))); return TRUE; } case OP_REMOVE_ALL2_ASYNC: { readAndListenFuture(reader, cache.removeAllAsync()); return TRUE; } case OP_SIZE_ASYNC: { CachePeekMode[] modes = PlatformUtils.decodeCachePeekModes(reader.readInt()); readAndListenFuture(reader, cache.sizeAsync(modes)); return TRUE; } case OP_CLEAR_ASYNC: { readAndListenFuture(reader, cache.clearAsync(reader.readObjectDetached())); return TRUE; } case OP_LOAD_CACHE_ASYNC: { readAndListenFuture(reader, loadCacheAsync0(reader, false)); return TRUE; } case OP_LOC_LOAD_CACHE_ASYNC: { readAndListenFuture(reader, loadCacheAsync0(reader, true)); return TRUE; } case OP_PUT_ALL_ASYNC: readAndListenFuture(reader, cache.putAllAsync(PlatformUtils.readMap(reader))); return TRUE; case OP_REMOVE_ALL_ASYNC: readAndListenFuture(reader, cache.removeAllAsync(PlatformUtils.readSet(reader))); return TRUE; case OP_REBALANCE: readAndListenFuture(reader, cache.rebalance()); return TRUE; case OP_GET_ASYNC: readAndListenFuture(reader, cache.getAsync(reader.readObjectDetached())); return TRUE; case OP_CONTAINS_KEY_ASYNC: readAndListenFuture(reader, cache.containsKeyAsync(reader.readObjectDetached())); return TRUE; case OP_CONTAINS_KEYS_ASYNC: readAndListenFuture(reader, cache.containsKeysAsync(PlatformUtils.readSet(reader))); return TRUE; case OP_REMOVE_OBJ_ASYNC: readAndListenFuture(reader, cache.removeAsync(reader.readObjectDetached())); return TRUE; case OP_REMOVE_BOOL_ASYNC: readAndListenFuture(reader, cache.removeAsync(reader.readObjectDetached(), reader.readObjectDetached())); return TRUE; case OP_GET_ALL_ASYNC: { Set keys = PlatformUtils.readSet(reader); readAndListenFuture(reader, cache.getAllAsync(keys), WRITER_GET_ALL); return TRUE; } case OP_GET_AND_PUT_ASYNC: readAndListenFuture(reader, cache.getAndPutAsync(reader.readObjectDetached(), reader.readObjectDetached())); return TRUE; case OP_GET_AND_PUT_IF_ABSENT_ASYNC: readAndListenFuture(reader, cache.getAndPutIfAbsentAsync(reader.readObjectDetached(), reader.readObjectDetached())); return TRUE; case OP_GET_AND_REMOVE_ASYNC: readAndListenFuture(reader, cache.getAndRemoveAsync(reader.readObjectDetached())); return TRUE; case OP_GET_AND_REPLACE_ASYNC: readAndListenFuture(reader, cache.getAndReplaceAsync(reader.readObjectDetached(), reader.readObjectDetached())); return TRUE; case OP_REPLACE_2_ASYNC: readAndListenFuture(reader, cache.replaceAsync(reader.readObjectDetached(), reader.readObjectDetached())); return TRUE; case OP_REPLACE_3_ASYNC: readAndListenFuture(reader, cache.replaceAsync(reader.readObjectDetached(), reader.readObjectDetached(), reader.readObjectDetached())); return TRUE; case OP_INVOKE_ASYNC: { Object key = reader.readObjectDetached(); CacheEntryProcessor proc = platformCtx.createCacheEntryProcessor(reader.readObjectDetached(), 0); readAndListenFuture(reader, cache.invokeAsync(key, proc), WRITER_INVOKE); return TRUE; } case OP_INVOKE_ALL_ASYNC: { Set<Object> keys = PlatformUtils.readSet(reader); CacheEntryProcessor proc = platformCtx.createCacheEntryProcessor(reader.readObjectDetached(), 0); readAndListenFuture(reader, cache.invokeAllAsync(keys, proc), WRITER_INVOKE_ALL); return TRUE; } case OP_PUT_IF_ABSENT_ASYNC: readAndListenFuture(reader, cache.putIfAbsentAsync(reader.readObjectDetached(), reader.readObjectDetached())); return TRUE; case OP_INVOKE: { Object key = reader.readObjectDetached(); CacheEntryProcessor proc = platformCtx.createCacheEntryProcessor(reader.readObjectDetached(), 0); return writeResult(mem, cache.invoke(key, proc)); } case OP_INVOKE_ALL: { Set<Object> keys = PlatformUtils.readSet(reader); CacheEntryProcessor proc = platformCtx.createCacheEntryProcessor(reader.readObjectDetached(), 0); Map results = cache.invokeAll(keys, proc); return writeResult(mem, results, new PlatformWriterClosure<Map>() { @Override public void write(BinaryRawWriterEx writer, Map val) { writeInvokeAllResult(writer, val); } }); } case OP_LOCK: { long id = registerLock(cache.lock(reader.readObjectDetached())); return writeResult(mem, id, new PlatformWriterClosure<Long>() { @Override public void write(BinaryRawWriterEx writer, Long val) { writer.writeLong(val); } }); } case OP_LOCK_ALL: { long id = registerLock(cache.lockAll(PlatformUtils.readCollection(reader))); return writeResult(mem, id, new PlatformWriterClosure<Long>() { @Override public void write(BinaryRawWriterEx writer, Long val) { writer.writeLong(val); } }); } case OP_EXTENSION: PlatformCacheExtension ext = extension(reader.readInt()); return ext.processInOutStreamLong(this, reader.readInt(), reader, mem); } } catch (Exception e) { PlatformOutputStream out = mem.output(); BinaryRawWriterEx writer = platformCtx.writer(out); Exception err = convertException(e); PlatformUtils.writeError(err, writer); PlatformUtils.writeErrorData(err, writer); out.synchronize(); return ERROR; } return super.processInStreamOutLong(type, reader, mem); } /** * Writes the result to reused stream, if any. */ public long writeResult(PlatformMemory mem, Object obj) { return writeResult(mem, obj, null); } /** * Writes the result to reused stream, if any. */ public long writeResult(PlatformMemory mem, Object obj, PlatformWriterClosure clo) { if (obj == null) return FALSE; PlatformOutputStream out = mem.output(); BinaryRawWriterEx writer = platformCtx.writer(out); if (clo == null) writer.writeObjectDetached(obj); else clo.write(writer, obj); out.synchronize(); return TRUE; } /** * Loads cache via localLoadCache or loadCache. * * @param reader Binary reader. * @param loc Local flag. * @return Cache async operation future. */ private void loadCache0(BinaryRawReaderEx reader, boolean loc) { PlatformCacheEntryFilter filter = createPlatformCacheEntryFilter(reader); Object[] args = readLoadCacheArgs(reader); if (loc) cache.localLoadCache(filter, args); else cache.loadCache(filter, args); } /** * Asynchronously loads cache via localLoadCacheAsync or loadCacheAsync. * * @param reader Binary reader. * @param loc Local flag. * @return Cache async operation future. */ private IgniteFuture<Void> loadCacheAsync0(BinaryRawReaderEx reader, boolean loc) { PlatformCacheEntryFilter filter = createPlatformCacheEntryFilter(reader); Object[] args = readLoadCacheArgs(reader); if (loc) return cache.localLoadCacheAsync(filter, args); else return cache.loadCacheAsync(filter, args); } /** * @param reader Binary reader. * @return created object. */ @Nullable private PlatformCacheEntryFilter createPlatformCacheEntryFilter(BinaryRawReaderEx reader) { PlatformCacheEntryFilter filter = null; Object pred = reader.readObjectDetached(); if (pred != null) filter = platformCtx.createCacheEntryFilter(pred, 0); return filter; } /** * @param reader Binary reader. * @return Arguments array. */ @Nullable private Object[] readLoadCacheArgs(BinaryRawReaderEx reader) { Object[] args = null; int argCnt = reader.readInt(); if (argCnt > 0) { args = new Object[argCnt]; for (int i = 0; i < argCnt; i++) args[i] = reader.readObjectDetached(); } return args; } /** {@inheritDoc} */ @Override public PlatformTarget processInStreamOutObject(int type, BinaryRawReaderEx reader) throws IgniteCheckedException { switch (type) { case OP_QRY_SQL: return runQuery(readSqlQuery(reader)); case OP_QRY_SQL_FIELDS: return runFieldsQuery(readFieldsQuery(reader)); case OP_QRY_TXT: return runQuery(readTextQuery(reader)); case OP_QRY_SCAN: return runQuery(readScanQuery(reader)); case OP_QRY_CONTINUOUS: { long ptr = reader.readLong(); boolean loc = reader.readBoolean(); boolean hasFilter = reader.readBoolean(); Object filter = reader.readObjectDetached(); int bufSize = reader.readInt(); long timeInterval = reader.readLong(); boolean autoUnsubscribe = reader.readBoolean(); Query initQry = readInitialQuery(reader); PlatformContinuousQuery qry = platformCtx.createContinuousQuery(ptr, hasFilter, filter); qry.start(cache, loc, bufSize, timeInterval, autoUnsubscribe, initQry); return new PlatformContinuousQueryProxy(platformCtx, qry); } case OP_WITH_EXPIRY_POLICY: { long create = reader.readLong(); long update = reader.readLong(); long access = reader.readLong(); IgniteCache cache0 = rawCache.withExpiryPolicy(new PlatformExpiryPolicy(create, update, access)); return copy(cache0, keepBinary); } case OP_LOC_ITERATOR: { int peekModes = reader.readInt(); CachePeekMode[] peekModes0 = PlatformUtils.decodeCachePeekModes(peekModes); Iterator<Cache.Entry> iter = cache.localEntries(peekModes0).iterator(); return new PlatformCacheIterator(platformCtx, iter); } default: return super.processInStreamOutObject(type, reader); } } /** * Read arguments for SQL query. * * @param reader Reader. * @return Arguments. */ @Nullable private Object[] readQueryArgs(BinaryRawReaderEx reader) { int cnt = reader.readInt(); if (cnt > 0) { Object[] args = new Object[cnt]; for (int i = 0; i < cnt; i++) args[i] = reader.readObjectDetached(); return args; } else return null; } /** {@inheritDoc} */ @Override public void processOutStream(int type, BinaryRawWriterEx writer) throws IgniteCheckedException { switch (type) { case OP_GET_NAME: writer.writeObject(cache.getName()); break; case OP_LOCAL_METRICS: { CacheMetrics metrics = cache.localMetrics(); writeCacheMetrics(writer, metrics); break; } case OP_GLOBAL_METRICS: { CacheMetrics metrics = cache.metrics(); writeCacheMetrics(writer, metrics); break; } case OP_GET_CONFIG: CacheConfiguration ccfg = ((IgniteCache<Object, Object>)cache). getConfiguration(CacheConfiguration.class); PlatformConfigurationUtils.writeCacheConfiguration(writer, ccfg); break; case OP_GET_LOST_PARTITIONS: Collection<Integer> parts = cache.lostPartitions(); writer.writeInt(parts.size()); for (int p : parts) { writer.writeInt(p); } break; default: super.processOutStream(type, writer); } } /** {@inheritDoc} */ @Override public PlatformTarget processOutObject(int type) throws IgniteCheckedException { switch (type) { case OP_WITH_PARTITION_RECOVER: { return copy(rawCache.withPartitionRecover(), keepBinary); } case OP_WITH_KEEP_BINARY: { if (keepBinary) return this; return copy(rawCache.withKeepBinary(), true); } case OP_WITH_NO_RETRIES: { CacheOperationContext opCtx = cache.operationContext(); if (opCtx != null && opCtx.noRetries()) return this; return copy(rawCache.withNoRetries(), keepBinary); } case OP_WITH_SKIP_STORE: { if (cache.delegate().skipStore()) return this; return copy(rawCache.withSkipStore(), keepBinary); } case OP_ITERATOR: { Iterator<Cache.Entry> iter = cache.iterator(); return new PlatformCacheIterator(platformCtx, iter); } } return super.processOutObject(type); } /** {@inheritDoc} */ @Override public long processInLongOutLong(int type, long val) throws IgniteCheckedException { switch (type) { case OP_SIZE: { CachePeekMode[] modes = PlatformUtils.decodeCachePeekModes((int)val); return cache.size(modes); } case OP_SIZE_LOC: { CachePeekMode[] modes = PlatformUtils.decodeCachePeekModes((int)val); return cache.localSize(modes); } case OP_ENTER_LOCK: { try { lock(val).lockInterruptibly(); return TRUE; } catch (InterruptedException e) { throw new IgniteCheckedException("Failed to enter cache lock.", e); } } case OP_EXIT_LOCK: { lock(val).unlock(); return TRUE; } case OP_CLOSE_LOCK: { Lock lock = lockMap.remove(val); assert lock != null : "Failed to unregister lock: " + val; return TRUE; } case OP_REBALANCE: { PlatformFutureUtils.listen(platformCtx, cache.rebalance().chain(new C1<IgniteFuture, Object>() { @Override public Object apply(IgniteFuture fut) { return null; } }), val, PlatformFutureUtils.TYP_OBJ, this); return TRUE; } case OP_CLEAR_CACHE: cache.clear(); return TRUE; case OP_REMOVE_ALL2: cache.removeAll(); return TRUE; } return super.processInLongOutLong(type, val); } /** {@inheritDoc} */ @Override public Exception convertException(Exception e) { if (e instanceof CachePartialUpdateException) return new PlatformCachePartialUpdateException((CachePartialUpdateCheckedException)e.getCause(), platformCtx, keepBinary); if (e instanceof CachePartialUpdateCheckedException) return new PlatformCachePartialUpdateException((CachePartialUpdateCheckedException)e, platformCtx, keepBinary); if (e.getCause() instanceof EntryProcessorException) return (Exception)e.getCause(); TransactionDeadlockException deadlockException = X.cause(e, TransactionDeadlockException.class); if (deadlockException != null) return deadlockException; TransactionTimeoutException timeoutException = X.cause(e, TransactionTimeoutException.class); if (timeoutException != null) return timeoutException; return super.convertException(e); } /** * Writes the result of InvokeAll cache method. * * @param writer Writer. * @param results Results. */ private static void writeInvokeAllResult(BinaryRawWriterEx writer, Map<Object, EntryProcessorResult> results) { if (results == null) { writer.writeInt(-1); return; } writer.writeInt(results.size()); for (Map.Entry<Object, EntryProcessorResult> entry : results.entrySet()) { writer.writeObjectDetached(entry.getKey()); EntryProcessorResult procRes = entry.getValue(); try { Object res = procRes.get(); writer.writeBoolean(false); // No exception writer.writeObjectDetached(res); } catch (Exception ex) { writer.writeBoolean(true); // Exception PlatformUtils.writeError(ex, writer); } } } /** * Writes an error to the writer either as a native exception, or as a couple of strings. * @param writer Writer. * @param ex Exception. */ private static void writeError(BinaryRawWriterEx writer, Exception ex) { if (ex.getCause() instanceof PlatformNativeException) writer.writeObjectDetached(((PlatformNativeException)ex.getCause()).cause()); else { writer.writeObjectDetached(ex.getClass().getName()); writer.writeObjectDetached(ex.getMessage()); writer.writeObjectDetached(X.getFullStackTrace(ex)); } } /** * Get lock by id. * * @param id Id. * @return Lock. */ private Lock lock(long id) { Lock lock = lockMap.get(id); assert lock != null : "Lock not found for ID: " + id; return lock; } /** * Registers a lock in a map. * * @param lock Lock to register. * @return Registered lock id. */ private long registerLock(Lock lock) { long id = LOCK_ID_GEN.incrementAndGet(); lockMap.put(id, lock); return id; } /** * Runs specified query. * * @param qry Query. * @return Query cursor. * @throws IgniteCheckedException On error. */ private PlatformQueryCursor runQuery(Query qry) throws IgniteCheckedException { try { QueryCursorEx cursor = (QueryCursorEx) cache.query(qry); return new PlatformQueryCursor(platformCtx, cursor, qry.getPageSize() > 0 ? qry.getPageSize(): Query.DFLT_PAGE_SIZE); } catch (Exception err) { throw PlatformUtils.unwrapQueryException(err); } } /** * Runs specified fields query. * * @param qry Query. * @return Query cursor. * @throws IgniteCheckedException On error. */ private PlatformFieldsQueryCursor runFieldsQuery(Query qry) throws IgniteCheckedException { try { QueryCursorEx cursor = (QueryCursorEx) cache.query(qry); return new PlatformFieldsQueryCursor(platformCtx, cursor, qry.getPageSize() > 0 ? qry.getPageSize() : Query.DFLT_PAGE_SIZE); } catch (Exception err) { throw PlatformUtils.unwrapQueryException(err); } } /** * Reads the query of specified type. * * @param reader Binary reader. * @return Query. * @throws IgniteCheckedException On error. */ private Query readInitialQuery(BinaryRawReaderEx reader) throws IgniteCheckedException { int typ = reader.readInt(); switch (typ) { case -1: return null; case OP_QRY_SCAN: return readScanQuery(reader); case OP_QRY_SQL: return readSqlQuery(reader); case OP_QRY_TXT: return readTextQuery(reader); } throw new IgniteCheckedException("Unsupported query type: " + typ); } /** * Reads sql query. * * @param reader Binary reader. * @return Query. */ private Query readSqlQuery(BinaryRawReaderEx reader) { boolean loc = reader.readBoolean(); String sql = reader.readString(); String typ = reader.readString(); final int pageSize = reader.readInt(); Object[] args = readQueryArgs(reader); boolean distrJoins = reader.readBoolean(); return new SqlQuery(typ, sql).setPageSize(pageSize).setArgs(args).setLocal(loc).setDistributedJoins(distrJoins); } /** * Reads fields query. * * @param reader Binary reader. * @return Query. */ private Query readFieldsQuery(BinaryRawReaderEx reader) { boolean loc = reader.readBoolean(); String sql = reader.readString(); final int pageSize = reader.readInt(); Object[] args = readQueryArgs(reader); boolean distrJoins = reader.readBoolean(); boolean enforceJoinOrder = reader.readBoolean(); return new SqlFieldsQuery(sql).setPageSize(pageSize).setArgs(args).setLocal(loc) .setDistributedJoins(distrJoins).setEnforceJoinOrder(enforceJoinOrder); } /** * Reads text query. * * @param reader Binary reader. * @return Query. */ private Query readTextQuery(BinaryRawReader reader) { boolean loc = reader.readBoolean(); String txt = reader.readString(); String typ = reader.readString(); final int pageSize = reader.readInt(); return new TextQuery(typ, txt).setPageSize(pageSize).setLocal(loc); } /** * Reads scan query. * * @param reader Binary reader. * @return Query. */ private Query readScanQuery(BinaryRawReaderEx reader) { boolean loc = reader.readBoolean(); final int pageSize = reader.readInt(); boolean hasPart = reader.readBoolean(); Integer part = hasPart ? reader.readInt() : null; ScanQuery qry = new ScanQuery().setPageSize(pageSize); qry.setPartition(part); Object pred = reader.readObjectDetached(); if (pred != null) qry.setFilter(platformCtx.createCacheEntryFilter(pred, 0)); qry.setLocal(loc); return qry; } /** * Clones this instance. * * @param cache Cache. * @param keepBinary Keep binary flag. * @return Cloned instance. */ private PlatformCache copy(IgniteCache cache, boolean keepBinary) { return new PlatformCache(platformCtx, cache, keepBinary, exts); } /** * Get extension by ID. * * @param id ID. * @return Extension. */ private PlatformCacheExtension extension(int id) { if (exts != null && id < exts.length) { PlatformCacheExtension ext = exts[id]; if (ext != null) return ext; } throw new IgniteException("Platform cache extension is not registered [id=" + id + ']'); } /** * Writes cache metrics. * * @param writer Writer. * @param metrics Metrics. */ public static void writeCacheMetrics(BinaryRawWriter writer, CacheMetrics metrics) { assert writer != null; assert metrics != null; writer.writeLong(metrics.getCacheHits()); writer.writeFloat(metrics.getCacheHitPercentage()); writer.writeLong(metrics.getCacheMisses()); writer.writeFloat(metrics.getCacheMissPercentage()); writer.writeLong(metrics.getCacheGets()); writer.writeLong(metrics.getCachePuts()); writer.writeLong(metrics.getCacheRemovals()); writer.writeLong(metrics.getCacheEvictions()); writer.writeFloat(metrics.getAverageGetTime()); writer.writeFloat(metrics.getAveragePutTime()); writer.writeFloat(metrics.getAverageRemoveTime()); writer.writeFloat(metrics.getAverageTxCommitTime()); writer.writeFloat(metrics.getAverageTxRollbackTime()); writer.writeLong(metrics.getCacheTxCommits()); writer.writeLong(metrics.getCacheTxRollbacks()); writer.writeString(metrics.name()); writer.writeLong(metrics.getOffHeapGets()); writer.writeLong(metrics.getOffHeapPuts()); writer.writeLong(metrics.getOffHeapRemovals()); writer.writeLong(metrics.getOffHeapEvictions()); writer.writeLong(metrics.getOffHeapHits()); writer.writeFloat(metrics.getOffHeapHitPercentage()); writer.writeLong(metrics.getOffHeapMisses()); writer.writeFloat(metrics.getOffHeapMissPercentage()); writer.writeLong(metrics.getOffHeapEntriesCount()); writer.writeLong(metrics.getOffHeapPrimaryEntriesCount()); writer.writeLong(metrics.getOffHeapBackupEntriesCount()); writer.writeLong(metrics.getOffHeapAllocatedSize()); writer.writeInt(metrics.getSize()); writer.writeInt(metrics.getKeySize()); writer.writeBoolean(metrics.isEmpty()); writer.writeInt(metrics.getDhtEvictQueueCurrentSize()); writer.writeInt(metrics.getTxThreadMapSize()); writer.writeInt(metrics.getTxXidMapSize()); writer.writeInt(metrics.getTxCommitQueueSize()); writer.writeInt(metrics.getTxPrepareQueueSize()); writer.writeInt(metrics.getTxStartVersionCountsSize()); writer.writeInt(metrics.getTxCommittedVersionsSize()); writer.writeInt(metrics.getTxRolledbackVersionsSize()); writer.writeInt(metrics.getTxDhtThreadMapSize()); writer.writeInt(metrics.getTxDhtXidMapSize()); writer.writeInt(metrics.getTxDhtCommitQueueSize()); writer.writeInt(metrics.getTxDhtPrepareQueueSize()); writer.writeInt(metrics.getTxDhtStartVersionCountsSize()); writer.writeInt(metrics.getTxDhtCommittedVersionsSize()); writer.writeInt(metrics.getTxDhtRolledbackVersionsSize()); writer.writeBoolean(metrics.isWriteBehindEnabled()); writer.writeInt(metrics.getWriteBehindFlushSize()); writer.writeInt(metrics.getWriteBehindFlushThreadCount()); writer.writeLong(metrics.getWriteBehindFlushFrequency()); writer.writeInt(metrics.getWriteBehindStoreBatchSize()); writer.writeInt(metrics.getWriteBehindTotalCriticalOverflowCount()); writer.writeInt(metrics.getWriteBehindCriticalOverflowCount()); writer.writeInt(metrics.getWriteBehindErrorRetryCount()); writer.writeInt(metrics.getWriteBehindBufferSize()); writer.writeString(metrics.getKeyType()); writer.writeString(metrics.getValueType()); writer.writeBoolean(metrics.isStoreByValue()); writer.writeBoolean(metrics.isStatisticsEnabled()); writer.writeBoolean(metrics.isManagementEnabled()); writer.writeBoolean(metrics.isReadThrough()); writer.writeBoolean(metrics.isWriteThrough()); } /** * Writes error with EntryProcessorException cause. */ private static class GetAllWriter implements PlatformFutureUtils.Writer { /** <inheritDoc /> */ @Override public void write(BinaryRawWriterEx writer, Object obj, Throwable err) { assert obj instanceof Map; PlatformUtils.writeNullableMap(writer, (Map) obj); } /** <inheritDoc /> */ @Override public boolean canWrite(Object obj, Throwable err) { return err == null; } } /** * Writes error with EntryProcessorException cause. */ private static class EntryProcessorInvokeWriter implements PlatformFutureUtils.Writer { /** <inheritDoc /> */ @Override public void write(BinaryRawWriterEx writer, Object obj, Throwable err) { if (err == null) { writer.writeBoolean(false); // No error. writer.writeObjectDetached(obj); } else { writer.writeBoolean(true); // Error. PlatformUtils.writeError(err, writer); } } /** <inheritDoc /> */ @Override public boolean canWrite(Object obj, Throwable err) { return true; } } /** * Writes results of InvokeAll method. */ private static class EntryProcessorInvokeAllWriter implements PlatformFutureUtils.Writer { /** <inheritDoc /> */ @Override public void write(BinaryRawWriterEx writer, Object obj, Throwable err) { writeInvokeAllResult(writer, (Map)obj); } /** <inheritDoc /> */ @Override public boolean canWrite(Object obj, Throwable err) { return obj != null && err == null; } } /** * Listenable around CompletionListener. */ private static class CompletionListenable implements PlatformListenable, CompletionListener { /** */ private IgniteBiInClosure<Object, Throwable> lsnr; /** {@inheritDoc} */ @Override public void onCompletion() { assert lsnr != null; lsnr.apply(null, null); } /** {@inheritDoc} */ @Override public void onException(Exception e) { lsnr.apply(null, e); } /** {@inheritDoc} */ @Override public void listen(IgniteBiInClosure<Object, Throwable> lsnr) { this.lsnr = lsnr; } /** {@inheritDoc} */ @Override public boolean cancel() throws IgniteCheckedException { return false; } /** {@inheritDoc} */ @Override public boolean isCancelled() { return false; } } }