예제 #1
0
func (server *Server) serve(clientid int64, clientCommitCh chan ClientResponse, conn *net.TCPConn) {

	reader := bufio.NewReader(conn)
	var res ClientResponse
	var response *fs.Msg
	for {

		msg, msgerr, fatalerr := fs.GetMsg(clientid, reader)
		//		msg.ClientId=clientid
		if fatalerr != nil {
			reply(conn, &fs.Msg{Kind: 'M'})
			conn.Close()
			break
		}

		if msgerr != nil {
			if (!reply(conn, &fs.Msg{Kind: 'M'})) {
				conn.Close()
				break
			}
			continue
		}

		// if message not of read type
		if msg.Kind == 'w' || msg.Kind == 'c' || msg.Kind == 'd' {
			dbytes, err := encode(*msg)
			if err != nil {
				if (!reply(conn, &fs.Msg{Kind: 'I'})) {
					conn.Close()
					break
				}
				continue
			}
			// append the msg to the raft node log
			server.rn.Append(dbytes)
			//wait for the msg to appear on the client commit channel
			res = <-clientCommitCh
			if res.Err != nil {
				msgContent := server.getAddress(server.rn.LeaderId())
				//				fmt.Printf("Leader address : %v\n", rc.LeaderId())
				reply(conn, &fs.Msg{Kind: 'R', Contents: []byte(msgContent)})
				conn.Close()
				break
			}
			response = res.Message
			//		fmt.Printf("Response Message %v\n", string(response.Contents))

		} else if msg.Kind == 'r' {
			response = fs.ProcessMsg(server.fileMap, &(server.gversion), msg)
		}

		if !reply(conn, response) {
			conn.Close()
			break
		}
	}
}
예제 #2
0
func (server *Server) ListenCommitChannel() {
	getMsg := func(index int) {
		err, emsg := server.rn.Get(index)
		if err != nil {
			fmt.Printf("ListenCommitChannel: Error in getting message 4")
			assert(err == nil)
		}

		dmsg, err := decode(emsg)
		if err != nil {
			fmt.Printf("ListenCommitChannel: Error in decoding message 3")
			assert(err == nil)
		}
		response := fs.ProcessMsg(server.fileMap, &(server.gversion), &dmsg)
		server.Lock()
		if ch, ok := server.ClientChanMap[dmsg.ClientId]; ok {
			ch <- ClientResponse{response, nil}
		}
		server.Unlock()
	}

	var prevLogIndexProcessed = -1
	for {
		//listen on commit channel of raft node
		commitval := <-server.rn.CommitChannel()
		if commitval.Err != nil {
			//Redirect the client. Assume the server for which this server voted is the leader. So, redirect it there.
			dmsg, err := decode(commitval.Data)
			if err != nil {
				fmt.Printf("ListenCommitChannel: Error in decoding message 1")
				assert(err == nil)
			}
			server.Lock()
			if ch, ok := server.ClientChanMap[dmsg.ClientId]; ok {
				ch <- ClientResponse{nil, errors.New("ERR_REDIRECT")}
			}
			server.Unlock()

		} else {
			//check if there are missing or duplicate commits
			if commitval.Index <= prevLogIndexProcessed {
				// already processed. So continue
				continue
			}
			// if missing get them
			for i := prevLogIndexProcessed + 1; i < commitval.Index; i++ {
				getMsg(i)
			}

			dmsg, err := decode(commitval.Data)
			if err != nil {
				fmt.Printf("ListenCommitChannel: Error in decoding message 3")
				assert(err == nil)
			}
			// process the message and send response to client
			response := fs.ProcessMsg(server.fileMap, &(server.gversion), &dmsg)
			//			fmt.Printf("Response: %v", *response)
			//server.ClientChanMap[dmsg.ClientId]<-ClientEntry{dmsg,nil}
			server.Lock()
			if ch, ok := server.ClientChanMap[dmsg.ClientId]; ok {
				ch <- ClientResponse{response, nil}
			}
			server.Unlock()
			prevLogIndexProcessed = commitval.Index
		}

	}

}