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 }