public void AddCommandWaitingQueue(Transactions Transactions, string Command) { // Adiciona a transação à fila quando ainda não existir TransactionQueueCommand transactionQueueCommand = null; if (!WaitingTransactionsList.ContainsKey(Transactions.TransactionNumber)) { Transactions.LockType = TransactionTypeLock.Waiting; transactionQueueCommand = new TransactionQueueCommand(Transactions); WaitingTransactionsList.Add(Transactions.TransactionNumber, transactionQueueCommand); } // Retorna a fila de Commands da transação. else { transactionQueueCommand = WaitingTransactionsList[Transactions.TransactionNumber]; } // Adiciona Command à fila de espera da transação. transactionQueueCommand.AddComamand(Command); AddOutPut("Comando: " + Command + " adicionado à fila de espera."); }
private string CheckDeadLock(int TransactionNumber, string Dado, List <int> TransacoesWaiting) { string retorno = "-1|x"; DataLockTransactions TransactionsUsingData; // Se não existir o dado é pq a transação já foi abortada if (TransactionDataLock.ContainsKey(Dado)) { TransactionsUsingData = TransactionDataLock[Dado]; foreach (var transactionNumber in TransactionsUsingData.ReturnTransactions()) { // Não verifica a própria transação if (!transactionNumber.Equals(TransactionNumber)) { // Adiciona na lista e verifica se ocorreu dead lock. if (TransactionsList[TransactionNumber].LockType.Equals(TransactionTypeLock.Waiting)) { if (TransacoesWaiting.Contains(TransactionNumber)) { // Elimina deadlock int eliminatedTransaction = RemoveDeadLock(TransacoesWaiting); retorno = eliminatedTransaction + "|" + ReturnTransactionsCycle(TransacoesWaiting, eliminatedTransaction); } else { TransacoesWaiting.Add(TransactionNumber); // Retorna dado que a transação está espera. TransactionQueueCommand commandsTransactions = WaitingTransactionsList[TransactionNumber]; // Verifica pendencias desta transação. retorno = CheckDeadLock(TransactionNumber, commandsTransactions.WaitingData, TransacoesWaiting); } } } } } return(retorno); }
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); } }