예제 #1
0
 public void Recycle(TxState state)
 {
     if (state != null)
     {
         _resuableTxState.Add(state);
     }
 }
예제 #2
0
파일: AutoTx.cs 프로젝트: imcf/auto-tx
 /// <summary>
 /// Executes when a Stop command is sent to the service by the Service Control Manager.
 /// NOTE: the method is NOT triggered when the operating system shuts down, instead
 /// the OnShutdown() method is used!
 /// </summary>
 protected override void OnStop()
 {
     Log.Warn("{0} service stop requested...", ServiceName);
     if (_transferState != TxState.Stopped)
     {
         _transferState = TxState.DoNothing;
         // RoboCommand.Stop() is calling Process.Kill() (immediately forcing a termination
         // of the process, returning asynchronously), followed by Process.Dispose()
         // (releasing all resources used by the component). Would be nice if RoboSharp
         // implemented a method to check if the process has actually terminated, but
         // this is probably something we have to do ourselves.
         // TODO: this has probably improved with recent versions of RoboSharp, check it!
         try {
             _roboCommand.Stop();
         }
         catch (Exception ex) {
             Log.Error("Error terminating the RoboCopy process: {0}", ex.Message);
         }
         _status.TransferInProgress = true;
         Log.Info("Not all files were transferred - will resume upon next start");
         Log.Debug("CurrentTransferSrc: " + _status.CurrentTransferSrc);
         // should we delete an incompletely transferred file on the target?
         SendTransferInterruptedMail();
     }
     // set the shutdown status to clean:
     _status.CleanShutdown = true;
     Log.Info("-----------------------");
     Log.Info("{0} service stopped", ServiceName);
     Log.Info("-----------------------");
 }
예제 #3
0
        public void Begin(Transaction transaction)
        {
            lock (syncObject)
            {
                this.netTxState = TxState.Active;
                dtcControlEvent.Reset();

                Tracer.Debug("Begin notification received");

                if (InNetTransaction)
                {
                    throw new TransactionInProgressException("A Transaction is already in Progress");
                }

                try
                {
                    Guid rmId = ResourceManagerGuid;

                    // Enlist this object in the transaction.
                    this.currentEnlistment =
                        transaction.EnlistDurable(rmId, this, EnlistmentOptions.None);

                    Tracer.Debug("Enlisted in Durable Transaction with RM Id: " + rmId);

                    TransactionInformation txInfo = transaction.TransactionInformation;

                    XATransactionId xaId = new XATransactionId();
                    this.transactionId = xaId;

                    if (txInfo.DistributedIdentifier != Guid.Empty)
                    {
                        xaId.GlobalTransactionId = txInfo.DistributedIdentifier.ToByteArray();
                        xaId.BranchQualifier     = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
                    }
                    else
                    {
                        xaId.GlobalTransactionId = Encoding.UTF8.GetBytes(txInfo.LocalIdentifier);
                        xaId.BranchQualifier     = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
                    }

                    // Now notify the broker that a new XA'ish transaction has started.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId  = this.connection.ConnectionId;
                    info.TransactionId = this.transactionId;
                    info.Type          = (int)TransactionType.Begin;

                    this.session.Connection.Oneway(info);

                    if (Tracer.IsDebugEnabled)
                    {
                        Tracer.Debug("Began XA'ish Transaction:" + xaId.GlobalTransactionId.ToString());
                    }
                }
                catch (Exception)
                {
                    dtcControlEvent.Set();
                    throw;
                }
            }
        }
예제 #4
0
 public AcceptUpdateMessage(string reqId, string txId, BallotNumber ballot, TxState state)
 {
     this.ReqID  = reqId;
     this.TxID   = txId;
     this.Ballot = ballot;
     this.State  = state;
 }
예제 #5
0
        // 乐观的修改global tx state,如果version老了就重试
        public async Task <TxState> SubmitGlobalTxStateOptimismAsync(
            string xid, TxState state)
        {
            var tryCount    = 0;
            var maxTryTimes = 10;

            do
            {
                tryCount++;
                if (tryCount > maxTryTimes)
                {
                    throw new SagaServerException("retry too many times but version expired");
                }
                var detail = await QueryGlobalTxAsync(xid);

                var reply = await Client.SubmitGlobalTransactionStateAsync(
                    new SubmitGlobalTransactionStateRequest()
                {
                    Xid        = xid,
                    OldState   = detail.State,
                    State      = state,
                    OldVersion = detail.Version
                });

                if (reply.Code == ResourceChangedErrorCode)
                {
                    continue;
                }
                if (reply.Code != OkCode)
                {
                    throw new SagaServerException(reply.Error);
                }
                return(reply.State);
            } while (true);
        }
