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 } } }
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 } } }