/** {@inheritDoc} */ @Override public void stopListenAsync(@Nullable GridInClosure<? super GridFuture<R>>... lsnr) { if (F.isEmpty(lsnr)) synchronized (mux) { lsnrs.clear(); } else synchronized (mux) { lsnrs.removeAll(F.asList(lsnr)); } }
/** @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 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 nodeId Sender node ID. * @param req Finish transaction message. */ @SuppressWarnings({"CatchGenericClass"}) private void processFinishRequest(UUID nodeId, GridDistributedTxFinishRequest<K, V> req) { assert nodeId != null; assert req != null; GridReplicatedTxRemote<K, V> tx = ctx.tm().tx(req.version()); try { ClassLoader ldr = ctx.deploy().globalLoader(); if (req.commit()) { // If lock was acquired explicitly. if (tx == null) { // Create transaction and add entries. tx = ctx.tm() .onCreated( new GridReplicatedTxRemote<K, V>( ldr, nodeId, req.threadId(), req.version(), req.commitVersion(), PESSIMISTIC, READ_COMMITTED, req.isInvalidate(), /*timeout */ 0, /*read entries*/ null, req.writes(), ctx)); if (tx == null || !ctx.tm().onStarted(tx)) throw new GridCacheTxRollbackException( "Attempt to start a completed " + "transaction: " + req); } else { boolean set = tx.commitVersion(req.commitVersion()); assert set; } Collection<GridCacheTxEntry<K, V>> writeEntries = req.writes(); if (!F.isEmpty(writeEntries)) { // In OPTIMISTIC mode, we get the values at PREPARE stage. assert tx.concurrency() == PESSIMISTIC; for (GridCacheTxEntry<K, V> entry : writeEntries) { // Unmarshal write entries. entry.unmarshal(ctx, ldr); if (log.isDebugEnabled()) log.debug( "Unmarshalled transaction entry from pessimistic transaction [key=" + entry.key() + ", value=" + entry.value() + ", tx=" + tx + ']'); if (!tx.setWriteValue(entry)) U.warn( log, "Received entry to commit that was not present in transaction [entry=" + entry + ", tx=" + tx + ']'); } } // Add completed versions. tx.doneRemote(req.baseVersion(), req.committedVersions(), req.rolledbackVersions()); if (tx.pessimistic()) tx.prepare(); tx.commit(); } else if (tx != null) { tx.doneRemote(req.baseVersion(), req.committedVersions(), req.rolledbackVersions()); tx.rollback(); } if (req.replyRequired()) { GridCacheMessage<K, V> res = new GridDistributedTxFinishResponse<K, V>(req.version(), req.futureId()); try { ctx.io().send(nodeId, res); } catch (Throwable e) { // Double-check. if (ctx.discovery().node(nodeId) == null) { if (log.isDebugEnabled()) log.debug( "Node left while sending finish response [nodeId=" + nodeId + ", res=" + res + ']'); } else U.error( log, "Failed to send finish response to node [nodeId=" + nodeId + ", res=" + res + ']', e); } } } catch (GridCacheTxRollbackException e) { if (log.isDebugEnabled()) log.debug("Attempted to start a completed transaction (will ignore): " + e); } catch (Throwable e) { U.error( log, "Failed completing transaction [commit=" + req.commit() + ", tx=" + CU.txString(tx) + ']', e); if (tx != null) tx.rollback(); } }
/** * Records all undeployed tasks. * * @param nodeId Left node ID. * @param undeployed Undeployed deployments. */ private void recordUndeployed(@Nullable UUID nodeId, Collection<SharedDeployment> undeployed) { if (!F.isEmpty(undeployed)) for (SharedDeployment d : undeployed) d.recordUndeployed(nodeId); }