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 } }
func (ln *leaseNode) Accept(args *leaserpc.Args, reply *leaserpc.Reply) error { LOGV.Printf("node %d receives accept %d\n", ln.nodeID, args.N) ln.leaseMutex.Lock() if args.N < ln.Nh { reply.Status = leaserpc.Reject LOGV.Printf("node %d rejects accept %d\n", ln.nodeID, args.N) } else { ln.Nh = args.N ln.Na = args.N ln.acceptLeaseLen = LEASE_LEN reply.Status = leaserpc.OK LOGV.Printf("node %d accepts accept %d\n", ln.nodeID, args.N) } ln.leaseMutex.Unlock() return nil }
func (ln *leaseNode) RenewPrepare(args *leaserpc.Args, reply *leaserpc.Reply) error { LOGV.Printf("node %d receives renewprepare %d\n", ln.nodeID, args.N) ln.leaseMutex.Lock() if ln.Nh < args.N { ln.Nh = args.N } if ln.Na == args.N || (ln.acceptLeaseLen == 0 && ln.masterLeaseLen == 0) { reply.Status = leaserpc.OK LOGV.Printf("node %d accepts renewprepare %d\n", ln.nodeID, args.N) } else { reply.Status = leaserpc.Reject LOGV.Printf("node %d rejects renewprepare %d\n", ln.nodeID, args.N) } ln.leaseMutex.Unlock() return nil }
func (ln *leaseNode) Prepare(args *leaserpc.Args, reply *leaserpc.Reply) error { LOGV.Printf("node %d receives prepare %d\n", ln.nodeID, args.N) ln.leaseMutex.Lock() if args.N < ln.Nh { reply.Status = leaserpc.Reject } else { ln.Nh = args.N if ln.masterLeaseLen > 0 || ln.acceptLeaseLen > 0 { reply.Status = leaserpc.Reject LOGV.Printf("node %d rejects prepare %d\n", ln.nodeID, args.N) } else { reply.Status = leaserpc.OK LOGV.Printf("node %d accepts prepare %d\n", ln.nodeID, args.N) } } ln.leaseMutex.Unlock() return nil }