Example #1
0
func (pn *paxosNode) Replicate(command *command.Command) error {
	i := 1
	command.AddrPort = pn.addrport
	LOGV2.Printf("node %d get lock in DoReplicate()\n", pn.nodeID)
	pn.cmdMutex.Lock()
	index := len(pn.commitedCommands)
	LOGV.Printf("in replicate, cur len %d\n", index)
	LOGV2.Printf("node %d release lock in DoReplicate()\n", pn.nodeID)
	pn.cmdMutex.Unlock()
	_, success, num := pn.DoReplicate(command, 0, index)
	for !success {
		LOGV.Printf("node %d last Paxos is not success, waiting to try again...\n", pn.nodeID)
		time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond)
		LOGV.Printf("node %d last Paxos slot %d is not success, try again... iter:%d\n", pn.nodeID, index, i)
		LOGV2.Printf("node %d get lock in DoReplicate()\n", pn.nodeID)
		pn.cmdMutex.Lock()
		length := len(pn.commitedCommands)
		LOGV.Printf("in retry, cur len %d\n", index)
		LOGV2.Printf("node %d release lock in DoReplicate()\n", pn.nodeID)
		pn.cmdMutex.Unlock()
		if index < length { // the slot has been passed
			//LOGV.Printf("node %d slot %d need no retry, since other nodes commited %s\n", pn.nodeID, index, pn.commitedCommands[index].ToString())
			if pn.commitedCommands[index].AddrPort == "" {
				//empty slot here, index keeps the same, iter increases
				i = (num/pn.numNodes + 1)
			} else if pn.commitedCommands[index].AddrPort == pn.addrport {
				//Has commited by other nodes, just return
				return nil
			} else {
				//the slot has been occupied by other node's command
				//try to contend to a new slot
				index = length
				i = 0
			}
		} else {
			i = (num/pn.numNodes + 1)
		}
		_, success, num = pn.DoReplicate(command, i, index)
	}
	return nil
}