//Use NOP to detect the gap slots [from, to) func CatchUp(pn *paxosNode, from, to int) { pn.catchupMutex.Lock() pn.catchupCounter++ pn.catchupMutex.Unlock() for index := from; index < to; index++ { i := 1 c := new(command.Command) c.Type = command.NOP LOGV.Printf("node %d Try to catch up with slot %d\n", pn.nodeID, index) success, _, num := pn.DoReplicate(c, 0, index) for !success { LOGV.Printf("node %d last Paxos is not success, waiting to try again...\n", pn.nodeID) //TODO:maybe do not need to wait time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond) LOGV.Printf("node %d last Paxos is not success, try again...\n", pn.nodeID) //i++ LOGV.Printf("node %d Try to catch up with slot %d\n", pn.nodeID, index) i = (num/pn.numNodes + 1) success, _, num = pn.DoReplicate(c, i, index) } LOGV.Printf("Catched up with slot %d\n", index) } pn.catchupMutex.Lock() pn.catchupCounter-- pn.catchupMutex.Unlock() }
func (q *Queue) Enqueue(c *command.Command) { //fmt.Println("Enqueue command:"+c.ToString()) q.lock.Lock() //q.cond.L.Lock() if c.Type == command.Acquire { c.Value = strconv.FormatInt(time.Now().UnixNano(), 10) } q.l.PushBack(c) q.lock.Unlock() //q.cond.L.Unlock() q.cond.Signal() //fmt.Println("After Enqueue command:"+c.ToString()) }
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 }
func fakecallback(index int, c command.Command) { fmt.Printf("\n%d's index %d is %s\n", nid, index, c.ToString()) done <- struct{}{} }