func mustMarshalMsg(t *testing.T, m raftpb.Message) []byte { json, err := m.Marshal() if err != nil { t.Fatalf("error marshalling raft Message: %#v", err) } return json }
func stepFollower(r *raft, m pb.Message) { switch m.Type { case pb.MsgProp: if r.lead == None { r.logger.Infof("%x no leader at term %d; dropping proposal", r.id, r.Term) return } m.To = r.lead r.send(m) case pb.MsgApp: r.electionElapsed = 0 r.lead = m.From r.handleAppendEntries(m) case pb.MsgHeartbeat: r.electionElapsed = 0 r.lead = m.From r.handleHeartbeat(m) case pb.MsgSnap: r.electionElapsed = 0 r.lead = m.From r.handleSnapshot(m) case pb.MsgVote: if (r.Vote == None || r.Vote == m.From) && r.raftLog.isUpToDate(m.Index, m.LogTerm) { r.electionElapsed = 0 r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] voted for %x [logterm: %d, index: %d] at term %d", r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.From, m.LogTerm, m.Index, r.Term) r.Vote = m.From r.send(pb.Message{To: m.From, Type: pb.MsgVoteResp}) } else { r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] rejected vote from %x [logterm: %d, index: %d] at term %d", r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.From, m.LogTerm, m.Index, r.Term) r.send(pb.Message{To: m.From, Type: pb.MsgVoteResp, Reject: true}) } case pb.MsgTransferLeader: if r.lead == None { r.logger.Infof("%x no leader at term %d; dropping leader transfer msg", r.id, r.Term) return } m.To = r.lead r.send(m) case pb.MsgTimeoutNow: r.logger.Infof("%x [term %d] received MsgTimeoutNow from %x and starts an election to get leadership.", r.id, r.Term, m.From) r.campaign(campaignTransfer) case pb.MsgReadIndex: if r.lead == None { r.logger.Infof("%x no leader at term %d; dropping index reading msg", r.id, r.Term) return } m.To = r.lead r.send(m) case pb.MsgReadIndexResp: if len(m.Entries) != 1 { r.logger.Errorf("%x invalid format of MsgReadIndexResp from %x, entries count: %d", r.id, m.From, len(m.Entries)) return } r.readState.Index = m.Index r.readState.RequestCtx = m.Entries[0].Data } }
func (w *grpcWorker) RaftMessage(ctx context.Context, query *Payload) (*Payload, error) { if ctx.Err() != nil { return &Payload{}, ctx.Err() } for idx := 0; idx < len(query.Data); { sz := int(binary.LittleEndian.Uint32(query.Data[idx : idx+4])) idx += 4 msg := raftpb.Message{} if idx+sz-1 > len(query.Data) { return &Payload{}, x.Errorf( "Invalid query. Size specified: %v. Size of array: %v\n", sz, len(query.Data)) } if err := msg.Unmarshal(query.Data[idx : idx+sz]); err != nil { x.Check(err) } if msg.Type != raftpb.MsgHeartbeat && msg.Type != raftpb.MsgHeartbeatResp { fmt.Printf("RECEIVED: %v %v-->%v\n", msg.Type, msg.From, msg.To) } if err := w.applyMessage(ctx, msg); err != nil { return &Payload{}, err } idx += sz } // fmt.Printf("Got %d messages\n", count) return &Payload{}, nil }
func (h serverHandler) serveRaft(w http.ResponseWriter, r *http.Request) { if !allowMethod(w, r.Method, "POST") { return } b, err := ioutil.ReadAll(r.Body) if err != nil { log.Println("etcdhttp: error reading raft message:", err) http.Error(w, "error reading raft message", http.StatusBadRequest) return } var m raftpb.Message if err := m.Unmarshal(b); err != nil { log.Println("etcdhttp: error unmarshaling raft message:", err) http.Error(w, "error unmarshaling raft message", http.StatusBadRequest) return } log.Printf("etcdhttp: raft recv message from %#x: %+v", m.From, m) if err := h.server.Process(context.TODO(), m); err != nil { log.Println("etcdhttp: error processing raft message:", err) writeError(w, err) return } w.WriteHeader(http.StatusNoContent) }
func (enc *messageEncoder) encode(m raftpb.Message) error { if err := binary.Write(enc.w, binary.BigEndian, uint64(m.Size())); err != nil { return err } _, err := enc.w.Write(pbutil.MustMarshal(&m)) return err }
func send(c *http.Client, cls ClusterStore, m raftpb.Message) { // TODO (xiangli): reasonable retry logic for i := 0; i < 3; i++ { u := cls.Get().Pick(m.To) if u == "" { // TODO: unknown peer id.. what do we do? I // don't think his should ever happen, need to // look into this further. log.Printf("etcdhttp: no addr for %d", m.To) return } u = fmt.Sprintf("%s%s", u, raftPrefix) // TODO: don't block. we should be able to have 1000s // of messages out at a time. data, err := m.Marshal() if err != nil { log.Println("etcdhttp: dropping message:", err) return // drop bad message } if httpPost(c, u, data) { return // success } // TODO: backoff } }
func send(p Peers, m raftpb.Message) { // TODO (xiangli): reasonable retry logic for i := 0; i < 3; i++ { url := p.Pick(m.To) if url == "" { // TODO: unknown peer id.. what do we do? I // don't think his should ever happen, need to // look into this further. log.Printf("etcdhttp: no addr for %d", m.To) return } url += raftPrefix // TODO: don't block. we should be able to have 1000s // of messages out at a time. data, err := m.Marshal() if err != nil { log.Println("etcdhttp: dropping message:", err) return // drop bad message } if httpPost(url, data) { return // success } // TODO: backoff } }
func (h *pipelineHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { w.Header().Set("Allow", "POST") http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } w.Header().Set("X-Etcd-Cluster-ID", h.cid.String()) if err := checkClusterCompatibilityFromHeader(r.Header, h.cid); err != nil { http.Error(w, err.Error(), http.StatusPreconditionFailed) return } if from, err := types.IDFromString(r.Header.Get("X-Server-From")); err != nil { if urls := r.Header.Get("X-PeerURLs"); urls != "" { h.tr.AddRemote(from, strings.Split(urls, ",")) } } // Limit the data size that could be read from the request body, which ensures that read from // connection will not time out accidentally due to possible blocking in underlying implementation. limitedr := pioutil.NewLimitedBufferReader(r.Body, connReadLimitByte) b, err := ioutil.ReadAll(limitedr) if err != nil { plog.Errorf("failed to read raft message (%v)", err) http.Error(w, "error reading raft message", http.StatusBadRequest) recvFailures.WithLabelValues(r.RemoteAddr).Inc() return } var m raftpb.Message if err := m.Unmarshal(b); err != nil { plog.Errorf("failed to unmarshal raft message (%v)", err) http.Error(w, "error unmarshaling raft message", http.StatusBadRequest) recvFailures.WithLabelValues(r.RemoteAddr).Inc() return } receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(len(b))) if err := h.r.Process(context.TODO(), m); err != nil { switch v := err.(type) { case writerToResponse: v.WriteTo(w) default: plog.Warningf("failed to process raft message (%v)", err) http.Error(w, "error processing raft message", http.StatusInternalServerError) w.(http.Flusher).Flush() // disconnect the http stream panic(err) } return } // Write StatusNoContent header after the message has been processed by // raft, which facilitates the client to report MsgSnap status. w.WriteHeader(http.StatusNoContent) }
func NewMessage(rs raftpb.Message, rc io.ReadCloser, rcSize int64) *Message { return &Message{ Message: rs, ReadCloser: ioutil.NewExactReadCloser(rc, rcSize), TotalSize: int64(rs.Size()) + rcSize, closeC: make(chan bool, 1), } }
func (s *EtcdServer) Process(ctx context.Context, m raftpb.Message) error { if s.cluster.IsIDRemoved(types.ID(m.From)) { plog.Warningf("reject message from removed member %s", types.ID(m.From).String()) return httptypes.NewHTTPError(http.StatusForbidden, "cannot process message from removed member") } if m.Type == raftpb.MsgApp { s.stats.RecvAppendReq(types.ID(m.From).String(), m.Size()) } return s.r.Step(ctx, m) }
// send persists state to stable storage and then sends to its mailbox. func (r *raft) send(m pb.Message) { m.From = r.id // do not attach term to MsgProp // proposals are a way to forward to the leader and // should be treated as local message. if m.Type != pb.MsgProp { m.Term = r.Term } r.msgs = append(r.msgs, m) }
// sendAppend sends RRPC, with entries to the given peer. func (r *raft) sendAppend(to uint64) { pr := r.prs[to] m := pb.Message{} m.To = to if r.needSnapshot(pr.next) { m.Type = pb.MsgSnap snapshot, err := r.raftLog.snapshot() if err != nil { panic(err) // TODO(bdarnell) } if IsEmptySnap(snapshot) { panic("need non-empty snapshot") } m.Snapshot = snapshot } else { m.Type = pb.MsgApp m.Index = pr.next - 1 m.LogTerm = r.raftLog.term(pr.next - 1) m.Entries = r.raftLog.entries(pr.next) m.Commit = r.raftLog.committed // optimistically increase the next if the follower // has been matched. if n := len(m.Entries); pr.match != 0 && n != 0 { pr.optimisticUpdate(m.Entries[n-1].Index) } } r.send(m) }
// sendAppend sends RRPC, with entries to the given peer. func (r *raft) sendAppend(to uint64) { pr := r.prs[to] m := pb.Message{} m.To = to if r.needSnapshot(pr.next) { m.Type = pb.MsgSnap snapshot, err := r.raftLog.snapshot() if err != nil { panic(err) // TODO(bdarnell) } if IsEmptySnap(snapshot) { panic("need non-empty snapshot") } m.Snapshot = snapshot sindex, sterm := snapshot.Metadata.Index, snapshot.Metadata.Term log.Printf("raft: %x [firstindex: %d, commit: %d] sent snapshot[index: %d, term: %d] to %x [%s]", r.id, r.raftLog.firstIndex(), r.Commit, sindex, sterm, to, pr) } else { m.Type = pb.MsgApp m.Index = pr.next - 1 m.LogTerm = r.raftLog.term(pr.next - 1) m.Entries = r.raftLog.entries(pr.next) m.Commit = r.raftLog.committed // optimistically increase the next if the follower // has been matched. if n := len(m.Entries); pr.match != 0 && n != 0 { pr.optimisticUpdate(m.Entries[n-1].Index) } } r.send(m) }
// Handles incoming requests. func (t *TCPServer) handleRequest(conn net.Conn) { var b []byte buffer := bytes.NewBuffer(b) bufReader := bufio.NewReader(conn) size := make([]byte, 4) ack := []byte{byte(AckMessageType)} for { typ, err := bufReader.ReadByte() if err != nil { log.Printf("Failed to read message type from TCP client") break } switch UserMessageType(typ) { case RaftMessageType: log.Printf("Received Raft message type") // Read size n, err := bufReader.Read(size) if err != nil || n != 4 { log.Printf("Failed to read message size from TCP client") break } byteCount, _ := xbinary.LittleEndian.Uint32(size, 0) if n, err := buffer.ReadFrom(io.LimitReader(bufReader, int64(byteCount))); err != nil || n != int64(byteCount) { log.Printf("Failed to read message from TCP client") break } m := raftpb.Message{} if err := m.Unmarshal(buffer.Bytes()); err != nil { log.Printf("Failed to decode message from TCP client") break } log.Printf("Applying Raft message") t.raft.Step(m) // Write the message in the connection channel. conn.Write(ack) // Reset Buffer buffer.Reset() default: break } } // Close the connection when you're done with it. conn.Close() }
func stepFollower(r *raft, m pb.Message) { switch m.Type { case pb.MsgProp: if r.lead == None { r.logger.Infof("%x no leader at term %d; dropping proposal", r.id, r.Term) return } m.To = r.lead r.send(m) case pb.MsgApp: r.electionElapsed = 0 r.lead = m.From r.handleAppendEntries(m) case pb.MsgHeartbeat: r.electionElapsed = 0 r.lead = m.From r.handleHeartbeat(m) case pb.MsgSnap: r.electionElapsed = 0 r.lead = m.From r.handleSnapshot(m) case pb.MsgTransferLeader: if r.lead == None { r.logger.Infof("%x no leader at term %d; dropping leader transfer msg", r.id, r.Term) return } m.To = r.lead r.send(m) case pb.MsgTimeoutNow: if r.promotable() { r.logger.Infof("%x [term %d] received MsgTimeoutNow from %x and starts an election to get leadership.", r.id, r.Term, m.From) // Leadership transfers never use pre-vote even if r.preVote is true; we // know we are not recovering from a partition so there is no need for the // extra round trip. r.campaign(campaignTransfer) } else { r.logger.Infof("%x received MsgTimeoutNow from %x but is not promotable", r.id, m.From) } case pb.MsgReadIndex: if r.lead == None { r.logger.Infof("%x no leader at term %d; dropping index reading msg", r.id, r.Term) return } m.To = r.lead r.send(m) case pb.MsgReadIndexResp: if len(m.Entries) != 1 { r.logger.Errorf("%x invalid format of MsgReadIndexResp from %x, entries count: %d", r.id, m.From, len(m.Entries)) return } r.readStates = append(r.readStates, ReadState{Index: m.Index, RequestCtx: m.Entries[0].Data}) } }
func (dec *messageDecoder) decode() (raftpb.Message, error) { var m raftpb.Message var l uint64 if err := binary.Read(dec.r, binary.BigEndian, &l); err != nil { return m, err } buf := make([]byte, int(l)) if _, err := io.ReadFull(dec.r, buf); err != nil { return m, err } return m, m.Unmarshal(buf) }
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { w.Header().Set("Allow", "POST") http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } if err := checkVersionCompability(r.Header.Get("X-Server-From"), serverVersion(r.Header), minClusterVersion(r.Header)); err != nil { plog.Errorf("request received was ignored (%v)", err) http.Error(w, errIncompatibleVersion.Error(), http.StatusPreconditionFailed) return } wcid := h.cid.String() w.Header().Set("X-Etcd-Cluster-ID", wcid) gcid := r.Header.Get("X-Etcd-Cluster-ID") if gcid != wcid { plog.Errorf("request received was ignored (cluster ID mismatch got %s want %s)", gcid, wcid) http.Error(w, errClusterIDMismatch.Error(), http.StatusPreconditionFailed) return } // Limit the data size that could be read from the request body, which ensures that read from // connection will not time out accidentally due to possible block in underlying implementation. limitedr := pioutil.NewLimitedBufferReader(r.Body, ConnReadLimitByte) b, err := ioutil.ReadAll(limitedr) if err != nil { plog.Errorf("failed to read raft message (%v)", err) http.Error(w, "error reading raft message", http.StatusBadRequest) return } var m raftpb.Message if err := m.Unmarshal(b); err != nil { plog.Errorf("failed to unmarshal raft message (%v)", err) http.Error(w, "error unmarshaling raft message", http.StatusBadRequest) return } if err := h.r.Process(context.TODO(), m); err != nil { switch v := err.(type) { case writerToResponse: v.WriteTo(w) default: plog.Warningf("failed to process raft message (%v)", err) http.Error(w, "error processing raft message", http.StatusInternalServerError) } return } // Write StatusNoContet header after the message has been processed by // raft, which faciliates the client to report MsgSnap status. w.WriteHeader(http.StatusNoContent) }
// sendAppend sends RPC, with entries to the given peer. func (r *raft) sendAppend(to uint64) { pr := r.prs[to] if pr.isPaused() { return } m := pb.Message{} m.To = to term, errt := r.raftLog.term(pr.Next - 1) ents, erre := r.raftLog.entries(pr.Next, r.maxMsgSize) if errt != nil || erre != nil { // send snapshot if we failed to get term or entries if !pr.RecentActive { r.logger.Debugf("ignore sending snapshot to %x since it is not recently active", to) return } m.Type = pb.MsgSnap snapshot, err := r.raftLog.snapshot() if err != nil { if err == ErrSnapshotTemporarilyUnavailable { r.logger.Debugf("%x failed to send snapshot to %x because snapshot is temporarily unavailable", r.id, to) return } panic(err) // TODO(bdarnell) } if IsEmptySnap(snapshot) { panic("need non-empty snapshot") } m.Snapshot = snapshot sindex, sterm := snapshot.Metadata.Index, snapshot.Metadata.Term r.logger.Debugf("%x [firstindex: %d, commit: %d] sent snapshot[index: %d, term: %d] to %x [%s]", r.id, r.raftLog.firstIndex(), r.raftLog.committed, sindex, sterm, to, pr) pr.becomeSnapshot(sindex) r.logger.Debugf("%x paused sending replication messages to %x [%s]", r.id, to, pr) } else { m.Type = pb.MsgApp m.Index = pr.Next - 1 m.LogTerm = term m.Entries = ents m.Commit = r.raftLog.committed if n := len(m.Entries); n != 0 { switch pr.State { // optimistically increase the next when in ProgressStateReplicate case ProgressStateReplicate: last := m.Entries[n-1].Index pr.optimisticUpdate(last) pr.ins.add(last) case ProgressStateProbe: pr.pause() default: r.logger.Panicf("%x is sending append in unhandled state %s", r.id, pr.State) } } } r.send(m) }
// Send a message. Returns false if the message was dropped. func (rttc *raftTransportTestContext) Send( from, to roachpb.ReplicaDescriptor, rangeID roachpb.RangeID, msg raftpb.Message, ) bool { msg.To = uint64(to.ReplicaID) msg.From = uint64(from.ReplicaID) req := &storage.RaftMessageRequest{ RangeID: rangeID, Message: msg, ToReplica: to, FromReplica: from, } return rttc.transports[from.NodeID].SendAsync(req) }
func (n *node) send(m raftpb.Message) { x.AssertTruef(n.id != m.To, "Seding message to itself") data, err := m.Marshal() x.Check(err) if m.Type != raftpb.MsgHeartbeat && m.Type != raftpb.MsgHeartbeatResp { fmt.Printf("\t\tSENDING: %v %v-->%v\n", m.Type, m.From, m.To) } select { case n.messages <- sendmsg{to: m.To, data: data}: // pass default: log.Fatalf("Unable to push messages to channel in send") } }
func (h Handler) serveRaft(ctx context.Context, w http.ResponseWriter, r *http.Request) { b, err := ioutil.ReadAll(r.Body) if err != nil { log.Println("etcdhttp: error reading raft message:", err) } var m raftpb.Message if err := m.Unmarshal(b); err != nil { log.Println("etcdhttp: error unmarshaling raft message:", err) } log.Printf("etcdhttp: raft recv message from %#x: %+v", m.From, m) if err := h.Server.Node.Step(ctx, m); err != nil { log.Println("etcdhttp: error stepping raft messages:", err) } }
func stepFollower(r *raft, m pb.Message) { switch m.Type { case pb.MsgProp: if r.lead == None { panic("no leader") } m.To = r.lead r.send(m) case pb.MsgApp: r.elapsed = 0 r.lead = m.From if m.LogTerm == 0 && m.Index == 0 && len(m.Entries) == 0 { r.handleHeartbeat(m) } else { r.handleAppendEntries(m) } case pb.MsgSnap: r.elapsed = 0 r.handleSnapshot(m) case pb.MsgVote: if (r.Vote == None || r.Vote == m.From) && r.raftLog.isUpToDate(m.Index, m.LogTerm) { r.elapsed = 0 r.Vote = m.From r.send(pb.Message{To: m.From, Type: pb.MsgVoteResp}) } else { r.send(pb.Message{To: m.From, Type: pb.MsgVoteResp, Reject: true}) } } }
func stepFollower(r *raft, m pb.Message) { switch m.Type { case pb.MsgProp: if r.lead == None { r.logger.Infof("%x no leader at term %d; dropping proposal", r.id, r.Term) return } m.To = r.lead r.send(m) case pb.MsgApp: r.electionElapsed = 0 r.lead = m.From r.handleAppendEntries(m) case pb.MsgHeartbeat: r.electionElapsed = 0 r.lead = m.From r.handleHeartbeat(m) case pb.MsgSnap: r.electionElapsed = 0 r.handleSnapshot(m) case pb.MsgVote: if (r.Vote == None || r.Vote == m.From) && r.raftLog.isUpToDate(m.Index, m.LogTerm) { r.electionElapsed = 0 r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] voted for %x [logterm: %d, index: %d] at term %d", r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.From, m.LogTerm, m.Index, r.Term) r.Vote = m.From r.send(pb.Message{To: m.From, Type: pb.MsgVoteResp}) } else { r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] rejected vote from %x [logterm: %d, index: %d] at term %d", r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.From, m.LogTerm, m.Index, r.Term) r.send(pb.Message{To: m.From, Type: pb.MsgVoteResp, Reject: true}) } } }
func stepFollower(r *raft, m pb.Message) { switch m.Type { case msgProp: if r.lead == None { panic("no leader") } m.To = r.lead r.send(m) case msgApp: r.elapsed = 0 r.lead = m.From r.handleAppendEntries(m) case msgSnap: r.elapsed = 0 r.handleSnapshot(m) case msgVote: if (r.Vote == None || r.Vote == m.From) && r.raftLog.isUpToDate(m.Index, m.LogTerm) { r.elapsed = 0 r.Vote = m.From r.send(pb.Message{To: m.From, Type: msgVoteResp, Index: r.raftLog.lastIndex()}) } else { r.send(pb.Message{To: m.From, Type: msgVoteResp, Index: -1}) } } }
// createMergedSnapshotMessage creates a snapshot message that contains: raft status (term, conf), // a snapshot of v2 store inside raft.Snapshot as []byte, a snapshot of v3 KV in the top level message // as ReadCloser. func (s *EtcdServer) createMergedSnapshotMessage(m raftpb.Message, snapi uint64, confState raftpb.ConfState) snap.Message { snapt, err := s.r.raftStorage.Term(snapi) if err != nil { log.Panicf("get term should never fail: %v", err) } // get a snapshot of v2 store as []byte clone := s.store.Clone() d, err := clone.SaveNoCopy() if err != nil { plog.Panicf("store save should never fail: %v", err) } // get a snapshot of v3 KV as readCloser rc := newSnapshotReaderCloser(s.kv.Snapshot()) // put the []byte snapshot of store into raft snapshot and return the merged snapshot with // KV readCloser snapshot. snapshot := raftpb.Snapshot{ Metadata: raftpb.SnapshotMetadata{ Index: snapi, Term: snapt, ConfState: confState, }, Data: d, } m.Snapshot = snapshot return snap.Message{ Message: m, ReadCloser: rc, } }
// createMergedSnapshotMessage creates a snapshot message that contains: raft status (term, conf), // a snapshot of v2 store inside raft.Snapshot as []byte, a snapshot of v3 KV in the top level message // as ReadCloser. func (s *EtcdServer) createMergedSnapshotMessage(m raftpb.Message, snapi uint64, confState raftpb.ConfState) snap.Message { snapt, err := s.r.raftStorage.Term(snapi) if err != nil { log.Panicf("get term should never fail: %v", err) } // get a snapshot of v2 store as []byte clone := s.store.Clone() d, err := clone.SaveNoCopy() if err != nil { plog.Panicf("store save should never fail: %v", err) } // commit kv to write metadata(for example: consistent index). s.KV().Commit() dbsnap := s.be.Snapshot() // get a snapshot of v3 KV as readCloser rc := newSnapshotReaderCloser(dbsnap) // put the []byte snapshot of store into raft snapshot and return the merged snapshot with // KV readCloser snapshot. snapshot := raftpb.Snapshot{ Metadata: raftpb.SnapshotMetadata{ Index: snapi, Term: snapt, ConfState: confState, }, Data: d, } m.Snapshot = snapshot return *snap.NewMessage(m, rc, dbsnap.Size()) }
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { w.Header().Set("Allow", "POST") http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } wcid := h.cid.String() w.Header().Set("X-Etcd-Cluster-ID", wcid) gcid := r.Header.Get("X-Etcd-Cluster-ID") if gcid != wcid { log.Printf("rafthttp: request ignored due to cluster ID mismatch got %s want %s", gcid, wcid) http.Error(w, "clusterID mismatch", http.StatusPreconditionFailed) return } // Limit the data size that could be read from the request body, which ensures that read from // connection will not time out accidentally due to possible block in underlying implementation. limitedr := ioutils.NewLimitedBufferReader(r.Body, ConnReadLimitByte) b, err := ioutil.ReadAll(limitedr) if err != nil { log.Println("rafthttp: error reading raft message:", err) http.Error(w, "error reading raft message", http.StatusBadRequest) return } var m raftpb.Message if err := m.Unmarshal(b); err != nil { log.Println("rafthttp: error unmarshaling raft message:", err) http.Error(w, "error unmarshaling raft message", http.StatusBadRequest) return } if err := h.p.Process(context.TODO(), m); err != nil { switch v := err.(type) { case writerToResponse: v.WriteTo(w) default: log.Printf("rafthttp: error processing raft message: %v", err) http.Error(w, "error processing raft message", http.StatusInternalServerError) } return } w.WriteHeader(http.StatusNoContent) }
func (t *tcpTransport) handleConnection(c net.Conn) { for { p, e := ReadPacket(c) if e != nil { fmt.Fprintf(os.Stdout, "read from connection err:%s\n", e.Error()) } m := pb.Message{} if e := m.Unmarshal(p.Data); e != nil { fmt.Fprint(os.Stdout, "unmarshal protobuf Message data error:", e) } select { case t.reciv <- m: fmt.Fprintln(os.Stdout, "receive from:", m.From, "to:", m.To) default: } } }
// sendAppend sends RRPC, with entries to the given peer. func (r *raft) sendAppend(to int64) { pr := r.prs[to] m := pb.Message{} m.To = to m.Index = pr.next - 1 if r.needSnapshot(m.Index) { m.Type = msgSnap m.Snapshot = r.raftLog.snapshot } else { m.Type = msgApp m.LogTerm = r.raftLog.term(pr.next - 1) m.Entries = r.raftLog.entries(pr.next) m.Commit = r.raftLog.committed } r.send(m) }
func (h *raftHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if !allowMethod(w, r.Method, "POST") { return } wcid := strconv.FormatUint(h.clusterInfo.ID(), 16) w.Header().Set("X-Etcd-Cluster-ID", wcid) gcid := r.Header.Get("X-Etcd-Cluster-ID") if gcid != wcid { log.Printf("etcdhttp: request ignored due to cluster ID mismatch got %s want %s", gcid, wcid) http.Error(w, "clusterID mismatch", http.StatusPreconditionFailed) return } b, err := ioutil.ReadAll(r.Body) if err != nil { log.Println("etcdhttp: error reading raft message:", err) http.Error(w, "error reading raft message", http.StatusBadRequest) return } var m raftpb.Message if err := m.Unmarshal(b); err != nil { log.Println("etcdhttp: error unmarshaling raft message:", err) http.Error(w, "error unmarshaling raft message", http.StatusBadRequest) return } if err := h.server.Process(context.TODO(), m); err != nil { log.Println("etcdhttp: error processing raft message:", err) switch err { case etcdserver.ErrRemoved: http.Error(w, "cannot process message from removed node", http.StatusForbidden) default: writeError(w, err) } return } if m.Type == raftpb.MsgApp { h.stats.UpdateRecvApp(m.From, r.ContentLength) } w.WriteHeader(http.StatusNoContent) }