private void RemoveDataLocksList(Transactions Transactions, string Dado) { DataLockTransactions dadoLockTransactions = TransactionDataLock[Dado]; if (dadoLockTransactions != null) { dadoLockTransactions.RemoveTransaction(Transactions); /* Se não existe mais nenhuma transação utilizando o dado * então remove da lista de dados utilizados. */ if (dadoLockTransactions.NumberOfTransactions().Equals(0)) { TransactionDataLock.Remove(Dado); } } }
private FreeData ReturnFreeData(Transactions Transactions, LockDataType LockDataType, string Dado) { // Verifica se o dado está lockado para alguma sessão if (TransactionDataLock.ContainsKey(Dado)) { DataLockTransactions usedData = TransactionDataLock[Dado]; // Verifica se está lockado para a transação que está tentando acessar. if (usedData.CheckLockForTransaction(Transactions.TransactionNumber)) { /* Se o tipo de dado for restrito deve ter lock exclusivo, neste caso * não pode estar lockado para outras transações */ if (LockDataType.Equals(LockDataType.Exclusive) && usedData.NumberOfTransactions() > 1) { return(FreeData.ExclusiveOtherTransactionsData); } else { return(FreeData.SharedTransactionsData); } } // Verifica se tem lock exclusivo para outra sessão. else { /* Adiciona à lista de espera quando estiver lock exclusivo para outra transação * Ou quando a transação pediu lock exclusivo */ if (usedData.LockType.Equals(LockDataType.Exclusive) || LockDataType.Equals(LockDataType.Exclusive)) { return(FreeData.ExclusiveOtherTransactionsData); } else { return(FreeData.OtherSharedTransactionsData); } } } // Quandoo dado não está sendo utilizado por nenhuma sessão else { return(FreeData.FreeData); } }
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); }
public void SolvingExecutingTransactions(LockDataType LockDataType, string Dado, Transactions Transactions, string Command) { DataLockTransactions usedData; // Verifica se o dado está disponível if (LockDataType.Equals(LockDataType.Commit)) { /* Quando for commit, verifica se o status da transação esta waiting. * se não estiver percorre a lista de dados lockadas pela transação e libera todas e dispara o commit * Se estiver Waiting adiciona o comando commit a lista de espera */ if (Transactions.LockType.Equals(TransactionTypeLock.Waiting)) { AddCommandWaitingQueue(Transactions, Command); } // libera lock dados e realiza commit. else if (!Transactions.LockType.Equals(TransactionTypeLock.Aborted)) { // Realiza unlock do dado e retira da lista de dados utilizados. string[] usedDataVet = Transactions.ReturnDataUsed(); foreach (var dado in usedDataVet) { // 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); } // Incrementa Commands executados da transação Transactions.ExecutedCommands++; // Adiciona saída para commit. AddOutPut(Command); } } // Verifica disponibidade do dado para a transação e Command else { //DadoLockTransactions usedData; FreeData freeData = ReturnFreeData(Transactions, LockDataType, Dado); // Dado não foi lockado por nenhuma transação if (freeData.Equals(FreeData.FreeData)) { usedData = new DataLockTransactions(Dado, LockDataType); TransactionDataLock.Add(Dado, usedData); TransactionDataLock[Dado].AddTransaction(Transactions); Transactions.AddData(Dado, LockDataType); // Adiciona lock. AddOutPut(CreateLock(LockDataType, Transactions.TransactionNumber, Dado, null)); // Incrementa Commands executados da transação Transactions.ExecutedCommands++; // Adiciona Command lido AddOutPut(Command); } // Dado já esta lockado para a transação, mas como shared else if (freeData.Equals(FreeData.SharedTransactionsData)) { usedData = TransactionDataLock[Dado]; // Faz upgrade no lock se necessário. if (UpgradeLock(usedData, LockDataType, Transactions)) { AddOutPut(CreateLock(LockDataType, Transactions.TransactionNumber, Dado, null)); } // Incrementa Commands executados da transação Transactions.ExecutedCommands++; // Adiciona Command lido AddOutPut(Command); } // Dado está com lock shared em outra transação else if (freeData.Equals(FreeData.OtherSharedTransactionsData)) { // Adiciona o dado à lista de dados da transação Transactions.AddData(Dado, LockDataType); TransactionDataLock[Dado].AddTransaction(Transactions); // Adiciona lock. AddOutPut(CreateLock(LockDataType, Transactions.TransactionNumber, Dado, null)); // Incrementa Commands executados da transação Transactions.ExecutedCommands++; // Adiciona Command lido AddOutPut(Command); } /* Dado está com lock exclusivo em outra transação * ou precisa de lock exclusivo para a transação atual */ else if (freeData.Equals(FreeData.ExclusiveOtherTransactionsData)) { AddCommandWaitingQueue(Transactions, Command); } } }