コード例 #1
0
ファイル: echoclient.go プロジェクト: yuguess/440_P3
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
}
コード例 #2
0
ファイル: echoserver.go プロジェクト: yuguess/440_P3
// 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
}