Exemple #1
0
// Return the number of times we have tripped an ask for this request.
func (p *ProcessList) AskDBState(vmIndex int, height int) int {
	now := p.State.GetTimestamp().GetTimeMilli()

	r := p.GetRequest(now, vmIndex, height, 60)

	if now-r.sent >= r.wait*1000+500 {
		dbstate := messages.NewDBStateMissing(p.State, p.State.LLeaderHeight, p.State.LLeaderHeight+1)

		dbstate.SendOut(p.State, dbstate)
		p.State.DBStateAskCnt++

		r.sent = now
		r.requestCnt++
	}

	return r.requestCnt
}
// When we process the directory Signature, and we are the leader for said signature, it
// is then that we push it out to the rest of the network.  Otherwise, if we are not the
// leader for the signature, it marks the sig complete for that list
func (s *State) ProcessDBSig(dbheight uint32, msg interfaces.IMsg) bool {

	dbs := msg.(*messages.DirectoryBlockSignature)
	// Don't process if syncing an EOM
	if s.Syncing && !s.DBSig {
		return false
	}

	pl := s.ProcessLists.Get(dbheight)
	vm := s.ProcessLists.Get(dbheight).VMs[msg.GetVMIndex()]

	if uint32(pl.System.Height) >= dbs.SysHeight {
		s.DBSigSys = true
	}

	// If we are done with DBSigs, and this message is processed, then we are done.  Let everything go!
	if s.DBSigSys && s.DBSig && s.DBSigDone {
		s.DBSigProcessed--
		if s.DBSigProcessed <= 0 {
			s.DBSig = false
			s.Syncing = false
		}
		vm.Signed = true
		//s.LeaderPL.AdminBlock
		return true
	}

	// Put the stuff that only executes once at the start of DBSignatures here
	if !s.DBSig {
		s.DBSigLimit = len(pl.FedServers)
		s.DBSigProcessed = 0
		s.DBSig = true
		s.Syncing = true
		s.DBSigDone = false
		for _, vm := range pl.VMs {
			vm.Synced = false
		}
		pl.ResetDiffSigTally()
	}

	// Put the stuff that executes per DBSignature here
	if !dbs.Processed {
		if dbs.VMIndex == 0 {
			s.SetLeaderTimestamp(dbs.GetTimestamp())
		}
		dbstate := s.GetDBState(dbheight - 1)

		if dbstate == nil || !dbs.DirectoryBlockHeader.GetBodyMR().IsSameAs(dbstate.DirectoryBlock.GetHeader().GetBodyMR()) {
			//fmt.Println(s.FactomNodeName, "JUST COMPARED", dbs.DirectoryBlockHeader.GetBodyMR().String()[:10], " : ", dbstate.DirectoryBlock.GetHeader().GetBodyMR().String()[:10])
			pl.IncrementDiffSigTally()
		}

		// Adds DB Sig to be added to Admin block if passes sig checks
		allChecks := false
		data, err := dbs.DirectoryBlockHeader.MarshalBinary()
		if err != nil {
			fmt.Println("Debug: DBSig Signature Error, Marshal binary errored")
		} else {
			if !dbs.DBSignature.Verify(data) {
				fmt.Println("Debug: DBSig Signature Error, Verify errored")
			} else {
				if valid, err := s.VerifyAuthoritySignature(data, dbs.DBSignature.GetSignature(), dbs.DBHeight); err == nil && valid == 1 {
					allChecks = true
				}
			}
		}

		if allChecks {
			dbs.Matches = true
			s.AddDBSig(dbheight, dbs.ServerIdentityChainID, dbs.DBSignature)
		}

		dbs.Processed = true
		s.DBSigProcessed++
		vm.Synced = true
	}

	allfaults := s.LeaderPL.System.Height >= s.LeaderPL.SysHighest

	// Put the stuff that executes once for set of DBSignatures (after I have them all) here
	if allfaults && !s.DBSigDone && s.DBSigProcessed >= s.DBSigLimit {
		fails := 0
		for i := range pl.FedServers {
			vm := pl.VMs[i]
			tdbsig, ok := vm.List[0].(*messages.DirectoryBlockSignature)
			if !ok || !tdbsig.Matches {
				fails++
				vm.List[0] = nil
				vm.Height = 0
				s.DBSigProcessed--
			}
		}
		if fails > len(pl.FedServers)/2 {
			//s.DoReset()
			return false
		} else if fails > 0 {
			return false
		}
		dbstate := s.DBStates.Get(int(dbheight - 1))

		// TODO: check signatures here.  Count what match and what don't.  Then if a majority
		// disagree with us, null our entry out.  Otherwise toss our DBState and ask for one from
		// our neighbors.
		if s.KeepMismatch || pl.CheckDiffSigTally() {
			if !dbstate.Saved {
				dbstate.ReadyToSave = true
				s.DBStates.SaveDBStateToDB(dbstate)
				//s.LeaderPL.AddDBSig(dbs.ServerIdentityChainID, dbs.DBSignature)
			}
		} else {
			s.DBSigFails++
			s.Reset()
			msg := messages.NewDBStateMissing(s, uint32(dbheight-1), uint32(dbheight-1))

			if msg != nil {
				s.RunLeader = false
				s.StartDelay = s.GetTimestamp().GetTimeMilli()
				s.NetworkOutMsgQueue() <- msg
			}
		}
		s.ReviewHolding()
		s.Saving = false
		s.DBSigDone = true
	}
	return false
	/*
		err := s.LeaderPL.AdminBlock.AddDBSig(dbs.ServerIdentityChainID, dbs.DBSignature)
		if err != nil {
			fmt.Printf("Error in adding DB sig to admin block, %s\n", err.Error())
		}
	*/
}
// Once a second at most, we check to see if we need to pull down some blocks to catch up.
func (list *DBStateList) Catchup() {

	now := list.State.GetTimestamp()

	dbsHeight := list.GetHighestCompletedBlock()

	// We only check if we need updates once every so often.

	begin := -1
	end := -1

	// Find the first range of blocks that we don't have.
	for i, v := range list.DBStates {
		if (v == nil || v.DirectoryBlock == nil) && begin < 0 {
			begin = i
		}
		if v == nil {
			end = i
		}
	}

	if begin > 0 {
		begin += int(list.Base)
		end += int(list.Base)
	} else {
		plHeight := list.State.GetHighestKnownBlock()
		// Don't worry about the block initialization case.
		if plHeight < 1 {
			list.LastTime = nil
			return
		}

		if plHeight >= dbsHeight && plHeight-dbsHeight > 1 {
			begin = int(dbsHeight + 1)
			end = int(plHeight - 1)
		} else {
			list.LastTime = nil
			return
		}

		for list.State.ProcessLists.Get(uint32(begin)) != nil && list.State.ProcessLists.Get(uint32(begin)).Complete() {
			begin++
			if uint32(begin) >= plHeight || begin > end {
				list.LastTime = nil
				return
			}
		}
	}

	if begin > 0 {
		begin--
	}
	end++ // ask for one more, just in case.

	list.Lastreq = begin

	end2 := begin + 400
	if end < end2 {
		end2 = end
	}

	if list.LastTime != nil && now.GetTimeMilli()-list.LastTime.GetTimeMilli() < list.State.StartDelayLimit/2 {
		return
	}

	if list.LastTime == nil {
		list.LastTime = now
		return
	}

	list.State.RunLeader = false

	list.LastTime = now

	msg := messages.NewDBStateMissing(list.State, uint32(begin), uint32(end2))

	if msg != nil {
		//		list.State.RunLeader = false
		//		list.State.StartDelay = list.State.GetTimestamp().GetTimeMilli()
		msg.SendOut(list.State, msg)
		msg.SendOut(list.State, msg)
		msg.SendOut(list.State, msg)
		list.LastTime = now
		list.State.DBStateAskCnt++
	}

}