mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 17:15:56 +00:00
Merge pull request #470 from travisturner/nodestate
Implement NodeState as an attribute of *Node
This commit is contained in:
commit
03aa9447a8
9 changed files with 318 additions and 99 deletions
|
|
@ -34,6 +34,11 @@ func (s *StaticNodeSet) Open() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *StaticNodeSet) Join(nodes []*Node) error {
|
||||
s.nodes = nodes
|
||||
return nil
|
||||
}
|
||||
|
||||
// Broadcaster is an interface for broadcasting messages.
|
||||
type Broadcaster interface {
|
||||
SendSync(pb proto.Message) error
|
||||
|
|
|
|||
47
cluster.go
47
cluster.go
|
|
@ -3,6 +3,8 @@ package pilosa
|
|||
import (
|
||||
"encoding/binary"
|
||||
"hash/fnv"
|
||||
|
||||
"github.com/pilosa/pilosa/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -12,15 +14,30 @@ const (
|
|||
// DefaultReplicaN is the default number of replicas per partition.
|
||||
DefaultReplicaN = 1
|
||||
|
||||
// HealthStatus is the return value of the /health endpoint for a node in the cluster.
|
||||
HealthStatusUp = "UP"
|
||||
HealthStatusDown = "DOWN"
|
||||
// NodeState represents node state returned in /status endpoint for a node in the cluster.
|
||||
NodeStateUp = "UP"
|
||||
NodeStateDown = "DOWN"
|
||||
)
|
||||
|
||||
// Node represents a node in the cluster.
|
||||
type Node struct {
|
||||
Host string `json:"host"`
|
||||
InternalHost string `json:"internalHost"`
|
||||
|
||||
status *internal.NodeStatus `json:"status"`
|
||||
}
|
||||
|
||||
// SetStatus sets the NodeStatus.
|
||||
func (n *Node) SetStatus(s *internal.NodeStatus) {
|
||||
n.status = s
|
||||
}
|
||||
|
||||
// SetState sets the Node.status.state.
|
||||
func (n *Node) SetState(s string) {
|
||||
if n.status == nil {
|
||||
n.status = &internal.NodeStatus{}
|
||||
}
|
||||
n.status.State = s
|
||||
}
|
||||
|
||||
// Nodes represents a list of nodes.
|
||||
|
|
@ -120,21 +137,37 @@ func (c *Cluster) NodeSetHosts() []string {
|
|||
return a
|
||||
}
|
||||
|
||||
// Health returns a map of nodes in the cluster with each node's state (UP/DOWN) as the value.
|
||||
func (c *Cluster) Health() map[string]string {
|
||||
// NodeStates returns a map of nodes in the cluster with each node's state (UP/DOWN) as the value.
|
||||
func (c *Cluster) NodeStates() map[string]string {
|
||||
h := make(map[string]string)
|
||||
for _, n := range c.Nodes {
|
||||
h[n.Host] = HealthStatusDown
|
||||
h[n.Host] = NodeStateDown
|
||||
}
|
||||
// we are assuming that NodeSetHosts is a subset of c.Nodes
|
||||
for _, m := range c.NodeSetHosts() {
|
||||
if _, ok := h[m]; ok {
|
||||
h[m] = HealthStatusUp
|
||||
h[m] = NodeStateUp
|
||||
}
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// State returns the internal ClusterState representation.
|
||||
func (c *Cluster) Status() *internal.ClusterStatus {
|
||||
return &internal.ClusterStatus{
|
||||
Nodes: encodeClusterStatus(c.Nodes),
|
||||
}
|
||||
}
|
||||
|
||||
// encodeClusterStatus converts a into its internal representation.
|
||||
func encodeClusterStatus(a []*Node) []*internal.NodeStatus {
|
||||
other := make([]*internal.NodeStatus, len(a))
|
||||
for i := range a {
|
||||
other[i] = a[i].status
|
||||
}
|
||||
return other
|
||||
}
|
||||
|
||||
// NodeByHost returns a node reference by host.
|
||||
func (c *Cluster) NodeByHost(host string) *Node {
|
||||
for _, n := range c.Nodes {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ func TestCluster_NodeSetHosts(t *testing.T) {
|
|||
}
|
||||
|
||||
// Ensure cluster can compare its Nodes and Members
|
||||
func TestCluster_Health(t *testing.T) {
|
||||
func TestCluster_NodeStates(t *testing.T) {
|
||||
c := pilosa.Cluster{
|
||||
Nodes: []*pilosa.Node{
|
||||
{Host: "serverA:1000"},
|
||||
|
|
@ -109,12 +109,12 @@ func TestCluster_Health(t *testing.T) {
|
|||
}
|
||||
|
||||
// Verify a DOWN node is reported, and extraneous nodes are ignored
|
||||
if a := c.Health(); !reflect.DeepEqual(a, map[string]string{
|
||||
"serverA:1000": pilosa.HealthStatusUp,
|
||||
"serverB:1000": pilosa.HealthStatusDown,
|
||||
"serverC:1000": pilosa.HealthStatusUp,
|
||||
if a := c.NodeStates(); !reflect.DeepEqual(a, map[string]string{
|
||||
"serverA:1000": pilosa.NodeStateUp,
|
||||
"serverB:1000": pilosa.NodeStateDown,
|
||||
"serverC:1000": pilosa.NodeStateUp,
|
||||
}) {
|
||||
t.Fatalf("unexpected health: %s", spew.Sdump(a))
|
||||
t.Fatalf("unexpected node state: %s", spew.Sdump(a))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,14 +14,6 @@ import (
|
|||
"github.com/pilosa/pilosa/internal"
|
||||
)
|
||||
|
||||
// StateHandler specifies two methods which an object must implement to share
|
||||
// state in the cluster. These are used by the GossipNodeSet to implement the
|
||||
// LocalState and MergeRemoteState methods of memberlist.Delegate
|
||||
type StateHandler interface {
|
||||
LocalState() (proto.Message, error)
|
||||
HandleRemoteState(proto.Message) error
|
||||
}
|
||||
|
||||
// GossipNodeSet represents a gossip implementation of NodeSet using memberlist
|
||||
// GossipNodeSet also represents a gossip implementation of pilosa.Broadcaster
|
||||
// GossipNodeSet also represents an implementation of memberlist.Delegate
|
||||
|
|
@ -31,8 +23,8 @@ type GossipNodeSet struct {
|
|||
|
||||
broadcasts *memberlist.TransmitLimitedQueue
|
||||
|
||||
stateHandler StateHandler
|
||||
config *GossipConfig
|
||||
statusHandler pilosa.StatusHandler
|
||||
config *GossipConfig
|
||||
|
||||
// The writer for any logging.
|
||||
LogOutput io.Writer
|
||||
|
|
@ -89,7 +81,7 @@ type GossipConfig struct {
|
|||
}
|
||||
|
||||
// NewGossipNodeSet returns a new instance of GossipNodeSet.
|
||||
func NewGossipNodeSet(name string, gossipHost string, gossipPort int, gossipSeed string, sh StateHandler) *GossipNodeSet {
|
||||
func NewGossipNodeSet(name string, gossipHost string, gossipPort int, gossipSeed string, sh pilosa.StatusHandler) *GossipNodeSet {
|
||||
g := &GossipNodeSet{
|
||||
LogOutput: os.Stderr,
|
||||
}
|
||||
|
|
@ -106,7 +98,7 @@ func NewGossipNodeSet(name string, gossipHost string, gossipPort int, gossipSeed
|
|||
g.config.memberlistConfig.AdvertisePort = gossipPort
|
||||
g.config.memberlistConfig.Delegate = g
|
||||
|
||||
g.stateHandler = sh
|
||||
g.statusHandler = sh
|
||||
|
||||
return g
|
||||
}
|
||||
|
|
@ -176,7 +168,7 @@ func (g *GossipNodeSet) GetBroadcasts(overhead, limit int) [][]byte {
|
|||
}
|
||||
|
||||
func (g *GossipNodeSet) LocalState(join bool) []byte {
|
||||
pb, err := g.stateHandler.LocalState()
|
||||
pb, err := g.statusHandler.LocalStatus()
|
||||
if err != nil {
|
||||
g.logger().Printf("error getting local state, err=%s", err)
|
||||
return []byte{}
|
||||
|
|
@ -193,12 +185,12 @@ func (g *GossipNodeSet) LocalState(join bool) []byte {
|
|||
|
||||
func (g *GossipNodeSet) MergeRemoteState(buf []byte, join bool) {
|
||||
// Unmarshal nodestate data.
|
||||
var pb internal.NodeState
|
||||
var pb internal.NodeStatus
|
||||
if err := proto.Unmarshal(buf, &pb); err != nil {
|
||||
g.logger().Printf("error unmarshalling nodestate data, err=%s", err)
|
||||
return
|
||||
}
|
||||
err := g.stateHandler.HandleRemoteState(&pb)
|
||||
err := g.statusHandler.HandleRemoteStatus(&pb)
|
||||
if err != nil {
|
||||
g.logger().Printf("merge state error: %s", err)
|
||||
}
|
||||
|
|
|
|||
15
handler.go
15
handler.go
|
|
@ -27,8 +27,9 @@ import (
|
|||
|
||||
// Handler represents an HTTP handler.
|
||||
type Handler struct {
|
||||
Holder *Holder
|
||||
Broadcaster Broadcaster
|
||||
Holder *Holder
|
||||
Broadcaster Broadcaster
|
||||
StatusHandler StatusHandler
|
||||
|
||||
// Local hostname & cluster configuration.
|
||||
Host string
|
||||
|
|
@ -85,6 +86,7 @@ func NewRouter(handler *Handler) *mux.Router {
|
|||
router.HandleFunc("/nodes", handler.handleGetNodes).Methods("GET")
|
||||
router.HandleFunc("/schema", handler.handleGetSchema).Methods("GET")
|
||||
router.HandleFunc("/slices/max", handler.handleGetSliceMax).Methods("GET")
|
||||
router.HandleFunc("/status", handler.handleGetStatus).Methods("GET")
|
||||
router.HandleFunc("/version", handler.handleGetVersion).Methods("GET")
|
||||
|
||||
// TODO: Apply MethodNotAllowed statuses to all endpoints.
|
||||
|
|
@ -116,8 +118,13 @@ func (h *Handler) handleGetSchema(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// handleGetStatus handles GET /status requests.
|
||||
func (h *Handler) handleGetStatus(w http.ResponseWriter, r *http.Request) {
|
||||
status, err := h.StatusHandler.ClusterStatus()
|
||||
if err != nil {
|
||||
h.logger().Printf("cluster status error: %s", err)
|
||||
return
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(getStatusResponse{
|
||||
Health: h.Cluster.Health(),
|
||||
Status: status,
|
||||
}); err != nil {
|
||||
h.logger().Printf("write status response error: %s", err)
|
||||
}
|
||||
|
|
@ -128,7 +135,7 @@ type getSchemaResponse struct {
|
|||
}
|
||||
|
||||
type getStatusResponse struct {
|
||||
Health map[string]string `json:"health"`
|
||||
Status proto.Message `json:"status"`
|
||||
}
|
||||
|
||||
// handlePostQuery handles /query requests.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
DeleteFrameMessage
|
||||
Frame
|
||||
Index
|
||||
NodeState
|
||||
NodeStatus
|
||||
ClusterStatus
|
||||
*/
|
||||
package internal
|
||||
|
||||
|
|
@ -231,24 +232,40 @@ func (m *Index) GetFrames() []*Frame {
|
|||
return nil
|
||||
}
|
||||
|
||||
type NodeState struct {
|
||||
type NodeStatus struct {
|
||||
Host string `protobuf:"bytes,1,opt,name=Host,proto3" json:"Host,omitempty"`
|
||||
State string `protobuf:"bytes,2,opt,name=State,proto3" json:"State,omitempty"`
|
||||
Indexes []*Index `protobuf:"bytes,3,rep,name=Indexes" json:"Indexes,omitempty"`
|
||||
}
|
||||
|
||||
func (m *NodeState) Reset() { *m = NodeState{} }
|
||||
func (m *NodeState) String() string { return proto.CompactTextString(m) }
|
||||
func (*NodeState) ProtoMessage() {}
|
||||
func (*NodeState) Descriptor() ([]byte, []int) { return fileDescriptorPrivate, []int{14} }
|
||||
func (m *NodeStatus) Reset() { *m = NodeStatus{} }
|
||||
func (m *NodeStatus) String() string { return proto.CompactTextString(m) }
|
||||
func (*NodeStatus) ProtoMessage() {}
|
||||
func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorPrivate, []int{14} }
|
||||
|
||||
func (m *NodeState) GetIndexes() []*Index {
|
||||
func (m *NodeStatus) GetIndexes() []*Index {
|
||||
if m != nil {
|
||||
return m.Indexes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ClusterStatus struct {
|
||||
Nodes []*NodeStatus `protobuf:"bytes,1,rep,name=Nodes" json:"Nodes,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ClusterStatus) Reset() { *m = ClusterStatus{} }
|
||||
func (m *ClusterStatus) String() string { return proto.CompactTextString(m) }
|
||||
func (*ClusterStatus) ProtoMessage() {}
|
||||
func (*ClusterStatus) Descriptor() ([]byte, []int) { return fileDescriptorPrivate, []int{15} }
|
||||
|
||||
func (m *ClusterStatus) GetNodes() []*NodeStatus {
|
||||
if m != nil {
|
||||
return m.Nodes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*IndexMeta)(nil), "internal.IndexMeta")
|
||||
proto.RegisterType((*FrameMeta)(nil), "internal.FrameMeta")
|
||||
|
|
@ -264,7 +281,8 @@ func init() {
|
|||
proto.RegisterType((*DeleteFrameMessage)(nil), "internal.DeleteFrameMessage")
|
||||
proto.RegisterType((*Frame)(nil), "internal.Frame")
|
||||
proto.RegisterType((*Index)(nil), "internal.Index")
|
||||
proto.RegisterType((*NodeState)(nil), "internal.NodeState")
|
||||
proto.RegisterType((*NodeStatus)(nil), "internal.NodeStatus")
|
||||
proto.RegisterType((*ClusterStatus)(nil), "internal.ClusterStatus")
|
||||
}
|
||||
func (m *IndexMeta) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
|
|
@ -780,7 +798,7 @@ func (m *Index) MarshalTo(dAtA []byte) (int, error) {
|
|||
return i, nil
|
||||
}
|
||||
|
||||
func (m *NodeState) Marshal() (dAtA []byte, err error) {
|
||||
func (m *NodeStatus) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
|
|
@ -790,7 +808,7 @@ func (m *NodeState) Marshal() (dAtA []byte, err error) {
|
|||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *NodeState) MarshalTo(dAtA []byte) (int, error) {
|
||||
func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
|
|
@ -822,6 +840,36 @@ func (m *NodeState) MarshalTo(dAtA []byte) (int, error) {
|
|||
return i, nil
|
||||
}
|
||||
|
||||
func (m *ClusterStatus) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *ClusterStatus) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Nodes) > 0 {
|
||||
for _, msg := range m.Nodes {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintPrivate(dAtA, i, uint64(msg.Size()))
|
||||
n, err := msg.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Private(dAtA []byte, offset int, v uint64) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
|
|
@ -1074,7 +1122,7 @@ func (m *Index) Size() (n int) {
|
|||
return n
|
||||
}
|
||||
|
||||
func (m *NodeState) Size() (n int) {
|
||||
func (m *NodeStatus) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Host)
|
||||
|
|
@ -1094,6 +1142,18 @@ func (m *NodeState) Size() (n int) {
|
|||
return n
|
||||
}
|
||||
|
||||
func (m *ClusterStatus) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Nodes) > 0 {
|
||||
for _, e := range m.Nodes {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovPrivate(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovPrivate(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
|
|
@ -2899,7 +2959,7 @@ func (m *Index) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (m *NodeState) Unmarshal(dAtA []byte) error {
|
||||
func (m *NodeStatus) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
|
|
@ -2922,10 +2982,10 @@ func (m *NodeState) Unmarshal(dAtA []byte) error {
|
|||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: NodeState: wiretype end group for non-group")
|
||||
return fmt.Errorf("proto: NodeStatus: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: NodeState: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
return fmt.Errorf("proto: NodeStatus: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
|
|
@ -3038,6 +3098,87 @@ func (m *NodeState) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ClusterStatus) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPrivate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: ClusterStatus: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ClusterStatus: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Nodes", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPrivate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthPrivate
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Nodes = append(m.Nodes, &NodeStatus{})
|
||||
if err := m.Nodes[len(m.Nodes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipPrivate(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthPrivate
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipPrivate(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
|
@ -3146,43 +3287,44 @@ var (
|
|||
func init() { proto.RegisterFile("private.proto", fileDescriptorPrivate) }
|
||||
|
||||
var fileDescriptorPrivate = []byte{
|
||||
// 594 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x54, 0xc1, 0x6e, 0xd3, 0x4c,
|
||||
0x10, 0xfe, 0x9d, 0xb8, 0xfd, 0xe3, 0x89, 0x1a, 0xd2, 0x05, 0x21, 0x53, 0xa1, 0x28, 0xda, 0x03,
|
||||
0x0d, 0x3d, 0xe4, 0x50, 0x2e, 0x08, 0x71, 0xa8, 0x9a, 0x04, 0x35, 0x12, 0x29, 0x62, 0x53, 0x71,
|
||||
0x66, 0x93, 0x8c, 0xc0, 0x8a, 0x63, 0x07, 0x7b, 0x93, 0x34, 0x1c, 0xb8, 0xf3, 0x06, 0x48, 0x3c,
|
||||
0x03, 0xef, 0xc1, 0x91, 0x47, 0x40, 0xe1, 0x45, 0xd0, 0x8e, 0xd7, 0x76, 0x70, 0x29, 0x15, 0xdc,
|
||||
0x76, 0xbe, 0x99, 0x9d, 0xef, 0x9b, 0xcf, 0xb3, 0x86, 0xbd, 0x79, 0xe4, 0x2d, 0xa5, 0xc2, 0xf6,
|
||||
0x3c, 0x0a, 0x55, 0xc8, 0x2a, 0x5e, 0xa0, 0x30, 0x0a, 0xa4, 0xcf, 0x5f, 0x80, 0xd3, 0x0f, 0x26,
|
||||
0x78, 0x39, 0x40, 0x25, 0x59, 0x13, 0xaa, 0x9d, 0xd0, 0x5f, 0xcc, 0x82, 0xe7, 0x72, 0x84, 0xbe,
|
||||
0x6b, 0x35, 0xad, 0x96, 0x23, 0xb6, 0x21, 0x5d, 0x71, 0xe1, 0xcd, 0xf0, 0xe5, 0x42, 0x06, 0x6a,
|
||||
0x31, 0x73, 0x4b, 0x49, 0xc5, 0x16, 0xc4, 0xbf, 0x58, 0xe0, 0x3c, 0x8b, 0xe4, 0x0c, 0xa9, 0xe3,
|
||||
0x01, 0x54, 0x44, 0xb8, 0xda, 0x6e, 0x97, 0xc5, 0xec, 0x01, 0xd4, 0xfa, 0xc1, 0x12, 0xa3, 0x18,
|
||||
0x7b, 0x81, 0x1c, 0xf9, 0x38, 0xa1, 0x76, 0x15, 0x51, 0x40, 0xd9, 0x7d, 0x70, 0x3a, 0x72, 0xfc,
|
||||
0x16, 0x2f, 0xd6, 0x73, 0x74, 0xcb, 0xd4, 0x24, 0x07, 0xb2, 0xec, 0xd0, 0x7b, 0x8f, 0xae, 0xdd,
|
||||
0xb4, 0x5a, 0x7b, 0x22, 0x07, 0x8a, 0x7a, 0x77, 0xae, 0xea, 0xe5, 0x50, 0xeb, 0xcf, 0xe6, 0x61,
|
||||
0xa4, 0x04, 0xc6, 0xf3, 0x30, 0x88, 0x91, 0xd5, 0xa1, 0xdc, 0x8b, 0x22, 0x23, 0x57, 0x1f, 0xf9,
|
||||
0x07, 0xa8, 0x9f, 0xfa, 0xe1, 0x78, 0xda, 0x95, 0x4a, 0x0a, 0x7c, 0xb7, 0xc0, 0x58, 0xb1, 0x3b,
|
||||
0xb0, 0x43, 0xc6, 0x99, 0xba, 0x24, 0xd0, 0x28, 0x0d, 0x6f, 0x9c, 0x49, 0x02, 0x8d, 0xd2, 0x7d,
|
||||
0x52, 0x6f, 0x8b, 0x24, 0xd0, 0xe8, 0xd0, 0xf7, 0xc6, 0x89, 0x6a, 0x5b, 0x24, 0x01, 0x63, 0x60,
|
||||
0xbf, 0xf2, 0x70, 0x65, 0xa4, 0xd2, 0x99, 0xf7, 0x61, 0x7f, 0x8b, 0xdf, 0xc8, 0xbc, 0x0b, 0xbb,
|
||||
0x22, 0x5c, 0xf5, 0xbb, 0xb1, 0x6b, 0x35, 0xcb, 0x2d, 0x5b, 0x98, 0x88, 0x0c, 0xa1, 0x2f, 0xa6,
|
||||
0x53, 0x25, 0x4a, 0xe5, 0x00, 0xbf, 0x07, 0x3b, 0xe4, 0x8e, 0x9e, 0x32, 0xbf, 0xab, 0x8f, 0xfc,
|
||||
0xb3, 0x05, 0xfb, 0x03, 0x79, 0x49, 0x32, 0xe2, 0x8c, 0xe6, 0x0c, 0x9c, 0x0c, 0xa4, 0xea, 0xea,
|
||||
0xf1, 0x51, 0x3b, 0x5d, 0x9f, 0xf6, 0x95, 0xfa, 0x1c, 0xe9, 0x05, 0x2a, 0x5a, 0x8b, 0xfc, 0xf2,
|
||||
0xc1, 0x53, 0xa8, 0xfd, 0x9a, 0xd4, 0x1a, 0xa6, 0xb8, 0x4e, 0x9d, 0x9e, 0xe2, 0x5a, 0x7b, 0xb2,
|
||||
0x94, 0xfe, 0x22, 0xf1, 0xcf, 0x16, 0x49, 0xf0, 0xa4, 0xf4, 0xd8, 0xe2, 0x27, 0xc0, 0x3a, 0x11,
|
||||
0x4a, 0x85, 0xd4, 0x60, 0x80, 0x71, 0x2c, 0xdf, 0xe0, 0xf5, 0x5f, 0x21, 0x71, 0xb6, 0xb4, 0xe5,
|
||||
0x2c, 0x3f, 0x02, 0xd6, 0x45, 0x1f, 0x15, 0x9a, 0x85, 0xff, 0x43, 0x07, 0x3e, 0x4c, 0xd9, 0x6e,
|
||||
0xae, 0x65, 0x87, 0x60, 0xeb, 0x5d, 0x27, 0xb2, 0xea, 0xf1, 0xed, 0xdc, 0x9c, 0xec, 0x61, 0x09,
|
||||
0x2a, 0xe0, 0x5e, 0xda, 0xd4, 0xbc, 0x8f, 0x1b, 0x46, 0xf8, 0xcd, 0x22, 0xa5, 0x54, 0xe5, 0x22,
|
||||
0x55, 0xf6, 0xe2, 0x0c, 0xd5, 0x49, 0x3a, 0xeb, 0xbf, 0x52, 0xf1, 0xae, 0x41, 0xf5, 0x42, 0x9e,
|
||||
0xeb, 0x6c, 0x72, 0x87, 0xce, 0xd7, 0x8f, 0x5c, 0xd4, 0xf1, 0xd1, 0x32, 0x94, 0x7f, 0xd7, 0xa6,
|
||||
0xe0, 0x9c, 0xfe, 0x8d, 0xa4, 0xab, 0x63, 0xde, 0x50, 0x16, 0xb3, 0x43, 0xd8, 0x25, 0xd6, 0xd8,
|
||||
0xb5, 0x69, 0x3b, 0x6f, 0x15, 0xd4, 0x08, 0x93, 0xe6, 0xaf, 0xc1, 0x39, 0x0f, 0x27, 0x38, 0x54,
|
||||
0x52, 0xd1, 0x54, 0x67, 0x61, 0xac, 0x52, 0x39, 0xfa, 0x4c, 0x6b, 0xa3, 0x93, 0xa9, 0x11, 0x49,
|
||||
0xe5, 0x43, 0xf8, 0x9f, 0xe4, 0x60, 0xec, 0x96, 0x8b, 0x04, 0x94, 0x10, 0x69, 0xfe, 0xb4, 0xfe,
|
||||
0x75, 0xd3, 0xb0, 0xbe, 0x6d, 0x1a, 0xd6, 0xf7, 0x4d, 0xc3, 0xfa, 0xf4, 0xa3, 0xf1, 0xdf, 0x68,
|
||||
0x97, 0xfe, 0xb7, 0x8f, 0x7e, 0x06, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x68, 0xdc, 0x63, 0x80, 0x05,
|
||||
0x00, 0x00,
|
||||
// 617 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x54, 0xc1, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0xc5, 0x89, 0x53, 0x9a, 0xa9, 0x5a, 0xda, 0xa5, 0x42, 0xa6, 0x42, 0x51, 0xb4, 0x07, 0x5a,
|
||||
0x7a, 0xe8, 0xa1, 0x5c, 0x10, 0x70, 0xa8, 0x9a, 0x04, 0x35, 0x12, 0x29, 0x62, 0x53, 0x71, 0xdf,
|
||||
0x24, 0x23, 0xb0, 0xe2, 0xd8, 0xc1, 0xbb, 0x4e, 0x1a, 0x0e, 0xdc, 0xf9, 0x03, 0x24, 0xbe, 0x81,
|
||||
0xff, 0xe0, 0xc8, 0x27, 0xa0, 0xf0, 0x23, 0x68, 0xc7, 0x6b, 0x3b, 0xb8, 0x94, 0x0a, 0x6e, 0x3b,
|
||||
0x6f, 0x66, 0xe7, 0xbd, 0x7d, 0x9e, 0x31, 0x6c, 0x4e, 0x63, 0x7f, 0x26, 0x35, 0x1e, 0x4d, 0xe3,
|
||||
0x48, 0x47, 0x6c, 0xdd, 0x0f, 0x35, 0xc6, 0xa1, 0x0c, 0xf8, 0x2b, 0xa8, 0x77, 0xc3, 0x11, 0x5e,
|
||||
0xf6, 0x50, 0x4b, 0xd6, 0x84, 0x8d, 0x56, 0x14, 0x24, 0x93, 0xf0, 0xa5, 0x1c, 0x60, 0xe0, 0x39,
|
||||
0x4d, 0xe7, 0xa0, 0x2e, 0x56, 0x21, 0x53, 0x71, 0xe1, 0x4f, 0xf0, 0x75, 0x22, 0x43, 0x9d, 0x4c,
|
||||
0xbc, 0x4a, 0x5a, 0xb1, 0x02, 0xf1, 0xaf, 0x0e, 0xd4, 0x5f, 0xc4, 0x72, 0x82, 0xd4, 0x71, 0x0f,
|
||||
0xd6, 0x45, 0x34, 0x5f, 0x6d, 0x97, 0xc7, 0xec, 0x21, 0x6c, 0x75, 0xc3, 0x19, 0xc6, 0x0a, 0x3b,
|
||||
0xa1, 0x1c, 0x04, 0x38, 0xa2, 0x76, 0xeb, 0xa2, 0x84, 0xb2, 0x07, 0x50, 0x6f, 0xc9, 0xe1, 0x3b,
|
||||
0xbc, 0x58, 0x4c, 0xd1, 0xab, 0x52, 0x93, 0x02, 0xc8, 0xb3, 0x7d, 0xff, 0x03, 0x7a, 0x6e, 0xd3,
|
||||
0x39, 0xd8, 0x14, 0x05, 0x50, 0xd6, 0x5b, 0xbb, 0xaa, 0x97, 0xc3, 0x56, 0x77, 0x32, 0x8d, 0x62,
|
||||
0x2d, 0x50, 0x4d, 0xa3, 0x50, 0x21, 0xdb, 0x86, 0x6a, 0x27, 0x8e, 0xad, 0x5c, 0x73, 0xe4, 0x1f,
|
||||
0x61, 0xfb, 0x34, 0x88, 0x86, 0xe3, 0xb6, 0xd4, 0x52, 0xe0, 0xfb, 0x04, 0x95, 0x66, 0xbb, 0x50,
|
||||
0x23, 0xe3, 0x6c, 0x5d, 0x1a, 0x18, 0x94, 0x1e, 0x6f, 0x9d, 0x49, 0x03, 0x83, 0xd2, 0x7d, 0x52,
|
||||
0xef, 0x8a, 0x34, 0x30, 0x68, 0x3f, 0xf0, 0x87, 0xa9, 0x6a, 0x57, 0xa4, 0x01, 0x63, 0xe0, 0xbe,
|
||||
0xf1, 0x71, 0x6e, 0xa5, 0xd2, 0x99, 0x77, 0x61, 0x67, 0x85, 0xdf, 0xca, 0xbc, 0x07, 0x6b, 0x22,
|
||||
0x9a, 0x77, 0xdb, 0xca, 0x73, 0x9a, 0xd5, 0x03, 0x57, 0xd8, 0x88, 0x0c, 0xa1, 0x2f, 0x66, 0x52,
|
||||
0x15, 0x4a, 0x15, 0x00, 0xbf, 0x0f, 0x35, 0x72, 0xc7, 0xbc, 0xb2, 0xb8, 0x6b, 0x8e, 0xfc, 0x8b,
|
||||
0x03, 0x3b, 0x3d, 0x79, 0x49, 0x32, 0x54, 0x4e, 0x73, 0x06, 0xf5, 0x1c, 0xa4, 0xea, 0x8d, 0xe3,
|
||||
0xc3, 0xa3, 0x6c, 0x7c, 0x8e, 0xae, 0xd4, 0x17, 0x48, 0x27, 0xd4, 0xf1, 0x42, 0x14, 0x97, 0xf7,
|
||||
0x9e, 0xc3, 0xd6, 0xef, 0x49, 0xa3, 0x61, 0x8c, 0x8b, 0xcc, 0xe9, 0x31, 0x2e, 0x8c, 0x27, 0x33,
|
||||
0x19, 0x24, 0xa9, 0x7f, 0xae, 0x48, 0x83, 0xa7, 0x95, 0x27, 0x0e, 0x3f, 0x01, 0xd6, 0x8a, 0x51,
|
||||
0x6a, 0xa4, 0x06, 0x3d, 0x54, 0x4a, 0xbe, 0xc5, 0xeb, 0xbf, 0x42, 0xea, 0x6c, 0x65, 0xc5, 0x59,
|
||||
0x7e, 0x08, 0xac, 0x8d, 0x01, 0x6a, 0xb4, 0x03, 0xff, 0x97, 0x0e, 0xbc, 0x9f, 0xb1, 0xdd, 0x5c,
|
||||
0xcb, 0xf6, 0xc1, 0x35, 0xb3, 0x4e, 0x64, 0x1b, 0xc7, 0x77, 0x0b, 0x73, 0xf2, 0xc5, 0x12, 0x54,
|
||||
0xc0, 0xfd, 0xac, 0xa9, 0xdd, 0x8f, 0x1b, 0x9e, 0xf0, 0x87, 0x41, 0xca, 0xa8, 0xaa, 0x65, 0xaa,
|
||||
0x7c, 0xe3, 0x2c, 0xd5, 0x49, 0xf6, 0xd6, 0xff, 0xa5, 0xe2, 0x6d, 0x8b, 0x9a, 0x81, 0x3c, 0x37,
|
||||
0xd9, 0xf4, 0x0e, 0x9d, 0xaf, 0x7f, 0x72, 0x59, 0xc7, 0x27, 0xc7, 0x52, 0xfe, 0x5b, 0x9b, 0x92,
|
||||
0x73, 0xe6, 0x37, 0x92, 0x8d, 0x8e, 0xdd, 0xa1, 0x3c, 0x66, 0xfb, 0xb0, 0x46, 0xac, 0xca, 0x73,
|
||||
0x69, 0x3a, 0xef, 0x94, 0xd4, 0x08, 0x9b, 0xe6, 0x12, 0xe0, 0x3c, 0x1a, 0x61, 0x5f, 0x4b, 0x9d,
|
||||
0x28, 0xa3, 0xe7, 0x2c, 0x52, 0x3a, 0xd3, 0x63, 0xce, 0x34, 0x37, 0x5a, 0xea, 0xdc, 0x09, 0x0a,
|
||||
0xd8, 0x23, 0xb8, 0x4d, 0x7a, 0x50, 0x79, 0xd5, 0x32, 0x03, 0x25, 0x44, 0x96, 0xe7, 0xcf, 0x60,
|
||||
0xb3, 0x15, 0x24, 0x4a, 0x63, 0x6c, 0x59, 0x0e, 0xa1, 0x66, 0x38, 0xb3, 0xcd, 0xd9, 0x2d, 0x6e,
|
||||
0x16, 0x52, 0x44, 0x5a, 0x72, 0xba, 0xfd, 0x6d, 0xd9, 0x70, 0xbe, 0x2f, 0x1b, 0xce, 0x8f, 0x65,
|
||||
0xc3, 0xf9, 0xfc, 0xb3, 0x71, 0x6b, 0xb0, 0x46, 0x7f, 0xeb, 0xc7, 0xbf, 0x02, 0x00, 0x00, 0xff,
|
||||
0xff, 0x77, 0x02, 0x29, 0xbb, 0xbe, 0x05, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,8 +77,12 @@ message Index {
|
|||
repeated Frame Frames = 4;
|
||||
}
|
||||
|
||||
message NodeState {
|
||||
message NodeStatus {
|
||||
string Host = 1;
|
||||
string State = 2;
|
||||
repeated Index Indexes = 3;
|
||||
}
|
||||
|
||||
message ClusterStatus {
|
||||
repeated NodeStatus Nodes = 1;
|
||||
}
|
||||
|
|
|
|||
51
server.go
51
server.go
|
|
@ -118,6 +118,7 @@ func (s *Server) Open() error {
|
|||
|
||||
// Initialize HTTP handler.
|
||||
s.Handler.Broadcaster = s.Broadcaster
|
||||
s.Handler.StatusHandler = s
|
||||
s.Handler.Host = s.Host
|
||||
s.Handler.Cluster = s.Cluster
|
||||
s.Handler.Executor = e
|
||||
|
|
@ -271,28 +272,49 @@ func (s *Server) ReceiveMessage(pb proto.Message) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Server implements gossip.StateHandler.
|
||||
// LocalState returns the state of the local node as well as the
|
||||
// Server implements StatusHandler.
|
||||
// LocalStatus returns the state of the local node as well as the
|
||||
// holder (indexes/frames) according to the local node.
|
||||
// In a gossip implementation, memberlist.Delegate.LocalState() uses this.
|
||||
func (s *Server) LocalState() (proto.Message, error) {
|
||||
func (s *Server) LocalStatus() (proto.Message, error) {
|
||||
if s.Holder == nil {
|
||||
return nil, errors.New("Server.Holder is nil.")
|
||||
}
|
||||
return &internal.NodeState{
|
||||
return &internal.NodeStatus{
|
||||
Host: s.Host,
|
||||
State: "OK", // TODO: make this work, pull from s.Cluster.Node
|
||||
State: NodeStateUp,
|
||||
Indexes: encodeIndexes(s.Holder.Indexes()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleRemoteState receives incoming NodeState from remote nodes.
|
||||
func (s *Server) HandleRemoteState(pb proto.Message) error {
|
||||
return s.mergeRemoteState(pb.(*internal.NodeState))
|
||||
// ClusterStatus returns the NodeState for all nodes in the cluster.
|
||||
func (s *Server) ClusterStatus() (proto.Message, error) {
|
||||
// Update local Node.state.
|
||||
ns, err := s.LocalStatus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node := s.Cluster.NodeByHost(s.Host)
|
||||
node.SetStatus(ns.(*internal.NodeStatus))
|
||||
|
||||
// Update NodeState for all nodes.
|
||||
for host, nodeState := range s.Cluster.NodeStates() {
|
||||
node := s.Cluster.NodeByHost(host)
|
||||
node.SetState(nodeState)
|
||||
}
|
||||
|
||||
return s.Cluster.Status(), nil
|
||||
}
|
||||
|
||||
func (s *Server) mergeRemoteState(ns *internal.NodeState) error {
|
||||
// TODO: update some node state value in the cluster (it should be in cluster.node i guess)
|
||||
// HandleRemoteStatus receives incoming NodeState from remote nodes.
|
||||
func (s *Server) HandleRemoteStatus(pb proto.Message) error {
|
||||
return s.mergeRemoteStatus(pb.(*internal.NodeStatus))
|
||||
}
|
||||
|
||||
func (s *Server) mergeRemoteStatus(ns *internal.NodeStatus) error {
|
||||
// Update Node.state.
|
||||
node := s.Cluster.NodeByHost(ns.Host)
|
||||
node.SetStatus(ns)
|
||||
|
||||
// Create indexes that don't exist.
|
||||
for _, index := range ns.Indexes {
|
||||
|
|
@ -364,3 +386,12 @@ func checkMaxSlices(hostport string) (map[string]uint64, error) {
|
|||
|
||||
return pb.MaxSlices, nil
|
||||
}
|
||||
|
||||
// StatusHandler specifies two methods which an object must implement to share
|
||||
// state in the cluster. These are used by the GossipNodeSet to implement the
|
||||
// LocalState and MergeRemoteState methods of memberlist.Delegate
|
||||
type StatusHandler interface {
|
||||
LocalStatus() (proto.Message, error)
|
||||
ClusterStatus() (proto.Message, error)
|
||||
HandleRemoteStatus(proto.Message) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// package server contains the `pilosa server` subcommand which runs Pilosa
|
||||
// Package server contains the `pilosa server` subcommand which runs Pilosa
|
||||
// itself. The purpose of this package is to define an easily tested Command
|
||||
// object which handles interpreting configuration and setting up all the
|
||||
// objects that Pilosa needs.
|
||||
|
|
@ -50,7 +50,7 @@ type Command struct {
|
|||
Done chan struct{}
|
||||
}
|
||||
|
||||
// NewMain returns a new instance of Main.
|
||||
// NewCommand returns a new instance of Main.
|
||||
func NewCommand(stdin io.Reader, stdout, stderr io.Writer) *Command {
|
||||
return &Command{
|
||||
Server: pilosa.NewServer(),
|
||||
|
|
@ -89,6 +89,7 @@ func (m *Command) Run(args ...string) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetupServer use the cluster configuration to setup this server
|
||||
func (m *Command) SetupServer() error {
|
||||
cluster := pilosa.NewCluster()
|
||||
cluster.ReplicaN = m.Config.Cluster.ReplicaN
|
||||
|
|
@ -163,8 +164,12 @@ func (m *Command) SetupServer() error {
|
|||
m.Server.Broadcaster = pilosa.NopBroadcaster
|
||||
m.Server.Cluster.NodeSet = pilosa.NewStaticNodeSet()
|
||||
m.Server.BroadcastReceiver = pilosa.NopBroadcastReceiver
|
||||
err := m.Server.Cluster.NodeSet.(*pilosa.StaticNodeSet).Join(m.Server.Cluster.Nodes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("'%v' is not a supported value for broadcaster type.", m.Config.Cluster.Type)
|
||||
return fmt.Errorf("'%v' is not a supported value for broadcaster type", m.Config.Cluster.Type)
|
||||
}
|
||||
|
||||
// Set configuration options.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue