/** {@inheritDoc} */ @Override public Map<K, V> peekAll( @Nullable Collection<? extends K> keys, @Nullable GridPredicate<? super GridCacheEntry<K, V>>[] filter) { if (keys == null || keys.isEmpty()) return emptyMap(); final Collection<K> skipped = new GridLeanSet<K>(); final Map<K, V> map = peekAll0(keys, filter, skipped); if (map.size() + skipped.size() != keys.size()) { map.putAll( dht.peekAll( F.view( keys, new P1<K>() { @Override public boolean apply(K k) { return !map.containsKey(k) && !skipped.contains(k); } }), filter)); } return map; }
/** @throws Exception If failed. */ public void testCreateFileColocated() throws Exception { GridGgfsPath path = new GridGgfsPath("/colocated"); UUID uuid = UUID.randomUUID(); GridUuid affKey; long idx = 0; while (true) { affKey = new GridUuid(uuid, idx); if (grid(0).mapKeyToNode(DATA_CACHE_NAME, affKey).id().equals(grid(0).localNode().id())) break; idx++; } try (GridGgfsOutputStream out = fs.create(path, 1024, true, affKey, 0, 1024, null)) { // Write 5M, should be enough to test distribution. for (int i = 0; i < 15; i++) out.write(new byte[1024 * 1024]); } GridGgfsFile info = fs.info(path); Collection<GridGgfsBlockLocation> affNodes = fs.affinity(path, 0, info.length()); assertEquals(1, affNodes.size()); Collection<UUID> nodeIds = F.first(affNodes).nodeIds(); assertEquals(1, nodeIds.size()); assertEquals(grid(0).localNode().id(), F.first(nodeIds)); }
/** @throws Exception If failed. */ public void testAffinityPut() throws Exception { Thread.sleep(2 * TOP_REFRESH_FREQ); assertEquals(NODES_CNT, client.compute().refreshTopology(false, false).size()); Map<UUID, Grid> gridsByLocNode = new HashMap<>(NODES_CNT); GridClientData partitioned = client.data(PARTITIONED_CACHE_NAME); GridClientCompute compute = client.compute(); for (int i = 0; i < NODES_CNT; i++) gridsByLocNode.put(grid(i).localNode().id(), grid(i)); for (int i = 0; i < 100; i++) { String key = "key" + i; UUID primaryNodeId = grid(0).mapKeyToNode(PARTITIONED_CACHE_NAME, key).id(); assertEquals("Affinity mismatch for key: " + key, primaryNodeId, partitioned.affinity(key)); assertEquals(primaryNodeId, partitioned.affinity(key)); // Must go to primary node only. Since backup count is 0, value must present on // primary node only. partitioned.put(key, "val" + key); for (Map.Entry<UUID, Grid> entry : gridsByLocNode.entrySet()) { Object val = entry.getValue().cache(PARTITIONED_CACHE_NAME).peek(key); if (primaryNodeId.equals(entry.getKey())) assertEquals("val" + key, val); else assertNull(val); } } // Now check that we will see value in near cache in pinned mode. for (int i = 100; i < 200; i++) { String pinnedKey = "key" + i; UUID primaryNodeId = grid(0).mapKeyToNode(PARTITIONED_CACHE_NAME, pinnedKey).id(); UUID pinnedNodeId = F.first(F.view(gridsByLocNode.keySet(), F.notEqualTo(primaryNodeId))); GridClientNode node = compute.node(pinnedNodeId); partitioned.pinNodes(node).put(pinnedKey, "val" + pinnedKey); for (Map.Entry<UUID, Grid> entry : gridsByLocNode.entrySet()) { Object val = entry.getValue().cache(PARTITIONED_CACHE_NAME).peek(pinnedKey); if (primaryNodeId.equals(entry.getKey()) || pinnedNodeId.equals(entry.getKey())) assertEquals("val" + pinnedKey, val); else assertNull(val); } } }
/** @throws Exception If failed. */ public void testTopologyListener() throws Exception { final Collection<UUID> added = new ArrayList<>(1); final Collection<UUID> rmvd = new ArrayList<>(1); final CountDownLatch addedLatch = new CountDownLatch(1); final CountDownLatch rmvLatch = new CountDownLatch(1); assertEquals(NODES_CNT, client.compute().refreshTopology(false, false).size()); GridClientTopologyListener lsnr = new GridClientTopologyListener() { @Override public void onNodeAdded(GridClientNode node) { added.add(node.nodeId()); addedLatch.countDown(); } @Override public void onNodeRemoved(GridClientNode node) { rmvd.add(node.nodeId()); rmvLatch.countDown(); } }; client.addTopologyListener(lsnr); try { Grid g = startGrid(NODES_CNT + 1); UUID id = g.localNode().id(); assertTrue(addedLatch.await(2 * TOP_REFRESH_FREQ, MILLISECONDS)); assertEquals(1, added.size()); assertEquals(id, F.first(added)); stopGrid(NODES_CNT + 1); assertTrue(rmvLatch.await(2 * TOP_REFRESH_FREQ, MILLISECONDS)); assertEquals(1, rmvd.size()); assertEquals(id, F.first(rmvd)); } finally { client.removeTopologyListener(lsnr); stopGrid(NODES_CNT + 1); } }
/** * @param rmtReducer Optional reducer. * @param rmtTransform Optional transformer. * @param args Arguments. * @return Future. */ @SuppressWarnings("IfMayBeConditional") private <R> GridCacheQueryFuture<R> execute( @Nullable GridReducer<T, R> rmtReducer, @Nullable GridClosure<T, R> rmtTransform, @Nullable Object... args) { Collection<GridNode> nodes = nodes(); cctx.checkSecurity(GridSecurityPermission.CACHE_READ); if (F.isEmpty(nodes)) return new GridCacheQueryErrorFuture<>( cctx.kernalContext(), new GridEmptyProjectionException("There are no data nodes for cache: " + cctx.namexx())); if (log.isDebugEnabled()) log.debug("Executing query [query=" + this + ", nodes=" + nodes + ']'); if (cctx.deploymentEnabled()) { try { cctx.deploy().registerClasses(filter, rmtReducer, rmtTransform); cctx.deploy().registerClasses(args); } catch (GridException e) { return new GridCacheQueryErrorFuture<>(cctx.kernalContext(), e); } } if (subjId == null) subjId = cctx.localNodeId(); taskHash = cctx.kernalContext().job().currentTaskNameHash(); GridCacheQueryBean bean = new GridCacheQueryBean( this, (GridReducer<Object, Object>) rmtReducer, (GridClosure<Object, Object>) rmtTransform, args); GridCacheQueryManager qryMgr = cctx.queries(); boolean loc = nodes.size() == 1 && F.first(nodes).id().equals(cctx.localNodeId()); if (type == SQL_FIELDS) return (GridCacheQueryFuture<R>) (loc ? qryMgr.queryFieldsLocal(bean) : qryMgr.queryFieldsDistributed(bean, nodes)); else return (GridCacheQueryFuture<R>) (loc ? qryMgr.queryLocal(bean) : qryMgr.queryDistributed(bean, nodes)); }
/** {@inheritDoc} */ @Override public Map<K, V> peekAll( @Nullable Collection<? extends K> keys, @Nullable Collection<GridCachePeekMode> modes) throws GridException { if (keys == null || keys.isEmpty()) return emptyMap(); final Collection<K> skipped = new GridLeanSet<K>(); final Map<K, V> map = !modes.contains(PARTITIONED_ONLY) ? peekAll0(keys, modes, ctx.tm().localTxx(), skipped) : new GridLeanMap<K, V>(0); if (map.size() != keys.size() && !modes.contains(NEAR_ONLY)) { map.putAll( dht.peekAll( F.view( keys, new P1<K>() { @Override public boolean apply(K k) { return !map.containsKey(k) && !skipped.contains(k); } }), modes)); } return map; }
/** {@inheritDoc} */ @Override public V unswap(K key) throws GridException { ctx.denyOnFlags(F.asList(READ, SKIP_SWAP)); // Unswap only from DHT. Near cache does not have swap storage. return dht.unswap(key); }
/** * @param mapping Mapping to order. * @param committedVers Committed versions. * @param rolledbackVers Rolled back versions. */ void orderCompleted( GridDistributedTxMapping<K, V> mapping, Collection<GridCacheVersion> committedVers, Collection<GridCacheVersion> rolledbackVers) { for (GridCacheTxEntry<K, V> txEntry : F.concat(false, mapping.reads(), mapping.writes())) { while (true) { GridDistributedCacheEntry<K, V> entry = (GridDistributedCacheEntry<K, V>) txEntry.cached(); try { // Handle explicit locks. GridCacheVersion base = txEntry.explicitVersion() != null ? txEntry.explicitVersion() : xidVer; entry.doneRemote(xidVer, base, committedVers, rolledbackVers); if (ec()) entry.recheck(); break; } catch (GridCacheEntryRemovedException ignored) { assert entry.obsoleteVersion() != null; if (log.isDebugEnabled()) log.debug( "Replacing obsolete entry in remote transaction [entry=" + entry + ", tx=" + this + ']'); // Replace the entry. txEntry.cached(cctx.cache().entryEx(txEntry.key()), entry.keyBytes()); } } } }
/** @return Nodes to execute on. */ private Collection<GridNode> nodes() { GridCacheMode cacheMode = cctx.config().getCacheMode(); switch (cacheMode) { case LOCAL: if (prj != null) U.warn( log, "Ignoring query projection because it's executed over LOCAL cache " + "(only local node will be queried): " + this); return Collections.singletonList(cctx.localNode()); case REPLICATED: if (prj != null) return nodes(cctx, prj); GridCacheDistributionMode mode = cctx.config().getDistributionMode(); return mode == PARTITIONED_ONLY || mode == NEAR_PARTITIONED ? Collections.singletonList(cctx.localNode()) : Collections.singletonList(F.rand(nodes(cctx, null))); case PARTITIONED: return nodes(cctx, prj); default: throw new IllegalStateException("Unknown cache distribution mode: " + cacheMode); } }
/** * @return Query info. * @throws GridException In case of error. */ @SuppressWarnings({"unchecked"}) private GridCacheQueryInfo localQueryInfo() throws GridException { GridCacheQueryBean qry = query(); GridPredicate<GridCacheEntry<Object, Object>> prjPred = qry.query().projectionFilter() == null ? F.<GridCacheEntry<Object, Object>>alwaysTrue() : qry.query().projectionFilter(); GridMarshaller marsh = cctx.marshaller(); GridReducer<Object, Object> rdc = qry.reducer() != null ? marsh.<GridReducer<Object, Object>>unmarshal(marsh.marshal(qry.reducer()), null) : null; GridClosure<Object, Object> trans = qry.transform() != null ? marsh.<GridClosure<Object, Object>>unmarshal(marsh.marshal(qry.transform()), null) : null; return new GridCacheQueryInfo( true, prjPred, trans, rdc, qry.query(), GridCacheLocalQueryFuture.this, ctx.localNodeId(), cctx.io().nextIoId(), qry.query().includeMetadata(), true, qry.arguments()); }
/** {@inheritDoc} */ @Override public <T> T affinityKey() { try { return (T) job.getDeployment().annotatedValue(job.getJob(), GridCacheAffinityMapped.class); } catch (GridException e) { throw F.wrap(e); } }
/** {@inheritDoc} */ @Override public String cacheName() { try { return (String) job.getDeployment().annotatedValue(job.getJob(), GridCacheName.class); } catch (GridException e) { throw F.wrap(e); } }
/** * @param g Grid. * @return Non-system caches. */ private Collection<GridCacheConfiguration> caches(Grid g) { return F.view( Arrays.asList(g.configuration().getCacheConfiguration()), new GridPredicate<GridCacheConfiguration>() { @Override public boolean apply(GridCacheConfiguration c) { return c.getName() == null || !c.getName().equals(CU.UTILITY_CACHE_NAME); } }); }
/** * @param id ID. * @param name Name. * @param age Age. * @param orgId Organization ID. */ private Person(int id, String name, int age, int orgId) { assert !F.isEmpty(name); assert age > 0; assert orgId > 0; this.id = id; this.name = name; this.age = age; this.orgId = orgId; }
/** * @param keys Keys. * @param timeout Timeout. * @param tx Transaction. * @param filter Filter. * @return Future. */ public GridFuture<Boolean> lockAllAsync( Collection<? extends K> keys, long timeout, @Nullable GridCacheTxLocalEx<K, V> tx, GridPredicate<? super GridCacheEntry<K, V>>[] filter) { if (F.isEmpty(keys)) { return new GridFinishedFuture<Boolean>(ctx.kernalContext(), true); } GridLocalLockFuture<K, V> fut = new GridLocalLockFuture<K, V>(ctx, keys, tx, this, timeout, filter); try { for (K key : keys) { while (true) { GridLocalCacheEntry<K, V> entry = null; try { entry = entryExx(key); if (!ctx.isAll(entry, filter)) { fut.onFailed(); return fut; } // Removed exception may be thrown here. GridCacheMvccCandidate<K> cand = fut.addEntry(entry); if (cand == null && fut.isDone()) { return fut; } break; } catch (GridCacheEntryRemovedException ignored) { if (log().isDebugEnabled()) { log().debug("Got removed entry in lockAsync(..) method (will retry): " + entry); } } } } if (!ctx.mvcc().addFuture(fut)) fut.onError(new GridException("Duplicate future ID (internal error): " + fut)); // Must have future added prior to checking locks. fut.checkLocks(); return fut; } catch (GridException e) { fut.onError(e); return fut; } }
/** * Checks entry for empty value. * * @param entry Entry to check. * @return {@code True} if entry is empty. */ private boolean empty(GridCacheEntry<K, V> entry) { try { return entry.peek(F.asList(GLOBAL)) == null; } catch (GridException e) { U.error(null, e.getMessage(), e); assert false : "Should never happen: " + e; return false; } }
/** {@inheritDoc} */ @Override public Iterator<GridCacheEntry<K, V>> iterator() { return new EntryIterator( nearSet.iterator(), F.iterator0( dhtSet, false, new P1<GridCacheEntry<K, V>>() { @Override public boolean apply(GridCacheEntry<K, V> e) { return !GridNearCache.super.containsKey(e.getKey(), null); } })); }
/** @throws GridException If failed. */ public void testAffinity() throws GridException { Grid g1 = grid(1); Grid g2 = grid(2); assert caches(g1).size() == 0; assert F.first(caches(g2)).getCacheMode() == PARTITIONED; Map<GridNode, Collection<String>> map = g1.mapKeysToNodes(null, F.asList("1")); assertNotNull(map); assertEquals("Invalid map size: " + map.size(), 1, map.size()); assertEquals(F.first(map.keySet()), g2.localNode()); UUID id1 = g1.mapKeyToNode(null, "2").id(); assertNotNull(id1); assertEquals(g2.localNode().id(), id1); UUID id2 = g1.mapKeyToNode(null, "3").id(); assertNotNull(id2); assertEquals(g2.localNode().id(), id2); }
/** @return Involved nodes. */ @Override public Collection<? extends GridNode> nodes() { return F.viewReadOnly( futures(), new GridClosure<GridFuture<?>, GridRichNode>() { @Nullable @Override public GridRichNode apply(GridFuture<?> f) { if (isMini(f)) return ((MiniFuture) f).node(); return cctx.rich().rich(cctx.discovery().localNode()); } }); }
/** @param mappings Mappings. */ void addEntryMapping(@Nullable Map<UUID, GridDistributedTxMapping<K, V>> mappings) { if (!F.isEmpty(mappings)) { this.mappings.putAll(mappings); if (log.isDebugEnabled()) log.debug( "Added mappings to transaction [locId=" + cctx.nodeId() + ", mappings=" + mappings + ", tx=" + this + ']'); } }
/** {@inheritDoc} */ @Override public GridFuture<Map<K, V>> getAllAsync( @Nullable Collection<? extends K> keys, @Nullable GridPredicate<? super GridCacheEntry<K, V>>[] filter) { ctx.denyOnFlag(LOCAL); if (F.isEmpty(keys)) return new GridFinishedFuture<Map<K, V>>(ctx.kernalContext(), Collections.<K, V>emptyMap()); GridCacheTxLocalAdapter<K, V> tx = ctx.tm().threadLocalTx(); if (tx != null && !tx.implicit()) return ctx.wrapCloneMap(tx.getAllAsync(keys, filter)); return loadAsync(keys, false, filter); }
/** * @param ldr Loader. * @param nodeId Sender node ID. * @param req Request. * @return Remote transaction. * @throws GridException If failed. */ @Nullable public GridNearTxRemote<K, V> startRemoteTx( ClassLoader ldr, UUID nodeId, GridDhtTxPrepareRequest<K, V> req) throws GridException { if (!F.isEmpty(req.nearWrites())) { GridNearTxRemote<K, V> tx = new GridNearTxRemote<K, V>( ldr, nodeId, req.nearNodeId(), req.threadId(), req.version(), req.commitVersion(), req.concurrency(), req.isolation(), req.isInvalidate(), req.timeout(), req.nearWrites(), ctx); if (!tx.empty()) { tx = ctx.tm().onCreated(tx); if (tx == null || !ctx.tm().onStarted(tx)) throw new GridCacheTxRollbackException("Attempt to start a completed transaction: " + tx); // Prepare prior to reordering, so the pending locks added // in prepare phase will get properly ordered as well. tx.prepare(); // Add remote candidates and reorder completed and uncompleted versions. tx.addRemoteCandidates( req.candidatesByKey(), req.committedVersions(), req.rolledbackVersions()); if (req.concurrency() == EVENTUALLY_CONSISTENT) { if (log.isDebugEnabled()) log.debug("Committing transaction during remote prepare: " + tx); tx.commit(); if (log.isDebugEnabled()) log.debug("Committed transaction during remote prepare: " + tx); } } return tx; } return null; }
/** * @param cctx Cache context. * @param prj Projection (optional). * @return Collection of data nodes in provided projection (if any). */ private static Collection<GridNode> nodes( final GridCacheContext<?, ?> cctx, @Nullable final GridProjection prj) { assert cctx != null; return F.view( CU.allNodes(cctx), new P1<GridNode>() { @Override public boolean apply(GridNode n) { GridCacheDistributionMode mode = U.distributionMode(n, cctx.name()); return (mode == PARTITIONED_ONLY || mode == NEAR_PARTITIONED) && (prj == null || prj.node(n.id()) != null); } }); }
/** * @param keys Keys to load. * @param reload Reload flag. * @param filter Filter. * @return Loaded values. */ public GridFuture<Map<K, V>> loadAsync( @Nullable Collection<? extends K> keys, boolean reload, @Nullable GridPredicate<? super GridCacheEntry<K, V>>[] filter) { if (F.isEmpty(keys)) return new GridFinishedFuture<Map<K, V>>(ctx.kernalContext(), Collections.<K, V>emptyMap()); GridNearGetFuture<K, V> fut = new GridNearGetFuture<K, V>(ctx, keys, reload, null, filter); // Register future for responses. ctx.mvcc().addFuture(fut); fut.init(); return ctx.wrapCloneMap(fut); }
/** * @param cctx Context. * @param tx Transaction. * @param commit Commit flag. */ public GridNearTxFinishFuture( GridCacheContext<K, V> cctx, GridNearTxLocal<K, V> tx, boolean commit) { super(cctx.kernalContext(), F.<GridCacheTx>identityReducer(tx)); assert cctx != null; this.cctx = cctx; this.tx = tx; this.commit = commit; mappings = tx.mappings(); futId = GridUuid.randomUuid(); log = U.logger(ctx, logRef, GridNearTxFinishFuture.class); }
/** {@inheritDoc} */ @Override public void isolated(boolean isolated) throws GridException { if (isolated()) return; GridNode node = F.first(ctx.grid().forCache(cacheName).nodes()); if (node == null) throw new GridException("Failed to get node for cache: " + cacheName); GridCacheAttributes a = U.cacheAttributes(node, cacheName); assert a != null; updater = a.atomicityMode() == GridCacheAtomicityMode.ATOMIC ? GridDataLoadCacheUpdaters.<K, V>batched() : GridDataLoadCacheUpdaters.<K, V>groupLocked(); }
/** {@inheritDoc} */ @Override public void execute(@Nullable GridProjection prj) throws GridException { if (cb == null) throw new IllegalStateException("Mandatory local callback is not set for the query: " + this); if (prj == null) prj = ctx.grid(); prj = prj.forCache(ctx.name()); if (prj.nodes().isEmpty()) throw new GridTopologyException("Failed to execute query (projection is empty): " + this); GridCacheMode mode = ctx.config().getCacheMode(); if (mode == LOCAL || mode == REPLICATED) { Collection<GridNode> nodes = prj.nodes(); GridNode node = nodes.contains(ctx.localNode()) ? ctx.localNode() : F.rand(nodes); assert node != null; if (nodes.size() > 1 && !ctx.cache().isDrSystemCache()) { if (node.id().equals(ctx.localNodeId())) U.warn( log, "Continuous query for " + mode + " cache can be run only on local node. " + "Will execute query locally: " + this); else U.warn( log, "Continuous query for " + mode + " cache can be run only on single node. " + "Will execute query on remote node [qry=" + this + ", node=" + node + ']'); } prj = prj.forNode(node); } closeLock.lock(); try { if (routineId != null) throw new IllegalStateException("Continuous query can't be executed twice."); guard.block(); GridContinuousHandler hnd = new GridCacheContinuousQueryHandler<>(ctx.name(), topic, cb, filter, prjPred); routineId = ctx.kernalContext() .continuous() .startRoutine(hnd, bufSize, timeInterval, autoUnsubscribe, prj.predicate()) .get(); } finally { closeLock.unlock(); } }
/** * Initializes store. * * @throws GridException If failed to initialize. */ private void init() throws GridException { if (initGuard.compareAndSet(false, true)) { if (log.isDebugEnabled()) log.debug("Initializing cache store."); try { if (sesFactory != null) // Session factory has been provided - nothing to do. return; if (!F.isEmpty(hibernateCfgPath)) { try { URL url = new URL(hibernateCfgPath); sesFactory = new Configuration().configure(url).buildSessionFactory(); if (log.isDebugEnabled()) log.debug("Configured session factory using URL: " + url); // Session factory has been successfully initialized. return; } catch (MalformedURLException e) { if (log.isDebugEnabled()) log.debug("Caught malformed URL exception: " + e.getMessage()); } // Provided path is not a valid URL. File? File cfgFile = new File(hibernateCfgPath); if (cfgFile.exists()) { sesFactory = new Configuration().configure(cfgFile).buildSessionFactory(); if (log.isDebugEnabled()) log.debug("Configured session factory using file: " + hibernateCfgPath); // Session factory has been successfully initialized. return; } // Provided path is not a file. Classpath resource? sesFactory = new Configuration().configure(hibernateCfgPath).buildSessionFactory(); if (log.isDebugEnabled()) log.debug("Configured session factory using classpath resource: " + hibernateCfgPath); } else { if (hibernateProps == null) { U.warn( log, "No Hibernate configuration has been provided for store (will use default)."); hibernateProps = new Properties(); hibernateProps.setProperty("hibernate.connection.url", DFLT_CONN_URL); hibernateProps.setProperty("hibernate.show_sql", DFLT_SHOW_SQL); hibernateProps.setProperty("hibernate.hbm2ddl.auto", DFLT_HBM2DDL_AUTO); } Configuration cfg = new Configuration(); cfg.setProperties(hibernateProps); assert resourceAvailable(MAPPING_RESOURCE); cfg.addResource(MAPPING_RESOURCE); sesFactory = cfg.buildSessionFactory(); if (log.isDebugEnabled()) log.debug("Configured session factory using properties: " + hibernateProps); } } catch (HibernateException e) { throw new GridException("Failed to initialize store.", e); } finally { initLatch.countDown(); } } else if (initLatch.getCount() > 0) U.await(initLatch); if (sesFactory == null) throw new GridException("Cache store was not properly initialized."); }
/** * Removes locks regardless of whether they are owned or not for given version and keys. * * @param ver Lock version. * @param keys Keys. */ @SuppressWarnings({"unchecked"}) public void removeLocks(GridCacheVersion ver, Collection<? extends K> keys) { if (keys.isEmpty()) return; try { Collection<GridRichNode> affNodes = null; int keyCnt = -1; Map<GridNode, GridNearUnlockRequest<K, V>> map = null; for (K key : keys) { // Send request to remove from remote nodes. GridNearUnlockRequest<K, V> req = null; while (true) { GridDistributedCacheEntry<K, V> entry = peekExx(key); try { if (entry != null) { GridCacheMvccCandidate<K> cand = entry.candidate(ver); if (cand != null) { if (affNodes == null) { affNodes = CU.allNodes(ctx, cand.topologyVersion()); keyCnt = (int) Math.ceil((double) keys.size() / affNodes.size()); map = new HashMap<GridNode, GridNearUnlockRequest<K, V>>(affNodes.size()); } GridRichNode primary = CU.primary0(ctx.affinity(key, affNodes)); if (!primary.isLocal()) { req = map.get(primary); if (req == null) { map.put(primary, req = new GridNearUnlockRequest<K, V>(keyCnt)); req.version(ver); } } // Remove candidate from local node first. if (entry.removeLock(cand.version())) { if (primary.isLocal()) { dht.removeLocks(primary.id(), ver, F.asList(key), true); assert req == null; continue; } req.addKey(entry.key(), entry.getOrMarshalKeyBytes(), ctx); } } } break; } catch (GridCacheEntryRemovedException ignored) { if (log.isDebugEnabled()) log.debug( "Attempted to remove lock from removed entry (will retry) [rmvVer=" + ver + ", entry=" + entry + ']'); } } } if (map == null || map.isEmpty()) return; Collection<GridCacheVersion> committed = ctx.tm().committedVersions(ver); Collection<GridCacheVersion> rolledback = ctx.tm().rolledbackVersions(ver); for (Map.Entry<GridNode, GridNearUnlockRequest<K, V>> mapping : map.entrySet()) { GridNode n = mapping.getKey(); GridDistributedUnlockRequest<K, V> req = mapping.getValue(); if (!req.keyBytes().isEmpty()) { req.completedVersions(committed, rolledback); // We don't wait for reply to this message. ctx.io().send(n, req); } } } catch (GridException ex) { U.error(log, "Failed to unlock the lock for keys: " + keys, ex); } }
/** * @param e Transaction entry. * @return {@code True} if entry is locally mapped as a primary or back up node. */ protected boolean isNearLocallyMapped(GridCacheEntryEx<K, V> e) { return F.contains(ctx.affinity(e.key(), CU.allNodes(ctx)), ctx.localNode()); }