func (cli *EchoClient) Send(str string) (string, error) { var args echoproto.Args var reply echoproto.Reply args.V = str args.N = 1 werr := cli.rpcSvr.Call("Server.AppendLog", args, &reply) if werr != nil { fmt.Printf("Lost contact with server on write: %s\n", werr.Error()) return "", werr } fmt.Printf("echo client send replay %d %s\n", reply.Response, reply.Data[0]) return reply.Data[0], nil }
// Initiate the Paxos protocol to append a new string to the log. func (svr *Server) AppendLog(args *echoproto.Args, reply *echoproto.Reply) error { var pargs echoproto.Args var preply echoproto.Reply var n_prepare, n_accept, n_error int var err error n_prepare = 0 n_accept = 0 log.Println("AppendLog(): Initiating Paxos protocol.") for n_accept <= svr.F { for n_prepare <= svr.F { // initiate a commit to the log svr.Lock.Lock() // increment the Lamport timestamp and append the string to the log svr.update() pargs.N = svr.Time svr.info("AppendLog()") svr.Lock.Unlock() n_prepare = 0 n_error = 0 for i := 0; i < len(svr.Peers); i++ { err = svr.Peers[i].Call("Server.Prepare", pargs, &preply) if err != nil { log.Println("rpc.Call() error:", err) n_error++ } else if preply.Response == echoproto.PREPARE_OK { n_prepare++ } } if n_error > svr.F { log.Fatalln("Too many failed nodes. No progress possible.") } if n_prepare <= svr.F { log.Println("AppendLog(): Majority PREPARE_REJECT. Restarting Paxos.") time.Sleep(1000 * time.Millisecond) } } svr.Lock.Lock() svr.info("AppendLog()") log.Println("AppendLog(): Majority PREPARE_OK. Initiating accept phase.") // n_prepare > svr.F // continue with accept if svr.V_accept == "" { svr.V_accept = args.V } pargs.V = svr.V_accept svr.Lock.Unlock() n_accept = 0 n_error = 0 for i := 0; i < len(svr.Peers); i++ { err = svr.Peers[i].Call("Server.Accept", pargs, &preply) if err != nil { log.Println("rpc.Call() error:", err) n_error++ } else if preply.Response == echoproto.ACCEPT_OK { n_accept++ } } if n_error > svr.F { log.Fatalln("Too many failed nodes. No progress possible.") } if n_accept <= svr.F { log.Println("AppendLog(): Majority ACCEPT_REJECT. Restarting Paxos.") time.Sleep(1000 * time.Millisecond) } } // n_accept > svr.F // continue with commit log.Println("AppendLog(): Majority ACCEPT_OK. Initiating commit phase.") n_error = 0 for i := 0; i < len(svr.Peers); i++ { err = svr.Peers[i].Call("Server.Commit", pargs, &preply) if err != nil { log.Println("rpc.Call() error:", err) n_error++ } } if n_error > svr.F { log.Fatalln("Too many failed nodes. No progress possible.") } svr.Commit(args, reply) return nil }