/** Initializes future. */ @SuppressWarnings("ForLoopReplaceableByForEach") void finish() { if (tx.onNeedCheckBackup()) { assert tx.onePhaseCommit(); checkBackup(); // If checkBackup is set, it means that primary node has crashed and we will not need to send // finish request to it, so we can mark future as initialized. markInitialized(); return; } try { if (tx.finish(commit) || (!commit && tx.state() == UNKNOWN)) { if ((tx.onePhaseCommit() && needFinishOnePhase()) || (!tx.onePhaseCommit() && mappings != null)) { if (mappings.single()) { GridDistributedTxMapping mapping = mappings.singleMapping(); if (mapping != null) finish(mapping); } else finish(mappings.mappings()); } markInitialized(); if (!isSync() && !isDone()) { boolean complete = true; synchronized (futs) { // Avoid collection copy and iterator creation. for (int i = 0; i < futs.size(); i++) { IgniteInternalFuture<IgniteInternalTx> f = futs.get(i); if (isMini(f) && !f.isDone()) { complete = false; break; } } } if (complete) onComplete(); } } else onDone(new IgniteCheckedException("Failed to commit transaction: " + CU.txString(tx))); } catch (Error | RuntimeException e) { onDone(e); throw e; } catch (IgniteCheckedException e) { onDone(e); } }
/** {@inheritDoc} */ @Override public IgniteInternalFuture<IgniteInternalTx> rollbackAsync() { if (log.isDebugEnabled()) log.debug("Rolling back near tx: " + this); GridNearTxFinishFuture fut = rollbackFut.get(); if (fut != null) return fut; if (!rollbackFut.compareAndSet(null, fut = new GridNearTxFinishFuture<>(cctx, this, false))) return rollbackFut.get(); cctx.mvcc().addFuture(fut, fut.futureId()); IgniteInternalFuture<?> prepFut = this.prepFut.get(); if (prepFut == null || prepFut.isDone()) { try { // Check for errors in prepare future. if (prepFut != null) prepFut.get(); } catch (IgniteCheckedException e) { if (log.isDebugEnabled()) log.debug("Got optimistic tx failure [tx=" + this + ", err=" + e + ']'); } fut.finish(); } else { prepFut.listen( new CI1<IgniteInternalFuture<?>>() { @Override public void apply(IgniteInternalFuture<?> f) { try { // Check for errors in prepare future. f.get(); } catch (IgniteCheckedException e) { if (log.isDebugEnabled()) log.debug("Got optimistic tx failure [tx=" + this + ", err=" + e + ']'); } GridNearTxFinishFuture fut0 = rollbackFut.get(); fut0.finish(); } }); } return fut; }
/** * Rolls back local part of colocated transaction. * * @return Commit future. */ public IgniteInternalFuture<IgniteInternalTx> rollbackAsyncLocal() { if (log.isDebugEnabled()) log.debug("Rolling back colocated tx locally: " + this); final GridDhtTxFinishFuture fut = new GridDhtTxFinishFuture<>(cctx, this, /*commit*/ false); cctx.mvcc().addFuture(fut, fut.futureId()); IgniteInternalFuture<?> prep = prepFut.get(); if (prep == null || prep.isDone()) { try { if (prep != null) prep.get(); } catch (IgniteCheckedException e) { if (log.isDebugEnabled()) log.debug( "Failed to prepare transaction during rollback (will ignore) [tx=" + this + ", msg=" + e.getMessage() + ']'); } fut.finish(); } else prep.listen( new CI1<IgniteInternalFuture<?>>() { @Override public void apply(IgniteInternalFuture<?> f) { try { f.get(); // Check for errors of a parent future. } catch (IgniteCheckedException e) { log.debug( "Failed to prepare transaction during rollback (will ignore) [tx=" + this + ", msg=" + e.getMessage() + ']'); } fut.finish(); } }); return fut; }
/** * Commits local part of colocated transaction. * * @return Commit future. */ public IgniteInternalFuture<IgniteInternalTx> commitAsyncLocal() { if (log.isDebugEnabled()) log.debug("Committing colocated tx locally: " + this); // In optimistic mode prepare was called explicitly. if (pessimistic()) prepareAsync(); IgniteInternalFuture<?> prep = prepFut.get(); // Do not create finish future if there are no remote nodes. if (F.isEmpty(dhtMap) && F.isEmpty(nearMap)) { if (prep != null) return (IgniteInternalFuture<IgniteInternalTx>) (IgniteInternalFuture) prep; return new GridFinishedFuture<IgniteInternalTx>(this); } final GridDhtTxFinishFuture fut = new GridDhtTxFinishFuture<>(cctx, this, /*commit*/ true); cctx.mvcc().addFuture(fut, fut.futureId()); if (prep == null || prep.isDone()) { assert prep != null || optimistic(); try { if (prep != null) prep.get(); // Check for errors of a parent future. fut.finish(); } catch (IgniteTxOptimisticCheckedException e) { if (log.isDebugEnabled()) log.debug("Failed optimistically to prepare transaction [tx=" + this + ", e=" + e + ']'); fut.onError(e); } catch (IgniteCheckedException e) { U.error(log, "Failed to prepare transaction: " + this, e); fut.onError(e); } } else prep.listen( new CI1<IgniteInternalFuture<?>>() { @Override public void apply(IgniteInternalFuture<?> f) { try { f.get(); // Check for errors of a parent future. fut.finish(); } catch (IgniteTxOptimisticCheckedException e) { if (log.isDebugEnabled()) log.debug( "Failed optimistically to prepare transaction [tx=" + this + ", e=" + e + ']'); fut.onError(e); } catch (IgniteCheckedException e) { U.error(log, "Failed to prepare transaction: " + this, e); fut.onError(e); } } }); return fut; }
/** @throws Exception If failed. */ private void testReentrantLockMultinode1(final boolean fair) throws Exception { if (gridCount() == 1) return; IgniteLock lock = grid(0).reentrantLock("s1", true, fair, true); List<IgniteInternalFuture<?>> futs = new ArrayList<>(); for (int i = 0; i < gridCount(); i++) { final Ignite ignite = grid(i); futs.add( GridTestUtils.runAsync( new Callable<Void>() { @Override public Void call() throws Exception { IgniteLock lock = ignite.reentrantLock("s1", true, fair, false); assertNotNull(lock); IgniteCondition cond1 = lock.getOrCreateCondition("c1"); IgniteCondition cond2 = lock.getOrCreateCondition("c2"); try { boolean wait = lock.tryLock(30_000, MILLISECONDS); assertTrue(wait); cond2.signal(); cond1.await(); } finally { lock.unlock(); } return null; } })); } boolean done = false; while (!done) { done = true; for (IgniteInternalFuture<?> fut : futs) { if (!fut.isDone()) done = false; } try { lock.lock(); lock.getOrCreateCondition("c1").signal(); lock.getOrCreateCondition("c2").await(10, MILLISECONDS); } finally { lock.unlock(); } } for (IgniteInternalFuture<?> fut : futs) fut.get(30_000); }
/** {@inheritDoc} */ @Override protected void body() throws InterruptedException, IgniteInterruptedCheckedException { try { IgfsDataInputStream dis = new IgfsDataInputStream(endpoint.inputStream()); byte[] hdr = new byte[IgfsMarshaller.HEADER_SIZE]; boolean first = true; while (!Thread.currentThread().isInterrupted()) { dis.readFully(hdr); final long reqId = U.bytesToLong(hdr, 0); int ordinal = U.bytesToInt(hdr, 8); if (first) { // First message must be HANDSHAKE. if (reqId != 0 || ordinal != IgfsIpcCommand.HANDSHAKE.ordinal()) { if (log.isDebugEnabled()) log.debug( "IGFS IPC handshake failed [reqId=" + reqId + ", ordinal=" + ordinal + ']'); return; } first = false; } final IgfsIpcCommand cmd = IgfsIpcCommand.valueOf(ordinal); IgfsMessage msg = marsh.unmarshall(cmd, hdr, dis); IgniteInternalFuture<IgfsMessage> fut = hnd.handleAsync(ses, msg, dis); // If fut is null, no response is required. if (fut != null) { if (fut.isDone()) { IgfsMessage res; try { res = fut.get(); } catch (IgniteCheckedException e) { res = new IgfsControlResponse(); ((IgfsControlResponse) res).error(e); } try { synchronized (out) { // Reuse header. IgfsMarshaller.fillHeader(hdr, reqId, res.command()); marsh.marshall(res, hdr, out); out.flush(); } } catch (IOException | IgniteCheckedException e) { shutdown0(e); } } else { fut.listen( new CIX1<IgniteInternalFuture<IgfsMessage>>() { @Override public void applyx(IgniteInternalFuture<IgfsMessage> fut) { IgfsMessage res; try { res = fut.get(); } catch (IgniteCheckedException e) { res = new IgfsControlResponse(); ((IgfsControlResponse) res).error(e); } try { synchronized (out) { byte[] hdr = IgfsMarshaller.createHeader(reqId, res.command()); marsh.marshall(res, hdr, out); out.flush(); } } catch (IOException | IgniteCheckedException e) { shutdown0(e); } } }); } } } } catch (EOFException ignored) { // Client closed connection. } catch (IgniteCheckedException | IOException e) { if (!isCancelled()) U.error(log, "Failed to read data from client (will close connection)", e); } finally { onFinished(); } }