func (s *Server) installSeqProcessingLoop() { processToInstallSeqMsgMap := make(map[view.Process]*InstallSeqMsg) // ENHANCEMENT: clean up quorum counter old views var installSeqQuorumCounter installSeqQuorumCounterType for { installSeqMsg := <-s.installSeqProcessingChan // Check for duplicate previousInstallSeq, ok := processToInstallSeqMsgMap[installSeqMsg.Sender] processToInstallSeqMsgMap[installSeqMsg.Sender] = &installSeqMsg if ok && previousInstallSeq.Equal(installSeqMsg) { // It's a duplicate continue } // Re-send install-seq to all processes := append(installSeqMsg.AssociatedView.GetMembers(), installSeqMsg.InstallView.GetMembers()...) mergedView := view.NewWithProcesses(processes...) go broadcastInstallSeq(mergedView, installSeqMsg) // Quorum check if installSeqQuorumCounter.count(&installSeqMsg.InstallSeq, installSeqMsg.AssociatedView.QuorumSize()) { s.gotInstallSeqQuorum(installSeqMsg.InstallSeq) } } }
func (s *Server) generatedViewSeqProcessingLoop() { for { newGeneratedViewSeq := <-s.generatedViewSeqChan log.Println("New generated view sequence:", newGeneratedViewSeq) leastUpdatedView := newGeneratedViewSeq.ViewSeq.GetLeastUpdatedView() installSeqMsg := InstallSeqMsg{ Sender: s.thisProcess, InstallSeq: InstallSeq{ AssociatedView: newGeneratedViewSeq.AssociatedView, InstallView: leastUpdatedView, ViewSeq: newGeneratedViewSeq.ViewSeq, }, } // Send install-seq to all from old and new view processes := append(newGeneratedViewSeq.AssociatedView.GetMembers(), leastUpdatedView.GetMembers()...) mergedView := view.NewWithProcesses(processes...) go broadcastInstallSeq(mergedView, installSeqMsg) } }
func (s *Server) gotInstallSeqQuorum(installSeq InstallSeq) { s.currentViewMu.Lock() defer s.currentViewMu.Unlock() log.Println("Running gotInstallSeqQuorum", installSeq) installViewIsMoreUpdatedThanCv := installSeq.InstallView.MoreUpdatedThan(s.currentView) // don't matter if installView is old, send state if server was a member of the associated view if installSeq.AssociatedView.HasMember(s.thisProcess) { // if installView is not old, disable r/w if installViewIsMoreUpdatedThanCv { // disable R/W operations if not already disabled s.registerLockOnce.Do(func() { s.register.mu.Lock() s.registerLockTime = time.Now() log.Println("R/W operations disabled for reconfiguration") }) } syncStateMsg := SyncStateMsg{} syncStateMsg.Value = s.register.Value syncStateMsg.Timestamp = s.register.Timestamp s.recvMutex.RLock() syncStateMsg.Recv = make(map[view.Update]bool, len(s.recv)) for update, _ := range s.recv { syncStateMsg.Recv[update] = true } s.recvMutex.RUnlock() syncStateMsg.AssociatedView = installSeq.AssociatedView // Send state to all go broadcastStateUpdate(installSeq.InstallView, syncStateMsg) log.Println("State sent!") } // stop here if installView is old if !installViewIsMoreUpdatedThanCv { if installSeq.ViewSeq.HasViewMoreUpdatedThan(s.currentView) { s.installOthersViewsFromViewSeqLocked(installSeq) return } else { log.Println("installSeq does not lead to a more updated view than current view. Skipping...") return } } if installSeq.InstallView.HasMember(s.thisProcess) { // Process is on the new view s.syncState(installSeq) s.updateCurrentViewLocked(installSeq.InstallView) viewInstalledMsg := ViewInstalledMsg{} viewInstalledMsg.InstalledView = s.currentView // Send view-installed to all processes := installSeq.AssociatedView.GetMembersNotIn(installSeq.InstallView) viewOfLeavingProcesses := view.NewWithProcesses(processes...) go broadcastViewInstalled(viewOfLeavingProcesses, viewInstalledMsg) if installSeq.ViewSeq.HasViewMoreUpdatedThan(s.currentView) { s.installOthersViewsFromViewSeqLocked(installSeq) } else { s.register.mu.Unlock() log.Println("R/W operations enabled") endTime := time.Now() if installSeq.AssociatedView.HasMember(s.thisProcess) { log.Printf("Reconfiguration completed in %v, the system was unavailable for %v.\n", endTime.Sub(s.startReconfigurationTime), endTime.Sub(s.registerLockTime)) s.registerLockOnce = sync.Once{} } else { log.Println("Reconfiguration completed, this process is now part of the system.") } s.resetReconfigurationTimerChan <- true } } else { // thisProcess is NOT on the new view var counter int log.Println("Waiting for view-installed quorum to leave") for { viewInstalled := <-s.newViewInstalledChan if installSeq.InstallView.Equal(viewInstalled.InstalledView) { counter++ if counter == installSeq.InstallView.QuorumSize() { break } } } log.Println("Leaving...") //shutdownChan <- true os.Exit(0) } }