예제 #1
0
        /// <summary>
        /// Aborts a transaction and releases it.
        /// </summary>
        /// <param name="trans">Transaction to be aborted.</param>
        public void AbortTransaction(IDbTransaction trans)
        {
            if (trans == null)
            {
                return;
            }

            bool            isRequestTransaction;
            TransactionInfo transInfo = GetTransactionInfo(trans, out isRequestTransaction);

            if (transInfo != null)
            {
#if DEBUG_DBCONNECTIONPOOLING
                OSTrace.Info("DBConnectionPooling[TID=" + transInfo.Transaction.GetHashCode() + "] - returned to pool");
                OSTrace.Error(new StackTrace().ToString());
#endif

                transInfo.Release();

                if (isRequestTransaction)
                {
                    RequestTransactionInfo = null;
                }
                else
                {
                    TransactionPool.Remove(transInfo.Transaction);
                }

                transInfo.ReturnConnectionToPool();
            }
        }
예제 #2
0
        /// <summary>
        /// Releases a transaction to the pool.
        /// If the transaction is poolable, it is released and put back into the pool, otherwise it is removed.
        /// Throws an <see cref="InvalidTransactionReleaseException"/> if the transaction is not releasable.
        /// </summary>
        /// <exception cref="InvalidTransactionReleaseException">Occurs if the transaction is not releasable.</exception>
        /// <param name="trans">Transaction to be released.</param>
        public virtual void ReleaseTransaction(IDbTransaction trans)
        {
            if (trans == null)
            {
                return;
            }
            TransactionInfo transInfo = (TransactionInfo)TransactionPool[trans];

            if (transInfo != null)
            {
                if (!transInfo.IsReleasable)
                {
                    throw (new InvalidTransactionReleaseException("Cannot release a transaction that was created with \"GetCommitableTransaction\". Use commit or rollback"));
                }
#if DEBUG_DBCONNECTIONPOOLING
                OSTrace.Info("DBConnectionPooling[TID=" + transInfo.Transaction.GetHashCode() + "] - returned to pool");
                OSTrace.Error(new StackTrace().ToString());
#endif
                if (transInfo.IsPoolable)
                {
                    transInfo.Release();
                }
                else
                {
                    TransactionPool.Remove(trans);
                }
            }
            else
            {
                try {
                    if (RequestTransactionInfo != null && trans == RequestTransactionInfo.Transaction)
                    {
                        //when releasing the request transaction make sure the connection is ok
                        if (trans.Connection != null && trans.Connection.State != ConnectionState.Open)
                        {
                            LogException(new InvalidTransactionException("Request transaction not open on release."), new StackTrace(), "Request Transaction discarded due to connection not being in a correct state.");
                            //clear and try to dispose connection
                            lock (this) {
                                RequestTransactionInfo = null;
                            }
                            trans.Connection.Dispose();
                        }
                        else
                        {
                            RequestTransactionInfo.MarkChange();
                        }
                    }
                } catch {
                    //this is a best effort
                }
            }
        }
예제 #3
0
 /// <summary>
 /// Ends a pooled transaction, performing additional cleanup code if necessary.
 /// An error if an exception is raised.
 /// </summary>
 /// <param name="transInfo">Object containing information about the transaction.</param>
 /// <param name="commit">If True, all transaction are committed. Otherwise, they are rolled back.</param>
 /// <param name="toFreeResources">If True, all resources are released and connections returned to the pool.</param>
 protected virtual void EndTransaction(TransactionInfo transInfo, bool commit, bool toFreeResources)
 {
     TransactionPool.Remove(transInfo.Transaction);
     transInfo.Release();
     try {
         if (commit)
         {
             transInfo.Transaction.Commit();
         }
         else
         {
             transInfo.Transaction.Rollback();
         }
     } finally {
         transInfo.ReturnConnectionToPool();
     }
 }
예제 #4
0
        protected TransactionInfo GetAndReserveFromPoolUnchecked()
        {
            TransactionInfo[] transactions;
            lock (TransactionPool.SyncRoot) {
                transactions = TransactionPool.Values.Cast <TransactionInfo>().ToArray();
            }

            foreach (TransactionInfo transInfo in transactions)
            {
                if (transInfo.Free)
                {
                    lock (transInfo) {
                        if (transInfo.Free)
                        {
                            DateTime lastChange = transInfo.LastChange;
                            transInfo.Reserve();

                            //#52135, we already have nice checks for the pooled connections
                            if (transInfo.Transaction.Connection == null || transInfo.Connection.State == ConnectionState.Closed)
                            {
                                // build exception report
                                IDbConnection shadowConnection = transInfo.Connection;
                                string        exceptTxt        = "Connection in transaction is null or closed (TransactionInfo Status: ";
                                try {
                                    if (shadowConnection == null)
                                    {
                                        exceptTxt += "Connection=null, ";
                                    }
                                    else
                                    {
                                        exceptTxt += String.Format("Connection.State=='{0}', ", shadowConnection.State.ToString());
                                    }

                                    exceptTxt += String.Format("Free='{0}', CreationTime='{1}', LastChange='{2}', ReaderCount='{3}')",
                                                               transInfo.Free, transInfo.CreationTime, lastChange, transInfo.ReaderCount);

                                    int numTransactions = transactions.Length;
                                    int numFree         = CountFreeTransactionsInPool(transactions);
                                    exceptTxt += String.Format(". (Pool Status: Total={0}, Free={1})", numTransactions, numFree);
                                } catch {
                                } finally {
                                    // remove and cleanup everything
                                    TransactionPool.Remove(transInfo.Transaction);

                                    transInfo.Transaction.Dispose();

                                    if (transInfo.Connection != null)
                                    {
                                        transInfo.Connection.Dispose();
                                    }
                                }
                                throw new InvalidTransactionException(exceptTxt);
                            }
                            else
                            {
#if DEBUG_DBCONNECTIONPOOLING
                                OSTrace.Info("DBConnectionPooling[TID=" + transInfo.Transaction.GetHashCode() + "] - reserved from pool");
                                OSTrace.Error(new StackTrace().ToString());
#endif
                                return(transInfo);
                            }
                        }
                    }
                }
            }
            // No free transaction found. Add a new one and return it.
            return(AddToPoolAndReserve());
        }