예제 #6
0
        internal void FreePage(long pageNumber)
        {
            if (_disposed != TxState.None)
            {
                ThrowObjectDisposed();
            }

            try
            {
                UntrackPage(pageNumber);
                Debug.Assert(pageNumber >= 0);

                _pageLocator.Reset(pageNumber); // Remove it from the page locator.

                _freeSpaceHandling.FreePage(this, pageNumber);
                _freedPages.Add(pageNumber);

                if (_scratchPagesTable.TryGetValue(pageNumber, out var scratchPage))
                {
                    if (_transactionPages.Remove(scratchPage))
                    {
                        _unusedScratchPages.Add(scratchPage);
                    }

                    _scratchPagesTable.Remove(pageNumber);
                }

                DiscardScratchModificationOn(pageNumber);
            }
            catch
            {
                _disposed |= TxState.Errored;
                throw;
            }
        }
예제 #7
0
        /// <summary>
        /// Completes the async commit began previously. Must be called *within* the
        /// write lock, and must happen *before* the new transaction call its own commit
        /// method.
        /// </summary>
        public void EndAsyncCommit()
        {
            if (AsyncCommit == null)
            {
                _disposed |= TxState.Errored;
                ThrowInvalidAsyncEndWithoutBegin();
                return;// never reached
            }

            try
            {
                AsyncCommit.Wait();
            }
            catch (Exception e)
            {
                // an exception being thrown while / after / somewhere in the middle
                // of writing to the journal means that we don't know what the current
                // state of the journal is. We have to shut down and run recovery to
                // come to a known good state
                _disposed |= TxState.Errored;
                _env.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e));

                throw;
            }

            if (AsyncCommit.Result)
            {
                Environment.LastWorkTime = DateTime.UtcNow;
            }

            CommitStage3_DisposeTransactionResources();
            BeforeCommitFinalization?.Invoke(this);
        }
예제 #8
0
        public void SetTxState(TxState state)
        {
            if (state == null)
            {
                return;
            }

            lock (listTxlock)
            {
                var results = transactions.Where(x => x.hash == state.hash).ToList();
                if (results.Count > 0)
                {
                    var oldstate = results[0];
                    oldstate.height   = state.height;
                    oldstate.time     = state.time;
                    oldstate.position = state.position;
                    oldstate.size     = state.size;
                    oldstate.offset   = state.offset;
                }
                else
                {
                    transactions.Add(state);
                }
            }
        }
