raft_handler.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package etcd
  2. import (
  3. "encoding/json"
  4. "log"
  5. "net/http"
  6. "strconv"
  7. "sync"
  8. "github.com/coreos/etcd/raft"
  9. )
  10. const (
  11. raftPrefix = "/raft"
  12. )
  13. type raftHandler struct {
  14. mu sync.RWMutex
  15. serving bool
  16. peerGetter peerGetter
  17. recv chan *raft.Message
  18. *http.ServeMux
  19. }
  20. func newRaftHandler(p peerGetter) *raftHandler {
  21. h := &raftHandler{
  22. recv: make(chan *raft.Message, 512),
  23. peerGetter: p,
  24. }
  25. h.ServeMux = http.NewServeMux()
  26. h.ServeMux.HandleFunc(raftPrefix+"/cfg/", h.serveCfg)
  27. h.ServeMux.HandleFunc(raftPrefix, h.serveRaft)
  28. return h
  29. }
  30. func (h *raftHandler) start() {
  31. h.mu.Lock()
  32. h.serving = true
  33. h.mu.Unlock()
  34. }
  35. func (h *raftHandler) stop() {
  36. h.mu.Lock()
  37. h.serving = false
  38. h.mu.Unlock()
  39. }
  40. func (h *raftHandler) serveRaft(w http.ResponseWriter, r *http.Request) {
  41. h.mu.RLock()
  42. serving := h.serving
  43. h.mu.RUnlock()
  44. if !serving {
  45. http.Error(w, "404 page not found", http.StatusNotFound)
  46. return
  47. }
  48. msg := new(raft.Message)
  49. if err := json.NewDecoder(r.Body).Decode(msg); err != nil {
  50. log.Println(err)
  51. return
  52. }
  53. select {
  54. case h.recv <- msg:
  55. default:
  56. log.Println("drop")
  57. // drop the incoming package at network layer if the upper layer
  58. // cannot consume them in time.
  59. // TODO(xiangli): not return 200.
  60. }
  61. return
  62. }
  63. func (h *raftHandler) serveCfg(w http.ResponseWriter, r *http.Request) {
  64. h.mu.RLock()
  65. serving := h.serving
  66. h.mu.RUnlock()
  67. if !serving {
  68. http.Error(w, "404 page not found", http.StatusNotFound)
  69. return
  70. }
  71. id, err := strconv.ParseInt(r.URL.Path[len("/raft/cfg/"):], 10, 64)
  72. if err != nil {
  73. http.Error(w, err.Error(), http.StatusBadRequest)
  74. return
  75. }
  76. p, err := h.peerGetter.peer(id)
  77. if err == nil {
  78. w.Write([]byte(p.url))
  79. return
  80. }
  81. http.Error(w, err.Error(), http.StatusNotFound)
  82. }