func (r *Replica) HandleQLeaseReply(ql *qlease.Lease, pr *qleaseproto.PromiseReply) { if pr.TimestampNs < ql.LatestTsSent { //old reply, ignore return } if pr.LeaseInstance > ql.PromisedByMeInst { ql.PromiseRejects++ if ql.PromiseRejects == r.N { ql.WriteInQuorumUntil = 0 } return } now := time.Now().UnixNano() max := now for i := int32(0); i < int32(r.N); i++ { if i == r.Id { continue } if i == pr.ReplicaId { ql.LatestRepliesReceived[i] = now + ql.Duration } if max < ql.LatestRepliesReceived[i] { max = ql.LatestRepliesReceived[i] } } ql.WriteInQuorumUntil = max r.LastReplyReceivedTimestamp[pr.ReplicaId] = now }
func (r *Replica) EstablishQLease(ql *qlease.Lease) { now := time.Now().UnixNano() ql.LatestTsSent = now ql.PromiseRejects = 0 g := &qleaseproto.Guard{r.Id, now, qlease.GUARD_DURATION_NS} for i := int32(0); i < int32(r.N); i++ { if i == r.Id || !r.Alive[i] { continue } r.SendMsg(i, r.qleaseGuardRPC, g) } }
func (r *Replica) RenewQLease(ql *qlease.Lease, latestAccInst int32) { now := time.Now().UnixNano() ql.PromiseRejects = 0 p := &qleaseproto.Promise{r.Id, ql.PromisedByMeInst, now, ql.Duration, latestAccInst} for i := int32(0); i < int32(r.N); i++ { if i == r.Id || !r.Alive[i] { continue } ql.LatestRepliesReceived[i] += ql.Duration r.SendMsg(i, r.qleasePromiseRPC, p) } ql.LatestTsSent = now // sufficient to extend wait time by the duration of the lease, because // grantees must receive the lease refresh message before the previous lease expires // (otherwise they will dicount the refresh) ql.WriteInQuorumUntil += ql.Duration }
func (r *Replica) HandleQLeasePromise(ql *qlease.Lease, p *qleaseproto.Promise) bool { now := time.Now().UnixNano() // check that this promise was received on time if ql.LatestPromisesReceived[p.ReplicaId] < now && ql.GuardExpires[p.ReplicaId] < now { //didn't receive promise on time, must ignore //TODO: send NACK as optimization return false } if p.LeaseInstance < ql.PromisedToMeInst { // the sender must update its lease view pr := &qleaseproto.PromiseReply{r.Id, ql.PromisedToMeInst, p.TimestampNs} r.SendMsg(p.ReplicaId, r.qleasePromiseReplyRPC, pr) return false } else if p.LeaseInstance > ql.PromisedToMeInst { ql.PromisedToMeInst = p.LeaseInstance for i := int32(0); i < int32(r.N); i++ { ql.LatestPromisesReceived[i] = 0 } } ql.LatestPromisesReceived[p.ReplicaId] = now + p.DurationNs //send reply pr := &qleaseproto.PromiseReply{r.Id, ql.PromisedToMeInst, p.TimestampNs} r.SendMsg(p.ReplicaId, r.qleasePromiseReplyRPC, pr) sorted := make([]int64, r.N) copy(sorted, ql.LatestPromisesReceived) sorted[r.Id] = 0 sort.Sort(Int64Slice(sorted)) ql.ReadLocallyUntil = sorted[r.N-(r.N/2)] return true }
func (r *Replica) HandleQLeaseGuardReply(ql *qlease.Lease, gr *qleaseproto.GuardReply, latestAccInst int32) { if gr.TimestampNs < ql.LatestTsSent { //old reply, must ignore return } now := time.Now().UnixNano() p := &qleaseproto.Promise{r.Id, ql.PromisedByMeInst, now, ql.Duration, latestAccInst} ql.LatestRepliesReceived[gr.ReplicaId] = now + qlease.GUARD_DURATION_NS + ql.Duration if ql.WriteInQuorumUntil < ql.LatestRepliesReceived[gr.ReplicaId] { ql.WriteInQuorumUntil = ql.LatestRepliesReceived[gr.ReplicaId] } r.SendMsg(gr.ReplicaId, r.qleasePromiseRPC, p) }