raft_handler.go 1.7 KB

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