/// <summary> /// + /// Only Leader's proc. /// Accepts entry return true if Committed /// </summary> /// <param name="majorityNumber"></param> /// <param name="LogId"></param> /// <param name="TermId"></param> public eEntryAcceptanceResult EntryIsAccepted(NodeRaftAddress address, uint majorityQuantity, StateLogEntryApplied applied) { //If we receive acceptance signals of already Committed entries, we just ignore them if (applied.StateLogEntryId <= this.log.LastCommittedIndex) { return(eEntryAcceptanceResult.AlreadyAccepted); //already accepted } if (applied.StateLogEntryId <= this.log.LastAppliedIndex) { return(eEntryAcceptanceResult.AlreadyAccepted); //already accepted } StateLogEntryAcceptance acc = null; if (acceptStateTable.TryGetValue(applied.StateLogEntryId, out acc)) { if (acc.Term != applied.StateLogEntryTerm) { return(eEntryAcceptanceResult.NotAccepted); //Came from wrong Leader probably } acc.acceptedEndPoints.Add(address.EndPointSID); } else { acc = new StateLogEntryAcceptance() { Index = applied.StateLogEntryId, Term = applied.StateLogEntryTerm }; acc.acceptedEndPoints.Add(address.EndPointSID); acceptStateTable[applied.StateLogEntryId] = acc; } if ((acc.acceptedEndPoints.Count + 1) >= majorityQuantity) { this.log.LastAppliedIndex = applied.StateLogEntryId; //Removing from Dictionary acceptStateTable.Remove(applied.StateLogEntryId); if (this.log.LastCommittedIndex < applied.StateLogEntryId && this.stateMachine.NodeTerm == applied.StateLogEntryTerm) //Setting LastCommittedId { bool commited = this.log.CommitLogEntry(address, majorityQuantity, applied); //todo:: the above operation may commit many log at the same time //should double check this logic // if (this.log.lstCommited.Count > 0) if (commited) { this.Commited(); } return(eEntryAcceptanceResult.Committed); } } return(eEntryAcceptanceResult.Accepted); }
/// <summary> /// + /// Only Leader's proc. /// Accepts entry return true if Committed /// </summary> /// <param name="majorityNumber"></param> /// <param name="LogId"></param> /// <param name="TermId"></param> public eEntryAcceptanceResult EntryIsAccepted(NodeAddress address, uint majorityQuantity, StateLogEntryApplied applied) { //If we receive acceptance signals of already Committed entries, we just ignore them if (applied.StateLogEntryId <= this.LastCommittedIndex) { return(eEntryAcceptanceResult.AlreadyAccepted); //already accepted } if (applied.StateLogEntryId <= this.LastAppliedIndex) { return(eEntryAcceptanceResult.AlreadyAccepted); //already accepted } StateLogEntryAcceptance acc = null; if (dStateLogEntryAcceptance.TryGetValue(applied.StateLogEntryId, out acc)) { if (acc.Term != applied.StateLogEntryTerm) { return(eEntryAcceptanceResult.NotAccepted); //Came from wrong Leader probably } //acc.Quantity += 1; acc.acceptedEndPoints.Add(address.EndPointSID); } else { acc = new StateLogEntryAcceptance() { //Quantity = 2, //Leader + first incoming Index = applied.StateLogEntryId, Term = applied.StateLogEntryTerm }; acc.acceptedEndPoints.Add(address.EndPointSID); dStateLogEntryAcceptance[applied.StateLogEntryId] = acc; } if ((acc.acceptedEndPoints.Count + 1) >= majorityQuantity) { this.LastAppliedIndex = applied.StateLogEntryId; //Removing from Dictionary dStateLogEntryAcceptance.Remove(applied.StateLogEntryId); if (this.LastCommittedIndex < applied.StateLogEntryId && rn.NodeTerm == applied.StateLogEntryTerm) //Setting LastCommittedId { //Saving committed entry (all previous are automatically committed) List <byte[]> lstCommited = new List <byte[]>(); using (var t = this.rn.db.GetTransaction()) { //Gathering all not commited entries that are bigger than latest committed index t.ValuesLazyLoadingIsOn = false; foreach (var el in t.SelectForwardFromTo <byte[], byte[]>(tblStateLogEntry, new byte[] { 1 }.ToBytes(this.LastCommittedIndex + 1, applied.StateLogEntryTerm), true, new byte[] { 1 }.ToBytes(ulong.MaxValue, applied.StateLogEntryTerm), true, true)) { lstCommited.Add(StateLogEntry.BiserDecode(el.Value).Data); } //Setting latest commited index if (rn.entitySettings.DelayedPersistenceIsActive) { foreach (var iel in sleCache.Where(r => r.Key >= this.LastCommittedIndex + 1 && r.Value.Item1 == applied.StateLogEntryTerm)) { lstCommited.Add(iel.Value.Item2.Data); } sleCacheIndex = applied.StateLogEntryId; sleCacheTerm = applied.StateLogEntryTerm; } else { t.Insert <byte[], byte[]>(tblStateLogEntry, new byte[] { 2 }, applied.StateLogEntryId.ToBytes(applied.StateLogEntryTerm)); t.Commit(); } //Removing entry from command queue //t.RemoveKey<byte[]>(tblAppendLogEntry, new byte[] { 1 }.ToBytes(applied.StateLogEntryTerm, applied.StateLogEntryId)); qDistribution.Remove(applied.StateLogEntryId); } this.LastCommittedIndex = applied.StateLogEntryId; this.LastCommittedIndexTerm = applied.StateLogEntryTerm; if (lstCommited.Count > 0) { this.rn.Commited(); } //this.rn.Commited(applied.StateLogEntryId); return(eEntryAcceptanceResult.Committed); } } return(eEntryAcceptanceResult.Accepted); }
/// <summary> /// + /// Only Leader's proc. /// Accepts entry return true if Committed /// </summary> /// <param name="majorityNumber"></param> /// <param name="LogId"></param> /// <param name="TermId"></param> public eEntryAcceptanceResult EntryIsAccepted(NodeRaftAddress address, uint majorityQuantity, StateLogEntryApplied applied) { //If we receive acceptance signals of already Committed entries, we just ignore them if (applied.StateLogEntryId <= this.LastCommittedIndex) { return(eEntryAcceptanceResult.AlreadyAccepted); //already accepted } if (applied.StateLogEntryId <= this.LastAppliedIndex) { return(eEntryAcceptanceResult.AlreadyAccepted); //already accepted } StateLogEntryAcceptance acc = null; if (dStateLogEntryAcceptance.TryGetValue(applied.StateLogEntryId, out acc)) { if (acc.Term != applied.StateLogEntryTerm) { return(eEntryAcceptanceResult.NotAccepted); //Came from wrong Leader probably } acc.acceptedEndPoints.Add(address.EndPointSID); } else { acc = new StateLogEntryAcceptance() { Index = applied.StateLogEntryId, Term = applied.StateLogEntryTerm }; acc.acceptedEndPoints.Add(address.EndPointSID); dStateLogEntryAcceptance[applied.StateLogEntryId] = acc; } if ((acc.acceptedEndPoints.Count + 1) >= majorityQuantity) { this.LastAppliedIndex = applied.StateLogEntryId; //Removing from Dictionary dStateLogEntryAcceptance.Remove(applied.StateLogEntryId); if (this.LastCommittedIndex < applied.StateLogEntryId && statemachine.NodeTerm == applied.StateLogEntryTerm) //Setting LastCommittedId { //Saving committed entry (all previous are automatically committed) List <byte[]> lstCommited = new List <byte[]>(); var col = this.db.GetCollection <StateLogEntry>(stateTableName); var list = col.Query().Where(s => s.Index >= this.LastCommittedIndex + 1 && s.Term == applied.StateLogEntryTerm).ToList(); foreach (var item in list) { lstCommited.Add(new byte[1]); item.IsCommitted = true; col.Update(item); qDistribution.Remove(applied.StateLogEntryId); } //using (var t = this.db.GetTransaction()) //{ // //Gathering all not commited entries that are bigger than latest committed index // t.ValuesLazyLoadingIsOn = false; // foreach (var el in t.SelectForwardFromTo<byte[], byte[]>(stateTableName, // new byte[] { 1 }.ToBytes(this.LastCommittedIndex + 1, applied.StateLogEntryTerm), true, // new byte[] { 1 }.ToBytes(ulong.MaxValue, applied.StateLogEntryTerm), true, true)) // { // lstCommited.Add(StateLogEntry.BiserDecode(el.Value).Data); // } // t.Insert<byte[], byte[]>(stateTableName, new byte[] { 2 }, applied.StateLogEntryId.ToBytes(applied.StateLogEntryTerm)); // t.Commit(); // qDistribution.Remove(applied.StateLogEntryId); //} this.LastCommittedIndex = applied.StateLogEntryId; this.LastCommittedIndexTerm = applied.StateLogEntryTerm; if (lstCommited.Count > 0) { this.statemachine.logHandler.Commited(); } return(eEntryAcceptanceResult.Committed); } } return(eEntryAcceptanceResult.Accepted); }
/// <summary> /// + /// Only Leader's proc. /// Accepts entry return true if Committed /// </summary> /// <param name="majorityNumber"></param> /// <param name="LogId"></param> /// <param name="TermId"></param> public eEntryAcceptanceResult EntryIsAccepted(NodeRaftAddress address, uint majorityQuantity, StateLogEntryApplied applied) { //If we receive acceptance signals of already Committed entries, we just ignore them if (applied.StateLogEntryId <= this.LastCommittedIndex) { return(eEntryAcceptanceResult.AlreadyAccepted); //already accepted } if (applied.StateLogEntryId <= this.LastAppliedIndex) { return(eEntryAcceptanceResult.AlreadyAccepted); //already accepted } StateLogEntryAcceptance acc = null; if (dStateLogEntryAcceptance.TryGetValue(applied.StateLogEntryId, out acc)) { if (acc.Term != applied.StateLogEntryTerm) { return(eEntryAcceptanceResult.NotAccepted); //Came from wrong Leader probably } acc.acceptedEndPoints.Add(address.EndPointSID); } else { acc = new StateLogEntryAcceptance() { //Quantity = 2, //Leader + first incoming Index = applied.StateLogEntryId, Term = applied.StateLogEntryTerm }; acc.acceptedEndPoints.Add(address.EndPointSID); dStateLogEntryAcceptance[applied.StateLogEntryId] = acc; } if ((acc.acceptedEndPoints.Count + 1) >= majorityQuantity) { this.LastAppliedIndex = applied.StateLogEntryId; //Removing from Dictionary dStateLogEntryAcceptance.Remove(applied.StateLogEntryId); if (this.LastCommittedIndex < applied.StateLogEntryId && rn.NodeTerm == applied.StateLogEntryTerm) //Setting LastCommittedId { //Saving committed entry (all previous are automatically committed) List <byte[]> lstCommited = new List <byte[]>(); lock (inMem.Sync) { foreach (var el in inMem.SelectForwardFromTo(this.LastCommittedIndex + 1, applied.StateLogEntryTerm, true, ulong.MaxValue, applied.StateLogEntryTerm)) { lstCommited.Add(el.Item3.Data); } } //Removing entry from command queue //t.RemoveKey<byte[]>(tblAppendLogEntry, new byte[] { 1 }.ToBytes(applied.StateLogEntryTerm, applied.StateLogEntryId)); this.leaderState.qDistribution.Remove(applied.StateLogEntryId); } this.LastCommittedIndex = applied.StateLogEntryId; this.LastCommittedIndexTerm = applied.StateLogEntryTerm; this.rn.logHandler.Commited(); return(eEntryAcceptanceResult.Committed); } return(eEntryAcceptanceResult.Accepted); }