예제 #5
0
파일: Node.cs 프로젝트: migiright/Matcha
 public Task Sync()
 {
     return(Task.Run(async() => {
         Log += "syncing..." + Environment.NewLine;
         OnLogChanged();
         while (true)
         {
             var(index, node) = Nodes.Aggregate((index: BlockChain.Last().Index, node: (Uri)null), (m, n) =>
                                                Task.Run(async() => {
                 HttpResponseMessage response;
                 try {
                     response = await httpClient_.PostAsync(n, new StringContent(JsonConvert.SerializeObject(
                                                                                     new GetCurrentIndex {
                         PortNumber = PortNumber
                     })));
                 } catch (HttpRequestException) {
                     return m;
                 }
                 if (!response.IsSuccessStatusCode)
                 {
                     return m;
                 }
                 var res = JsonConvert.DeserializeObject <GetCurrentIndexResponse>(await response.Content.ReadAsStringAsync());
                 if (res.CurrentIndex <= m.index)
                 {
                     return m;
                 }
                 return (index: res.CurrentIndex, node: n);
             }).Result);
             if (node == null)
             {
                 break;
             }
             if (index > BlockChain.Last().Index)
             {
                 IList <Block> branch;
                 var currentIndex = BlockChain.Last().Index;
                 {
                     HttpResponseMessage response;
                     try {
                         response = await httpClient_.PostAsync(node, new StringContent(JsonConvert.SerializeObject(
                                                                                            new GetBlocks {
                             Index = currentIndex + 1, NumBlocks = index - currentIndex
                         })));
                     } catch (HttpRequestException) {
                         continue;
                     }
                     if (!response.IsSuccessStatusCode)
                     {
                         continue;
                     }
                     var res = JsonConvert.DeserializeObject <GetBlocksResponse>(await response.Content.ReadAsStringAsync());
                     branch = res.Blocks;
                 }
                 if (branch.First().PreviousHash == LastHash)
                 {
                     var removed = false;
                     foreach (var block in branch)
                     {
                         foreach (var transaction in block.Transactions)
                         {
                             if (TransactionPool.Contains(transaction))
                             {
                                 TransactionPool.Remove(transaction);
                                 removed = true;
                             }
                         }
                     }
                     if (removed)
                     {
                         OnTransactionPoolChanged();
                     }
                     BlockChain.AddRange(branch);
                     break;
                 }
                 while (true)
                 {
                     HttpResponseMessage response;
                     try {
                         response = await httpClient_.PostAsync(node, new StringContent(JsonConvert.SerializeObject(
                                                                                            new GetBlocks {
                             Index = currentIndex, NumBlocks = 1
                         })));
                     } catch (HttpRequestException) {
                         goto con;
                     }
                     if (!response.IsSuccessStatusCode)
                     {
                         goto con;
                     }
                     var res = JsonConvert.DeserializeObject <GetBlocksResponse>(await response.Content.ReadAsStringAsync());
                     branch.Insert(0, res.Blocks.First());
                     if (BlockChain[currentIndex].PreviousHash == branch.First().PreviousHash)
                     {
                         break;
                     }
                     --currentIndex;
                 }
                 BlockChain.RemoveRange(currentIndex, BlockChain.Count - currentIndex);
                 var removed2 = false;
                 foreach (var block in branch)
                 {
                     foreach (var transaction in block.Transactions)
                     {
                         if (TransactionPool.Contains(transaction))
                         {
                             TransactionPool.Remove(transaction);
                             removed2 = true;
                         }
                     }
                 }
                 if (removed2)
                 {
                     OnTransactionPoolChanged();
                 }
                 BlockChain.AddRange(branch);
                 break;
             }
             con:;
         }
         LastHash = SerializeHash(GetHash(BlockChain.Last()));
         OnBlockChainChanged();
         Log += "sync completed." + Environment.NewLine;
         OnLogChanged();
     }));
 }
예제 #6
0
 public async Task Remove(IEnumerable <Domain.Transaction> batch) =>
 await TransactionPool.Remove(batch);