Example #1
0
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)
		}
	}
}
Example #2
0
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)
	}
}
Example #3
0
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)
	}
}