//o doCommit deveria ser atomico. pode dar problema? internal bool doCommit(ulong tid) { PadIntTransaction objectTransaction = null; PadIntTentative tentative = null; PadIntCommitted commited = null; List <PadIntRemote> toReplicate = new List <PadIntRemote>(); //desbloquear threads em espera no read com Console.WriteLine("Em do commit Tid: " + tid); foreach (int modifiedObject in transactions[tid].getModifiedObjectIds()) { //Console.WriteLine("Em do commit no for Tid: " + tid + "modificou" + modifiedObject); //por commited //remover objecto transaccao //remover objecto tentativa //por tentativa como commited se vamos remover vale a pena? ter em atenção que no read ele ve se o anterior esta commited. nao sei se deviamos eliminar. //actualizar o valor do commited objectTransaction = objectsInServer[modifiedObject]; SortedList <ulong, PadIntTentative> tentatives = objectTransaction.getTentatives(); tentative = tentatives[tid]; commited = objectTransaction.getCommitted(); commited.WriteTimestamp = tid; commited.Value = tentative.Value; toReplicate.Add(commited); tentative.SetCommited(); tentatives.Remove(tid); objectWaitHandle[modifiedObject].Set();//fez commit.temos de notificar threads para avancarem. pendingTransactions[modifiedObject].Set(); } transactions[tid].setCommited(); //Transacção efectuda e agora removida transactions.Remove(tid); if (replica != null) { replica.SendPadInt(toReplicate); } foreach (var p in toReplicate) { Console.WriteLine("replicado = " + p.uid + " " + p.Value); } checkTableOfPendingTransactions(tid); return(true); //sempre verdade? }
internal bool doAbort(ulong tid) { Console.WriteLine("doAbort"); PadIntTransaction objectTransaction = null; PadIntTentative tentative = null; //desbloquear threads em espera no read com foreach (int modifiedObject in transactions[tid].getModifiedObjectIds()) { Console.WriteLine("Abort: " + modifiedObject); //por abort //remover objecto transaccao check //remover objecto tentativa check //por tentativa como commited se vamos remover vale a pena? ter em atenção que no read ele ve se o anterior esta commited. nao sei se deviamos eliminar. //actualizar o valor do commited objectTransaction = objectsInServer[modifiedObject]; SortedList <ulong, PadIntTentative> tentatives = objectTransaction.getTentatives(); tentative = tentatives[tid]; tentative.SetAborted(); tentatives.Remove(tid); PadIntCommitted com = objectTransaction.getCommitted(); //Remove creates if (com.WriteTimestamp == 0) { objectsInServer.Remove(modifiedObject); objectWaitHandle[modifiedObject].Set();//fez commit.temos de notificar threads para avancarem. pendingTransactions[modifiedObject].Set(); objectWaitHandle.Remove(modifiedObject);//fez commit.temos de notificar threads para avancarem. pendingTransactions.Remove(modifiedObject); } else { objectWaitHandle[modifiedObject].Set();//fez commit.temos de notificar threads para avancarem. pendingTransactions[modifiedObject].Set(); } } transactions[tid].setAborted(); //Transacção efectuda e agora removida transactions.Remove(tid); return(true); //sempre verdade? }
public void addTentative(ulong tid, PadIntTentative tentative) { tentatives[tid] = tentative;; }
internal void Write(ulong tid, int uid, int value) { //addicionar objecto modificado //ServerApp.debug = "Write called!"; //fica a espera que sejam transferidos dados de um servidor que sofreu divisao do seeu range pela entrada deste novo server if (tid > maxTID) { waitForPadIntTransfer.Reset(); } if (!objectsInServer.ContainsKey(uid)) { //O objecto nao foi criado no servidor throw new PadIntNotExists(tid, uid); } PadIntTransaction obj = objectsInServer[uid]; PadIntCommitted committed = obj.getCommitted(); ulong tc = committed.WriteTimestamp; //Verificacao 1: Ja existem escritas committed com timestamp superior ao desta transaccao if (tid <= tc) throw new PadIntWriteTooLate(tid, uid); //Debug.WriteLine(); SortedList<ulong, PadIntTentative> tentatives = obj.getTentatives(); PadIntTentative t; //Não existem transações a mexer no objecto com identificador uid if (tentatives.Count == 0) { t = new PadIntTentative(uid, tid, value); obj.addTentative(tid, t); transactions[tid].addModifiedObjectId(uid); ////depois de modificar o object, adiciona-lo à transaccao para sabermos o que mudamos no fim. objectWaitHandle[uid].Reset();//escreveu, bloqueia as threads. O que acontece se não fôr a tempo de bloquear as threads??????? pendingTransactions[uid].Reset(); // dado que escrevemos, as que forem fazer commit teem de esperar //evitar que venha a esperar por si mesma espera por si mesma? return; } //Max de timestamp de leitura das versoes //Func<PadIntTentative, decimal> lam = tent => (decimal) tent.ReadTimestamp; // ulong tMax = tentatives.Max<PadIntTentative,ulong>(x => x.ReadTimestamp); //metodos extendidos. porque nao da? Não apagar. Ainda tenho de //perceber isto Ass:Braga :) ulong tMax = (ulong)tentatives.Max(x => x.Value.ReadTimestamp); //Console.WriteLine("Tid: " + tid + "Tmax: " + tMax); //Verificacao 2: Ja existem leituras de transaccoes a serem processadas if (tid < tMax) { throw new PadIntWriteTooLate(tid, uid); } if (tentatives.ContainsKey(tid)) { PadIntTentative transactionTentative = tentatives[tid]; // transactionTentative.Write(value);--> ja existe uma property //se tem tentativa é porque já escreveu antes. Não é preciso resetar o handle? Ou é???????? transactionTentative.Value = value; } else//primeira tentativa da transacçao tid { t = new PadIntTentative(uid, tid, value); obj.addTentative(tid, t); transactions[tid].addModifiedObjectId(uid); ////depois de modificar o object, adiciona-lo à transaccao para sabermos o que mudamos no fim. objectWaitHandle[uid].Reset();///primeira tentativa de escrita. Reseta handle para bloquear threads. pendingTransactions[uid].Reset(); // dado que escrevemos, as que forem fazer commit teem de esperar } }
public void addTentative(ulong tid,PadIntTentative tentative) { tentatives[tid] = tentative; ; }
internal void Write(ulong tid, int uid, int value) { //addicionar objecto modificado //ServerApp.debug = "Write called!"; //fica a espera que sejam transferidos dados de um servidor que sofreu divisao do seeu range pela entrada deste novo server if (tid > maxTID) { waitForPadIntTransfer.Reset(); } if (!objectsInServer.ContainsKey(uid)) { //O objecto nao foi criado no servidor throw new PadIntNotExists(tid, uid); } PadIntTransaction obj = objectsInServer[uid]; PadIntCommitted committed = obj.getCommitted(); ulong tc = committed.WriteTimestamp; //Verificacao 1: Ja existem escritas committed com timestamp superior ao desta transaccao if (tid <= tc) { throw new PadIntWriteTooLate(tid, uid); } //Debug.WriteLine(); SortedList <ulong, PadIntTentative> tentatives = obj.getTentatives(); PadIntTentative t; //Não existem transações a mexer no objecto com identificador uid if (tentatives.Count == 0) { t = new PadIntTentative(uid, tid, value); obj.addTentative(tid, t); transactions[tid].addModifiedObjectId(uid); ////depois de modificar o object, adiciona-lo à transaccao para sabermos o que mudamos no fim. objectWaitHandle[uid].Reset(); //escreveu, bloqueia as threads. O que acontece se não fôr a tempo de bloquear as threads??????? pendingTransactions[uid].Reset(); // dado que escrevemos, as que forem fazer commit teem de esperar //evitar que venha a esperar por si mesma espera por si mesma? return; } //Max de timestamp de leitura das versoes //Func<PadIntTentative, decimal> lam = tent => (decimal) tent.ReadTimestamp; // ulong tMax = tentatives.Max<PadIntTentative,ulong>(x => x.ReadTimestamp); //metodos extendidos. porque nao da? Não apagar. Ainda tenho de //perceber isto Ass:Braga :) ulong tMax = (ulong)tentatives.Max(x => x.Value.ReadTimestamp); //Console.WriteLine("Tid: " + tid + "Tmax: " + tMax); //Verificacao 2: Ja existem leituras de transaccoes a serem processadas if (tid < tMax) { throw new PadIntWriteTooLate(tid, uid); } if (tentatives.ContainsKey(tid)) { PadIntTentative transactionTentative = tentatives[tid]; // transactionTentative.Write(value);--> ja existe uma property //se tem tentativa é porque já escreveu antes. Não é preciso resetar o handle? Ou é???????? transactionTentative.Value = value; } else//primeira tentativa da transacçao tid { t = new PadIntTentative(uid, tid, value); obj.addTentative(tid, t); transactions[tid].addModifiedObjectId(uid); ////depois de modificar o object, adiciona-lo à transaccao para sabermos o que mudamos no fim. objectWaitHandle[uid].Reset(); ///primeira tentativa de escrita. Reseta handle para bloquear threads. pendingTransactions[uid].Reset(); // dado que escrevemos, as que forem fazer commit teem de esperar } }
internal int Read(ulong tid, int uid) { //ServerApp.debug = "Read called!"; //fica a espera que sejam transferidos dados de um servidor que sofreu divisao do seeu range pela entrada deste novo server if (tid > maxTID) { //Console.WriteLine("read: tid>mazxTID"); waitForPadIntTransfer.Reset(); } if (!objectsInServer.ContainsKey(uid)) { //O objecto nao foi criado no servidor throw new PadIntNotExists(tid, uid); } PadIntTransaction obj = objectsInServer[uid]; PadIntCommitted committed = obj.getCommitted(); // return committed.Read(); ulong tc = committed.WriteTimestamp; //ServerApp.debug = "Object commited with value: " + committed.Value; //Console.WriteLine(String.Format("on read:Tid:{0} Tc:{1}", tid, tc)); if (tid <= tc) { throw new PadIntReadTooLate(tid, uid); } SortedList <ulong, PadIntTentative> tentatives = obj.getTentatives(); //se não existirem versões tentativa, ele não/ninguém escreveu. pode ler do commited. if (tentatives.Count == 0) { objectsInServer[uid].addTentative(tid, new PadIntTentative(uid, tid, tid, committed.Value)); ////////////////////////////////////////////////////////////////////// transactions[tid].addModifiedObjectId(uid); ////depois de modificar o object, adiciona-lo à transaccao para sabermos o que mudamos no fim. pendingTransactions[uid].Reset(); // dado que temos uma tentativa, as que forem fazer commit teem de esperar return(committed.Value); } //se ja foi escrita uma versao, entao le-se dessa versão. if (tentatives.ContainsKey(tid)) { PadIntTentative ownTentative = tentatives[tid]; ownTentative.ReadTimestamp = tid; return(ownTentative.Value); } //versao de tentativa que tem um timestamp de escrita superior a todos os inferiores ao da transaccao que quer ler. PadIntTentative mostUpdated = tentatives.Values.Where(x => ((x.WriteTimestamp < tid) ? true : false)).Max(x => x.WriteTimestamp < tid ? x : null); //se nao existe nenhum que tenha escrito e que tenha timestamp inferior, significa que a transaccao actual pode ler o valor do commited. if (mostUpdated == null) { objectsInServer[uid].addTentative(tid, new PadIntTentative(uid, tid, tid, committed.Value)); ////////////////////////////////////////////////////////////////////// transactions[tid].addModifiedObjectId(uid); ////depois de modificar o object, adiciona-lo à transaccao para sabermos o que mudamos no fim. pendingTransactions[uid].Reset(); // dado que temos uma tentativa, as que forem fazer commit teem de esperar return(committed.Value); } ulong tMax = mostUpdated.WriteTimestamp;// este e o valor do maior timestamp de escrita menor que o da transaccao //verificar se a versao commited tem um timestamp igual ao de tmax. se tiver, significa que o tmax está commited. pode então ler if (tc == tMax)//pode ler { mostUpdated.ReadTimestamp = tid; return(mostUpdated.Value); } else //espera que a transaccao faca commit e volta a repetir todos os passos até aqui.É criada uma thred para cada chamada a esta função. { objectWaitHandle[uid].WaitOne(); //bloqueia e quando fôr desbloqueada, volta a tentar. return(Read(tid, uid)); } }