Example #1
0
func (ln *leaseNode) dofunction(args *leaserpc.Args, reply *leaserpc.Reply, funcname string) error {
	replychan := make(chan *leaserpc.Reply, len(ln.peers))

	for _, n := range ln.peers {
		go func(peernode Node) {
			if peernode.HostPort == ln.addrport {
				r := leaserpc.Reply{}
				switch {
				case funcname == "LeaseNode.Prepare":
					ln.Prepare(args, &r)
				case funcname == "LeaseNode.Accept":
					ln.Accept(args, &r)
				case funcname == "LeaseNode.RenewPrepare":
					ln.RenewPrepare(args, &r)
				case funcname == "LeaseNode.RenewAccept":
					ln.RenewAccept(args, &r)
				}
				replychan <- &r
			} else {
				r := leaserpc.Reply{}
				peer, err := rpcwrapper.DialHTTP("tcp", peernode.HostPort)
				if err != nil {
					r.Status = leaserpc.Reject
					replychan <- &r
					return
				}
				prepareCall := peer.Go(funcname, args, &r, nil)
				select {
				case _, _ = <-prepareCall.Done:
					replychan <- &r
				case _ = <-time.After(time.Second):
					r.Status = leaserpc.Reject
					replychan <- &r
				}
				peer.Close()
			}
		}(n)
	}

	numOK, numRej := 0, 0
	for num := 0; num < len(ln.peers); num++ {
		r, _ := <-replychan
		if r.Status == leaserpc.OK {
			numOK++
		} else {
			numRej++
		}
	}

	if numOK > ln.numNodes/2 {
		reply.Status = leaserpc.OK
		return nil
	} else {
		reply.Status = leaserpc.Reject
		return nil
	}
}
Example #2
0
func (pn *paxosNode) DoAccept(args *paxosrpc.AcceptArgs, reply *paxosrpc.AcceptReply) error {
	LOGV.Printf("node %d DoAccept:%d %s %d\n", pn.nodeID, args.SlotIdx, args.V.ToString(), args.N)
	replychan := make(chan *paxosrpc.AcceptReply, len(pn.peers))

	for i, n := range pn.peers {
		go func(idx int, peernode Node) {
			r := new(paxosrpc.AcceptReply)
			if peernode.HostPort == pn.addrport {
				pn.Accept(args, r)
				replychan <- r
			} else {
				peer, err := rpcwrapper.DialHTTP("tcp", peernode.HostPort)
				if err != nil {
					LOGE.Printf("node %d Cannot reach peer %d:%s\n", pn.nodeID, idx, peernode.HostPort)
					r.Status = paxosrpc.Reject
					replychan <- r
					return
				}
				prepareCall := peer.Go("PaxosNode.Accept", args, r, nil)
				select {
				case _, _ = <-prepareCall.Done:
					replychan <- r
				case _ = <-time.After(time.Second):
					r.Status = paxosrpc.Reject
					replychan <- r
				}
				peer.Close()
			}
		}(i, n)
	}

	numOK := 0
	numRej := 0
	for num := 0; num < pn.numNodes; num++ {
		r, _ := <-replychan
		if r.Status != paxosrpc.Reject {
			numOK++
		} else {
			numRej++
		}
	}
	LOGV.Printf("node %d DoAccept %d result: [%dOK %dRej]\n", pn.nodeID, args.SlotIdx, numOK, numRej)

	if numOK > len(pn.peers)/2 {
		reply.Status = paxosrpc.OK
		return nil
	} else {
		reply.Status = paxosrpc.Reject
		return nil
	}
}
Example #3
0
func (pn *paxosNode) DoCommit(args *paxosrpc.CommitArgs) error {
	LOGV.Printf("node %d DoCommit:%d %s %d\n", pn.nodeID, args.SlotIdx, args.V.ToString(), args.N)
	replychan := make(chan *paxosrpc.CommitReply, len(pn.peers))

	for i, n := range pn.peers {
		go func(idx int, peernode Node) {
			r := new(paxosrpc.CommitReply)
			if peernode.HostPort == pn.addrport {
				pn.Commit(args, r)
				replychan <- r
			} else {
				peer, err := rpcwrapper.DialHTTP("tcp", peernode.HostPort)
				if err != nil {
					LOGE.Printf("node %d Cannot reach peer %d:%s\n", pn.nodeID, idx, peernode.HostPort)
					r.Status = paxosrpc.Reject
					replychan <- r
					return
				}
				prepareCall := peer.Go("PaxosNode.Commit", args, r, nil)
				select {
				case <-prepareCall.Done:
					replychan <- r
				case <-time.After(time.Second):
					r.Status = paxosrpc.Reject
					replychan <- r
				}
				peer.Close()
			}
		}(i, n)
	}

	for num := 0; num < pn.numNodes; num++ {
		_, _ = <-replychan
		LOGV.Printf("in loop, receive %d\n", num)
	}
	return nil
}
Example #4
0
func (pn *paxosNode) DoPrepare(args *paxosrpc.PrepareArgs, reply *paxosrpc.PrepareReply) error {
	LOGV.Printf("node %d DoPrepare:%d %s %d\n", pn.nodeID, args.SlotIdx, args.V.ToString(), args.N)
	replychan := make(chan *paxosrpc.PrepareReply, len(pn.peers))

	for i, n := range pn.peers {
		go func(idx int, peernode Node) {
			r := paxosrpc.PrepareReply{}
			//if localhost, call locally
			if peernode.HostPort == pn.addrport {
				pn.Prepare(args, &r)
				replychan <- &r
			} else { //else, call rpc
				peer, err := rpcwrapper.DialHTTP("tcp", peernode.HostPort)
				if err != nil {
					LOGE.Printf("node %d Cannot reach peer %d:%s\n", pn.nodeID, idx, peernode.HostPort)
					r.Status = paxosrpc.Reject
					replychan <- &r
					return
				}
				prepareCall := peer.Go("PaxosNode.Prepare", args, &r, nil)
				select {
				case _, _ = <-prepareCall.Done:
					replychan <- &r
				case _ = <-time.After(time.Second):
					//TODO: how to handle timeout correctly?
					r.Status = paxosrpc.Reject
					replychan <- &r
				}
				peer.Close()
			}
		}(i, n)
	}

	numOK := 0
	numRej := 0
	reply.Na = -1
	for num := 0; num < len(pn.peers); num++ {
		r, _ := <-replychan
		if r.Status != paxosrpc.Reject {
			numOK++
			if r.Status == paxosrpc.Existed && r.Na > reply.Na {
				reply.Na = r.Na
				reply.Va = r.Va
			}
		} else {
			numRej++
		}
	}
	if reply.Na == -1 {
		reply.Na = args.N
		reply.Va = args.V
	}
	LOGV.Printf("node %d DoPrepare %d result:%s %d[%dOK %dRej]\n", pn.nodeID, args.SlotIdx, reply.Va.ToString(), reply.Na, numOK, numRej)

	if numOK > len(pn.peers)/2 {
		reply.Status = paxosrpc.OK
		return nil //return nil error, and let caller to do the accept step
	} else {
		reply.Status = paxosrpc.Reject
		return nil
	}
}