/// <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(); } }
/// <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 } } }
/// <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(); } }
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()); }
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(); })); }
public async Task Remove(IEnumerable <Domain.Transaction> batch) => await TransactionPool.Remove(batch);