// exemplo: w1(x)-r2(y)-w2(y)-c2-w1(y) public void History(string entryTransaction, TextBox output, TextBox RunningRow, TextBox WaitingTransaction, TextBox AbortedTransaction, TextBox Queue, TextBox DataLock) { string[] transactionList; // Quebra a string de entrada em um vetor de string transactionList = entryTransaction.Split('-'); OutPut = output; if (ExecutionRow == null) { ExecutionRow = new Queue <string>(transactionList); } if (ExecutionRow.Count > 0) { RunCommand(ExecutionRow.Dequeue()); CheckWaitingQueue(); RunningRow.Text = RetornaRunningRow(); WaitingTransaction.Text = ReturnWaitingTransactions(); AbortedTransaction.Text = ReturnTransactionsAborteds(); Queue.Text = ReturnQueue(); DataLock.Text = ReturnDataLock(); SetFinalPoint(OutPut); RunningRow.Refresh(); WaitingTransaction.Refresh(); AbortedTransaction.Refresh(); DataLock.Refresh(); SetFinalPoint(Queue); } else { OutPut.Text += "\r\nExecução finalizada."; SetFinalPoint(OutPut); } }
private void CheckWaitingQueue() { // Analisa primeiro comando de cada transação. List <int> excludes = new List <int>(); foreach (var TransactionNumber in WaitingTransactionsList.Keys) { TransactionQueueCommand commandsTransactions = WaitingTransactionsList[TransactionNumber]; if (!commandsTransactions.Transaction.LockType.Equals(TransactionTypeLock.Aborted)) { string firstCommand = commandsTransactions.CheckCommand(); LockDataType LockDataType = ReturnLockType(firstCommand.Substring(0, 1)); FreeData freeData = ReturnFreeData(commandsTransactions.Transaction, LockDataType, commandsTransactions.WaitingData); // Se o dado estiver disponivel remove todos os dados da fila e adiciona novamente à fila de execução int RemovedTransaction = 0; string ciclo = ""; string retorno = ""; switch (freeData) { case FreeData.FreeData: case FreeData.SharedTransactionsData: case FreeData.OtherSharedTransactionsData: Queue <string> tempQueue = new Queue <string>(); // Remove tudo que está na fila de execução para adicionar a fila de espera na frente while (ExecutionRow.Count > 0) { tempQueue.Enqueue(ExecutionRow.Dequeue()); } while (commandsTransactions.QueueCommands.Count > 0) { AddOutPut("Comando: " + commandsTransactions.CheckCommand() + " adicionado à fila de execução."); ExecutionRow.Enqueue(commandsTransactions.RemoveCommand()); } // Adiciona os commandos de volta a fila de execução while (tempQueue.Count > 0) { ExecutionRow.Enqueue(tempQueue.Dequeue()); } commandsTransactions.Transaction.LockType = TransactionTypeLock.Executing; // Adiciona à lista de excluídos para remover no final excludes.Add(TransactionNumber); break; case FreeData.ExclusiveOtherTransactionsData: // Realiza validação para analisar se a transação entrou em deadlock retorno = CheckDeadLock(TransactionNumber, commandsTransactions.WaitingData); RemovedTransaction = int.Parse(retorno.Substring(0, retorno.IndexOf("|"))); ciclo = retorno.Substring(retorno.IndexOf("|") + 1); if (RemovedTransaction > -1) { excludes.Add(RemovedTransaction); // Desaloca dados da transação. string msg = ""; Transactions Transactions = TransactionsList[RemovedTransaction]; // Realiza unlock do dado e retira da lista de dados utilizados. string[] usedData = Transactions.ReturnDataUsed(); msg = "----------- DEAD LOCK ----------- " + "\r\n"; msg += ciclo + "\r\n"; msg += "Transação " + RemovedTransaction + " eliminada, pois foi a que executou menos comandos.\r\n"; AddOutPut(msg); foreach (var dado in usedData) { // Adiciona saída unclok para dados liberados AddOutPut(CreateLock(LockDataType.Unlock, Transactions.TransactionNumber, dado, Transactions.ReturnDataLockType(dado))); // Remove dado e transação da lista de dados locks RemoveDataLocksList(Transactions, dado); // Remove dado da lista de transações Transactions.RemoveData(dado); } Transactions.LockType = TransactionTypeLock.Aborted; } break; } } } foreach (var transactionNumber in excludes) { WaitingTransactionsList.Remove(transactionNumber); } }