// handleFetchData handles a request for the current nodes meta data func (r *rpc) handleFetchData(req *internal.FetchDataRequest) (*internal.FetchDataResponse, error) { var ( b []byte data *Data err error ) for { data = r.store.cachedData() if data.Index != req.GetIndex() { b, err = data.MarshalBinary() if err != nil { return nil, err } break } if !req.GetBlocking() { break } if err := r.store.WaitForDataChanged(); err != nil { return nil, err } } return &internal.FetchDataResponse{ Header: &internal.ResponseHeader{ OK: proto.Bool(true), }, Index: proto.Uint64(data.Index), Term: proto.Uint64(data.Term), Data: b}, nil }
// marshal serializes to a protobuf representation. func (si ShardInfo) marshal() *internal.ShardInfo { pb := &internal.ShardInfo{ ID: proto.Uint64(si.ID), } pb.OwnerIDs = make([]uint64, len(si.OwnerIDs)) copy(pb.OwnerIDs, si.OwnerIDs) return pb }
// fetchMetaData returns the latest copy of the meta store data from the current // leader. func (r *rpc) fetchMetaData(blocking bool) (*Data, error) { assert(r.store != nil, "store is nil") // Retrieve the current known leader. leader := r.store.Leader() if leader == "" { return nil, errors.New("no leader") } var index, term uint64 data := r.store.cachedData() if data != nil { index = data.Index term = data.Index } resp, err := r.call(leader, &internal.FetchDataRequest{ Index: proto.Uint64(index), Term: proto.Uint64(term), Blocking: proto.Bool(blocking), }) if err != nil { return nil, err } switch t := resp.(type) { case *internal.FetchDataResponse: // If data is nil, then the term and index we sent matches the leader if t.GetData() == nil { return nil, nil } ms := &Data{} if err := ms.UnmarshalBinary(t.GetData()); err != nil { return nil, fmt.Errorf("rpc unmarshal metadata: %v", err) } return ms, nil case *internal.ErrorResponse: return nil, fmt.Errorf("rpc failed: %s", t.GetHeader().GetError()) default: return nil, fmt.Errorf("rpc failed: unknown response type: %v", t.String()) } }
// marshal serializes to a protobuf representation. func (data *Data) marshal() *internal.Data { pb := &internal.Data{ Term: proto.Uint64(data.Term), Index: proto.Uint64(data.Index), ClusterID: proto.Uint64(data.ClusterID), MaxNodeID: proto.Uint64(data.MaxNodeID), MaxShardGroupID: proto.Uint64(data.MaxShardGroupID), MaxShardID: proto.Uint64(data.MaxShardID), } pb.Nodes = make([]*internal.NodeInfo, len(data.Nodes)) for i := range data.Nodes { pb.Nodes[i] = data.Nodes[i].marshal() } pb.Databases = make([]*internal.DatabaseInfo, len(data.Databases)) for i := range data.Databases { pb.Databases[i] = data.Databases[i].marshal() } pb.Users = make([]*internal.UserInfo, len(data.Users)) for i := range data.Users { pb.Users[i] = data.Users[i].marshal() } return pb }
// marshal serializes to a protobuf representation. func (sgi *ShardGroupInfo) marshal() *internal.ShardGroupInfo { pb := &internal.ShardGroupInfo{ ID: proto.Uint64(sgi.ID), StartTime: proto.Int64(MarshalTime(sgi.StartTime)), EndTime: proto.Int64(MarshalTime(sgi.EndTime)), DeletedAt: proto.Int64(MarshalTime(sgi.DeletedAt)), } pb.Shards = make([]*internal.ShardInfo, len(sgi.Shards)) for i := range sgi.Shards { pb.Shards[i] = sgi.Shards[i].marshal() } return pb }
// handleJoinRequest handles a request to join the cluster func (r *rpc) handleJoinRequest(req *internal.JoinRequest) (*internal.JoinResponse, error) { r.traceCluster("join request from: %v", *req.Addr) node, err := func() (*NodeInfo, error) { // attempt to create the node node, err := r.store.CreateNode(*req.Addr) // if it exists, return the existing node if err == ErrNodeExists { return r.store.NodeByHost(*req.Addr) } else if err != nil { return nil, fmt.Errorf("create node: %v", err) } // FIXME: jwilder: adding raft nodes is tricky since going // from 1 node (leader) to two kills the cluster because // quorum is lost after adding the second node. For now, // can only add non-raft enabled nodes // If we have less than 3 nodes, add them as raft peers // if len(r.store.Peers()) < MaxRaftNodes { // if err = r.store.AddPeer(*req.Addr); err != nil { // return node, fmt.Errorf("add peer: %v", err) // } // } return node, err }() nodeID := uint64(0) if node != nil { nodeID = node.ID } if err != nil { return nil, err } return &internal.JoinResponse{ Header: &internal.ResponseHeader{ OK: proto.Bool(true), }, //EnableRaft: proto.Bool(contains(r.store.Peers(), *req.Addr)), EnableRaft: proto.Bool(false), RaftNodes: r.store.Peers(), NodeID: proto.Uint64(nodeID), }, err }
// marshal serializes to a protobuf representation. func (ni NodeInfo) marshal() *internal.NodeInfo { pb := &internal.NodeInfo{} pb.ID = proto.Uint64(ni.ID) pb.Host = proto.String(ni.Host) return pb }