/* * 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.InvalidObjectException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import javax.cache.Cache; import javax.cache.configuration.Factory; import javax.cache.expiry.EternalExpiryPolicy; import javax.cache.expiry.ExpiryPolicy; import javax.cache.processor.EntryProcessorResult; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.cache.CacheInterceptor; import org.apache.ignite.cache.CacheMode; import org.apache.ignite.cache.affinity.AffinityKeyMapper; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.IgniteKernal; import org.apache.ignite.internal.IgnitionEx; import org.apache.ignite.internal.binary.BinaryMarshaller; import org.apache.ignite.internal.managers.communication.GridIoManager; import org.apache.ignite.internal.managers.deployment.GridDeploymentManager; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager; import org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.database.MemoryPolicy; import org.apache.ignite.internal.processors.cache.database.freelist.FreeList; import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList; import org.apache.ignite.internal.processors.cache.datastructures.CacheDataStructuresManager; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheAdapter; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTransactionalCacheAdapter; import org.apache.ignite.internal.processors.cache.distributed.dht.colocated.GridDhtColocatedCache; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheAdapter; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTransactionalCache; import org.apache.ignite.internal.processors.cache.dr.GridCacheDrManager; import org.apache.ignite.internal.processors.cache.jta.CacheJtaManagerAdapter; import org.apache.ignite.internal.processors.cache.local.GridLocalCache; import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager; import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryManager; import org.apache.ignite.internal.processors.cache.store.CacheStoreManager; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxManager; import org.apache.ignite.internal.processors.cache.version.CacheVersionConflictResolver; import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; import org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext; import org.apache.ignite.internal.processors.cache.version.GridCacheVersionManager; import org.apache.ignite.internal.processors.cache.version.GridCacheVersionedEntryEx; import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor; import org.apache.ignite.internal.processors.closure.GridClosureProcessor; import org.apache.ignite.internal.processors.plugin.CachePluginManager; import org.apache.ignite.internal.processors.query.QueryUtils; import org.apache.ignite.internal.processors.timeout.GridTimeoutProcessor; import org.apache.ignite.internal.util.F0; import org.apache.ignite.internal.util.lang.GridFunc; import org.apache.ignite.internal.util.tostring.GridToStringExclude; import org.apache.ignite.internal.util.typedef.C1; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.internal.util.typedef.internal.CU; import org.apache.ignite.internal.util.typedef.internal.GPC; import org.apache.ignite.internal.util.typedef.internal.GPR; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteBiTuple; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.lang.IgniteUuid; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.plugin.security.SecurityException; import org.apache.ignite.plugin.security.SecurityPermission; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC; import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL; import static org.apache.ignite.cache.CacheRebalanceMode.NONE; import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC; import static org.apache.ignite.cache.CacheWriteSynchronizationMode.PRIMARY_SYNC; import static org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionState.OWNING; /** * Cache context. */ @GridToStringExclude public class GridCacheContext<K, V> implements Externalizable { /** */ private static final long serialVersionUID = 0L; /** Deserialization stash. */ private static final ThreadLocal<IgniteBiTuple<String, String>> stash = new ThreadLocal<IgniteBiTuple<String, String>>() { @Override protected IgniteBiTuple<String, String> initialValue() { return new IgniteBiTuple<>(); } }; /** Empty cache version array. */ private static final GridCacheVersion[] EMPTY_VERSION = new GridCacheVersion[0]; /** Kernal context. */ private GridKernalContext ctx; /** Cache shared context. */ private GridCacheSharedContext<K, V> sharedCtx; /** Memory policy. */ private MemoryPolicy memPlc; /** FreeList instance this cache is associated with. */ private FreeList freeList; /** ReuseList instance this cache is associated with */ private ReuseList reuseList; /** Logger. */ private IgniteLogger log; /** Cache configuration. */ private CacheConfiguration cacheCfg; /** Affinity manager. */ private GridCacheAffinityManager affMgr; /** Event manager. */ private GridCacheEventManager evtMgr; /** Query manager. */ private GridCacheQueryManager<K, V> qryMgr; /** Continuous query manager. */ private CacheContinuousQueryManager contQryMgr; /** Evictions manager. */ private CacheEvictionManager evictMgr; /** Data structures manager. */ private CacheDataStructuresManager dataStructuresMgr; /** Eager TTL manager. */ private GridCacheTtlManager ttlMgr; /** Store manager. */ private CacheStoreManager storeMgr; /** Replication manager. */ private GridCacheDrManager drMgr; /** */ private IgniteCacheOffheapManager offheapMgr; /** Conflict resolver manager. */ private CacheConflictResolutionManager rslvrMgr; /** Cache plugin manager. */ private CachePluginManager pluginMgr; /** Managers. */ private List<GridCacheManager<K, V>> mgrs = new LinkedList<>(); /** Cache gateway. */ private GridCacheGateway<K, V> gate; /** Grid cache. */ private GridCacheAdapter<K, V> cache; /** Cached local rich node. */ private ClusterNode locNode; /** * Thread local operation context. If it's set it means that method call was initiated * by child cache of initial cache. */ private ThreadLocal<CacheOperationContext> opCtxPerCall = new ThreadLocal<>(); /** Cache name. */ private String cacheName; /** Cache ID. */ private int cacheId; /** Cache type. */ private CacheType cacheType; /** IO policy. */ private byte plc; /** Default expiry policy. */ private ExpiryPolicy expiryPlc; /** Cache weak query iterator holder. */ private CacheWeakQueryIteratorsHolder<Map.Entry<K, V>> itHolder; /** Affinity node. */ private boolean affNode; /** Conflict resolver. */ private CacheVersionConflictResolver conflictRslvr; /** */ private CacheObjectContext cacheObjCtx; /** */ private CountDownLatch startLatch = new CountDownLatch(1); /** Start topology version. */ private AffinityTopologyVersion startTopVer; /** Dynamic cache deployment ID. */ private IgniteUuid dynamicDeploymentId; /** Updates allowed flag. */ private boolean updatesAllowed; /** Flag indicating that this cache is in a recovery mode. */ private boolean needsRecovery; /** Deployment enabled flag for this specific cache */ private boolean depEnabled; /** */ private boolean deferredDel; /** */ private boolean customAffMapper; /** * Empty constructor required for {@link Externalizable}. */ public GridCacheContext() { // No-op. } /** * @param ctx Kernal context. * @param sharedCtx Cache shared context. * @param cacheCfg Cache configuration. * @param cacheType Cache type. * @param memPlc MemoryPolicy instance. * @param freeList FreeList instance. * @param affNode {@code True} if local node is affinity node. * @param updatesAllowed Updates allowed flag. * @param evtMgr Cache event manager. * @param storeMgr Store manager. * @param evictMgr Cache eviction manager. * @param qryMgr Cache query manager. * @param contQryMgr Continuous query manager. * @param affMgr Affinity manager. * @param dataStructuresMgr Cache dataStructures manager. * @param ttlMgr TTL manager. * @param drMgr Data center replication manager. * @param rslvrMgr Conflict resolution manager. * @param pluginMgr Cache plugin manager. */ @SuppressWarnings({"unchecked"}) public GridCacheContext( GridKernalContext ctx, GridCacheSharedContext sharedCtx, CacheConfiguration cacheCfg, CacheType cacheType, boolean affNode, boolean updatesAllowed, MemoryPolicy memPlc, FreeList freeList, ReuseList reuseList, /* * Managers in starting order! * =========================== */ GridCacheEventManager evtMgr, CacheStoreManager storeMgr, CacheEvictionManager evictMgr, GridCacheQueryManager<K, V> qryMgr, CacheContinuousQueryManager contQryMgr, CacheDataStructuresManager dataStructuresMgr, GridCacheTtlManager ttlMgr, GridCacheDrManager drMgr, IgniteCacheOffheapManager offheapMgr, CacheConflictResolutionManager<K, V> rslvrMgr, CachePluginManager pluginMgr, GridCacheAffinityManager affMgr ) { assert ctx != null; assert sharedCtx != null; assert cacheCfg != null; assert evtMgr != null; assert storeMgr != null; assert evictMgr != null; assert qryMgr != null; assert contQryMgr != null; assert affMgr != null; assert dataStructuresMgr != null; assert ttlMgr != null; assert rslvrMgr != null; assert pluginMgr != null; assert offheapMgr != null; this.ctx = ctx; this.sharedCtx = sharedCtx; this.cacheCfg = cacheCfg; this.cacheType = cacheType; this.affNode = affNode; this.updatesAllowed = updatesAllowed; this.depEnabled = ctx.deploy().enabled() && !cacheObjects().isBinaryEnabled(cacheCfg); this.memPlc = memPlc; this.freeList = freeList; this.reuseList = reuseList; /* * Managers in starting order! * =========================== */ this.evtMgr = add(evtMgr); this.storeMgr = add(storeMgr); this.evictMgr = add(evictMgr); this.qryMgr = add(qryMgr); this.contQryMgr = add(contQryMgr); this.dataStructuresMgr = add(dataStructuresMgr); this.ttlMgr = add(ttlMgr); this.drMgr = add(drMgr); this.offheapMgr = add(offheapMgr); this.rslvrMgr = add(rslvrMgr); this.pluginMgr = add(pluginMgr); this.affMgr = add(affMgr); log = ctx.log(getClass()); gate = new GridCacheGateway<>(this); cacheName = cacheCfg.getName(); cacheId = CU.cacheId(cacheName); plc = cacheType.ioPolicy(); Factory<ExpiryPolicy> factory = cacheCfg.getExpiryPolicyFactory(); expiryPlc = factory != null ? factory.create() : null; if (expiryPlc instanceof EternalExpiryPolicy) expiryPlc = null; itHolder = new CacheWeakQueryIteratorsHolder(log); } /** * @return {@code True} if custom {@link AffinityKeyMapper} is configured for cache. */ public boolean customAffinityMapper() { return customAffMapper; } /** * @param dynamicDeploymentId Dynamic deployment ID. */ void dynamicDeploymentId(IgniteUuid dynamicDeploymentId) { this.dynamicDeploymentId = dynamicDeploymentId; } /** * @return Dynamic deployment ID. */ public IgniteUuid dynamicDeploymentId() { return dynamicDeploymentId; } /** * Initialize conflict resolver after all managers are started. */ void initConflictResolver() { conflictRslvr = rslvrMgr.conflictResolver(); } /** * @return {@code True} if local node is affinity node. */ public boolean affinityNode() { return affNode; } /** * @return {@code true} If this is a replicated cache and we are on a data node. */ public boolean isReplicatedAffinityNode() { return isReplicated() && affinityNode(); } /** * @throws IgniteCheckedException If failed to wait. */ public void awaitStarted() throws IgniteCheckedException { U.await(startLatch); GridCachePreloader prldr = preloader(); if (prldr != null) prldr.startFuture().get(); } /** * @return Started flag. */ public boolean started() { if (startLatch.getCount() != 0) return false; GridCachePreloader prldr = preloader(); return prldr == null || prldr.startFuture().isDone(); } /** * */ public void onStarted() { startLatch.countDown(); } /** * @return Start topology version. */ public AffinityTopologyVersion startTopologyVersion() { return startTopVer; } /** * @param startTopVer Start topology version. */ public void startTopologyVersion(AffinityTopologyVersion startTopVer) { this.startTopVer = startTopVer; } /** * @return Cache default {@link ExpiryPolicy}. */ @Nullable public ExpiryPolicy expiry() { return expiryPlc; } /** * @param txEntry TX entry. * @return Expiry policy for the given TX entry. */ @Nullable public ExpiryPolicy expiryForTxEntry(IgniteTxEntry txEntry) { ExpiryPolicy plc = txEntry.expiry(); return plc != null ? plc : expiryPlc; } /** * @param mgr Manager to add. * @return Added manager. */ @Nullable private <T extends GridCacheManager<K, V>> T add(@Nullable T mgr) { if (mgr != null) mgrs.add(mgr); return mgr; } /** * @return Cache managers. */ public List<GridCacheManager<K, V>> managers() { return mgrs; } /** * @return Shared cache context. */ public GridCacheSharedContext<K, V> shared() { return sharedCtx; } /** * @return Cache ID. */ public int cacheId() { return cacheId; } /** * @return {@code True} if should use system transactions which are isolated from user transactions. */ public boolean systemTx() { return cacheType == CacheType.UTILITY || (cacheType == CacheType.INTERNAL && transactional()); } /** * @return {@code True} if cache created by user. */ public boolean userCache() { return cacheType.userCache(); } /** * @return IO policy for the given cache. */ public byte ioPolicy() { return plc; } /** * @param cache Cache. */ public void cache(GridCacheAdapter<K, V> cache) { this.cache = cache; deferredDel = cache.isDht() || cache.isDhtAtomic() || cache.isColocated() || (cache.isNear() && cache.configuration().getAtomicityMode() == ATOMIC); } /** * @return Local cache. */ public GridLocalCache<K, V> local() { return (GridLocalCache<K, V>)cache; } /** * @return {@code True} if cache is DHT. */ public boolean isDht() { return cache != null && cache.isDht(); } /** * @return {@code True} if cache is DHT atomic. */ public boolean isDhtAtomic() { return cache != null && cache.isDhtAtomic(); } /** * @return {@code True} if cache is colocated (dht with near disabled). */ public boolean isColocated() { return cache != null && cache.isColocated(); } /** * @return {@code True} if cache is near cache. */ public boolean isNear() { return cache != null && cache.isNear(); } /** * @return {@code True} if cache is local. */ public boolean isLocal() { return cache != null && cache.isLocal(); } /** * @return {@code True} if cache is replicated cache. */ public boolean isReplicated() { return cacheCfg.getCacheMode() == CacheMode.REPLICATED; } /** * @return {@code True} if cache is partitioned cache. */ public boolean isPartitioned() { return cacheCfg.getCacheMode() == CacheMode.PARTITIONED; } /** * @return {@code True} in case replication is enabled. */ public boolean isDrEnabled() { return dr().enabled(); } /** * @return {@code True} if entries should not be deleted from cache immediately. */ public boolean deferredDelete() { return deferredDel; } /** * @param e Entry. */ public void incrementPublicSize(GridCacheMapEntry e) { assert deferredDelete(); assert e != null; assert !e.isInternal() : e; cache.incrementSize(e); } /** * @param e Entry. */ public void decrementPublicSize(GridCacheMapEntry e) { assert deferredDelete(); assert e != null; assert !e.isInternal() : e; cache.decrementSize(e); } /** * @return DHT cache. */ public GridDhtCacheAdapter<K, V> dht() { return (GridDhtCacheAdapter<K, V>)cache; } /** * @return Transactional DHT cache. */ public GridDhtTransactionalCacheAdapter<K, V> dhtTx() { return (GridDhtTransactionalCacheAdapter<K, V>)cache; } /** * @return Colocated cache. */ public GridDhtColocatedCache<K, V> colocated() { return (GridDhtColocatedCache<K, V>)cache; } /** * @return Near cache. */ public GridNearCacheAdapter<K, V> near() { return (GridNearCacheAdapter<K, V>)cache; } /** * @return Near cache for transactional mode. */ public GridNearTransactionalCache<K, V> nearTx() { return (GridNearTransactionalCache<K, V>)cache; } /** * @return Cache gateway. */ public GridCacheGateway<K, V> gate() { return gate; } /** * @return Kernal context. */ public GridKernalContext kernalContext() { return ctx; } /** * @return Grid instance. */ public IgniteEx grid() { return ctx.grid(); } /** * @return Ignite instance name. */ public String igniteInstanceName() { return ctx.igniteInstanceName(); } /** * @return Cache name. */ public String name() { return cacheName; } /** * @return Memory policy. */ public MemoryPolicy memoryPolicy() { return memPlc; } /** * @return Free List. */ public FreeList freeList() { return freeList; } /** * @return Reuse List. */ public ReuseList reuseList() { return reuseList; } /** * Gets public name for cache. * * @return Public name of the cache. */ public String namex() { return isDht() ? dht().near().name() : name(); } /** * Gets public cache name substituting null name by {@code 'default'}. * * @return Public cache name substituting null name by {@code 'default'}. */ public String namexx() { String name = namex(); return name == null ? "default" : name; } /** * @param key Key to construct tx key for. * @return Transaction key. */ public IgniteTxKey txKey(KeyCacheObject key) { return new IgniteTxKey(key, cacheId); } /** * @param op Operation to check. * @throws SecurityException If security check failed. */ public void checkSecurity(SecurityPermission op) throws SecurityException { if (CU.isSystemCache(name())) return; ctx.security().authorize(name(), op, null); } /** * @return Preloader. */ public GridCachePreloader preloader() { return cache().preloader(); } /** * @return Local node ID. */ public UUID nodeId() { return ctx.localNodeId(); } /** * @return {@code True} if rebalance is enabled. */ public boolean rebalanceEnabled() { return cacheCfg.getRebalanceMode() != NONE; } /** * @return {@code True} if atomic. */ public boolean atomic() { return cacheCfg.getAtomicityMode() == ATOMIC; } /** * @return {@code True} if transactional. */ public boolean transactional() { return cacheCfg.getAtomicityMode() == TRANSACTIONAL; } /** * @return Local node. */ public ClusterNode localNode() { if (locNode == null) locNode = ctx.discovery().localNode(); return locNode; } /** * @return Local node ID. */ public UUID localNodeId() { return ctx.localNodeId(); } /** * @param n Node to check. * @return {@code True} if node is local. */ public boolean isLocalNode(ClusterNode n) { assert n != null; return localNode().id().equals(n.id()); } /** * @param id Node ID to check. * @return {@code True} if node ID is local. */ public boolean isLocalNode(UUID id) { assert id != null; return localNode().id().equals(id); } /** * @param nodeId Node id. * @return Node. */ @Nullable public ClusterNode node(UUID nodeId) { assert nodeId != null; return ctx.discovery().node(nodeId); } /** * @return Partition topology. */ public GridDhtPartitionTopology topology() { GridCacheAdapter<K, V> cache = this.cache; if (cache == null) throw new IllegalStateException("Cache stopped: " + cacheName); assert cache.isNear() || cache.isDht() || cache.isColocated() || cache.isDhtAtomic() : cache; return topology(cache); } /** * @return Topology version future. */ public GridDhtTopologyFuture topologyVersionFuture() { GridCacheAdapter<K, V> cache = this.cache; if (cache == null) throw new IllegalStateException("Cache stopped: " + cacheName); assert cache.isNear() || cache.isDht() || cache.isColocated() || cache.isDhtAtomic() : cache; return topology(cache).topologyVersionFuture(); } /** * @param cache Cache. * @return Partition topology. */ private GridDhtPartitionTopology topology(GridCacheAdapter<K, V> cache) { return cache.isNear() ? ((GridNearCacheAdapter<K, V>)cache).dht().topology() : ((GridDhtCacheAdapter<K, V>)cache).topology(); } /** * @return Marshaller. */ public Marshaller marshaller() { return ctx.config().getMarshaller(); } /** * @param ctgr Category to log. * @return Logger. */ public IgniteLogger logger(String ctgr) { return new GridCacheLogger(this, ctgr); } /** * @param cls Class to log. * @return Logger. */ public IgniteLogger logger(Class<?> cls) { return logger(cls.getName()); } /** * @return Grid configuration. */ public IgniteConfiguration gridConfig() { return ctx.config(); } /** * @return Grid communication manager. */ public GridIoManager gridIO() { return ctx.io(); } /** * @return Grid timeout processor. */ public GridTimeoutProcessor time() { return ctx.timeout(); } /** * @return Grid deployment manager. */ public GridDeploymentManager gridDeploy() { return ctx.deploy(); } /** * @return Grid event storage manager. */ public GridEventStorageManager gridEvents() { return ctx.event(); } /** * @return Closures processor. */ public GridClosureProcessor closures() { return ctx.closure(); } /** * @return Grid discovery manager. */ public GridDiscoveryManager discovery() { return ctx.discovery(); } /** * @return Cache instance. */ public GridCacheAdapter<K, V> cache() { return cache; } /** * @return Cache configuration for given cache instance. */ public CacheConfiguration config() { return cacheCfg; } /** * @return {@code True} If store writes should be performed from dht transactions. This happens if both * {@code writeBehindEnabled} and {@code writeBehindPreferPrimary} cache configuration properties * are set to {@code true} or the store is local. */ public boolean writeToStoreFromDht() { return store().isLocal() || cacheCfg.isWriteBehindEnabled(); } /** * @return Cache transaction manager. */ public IgniteTxManager tm() { return sharedCtx.tm(); } /** * @return Lock order manager. */ public GridCacheVersionManager versions() { return sharedCtx.versions(); } /** * @return Lock manager. */ public GridCacheMvccManager mvcc() { return sharedCtx.mvcc(); } /** * @return Event manager. */ public GridCacheEventManager events() { return evtMgr; } /** * @return Cache affinity manager. */ public GridCacheAffinityManager affinity() { return affMgr; } /** * @return Query manager, {@code null} if disabled. */ public GridCacheQueryManager<K, V> queries() { return qryMgr; } /** * @return Continuous query manager, {@code null} if disabled. */ public CacheContinuousQueryManager continuousQueries() { return contQryMgr; } /** * @return Iterators Holder. */ public CacheWeakQueryIteratorsHolder<Map.Entry<K, V>> itHolder() { return itHolder; } /** * @return Store manager. */ public CacheStoreManager store() { return storeMgr; } /** * @return Cache deployment manager. */ public GridCacheDeploymentManager<K, V> deploy() { return sharedCtx.deploy(); } /** * @return Cache communication manager. */ public GridCacheIoManager io() { return sharedCtx.io(); } /** * @return Eviction manager. */ public CacheEvictionManager evicts() { return evictMgr; } /** * @return Data structures manager. */ public CacheDataStructuresManager dataStructures() { return dataStructuresMgr; } /** * @return DR manager. */ public GridCacheDrManager dr() { return drMgr; } /** * @return Offheap manager. */ public IgniteCacheOffheapManager offheap() { return offheapMgr; } /** * @return TTL manager. */ public GridCacheTtlManager ttl() { return ttlMgr; } /** * @return JTA manager. */ public CacheJtaManagerAdapter jta() { return sharedCtx.jta(); } /** * @return Cache plugin manager. */ public CachePluginManager plugin() { return pluginMgr; } /** * @param p Predicate. * @return {@code True} if given predicate is filter for {@code putIfAbsent} operation. */ public boolean putIfAbsentFilter(@Nullable CacheEntryPredicate[] p) { if (p == null || p.length == 0) return false; for (CacheEntryPredicate p0 : p) { if ((p0 instanceof CacheEntrySerializablePredicate) && ((CacheEntrySerializablePredicate)p0).predicate() instanceof CacheEntryPredicateNoValue) return true; } return false; } /** * @return No value filter. */ public CacheEntryPredicate noVal() { return new CacheEntrySerializablePredicate(new CacheEntryPredicateNoValue()); } /** * @return Has value filter. */ public CacheEntryPredicate hasVal() { return new CacheEntrySerializablePredicate(new CacheEntryPredicateHasValue()); } /** * @param val Value to check. * @return Predicate that checks for value. */ public CacheEntryPredicate equalsVal(V val) { return new CacheEntryPredicateContainsValue(toCacheObject(val)); } /** * @return Empty cache version array. */ public GridCacheVersion[] emptyVersion() { return EMPTY_VERSION; } /** * @return Default affinity key mapper. */ public AffinityKeyMapper defaultAffMapper() { return cacheObjCtx.defaultAffMapper(); } /** * Sets cache object context. * * @param cacheObjCtx Cache object context. */ public void cacheObjectContext(CacheObjectContext cacheObjCtx) { this.cacheObjCtx = cacheObjCtx; customAffMapper = cacheCfg.getAffinityMapper().getClass() != cacheObjCtx.defaultAffMapper().getClass(); } /** * @param p Single predicate. * @return Array containing single predicate. */ @SuppressWarnings({"unchecked"}) public IgnitePredicate<Cache.Entry<K, V>>[] vararg(IgnitePredicate<Cache.Entry<K, V>> p) { return p == null ? CU.<K, V>empty() : new IgnitePredicate[] {p}; } /** * Same as {@link GridFunc#isAll(Object, IgnitePredicate[])}, but safely unwraps exceptions. * * @param e Element. * @param p Predicates. * @return {@code True} if predicates passed. * @throws IgniteCheckedException If failed. */ public <K1, V1> boolean isAll( GridCacheEntryEx e, @Nullable IgnitePredicate<Cache.Entry<K1, V1>>[] p ) throws IgniteCheckedException { return F.isEmpty(p) || isAll(e.<K1, V1>wrapLazyValue(keepBinary()), p); } /** * Same as {@link GridFunc#isAll(Object, IgnitePredicate[])}, but safely unwraps exceptions. * * @param e Element. * @param p Predicates. * @param <E> Element type. * @return {@code True} if predicates passed. * @throws IgniteCheckedException If failed. */ @SuppressWarnings({"ErrorNotRethrown"}) public <E> boolean isAll(E e, @Nullable IgnitePredicate<? super E>[] p) throws IgniteCheckedException { if (F.isEmpty(p)) return true; try { boolean pass = F.isAll(e, p); if (log.isDebugEnabled()) log.debug("Evaluated filters for entry [pass=" + pass + ", entry=" + e + ", filters=" + Arrays.toString(p) + ']'); return pass; } catch (RuntimeException ex) { throw U.cast(ex); } } /** * @param e Entry. * @param p Predicates. * @return {@code True} if predicates passed. * @throws IgniteCheckedException If failed. */ public boolean isAll(GridCacheEntryEx e, CacheEntryPredicate[] p) throws IgniteCheckedException { if (p == null || p.length == 0) return true; try { for (CacheEntryPredicate p0 : p) { if (p0 != null && !p0.apply(e)) return false; } } catch (RuntimeException ex) { throw U.cast(ex); } return true; } /** * @param e Entry. * @param p Predicates. * @return {@code True} if predicates passed. * @throws IgniteCheckedException If failed. */ public boolean isAllLocked(GridCacheEntryEx e, CacheEntryPredicate[] p) throws IgniteCheckedException { if (p == null || p.length == 0) return true; try { for (CacheEntryPredicate p0 : p) { if (p0 != null) { p0.entryLocked(true); if (!p0.apply(e)) return false; } } } catch (RuntimeException ex) { throw U.cast(ex); } finally { for (CacheEntryPredicate p0 : p) { if (p0 != null) p0.entryLocked(false); } } return true; } /** * Sets thread local cache operation context. * * @param opCtx Operation context. */ public void operationContextPerCall(@Nullable CacheOperationContext opCtx) { if (nearContext()) dht().near().context().opCtxPerCall.set(opCtx); else opCtxPerCall.set(opCtx); } /** * Gets thread local cache operation context. * * @return Operation context per call. */ public CacheOperationContext operationContextPerCall() { return nearContext() ? dht().near().context().opCtxPerCall.get() : opCtxPerCall.get(); } /** * Gets subject ID per call. * * @param subjId Optional already existing subject ID. * @return Subject ID per call. */ public UUID subjectIdPerCall(@Nullable UUID subjId) { if (subjId != null) return subjId; return subjectIdPerCall(subjId, operationContextPerCall()); } /** * Gets subject ID per call. * * @param subjId Optional already existing subject ID. * @param opCtx Optional thread local operation context. * @return Subject ID per call. */ public UUID subjectIdPerCall(@Nullable UUID subjId, @Nullable CacheOperationContext opCtx) { if (opCtx != null) subjId = opCtx.subjectId(); if (subjId == null) subjId = ctx.localNodeId(); return subjId; } /** * @return {@code true} if the skip store flag is set. */ public boolean skipStore() { if (nearContext()) return dht().near().context().skipStore(); CacheOperationContext opCtx = opCtxPerCall.get(); return (opCtx != null && opCtx.skipStore()); } /** * @return {@code True} if need check near cache context. */ private boolean nearContext() { return isDht() || (isDhtAtomic() && dht().near() != null); } /** * Creates Runnable that can be executed safely in a different thread inheriting * the same thread local projection as for the current thread. If no projection is * set for current thread then there's no need to create new object and method simply * returns given Runnable. * * @param r Runnable. * @return Runnable that can be executed in a different thread with the same * projection as for current thread. */ public Runnable projectSafe(final Runnable r) { assert r != null; // Have to get operation context per call used by calling thread to use it in a new thread. final CacheOperationContext opCtx = operationContextPerCall(); if (opCtx == null) return r; return new GPR() { @Override public void run() { CacheOperationContext old = operationContextPerCall(); operationContextPerCall(opCtx); try { r.run(); } finally { operationContextPerCall(old); } } }; } /** * Creates callable that can be executed safely in a different thread inheriting * the same thread local projection as for the current thread. If no projection is * set for current thread then there's no need to create new object and method simply * returns given callable. * * @param r Callable. * @return Callable that can be executed in a different thread with the same * projection as for current thread. */ public <T> Callable<T> projectSafe(final Callable<T> r) { assert r != null; // Have to get operation context per call used by calling thread to use it in a new thread. final CacheOperationContext opCtx = operationContextPerCall(); if (opCtx == null) return r; return new GPC<T>() { @Override public T call() throws Exception { CacheOperationContext old = operationContextPerCall(); operationContextPerCall(opCtx); try { return r.call(); } finally { operationContextPerCall(old); } } }; } /** * @return {@code True} if deployment is enabled. */ public boolean deploymentEnabled() { return depEnabled; } /** * @return {@code True} if should use offheap (PageMemory) index. */ public boolean offheapIndex() { // TODO GG-10884. return true; } /** * @return {@code True} if store read-through mode is enabled. */ public boolean readThrough() { return cacheCfg.isReadThrough() && !skipStore(); } /** * @return {@code True} if store and read-through mode are enabled in configuration. */ public boolean readThroughConfigured() { return store().configured() && cacheCfg.isReadThrough(); } /** * @return {@code True} if {@link CacheConfiguration#isLoadPreviousValue()} flag is set. */ public boolean loadPreviousValue() { return cacheCfg.isLoadPreviousValue(); } /** * @return {@code True} if store write-through is enabled. */ public boolean writeThrough() { return cacheCfg.isWriteThrough() && !skipStore(); } /** * @return {@code True} if invalidation is enabled. */ public boolean isInvalidate() { return cacheCfg.isInvalidate(); } /** * @return {@code True} if synchronous commit is enabled. */ public boolean syncCommit() { return cacheCfg.getWriteSynchronizationMode() == FULL_SYNC; } /** * @return {@code True} if synchronous rollback is enabled. */ public boolean syncRollback() { return cacheCfg.getWriteSynchronizationMode() == FULL_SYNC; } /** * @return {@code True} if only primary node should be updated synchronously. */ public boolean syncPrimary() { return cacheCfg.getWriteSynchronizationMode() == PRIMARY_SYNC; } /** * @param nearNodeId Near node ID. * @param topVer Topology version. * @param entry Entry. * @param log Log. * @param dhtMap Dht mappings. * @param nearMap Near mappings. * @throws GridCacheEntryRemovedException If reader for entry is removed. */ public void dhtMap( UUID nearNodeId, AffinityTopologyVersion topVer, GridDhtCacheEntry entry, GridCacheVersion explicitLockVer, IgniteLogger log, Map<ClusterNode, List<GridDhtCacheEntry>> dhtMap, @Nullable Map<ClusterNode, List<GridDhtCacheEntry>> nearMap ) throws GridCacheEntryRemovedException { assert !AffinityTopologyVersion.NONE.equals(topVer); Collection<ClusterNode> dhtNodes = dht().topology().nodes(entry.partition(), topVer); if (log.isDebugEnabled()) log.debug("Mapping entry to DHT nodes [nodes=" + U.nodeIds(dhtNodes) + ", entry=" + entry + ']'); Collection<ClusterNode> dhtRemoteNodes = F.view(dhtNodes, F.remoteNodes(nodeId())); // Exclude local node. map(entry, dhtRemoteNodes, dhtMap); Collection<ClusterNode> nearRemoteNodes = null; if (nearMap != null) { Collection<UUID> readers = entry.readers(); Collection<ClusterNode> nearNodes = null; if (!F.isEmpty(readers)) { nearNodes = discovery().nodes(readers, F0.notEqualTo(nearNodeId)); if (log.isDebugEnabled()) log.debug("Mapping entry to near nodes [nodes=" + U.nodeIds(nearNodes) + ", entry=" + entry + ']'); } else if (log.isDebugEnabled()) log.debug("Entry has no near readers: " + entry); if (nearNodes != null && !nearNodes.isEmpty()) { nearRemoteNodes = F.view(nearNodes, F.notIn(dhtNodes)); map(entry, nearRemoteNodes, nearMap); } } if (explicitLockVer != null) { Collection<ClusterNode> dhtNodeIds = new ArrayList<>(dhtRemoteNodes); Collection<ClusterNode> nearNodeIds = F.isEmpty(nearRemoteNodes) ? null : new ArrayList<>(nearRemoteNodes); entry.mappings(explicitLockVer, dhtNodeIds, nearNodeIds); } } /** * @param entry Entry. * @param log Log. * @param dhtMap Dht mappings. * @param nearMap Near mappings. * @throws GridCacheEntryRemovedException If reader for entry is removed. */ public void dhtMap( GridDhtCacheEntry entry, GridCacheVersion explicitLockVer, IgniteLogger log, Map<ClusterNode, List<GridDhtCacheEntry>> dhtMap, Map<ClusterNode, List<GridDhtCacheEntry>> nearMap ) throws GridCacheEntryRemovedException { assert explicitLockVer != null; GridCacheMvccCandidate cand = entry.candidate(explicitLockVer); if (cand != null) { Collection<ClusterNode> dhtNodes = cand.mappedDhtNodes(); if (log.isDebugEnabled()) log.debug("Mapping explicit lock to DHT nodes [nodes=" + U.nodeIds(dhtNodes) + ", entry=" + entry + ']'); Collection<ClusterNode> nearNodes = cand.mappedNearNodes(); map(entry, dhtNodes, dhtMap); if (nearNodes != null && !nearNodes.isEmpty()) map(entry, nearNodes, nearMap); } } /** * @param entry Entry. * @param nodes Nodes. * @param map Map. */ private void map(GridDhtCacheEntry entry, Iterable<ClusterNode> nodes, Map<ClusterNode, List<GridDhtCacheEntry>> map) { if (nodes != null) { for (ClusterNode n : nodes) { List<GridDhtCacheEntry> entries = map.get(n); if (entries == null) map.put(n, entries = new LinkedList<>()); entries.add(entry); } } } /** * Check whether conflict resolution is required. * * @return {@code True} in case DR is required. */ public boolean conflictNeedResolve() { return conflictRslvr != null; } /** * Resolve DR conflict. * * @param oldEntry Old entry. * @param newEntry New entry. * @param atomicVerComp Whether to use atomic version comparator. * @return Conflict resolution result. * @throws IgniteCheckedException In case of exception. */ public GridCacheVersionConflictContext<K, V> conflictResolve(GridCacheVersionedEntryEx<K, V> oldEntry, GridCacheVersionedEntryEx<K, V> newEntry, boolean atomicVerComp) throws IgniteCheckedException { assert conflictRslvr != null : "Should not reach this place."; GridCacheVersionConflictContext<K, V> ctx = conflictRslvr.resolve(oldEntry, newEntry, atomicVerComp); if (ctx.isManualResolve()) drMgr.onReceiveCacheConflictResolved(ctx.isUseNew(), ctx.isUseOld(), ctx.isMerge()); return ctx; } /** * @return Data center ID. */ public byte dataCenterId() { return dr().dataCenterId(); } /** * @param entry Entry. * @param ver Version. */ public void onDeferredDelete(GridCacheEntryEx entry, GridCacheVersion ver) { assert entry != null; assert !Thread.holdsLock(entry) : entry; assert ver != null; assert deferredDelete() : cache; cache.onDeferredDelete(entry, ver); } /** * @param interceptorRes Result of {@link CacheInterceptor#onBeforeRemove} callback. * @return {@code True} if interceptor cancels remove. */ public boolean cancelRemove(@Nullable IgniteBiTuple<Boolean, ?> interceptorRes) { if (interceptorRes != null) { if (interceptorRes.get1() == null) { U.warn(log, "CacheInterceptor must not return null as cancellation flag value from " + "'onBeforeRemove' method."); return false; } else return interceptorRes.get1(); } else { U.warn(log, "CacheInterceptor must not return null from 'onBeforeRemove' method."); return false; } } /** * @return Binary processor. */ public IgniteCacheObjectProcessor cacheObjects() { return kernalContext().cacheObjects(); } /** * @return {@code True} if {@link BinaryMarshaller is configured}. */ public boolean binaryMarshaller() { return marshaller() instanceof BinaryMarshaller; } /** * @return Keep binary flag. */ public boolean keepBinary() { CacheOperationContext opCtx = operationContextPerCall(); return opCtx != null && opCtx.isKeepBinary(); } /** * @return {@code True} if the value for the cache object has to be copied because * of {@link CacheConfiguration#isCopyOnRead()}. */ public boolean needValueCopy() { return affNode && cacheCfg.isCopyOnRead(); } /** * Converts temporary offheap object to heap-based. * * @param obj Object. * @return Heap-based object. */ @Nullable public <T> T unwrapTemporary(@Nullable Object obj) { return (T)cacheObjects().unwrapTemporary(this, obj); } /** * Unwraps collection. * * @param col Collection to unwrap. * @param keepBinary Keep binary flag. * @return Unwrapped collection. */ public Collection<Object> unwrapBinariesIfNeeded(Collection<Object> col, boolean keepBinary) { return cacheObjCtx.unwrapBinariesIfNeeded(col, keepBinary); } /** * Unwraps object for binary. * * @param o Object to unwrap. * @param keepBinary Keep binary flag. * @return Unwrapped object. */ public Object unwrapBinaryIfNeeded(Object o, boolean keepBinary) { return cacheObjCtx.unwrapBinaryIfNeeded(o, keepBinary); } /** * Unwraps object for binary. * * @param o Object to unwrap. * @param keepBinary Keep binary flag. * @param cpy Copy value flag. * @return Unwrapped object. */ public Object unwrapBinaryIfNeeded(Object o, boolean keepBinary, boolean cpy) { return cacheObjCtx.unwrapBinaryIfNeeded(o, keepBinary, cpy); } /** * @param resMap Invoke results map. * @param keepBinary Keep binary flag. * @return Unwrapped results. */ public Map unwrapInvokeResult(@Nullable Map<Object, EntryProcessorResult> resMap, final boolean keepBinary) { return F.viewReadOnly(resMap, new C1<EntryProcessorResult, EntryProcessorResult>() { @Override public EntryProcessorResult apply(EntryProcessorResult res) { if (res instanceof CacheInvokeResult) { CacheInvokeResult invokeRes = (CacheInvokeResult)res; if (invokeRes.result() != null) res = CacheInvokeResult.fromResult(unwrapBinaryIfNeeded(invokeRes.result(), keepBinary, false)); } return res; } }); } /** * @return Cache object context. */ public CacheObjectContext cacheObjectContext() { return cacheObjCtx; } /** * @param obj Object. * @return Cache object. */ @Nullable public CacheObject toCacheObject(@Nullable Object obj) { assert validObjectForCache(obj) : obj; return cacheObjects().toCacheObject(cacheObjCtx, obj, true); } /** * @param obj Object. * @return Cache key object. */ public KeyCacheObject toCacheKeyObject(Object obj) { assert validObjectForCache(obj) : obj; return cacheObjects().toCacheKeyObject(cacheObjCtx, this, obj, true); } /** * @param obj Object. * @return {@code False} if objects is not expected for cache. */ private boolean validObjectForCache(Object obj) { return obj == null || !CU.isUtilityCache(cacheName) || ctx.marshallerContext().isSystemType(obj.getClass().getName()); } /** * @param bytes Bytes. * @return Cache key object. * @throws IgniteCheckedException If failed. */ public KeyCacheObject toCacheKeyObject(byte[] bytes) throws IgniteCheckedException { Object obj = ctx.cacheObjects().unmarshal(cacheObjCtx, bytes, deploy().localLoader()); return cacheObjects().toCacheKeyObject(cacheObjCtx, this, obj, false); } /** * @param map Map. * @param key Key. * @param val Value. * @param skipVals Skip values flag. * @param keepCacheObjects Keep cache objects flag. * @param deserializeBinary Deserialize binary flag. * @param cpy Copy flag. * @param ver GridCacheVersion. */ @SuppressWarnings("unchecked") public <K1, V1> void addResult(Map<K1, V1> map, KeyCacheObject key, CacheObject val, boolean skipVals, boolean keepCacheObjects, boolean deserializeBinary, boolean cpy, final GridCacheVersion ver, final long expireTime, final long ttl) { // Creates EntryGetResult addResult(map, key, val, skipVals, keepCacheObjects, deserializeBinary, cpy, null, ver, expireTime, ttl, ver != null); } /** * @param map Map. * @param key Key. * @param getRes EntryGetResult. * @param skipVals Skip values. * @param keepCacheObjects Keep CacheObject. * @param deserializeBinary Deserialize binary flag. * @param cpy Copy flag. * @param needVer Need version flag. */ @SuppressWarnings("unchecked") public <K1, V1> void addResult(Map<K1, V1> map, KeyCacheObject key, EntryGetResult getRes, boolean skipVals, boolean keepCacheObjects, boolean deserializeBinary, boolean cpy, boolean needVer) { // Uses getRes as result. addResult(map, key, getRes.<CacheObject>value(), skipVals, keepCacheObjects, deserializeBinary, cpy, getRes, null, 0, 0, needVer); } /** * @param map Map. * @param key Key. * @param val Value. * @param skipVals Skip values. * @param keepCacheObjects Keep CacheObject. * @param deserializeBinary Deserialize binary. * @param cpy Copy flag. * @param getRes EntryGetResult. * @param ver Version. * @param expireTime Entry expire time. * @param ttl Entry TTL. * @param needVer Need version flag. */ @SuppressWarnings("unchecked") public <K1, V1> void addResult(Map<K1, V1> map, KeyCacheObject key, CacheObject val, boolean skipVals, boolean keepCacheObjects, boolean deserializeBinary, boolean cpy, @Nullable EntryGetResult getRes, final GridCacheVersion ver, final long expireTime, final long ttl, boolean needVer) { assert key != null; assert val != null || skipVals; if (!keepCacheObjects) { Object key0 = unwrapBinaryIfNeeded(key, !deserializeBinary, cpy); Object val0 = skipVals ? true : unwrapBinaryIfNeeded(val, !deserializeBinary, cpy); assert key0 != null : key; assert val0 != null : val; V1 v = createValue(ver, expireTime, ttl, val0, getRes, needVer); map.put((K1)key0, v); } else { Object val0 = skipVals ? true : val; V1 v = createValue(ver, expireTime, ttl, val0, getRes, needVer); map.put((K1)key, v); } } /** * Creates new EntryGetResult or uses existing one. * * @param ver Version. * @param expireTime Entry expire time. * @param ttl Entry TTL. * @param val Value. * @param getRes EntryGetResult * @param needVer Need version flag. * @return EntryGetResult or value. */ @SuppressWarnings("unchecked") private <V1> V1 createValue(final GridCacheVersion ver, final long expireTime, final long ttl, final Object val, @Nullable final EntryGetResult getRes, final boolean needVer) { final V1 v; if (!needVer) v = (V1) val; else if (getRes == null) { v = expireTime != 0 || ttl != 0 ? (V1)new EntryGetWithTtlResult(val, ver, false, expireTime, ttl) : (V1)new EntryGetResult(val, ver, false); } else { getRes.value(val); v = (V1)getRes; } return v; } /** * @return Updates allowed. */ public boolean updatesAllowed() { return updatesAllowed; } /** * @return Current cache state. Must only be modified during exchange. */ public boolean needsRecovery() { return needsRecovery; } /** * @param needsRecovery Needs recovery flag. */ public void needsRecovery(boolean needsRecovery) { this.needsRecovery = needsRecovery; } /** * Nulling references to potentially leak-prone objects. */ public void cleanup() { cache = null; cacheCfg = null; evictMgr = null; qryMgr = null; dataStructuresMgr = null; cacheObjCtx = null; mgrs.clear(); } /** * Print memory statistics of all cache managers. * * NOTE: this method is for testing and profiling purposes only. */ public void printMemoryStats() { X.println(">>> "); X.println(">>> Cache memory stats [igniteInstanceName=" + ctx.igniteInstanceName() + ", cache=" + name() + ']'); cache().printMemoryStats(); Collection<GridCacheManager> printed = new LinkedList<>(); for (GridCacheManager mgr : managers()) { mgr.printMemoryStats(); printed.add(mgr); } if (isNear()) for (GridCacheManager mgr : near().dht().context().managers()) if (!printed.contains(mgr)) mgr.printMemoryStats(); } /** * @param keys Keys. * @return Read-only collection of KeyCacheObject instances. */ public Collection<KeyCacheObject> cacheKeysView(Collection<?> keys) { return F.viewReadOnly(keys, new C1<Object, KeyCacheObject>() { @Override public KeyCacheObject apply(Object key) { if (key == null) throw new NullPointerException("Null key."); return toCacheKeyObject(key); } }); } /** * @param part Partition. * @param affNodes Affinity nodes. * @param topVer Topology version. * @return {@code True} if cache 'get' operation is allowed to get entry locally. */ public boolean allowFastLocalRead(int part, List<ClusterNode> affNodes, AffinityTopologyVersion topVer) { return affinityNode() && rebalanceEnabled() && hasPartition(part, affNodes, topVer); } /** * Checks if it is possible to directly read data memory without entry creation (this * is optimization to avoid unnecessary blocking synchronization on cache entry). * * @param expiryPlc Optional expiry policy for read operation. * @param readers {@code True} if need update near cache readers. * @return {@code True} if it is possible to directly read offheap instead of using {@link GridCacheEntryEx#innerGet}. */ public boolean readNoEntry(@Nullable IgniteCacheExpiryPolicy expiryPlc, boolean readers) { return !config().isOnheapCacheEnabled() && !readers && expiryPlc == null; } /** * @return {@code True} if fast eviction is allowed. */ public boolean allowFastEviction() { return shared().database().persistenceEnabled() && !QueryUtils.isEnabled(cacheCfg); } /** * @param part Partition. * @param affNodes Affinity nodes. * @param topVer Topology version. * @return {@code True} if partition is available locally. */ private boolean hasPartition(int part, List<ClusterNode> affNodes, AffinityTopologyVersion topVer) { assert affinityNode(); GridDhtPartitionTopology top = topology(); return (top.rebalanceFinished(topVer) && (isReplicated() || affNodes.contains(locNode))) || (top.partitionState(localNodeId(), part) == OWNING); } /** {@inheritDoc} */ @Override public void writeExternal(ObjectOutput out) throws IOException { U.writeString(out, igniteInstanceName()); U.writeString(out, namex()); } /** {@inheritDoc} */ @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"}) @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { IgniteBiTuple<String, String> t = stash.get(); t.set1(U.readString(in)); t.set2(U.readString(in)); } /** * Reconstructs object on unmarshalling. * * @return Reconstructed object. * @throws ObjectStreamException Thrown in case of unmarshalling error. */ protected Object readResolve() throws ObjectStreamException { try { IgniteBiTuple<String, String> t = stash.get(); IgniteKernal grid = IgnitionEx.localIgnite(); GridCacheAdapter<K, V> cache = grid.internalCache(t.get2()); if (cache == null) throw new IllegalStateException("Failed to find cache for name: " + t.get2()); return cache.context(); } catch (IllegalStateException e) { throw U.withCause(new InvalidObjectException(e.getMessage()), e); } finally { stash.remove(); } } /** {@inheritDoc} */ @Override public String toString() { return "GridCacheContext: " + name(); } }