예제 #9
0
        public async Task <TxState> SubmitBranchTxStateAsync(
            string xid, string branchTxId, TxState oldState, TxState state, int oldVersion,
            string jobId, string errorReason, byte[] sagaData)
        {
            ByteString sagaDataByteString = null;

            if (sagaData != null)
            {
                using (var ms = new MemoryStream(sagaData))
                {
                    sagaDataByteString = ByteString.FromStream(ms);
                }
            }
            var reply = await Client.SubmitBranchTransactionStateAsync(
                new SubmitBranchTransactionStateRequest()
            {
                Xid         = xid,
                BranchId    = branchTxId,
                OldState    = oldState,
                State       = state,
                OldVersion  = oldVersion,
                JobId       = jobId,
                ErrorReason = errorReason,
                SagaData    = sagaDataByteString
            });

            if (reply.Code != OkCode)
            {
                throw new SagaServerException(reply.Error);
            }
            return(reply.State);
        }
        public async Task CommitAsync(Enlistment enlistment)
        {
            using (await this.syncObject.LockAsync().Await())
            {
                try
                {
                    Tracer.Debug("Commit notification received for TX id: " + this.TransactionId);

                    if (this.TransactionId != null)
                    {
                        // Now notify the broker that a new XA'ish transaction has completed.
                        TransactionInfo info = new TransactionInfo();
                        info.ConnectionId  = this.connection.ConnectionId;
                        info.TransactionId = this.TransactionId;
                        info.Type          = (int)TransactionType.CommitTwoPhase;

                        await this.connection.CheckConnectedAsync().Await();

                        await this.connection.SyncRequestAsync(info).Await();

                        Tracer.Debug("Transaction Commit Done TX id: " + this.TransactionId);

                        RecoveryLogger.LogRecovered(this.TransactionId as XATransactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        enlistment.Done();

                        AfterCommit();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Commit failed with error: {1}",
                                       this.TransactionId, ex.Message);
                    try
                    {
                        this.connection.OnAsyncException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.TransactionId     = null;
                    this.netTxState        = TxState.None;

                    CountDownLatch latch = this.recoveryComplete;
                    if (latch != null)
                    {
                        latch.countDown();
                    }

                    this.dtcControlEvent.Set();
                }
            }
        }
예제 #11
0
 public RefundResponseMessage(string oid, string pid, Refund refund, TxState state, string msg, ResponseReasonCode reason)
     : base(Methods.REFUND_RESPONSE)
 {
     this.orderId   = oid;
     this.paymentId = pid;
     this.refund    = refund;
     this.code      = state;
     this.message   = msg;
     this.reason    = reason;
 }
예제 #12
0
        public void SinglePhaseCommit(SinglePhaseEnlistment enlistment)
        {
            lock (this.syncObject)
            {
                try
                {
                    Tracer.Debug("Single Phase Commit notification received for TX id: " + this.transactionId);

                    if (this.transactionId != null)
                    {
                        BeforeEnd();

                        // Now notify the broker that a new XA'ish transaction has completed.
                        TransactionInfo info = new TransactionInfo();
                        info.ConnectionId  = this.connection.ConnectionId;
                        info.TransactionId = this.transactionId;
                        info.Type          = (int)TransactionType.CommitOnePhase;

                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        Tracer.Debug("Transaction Single Phase Commit Done TX id: " + this.transactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        enlistment.Done();

                        AfterCommit();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Single Phase Commit failed with error: {1}",
                                       this.transactionId, ex.Message);
                    AfterRollback();
                    enlistment.Done();
                    try
                    {
                        this.connection.OnException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.transactionId     = null;
                    this.netTxState        = TxState.None;

                    this.dtcControlEvent.Set();
                }
            }
        }
예제 #13
0
        /// <summary>
        /// This begins an async commit and starts a new transaction immediately.
        /// The current transaction is considered completed in memory but not yet
        /// committed to disk. This *must* be completed by calling EndAsyncCommit.
        /// </summary>
        public LowLevelTransaction BeginAsyncCommitAndStartNewTransaction()
        {
            if (Flags != TransactionFlags.ReadWrite)
            {
                ThrowReadTranscationCannotDoAsyncCommit();
            }
            if (_asyncCommitNextTransaction != null)
            {
                ThrowAsyncCommitAlreadyCalled();
            }

            // we have to check the state before we complete the transaction
            // because that would change whether we need to write to the journal
            var writeToJournalIsRequired = WriteToJournalIsRequired();

            CommitStage1_CompleteTransaction();

            var nextTx = new LowLevelTransaction(this,
                                                 writeToJournalIsRequired ? Id + 1 : Id
                                                 );

            _asyncCommitNextTransaction = nextTx;
            AsyncCommit = writeToJournalIsRequired
                  ? Task.Run(() => { CommitStage2_WriteToJournal(); return(true); })
                  : NoWriteToJournalRequiredTask;

            try
            {
                _env.IncrementUsageOnNewTransaction();
                _env.ActiveTransactions.Add(nextTx);
                _env.WriteTransactionStarted();

                return(nextTx);
            }
            catch (Exception)
            {
                // failure here means that we'll try to complete the current transaction normaly
                // then throw as if commit was called normally and the next transaction failed

                _env.DecrementUsageOnTransactionCreationFailure();

                EndAsyncCommit();

                AsyncCommit = null;

                _disposed |= TxState.Errored;

                throw;
            }
        }
        public async Task InDoubtAsync(Enlistment enlistment)
        {
            using (await syncObject.LockAsync().Await())
            {
                try
                {
                    Tracer.Debug("In Doubt notification received for TX id: " + this.TransactionId);

                    await BeforeEndAsync().Await();

                    // Now notify the broker that Rollback should be performed.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId  = this.connection.ConnectionId;
                    info.TransactionId = this.TransactionId;
                    info.Type          = (int)TransactionType.End;

                    await this.connection.CheckConnectedAsync().Await();

                    await this.connection.SyncRequestAsync((TransactionInfo)info.Clone()).Await();

                    info.Type = (int)TransactionType.Rollback;
                    await this.connection.CheckConnectedAsync().Await();

                    await this.connection.SyncRequestAsync(info).Await();

                    Tracer.Debug("InDoubt Transaction Rollback Done TX id: " + this.TransactionId);

                    RecoveryLogger.LogRecovered(this.TransactionId as XATransactionId);

                    // if server responds that nothing needs to be done, then reply done.
                    enlistment.Done();

                    AfterRollback();
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.TransactionId     = null;
                    this.netTxState        = TxState.None;

                    CountDownLatch latch = this.recoveryComplete;
                    if (latch != null)
                    {
                        latch.countDown();
                    }

                    this.dtcControlEvent.Set();
                }
            }
        }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private org.neo4j.kernel.impl.api.TransactionToApply createNodeAndProperty(int progress) throws Exception
            internal virtual TransactionToApply CreateNodeAndProperty(int progress)
            {
                TransactionState txState = new TxState();
                long             nodeId  = NodeIds.nextId();

                txState.NodeDoCreate(nodeId);
                txState.NodeDoAddLabel(outerInstance.descriptor.LabelId, nodeId);
                txState.NodeDoAddProperty(nodeId, outerInstance.descriptor.PropertyId, PropertyValue(Id, progress));
                ICollection <StorageCommand> commands = new List <StorageCommand>();

                using (StorageReader statement = StorageEngine.newReader())
                {
                    StorageEngine.createCommands(commands, txState, statement, null, 0, NO_DECORATION);
                }
                return(Tx(commands));
            }
예제 #16
0
 private void prepareToTransmitFlags(int seconds)
 {
     if (tx_state != TxState.IDLE)
     {
         if (ConsoleOut)
         {
             Console.WriteLine("Warning: trying to trasmit while Afsk1200 modulator is busy, discarding");
         }
         return;
     }
     ;
     tx_bytes        = null;                                                // no data
     tx_state        = TxState.PREAMBLE;
     tx_index        = (int)Math.Ceiling((double)seconds / (8.0 / 1200.0)); // number of flags to transmit
     tx_symbol_phase = tx_dds_phase = 0.0f;
 }
예제 #17
0
        private TxState GetTxState()
        {
            TxState state;

            if (!_resuableTxState.TryTake(out state))
            {
                state             = new TxState();
                state.ReadContext = new ReadContext();
                int capacity = PartitionSize + RESERVED_PARTITION_COUNT;
                state.Partitions           = new List <IPartition>(capacity);
                state.Locks                = new List <bool>();
                state.PartitionDataStorage = new PartitionTxData[capacity];
            }

            return(state);
        }
예제 #18
0
        public void Dispose()
        {
            if (_disposed.HasFlag(TxState.Disposed))
            {
                return;
            }

            try
            {
                if (!Committed && !RolledBack && Flags == TransactionFlags.ReadWrite)
                {
                    Rollback();
                }

                _disposed |= TxState.Disposed;

                PersistentContext.FreePageLocator(_pageLocator);
            }
            finally
            {
                _env.TransactionCompleted(this);

                foreach (var pagerState in _pagerStates)
                {
                    pagerState.Release();
                }

                if (JournalFiles != null)
                {
                    foreach (var journalFile in JournalFiles)
                    {
                        journalFile.Release();
                    }
                }

                _root?.Dispose();
                _freeSpaceTree?.Dispose();

                _allocator.AllocationFailed -= MarkTransactionAsFailed;
                if (_disposeAllocator)
                {
                    _allocator.Dispose();
                }

                OnDispose?.Invoke(this);
            }
        }
예제 #19
0
        private void StoreTxState(uint blocktime, uint height, DecodeRawTransactionResponse txraw, RawTransactionResponse tx,
                                  uint index, long offset, uint rawsize)
        {
            var time = blocktime < PeercoinConstants.ProtocolV10SwitchTime && txraw.time.HasValue
                                ? (uint)txraw.time.Value
                                : blocktime;

            var state = new TxState {
                hash     = txraw.txid,
                height   = height,
                offset   = (uint)offset,
                position = index,
                size     = rawsize,
                time     = time
            };

            transactionRepository.SetTxState(state);
        }
예제 #20
0
        public async Task <TxState> SubmitGlobalTxStateAsync(
            string xid, TxState oldState, TxState state, int oldVersion)
        {
            var reply = await Client.SubmitGlobalTransactionStateAsync(
                new SubmitGlobalTransactionStateRequest()
            {
                Xid        = xid,
                OldState   = oldState,
                State      = state,
                OldVersion = oldVersion
            });

            if (reply.Code != OkCode)
            {
                throw new SagaServerException(reply.Error);
            }
            return(reply.State);
        }
예제 #21
0
 public static string GetStateString(TxState state)
 {
     if (state == TxState.Confirmed)
     {
         return(TextTools.RetrieveStringFromResource("Confirmed"));
     }
     else if (state == TxState.Awaiting)
     {
         return(TextTools.RetrieveStringFromResource("Awaiting"));
     }
     else if (state == TxState.Unconfirmed)
     {
         return(TextTools.RetrieveStringFromResource("Unconfirmed"));
     }
     else
     {
         return("NA");
     }
 }
예제 #22
0
 private void prepareToTransmit(Packet p)
 {
     if (tx_state != TxState.IDLE)
     {
         if (ConsoleOut)
         {
             Console.WriteLine("Warning: trying to trasmit while Afsk1200 modulator is busy, discarding");
         }
         return;
     }
     ;
     tx_bytes = p.bytesWithCRC();                                    // This includes the CRC
     tx_state = TxState.PREAMBLE;
     tx_index = (int)Math.Ceiling(tx_delay * 0.01 / (8.0 / 1200.0)); // number of flags to transmit
     if (tx_index < 1)
     {
         tx_index = 1;
     }
     tx_symbol_phase = tx_dds_phase = 0.0f;
 }
예제 #23
0
        private sbyte[] CreateCommands(string tokenName)
        {
            StorageEngine storageEngine           = _storageEngineSupplier.get();
            ICollection <StorageCommand> commands = new List <StorageCommand>();
            TransactionState             txState  = new TxState();
            int tokenId = Math.toIntExact(_idGeneratorFactory.get(_tokenIdType).nextId());

            _tokenCreator.createToken(txState, tokenName, tokenId);
            try
            {
                using (StorageReader statement = storageEngine.NewReader())
                {
                    storageEngine.CreateCommands(commands, txState, statement, [email protected]_Fields.None, long.MaxValue, NO_DECORATION);
                }
            }
            catch (Exception e) when(e is CreateConstraintFailureException || e is TransactionFailureException || e is ConstraintValidationException)
            {
                throw new Exception("Unable to create token '" + tokenName + "'", e);
            }

            return(ReplicatedTokenRequestSerializer.CommandBytes(commands));
        }
예제 #24
0
        private void CommitStage2_WriteToJournal()
        {
            // In the case of non-lazy transactions, we must flush the data from older lazy transactions
            // to ensure the sequentiality of the data.
            Stopwatch sp = null;

            if (_requestedCommitStats != null)
            {
                sp = Stopwatch.StartNew();
            }

            string journalFilePath;
            CompressedPagesResult numberOfWrittenPages;

            try
            {
                numberOfWrittenPages = _journal.WriteToJournal(this, out journalFilePath);
                FlushedToJournal     = true;
                _updatePageTranslationTableAndUnusedPages = numberOfWrittenPages.UpdatePageTranslationTableAndUnusedPages;
                if (SimulateThrowingOnCommitStage2)
                {
                    ThrowSimulateErrorOnCommitStage2();
                }
            }
            catch
            {
                _disposed |= TxState.Errored;
                throw;
            }

            if (_requestedCommitStats != null)
            {
                _requestedCommitStats.WriteToJournalDuration    = sp.Elapsed;
                _requestedCommitStats.NumberOfModifiedPages     = numberOfWrittenPages.NumberOfUncompressedPages;
                _requestedCommitStats.NumberOf4KbsWrittenToDisk = numberOfWrittenPages.NumberOf4Kbs;
                _requestedCommitStats.JournalFilePath           = journalFilePath;
            }
        }
예제 #25
0
        private void CommitStage3_DisposeTransactionResources()
        {
            // an exception being thrown after the transaction has been committed to disk
            // will corrupt the in memory state, and require us to restart (and recover) to
            // be in a valid state
            try
            {
                ValidateAllPages();

                Allocator.Release(ref _txHeaderMemory);

                Committed = true;

                _updatePageTranslationTableAndUnusedPages?.ExecuteAfterCommit();

                _env.TransactionAfterCommit(this);

                if (_asyncCommitNextTransaction != null)
                {
                    var old = _asyncCommitNextTransaction.JournalFiles;
                    _asyncCommitNextTransaction.JournalFiles = _env.Journal.Files;
                    foreach (var journalFile in _asyncCommitNextTransaction.JournalFiles)
                    {
                        journalFile.AddRef();
                    }
                    foreach (var journalFile in old)
                    {
                        journalFile.Release();
                    }
                }
            }
            catch (Exception e)
            {
                _disposed |= TxState.Errored;
                _env.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e));
                throw;
            }
        }
예제 #26
0
        public void Prepare(PreparingEnlistment preparingEnlistment)
        {
            lock (this.syncObject)
            {
                this.netTxState = TxState.Pending;

                try
                {
                    Tracer.Debug("Prepare notification received for TX id: " + this.transactionId);

                    BeforeEnd();

                    // Before sending the request to the broker, log the recovery bits, if
                    // this fails we can't prepare and the TX should be rolled back.
                    RecoveryLogger.LogRecoveryInfo(this.transactionId as XATransactionId,
                                                   preparingEnlistment.RecoveryInformation());

                    // Inform the broker that work on the XA'sh TX Branch is complete.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId = this.connection.ConnectionId;
                    info.TransactionId = this.transactionId;
                    info.Type = (int) TransactionType.End;

                    this.connection.CheckConnected();
                    this.connection.SyncRequest(info);

                    // Prepare the Transaction for commit.
                    info.Type = (int) TransactionType.Prepare;
                    IntegerResponse response = (IntegerResponse) this.connection.SyncRequest(info);
                    if (response.Result == XA_READONLY)
                    {
                        Tracer.Debug("Transaction Prepare done and doesn't need a commit, TX id: " + this.transactionId);

                        this.transactionId = null;
                        this.currentEnlistment = null;

                        // Read Only means there's nothing to recover because there was no
                        // change on the broker.
                        RecoveryLogger.LogRecovered(this.transactionId as XATransactionId);

                        // if server responds that nothing needs to be done, then reply prepared
                        // but clear the current state data so we appear done to the commit method.
                        preparingEnlistment.Prepared();

                        // Done so commit won't be called.
                        AfterCommit();

                        // A Read-Only TX is considered closed at this point, DTC won't call us again.
                        this.dtcControlEvent.Set();
                    }
                    else
                    {
                        Tracer.Debug("Transaction Prepare succeeded TX id: " + this.transactionId);

                        // If work finished correctly, reply prepared
                        preparingEnlistment.Prepared();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Prepare failed with error: {1}",
                                       this.transactionId, ex.Message);

                    AfterRollback();
                    preparingEnlistment.ForceRollback();
                    try
                    {
                        this.connection.OnException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }

                    this.currentEnlistment = null;
                    this.transactionId = null;
                    this.netTxState = TxState.None;
                    this.dtcControlEvent.Set();
                }
            }
        }
예제 #27
0
        public void SinglePhaseCommit(SinglePhaseEnlistment enlistment)
        {
            lock (this.syncObject)
            {
                try
                {
                    Tracer.Debug("Single Phase Commit notification received for TX id: " + this.transactionId);

                    if (this.transactionId != null)
                    {
                        BeforeEnd();

                        // Now notify the broker that a new XA'ish transaction has completed.
                        TransactionInfo info = new TransactionInfo();
                        info.ConnectionId = this.connection.ConnectionId;
                        info.TransactionId = this.transactionId;
                        info.Type = (int) TransactionType.CommitOnePhase;

                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        Tracer.Debug("Transaction Single Phase Commit Done TX id: " + this.transactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        enlistment.Done();

                        AfterCommit();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Single Phase Commit failed with error: {1}",
                                       this.transactionId, ex.Message);
                    AfterRollback();
                    enlistment.Done();
                    try
                    {
                        this.connection.OnException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.transactionId = null;
                    this.netTxState = TxState.None;

                    this.dtcControlEvent.Set();
                }
            }
        }
예제 #28
0
        public void Rollback(Enlistment enlistment)
        {
            lock (this.syncObject)
            {
                try
                {
                    Tracer.Debug("Rollback notification received for TX id: " + this.transactionId);

                    if (this.transactionId != null)
                    {
                        BeforeEnd();

                        // Now notify the broker that a new XA'ish transaction has started.
                        TransactionInfo info = new TransactionInfo();
                        info.ConnectionId = this.connection.ConnectionId;
                        info.TransactionId = this.transactionId;
                        info.Type = (int) TransactionType.End;

                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        info.Type = (int) TransactionType.Rollback;
                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        Tracer.Debug("Transaction Rollback Done TX id: " + this.transactionId);

                        RecoveryLogger.LogRecovered(this.transactionId as XATransactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        enlistment.Done();

                        AfterRollback();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Rollback failed with error: {1}",
                                       this.transactionId, ex.Message);
                    AfterRollback();
                    try
                    {
                        this.connection.OnException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.transactionId = null;
                    this.netTxState = TxState.None;

                    CountDownLatch latch = this.recoveryComplete;
                    if (latch != null)
                    {
                        latch.countDown();
                    }

                    this.dtcControlEvent.Set();
                }
            }
        }
        public async Task PrepareAsync(PreparingEnlistment preparingEnlistment)
        {
            using (await this.syncObject.LockAsync().Await())
            {
                this.netTxState = TxState.Pending;

                try
                {
                    Tracer.Debug("Prepare notification received for TX id: " + this.TransactionId);

                    await BeforeEndAsync().Await();

                    // Before sending the request to the broker, log the recovery bits, if
                    // this fails we can't prepare and the TX should be rolled back.
                    RecoveryLogger.LogRecoveryInfo(this.TransactionId as XATransactionId,
                                                   preparingEnlistment.RecoveryInformation());

                    // Inform the broker that work on the XA'sh TX Branch is complete.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId  = this.connection.ConnectionId;
                    info.TransactionId = this.TransactionId;
                    info.Type          = (int)TransactionType.End;

                    await this.connection.CheckConnectedAsync().Await();

                    await this.connection.SyncRequestAsync((TransactionInfo)info.Clone()).Await();

                    // Prepare the Transaction for commit.
                    info.Type = (int)TransactionType.Prepare;
                    IntegerResponse response = (IntegerResponse)await this.connection.SyncRequestAsync(info).Await();

                    if (response.Result == XA_READONLY)
                    {
                        Tracer.Debug("Transaction Prepare done and doesn't need a commit, TX id: " + this.TransactionId);

                        this.TransactionId     = null;
                        this.currentEnlistment = null;

                        // Read Only means there's nothing to recover because there was no
                        // change on the broker.
                        RecoveryLogger.LogRecovered(this.TransactionId as XATransactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        // otherwise the DTC will call Commit or Rollback but another transaction
                        // can already be in progress and this one would be commited or rolled back
                        // immediately.
                        preparingEnlistment.Done();

                        // Done so commit won't be called.
                        AfterCommit();

                        // A Read-Only TX is considered closed at this point, DTC won't call us again.
                        this.dtcControlEvent.Set();
                    }
                    else
                    {
                        Tracer.Debug("Transaction Prepare succeeded TX id: " + this.TransactionId);

                        // If work finished correctly, reply prepared
                        preparingEnlistment.Prepared();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Prepare failed with error: {1}",
                                       this.TransactionId, ex.Message);

                    AfterRollback();
                    preparingEnlistment.ForceRollback();
                    try
                    {
                        this.connection.OnAsyncException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }

                    this.currentEnlistment = null;
                    this.TransactionId     = null;
                    this.netTxState        = TxState.None;
                    this.dtcControlEvent.Set();
                }
            }
        }
        public void Begin(Transaction transaction)
        {
            using (syncObject.Lock())
            {
                dtcControlEvent.Reset();

                Tracer.Debug("Begin notification received");

                if (InNetTransaction)
                {
                    throw new TransactionInProgressException("A Transaction is already in Progress");
                }

                try
                {
                    Guid rmId = ResourceManagerGuid;

                    // Enlist this object in the transaction.
                    this.currentEnlistment = transaction.EnlistDurable(rmId, this, EnlistmentOptions.None);

                    // In case of a exception in the current method the transaction will be rolled back.
                    // Until Begin Transaction is completed we consider to be in a rollback scenario.
                    this.netTxState = TxState.Pending;

                    Tracer.Debug("Enlisted in Durable Transaction with RM Id: " + rmId);

                    TransactionInformation txInfo = transaction.TransactionInformation;

                    XATransactionId xaId = new XATransactionId();
                    this.TransactionId = xaId;

                    if (txInfo.DistributedIdentifier != Guid.Empty)
                    {
                        xaId.GlobalTransactionId = txInfo.DistributedIdentifier.ToByteArray();
                        xaId.BranchQualifier     = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
                    }
                    else
                    {
                        xaId.GlobalTransactionId = Encoding.UTF8.GetBytes(txInfo.LocalIdentifier);
                        xaId.BranchQualifier     = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
                    }

                    // Now notify the broker that a new XA'ish transaction has started.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId  = this.connection.ConnectionId;
                    info.TransactionId = this.TransactionId;
                    info.Type          = (int)TransactionType.Begin;

                    this.session.Connection.Oneway(info);

                    // Begin Transaction is completed successfully. Change to transaction active state now.
                    this.netTxState = TxState.Active;

                    SignalTransactionStarted();

                    if (Tracer.IsDebugEnabled)
                    {
                        Tracer.Debug("Began XA'ish Transaction:" + xaId);
                    }
                }
                catch (Exception)
                {
                    // When in pending state the rollback will signal that a new transaction can be started. Otherwise do it here.
                    if (netTxState != TxState.Pending)
                    {
                        netTxState = TxState.None;
                        dtcControlEvent.Set();
                    }
                    throw;
                }
            }
        }
예제 #31
0
        private async Task UpdateState(ISet <string> acceptors, string txId, BallotNumber ballot, TxState state, int timeoutMs)
        {
            var reqId      = Guid.NewGuid().ToString();
            var localMutex = new object();
            var isAccepted = false;
            var acks       = new HashSet <string>();
            var accepted   = new TaskCompletionSource <bool>();

            foreach (var acceptorId in acceptors)
            {
                this.bus.AcceptUpdate(acceptorId, new AcceptUpdateMessage(reqId, txId, ballot, state));
            }

            var handler1 = this.bus.WaitForUpdateAccepted(reqId, (acceptorId) =>
            {
                lock (localMutex)
                {
                    if (isAccepted)
                    {
                        return(WaitStrategy.StopWaiting);
                    }
                    acks.Add(acceptorId);
                    if (acks.Count >= 1 + acceptors.Count / 2)
                    {
                        isAccepted = true;
                        accepted.SetResult(true);
                        return(WaitStrategy.StopWaiting);
                    }
                    return(WaitStrategy.KeepWaiting);
                }
            });

            this.timer.SetTimeout(() =>
            {
                lock (localMutex)
                {
                    if (isAccepted)
                    {
                        return;
                    }
                    accepted.SetException(new TimeoutException());
                    handler1.Dispose();
                }
            }, timeoutMs);

            _ = await accepted.Task;
        }
예제 #32
0
        public void Rollback(Enlistment enlistment)
        {
            lock (this.syncObject)
            {
                try
                {
                    Tracer.Debug("Rollback notification received for TX id: " + this.transactionId);

                    if (this.transactionId != null)
                    {
                        BeforeEnd();

                        // Now notify the broker that a new XA'ish transaction has started.
                        TransactionInfo info = new TransactionInfo();
                        info.ConnectionId  = this.connection.ConnectionId;
                        info.TransactionId = this.transactionId;
                        info.Type          = (int)TransactionType.End;

                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        info.Type = (int)TransactionType.Rollback;
                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        Tracer.Debug("Transaction Rollback Done TX id: " + this.transactionId);

                        RecoveryLogger.LogRecovered(this.transactionId as XATransactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        enlistment.Done();

                        AfterRollback();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Rollback failed with error: {1}",
                                       this.transactionId, ex.Message);
                    AfterRollback();
                    try
                    {
                        this.connection.OnException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.transactionId     = null;
                    this.netTxState        = TxState.None;

                    CountDownLatch latch = this.recoveryComplete;
                    if (latch != null)
                    {
                        latch.countDown();
                    }

                    this.dtcControlEvent.Set();
                }
            }
        }
예제 #33
0
 public TxStateMessage(TxState txState)
     : base(Methods.TX_STATE)
 {
     this.txState = txState;
 }
예제 #34
0
        public void Begin(Transaction transaction)
        {
            lock (syncObject)
            {
                this.netTxState = TxState.Active;
                dtcControlEvent.Reset();

                Tracer.Debug("Begin notification received");

                if (InNetTransaction)
                {
                    throw new TransactionInProgressException("A Transaction is already in Progress");
                }

                try
                {
                    Guid rmId = ResourceManagerGuid;

                    // Enlist this object in the transaction.
                    this.currentEnlistment =
                        transaction.EnlistDurable(rmId, this, EnlistmentOptions.None);

                    Tracer.Debug("Enlisted in Durable Transaction with RM Id: " + rmId);

                    TransactionInformation txInfo = transaction.TransactionInformation;

                    XATransactionId xaId = new XATransactionId();
                    this.transactionId = xaId;

                    if (txInfo.DistributedIdentifier != Guid.Empty)
                    {
                        xaId.GlobalTransactionId = txInfo.DistributedIdentifier.ToByteArray();
                        xaId.BranchQualifier = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
                    }
                    else
                    {
                        xaId.GlobalTransactionId = Encoding.UTF8.GetBytes(txInfo.LocalIdentifier);
                        xaId.BranchQualifier = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
                    }

                    // Now notify the broker that a new XA'ish transaction has started.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId = this.connection.ConnectionId;
                    info.TransactionId = this.transactionId;
                    info.Type = (int) TransactionType.Begin;

                    this.session.Connection.Oneway(info);

                    if (Tracer.IsDebugEnabled)
                    {
                        Tracer.Debug("Began XA'ish Transaction:" + xaId.GlobalTransactionId.ToString());
                    }
                }
                catch (Exception)
                {
                    dtcControlEvent.Set();
                    throw;
                }
            }
        }
예제 #35
0
        public void InDoubt(Enlistment enlistment)
        {
            lock (syncObject)
            {
                try
                {
                    Tracer.Debug("In Doubt notification received for TX id: " + this.transactionId);

                    BeforeEnd();

                    // Now notify the broker that Rollback should be performed.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId = this.connection.ConnectionId;
                    info.TransactionId = this.transactionId;
                    info.Type = (int) TransactionType.End;

                    this.connection.CheckConnected();
                    this.connection.SyncRequest(info);

                    info.Type = (int) TransactionType.Rollback;
                    this.connection.CheckConnected();
                    this.connection.SyncRequest(info);

                    Tracer.Debug("InDoubt Transaction Rollback Done TX id: " + this.transactionId);

                    RecoveryLogger.LogRecovered(this.transactionId as XATransactionId);

                    // if server responds that nothing needs to be done, then reply done.
                    enlistment.Done();

                    AfterRollback();
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.transactionId = null;
                    this.netTxState = TxState.None;

                    CountDownLatch latch = this.recoveryComplete;
                    if (latch != null)
                    {
                        latch.countDown();
                    }

                    this.dtcControlEvent.Set();
                }
            }
        }
예제 #36
0
 public PromiseAcceptedMessage(BallotNumber prevBallot, TxState state)
 {
     this.PrevBallot = prevBallot;
     this.State      = state;
 }
예제 #37
0
 public RefundResponseMessage(string oid, string pid, Refund refund, TxState state, string msg, ResponseReasonCode reason)
     : base(Methods.REFUND_RESPONSE)
 {
     this.orderId = oid;
     this.paymentId = pid;
     this.refund = refund;
     this.code = state;
     this.message = msg;
     this.reason = reason;
 }