// Ranges returns range info for the server specified func (s *statusServer) Ranges(ctx context.Context, req *serverpb.RangesRequest) (*serverpb.RangesResponse, error) { nodeID, local, err := s.parseNodeID(req.NodeId) if err != nil { return nil, grpc.Errorf(codes.InvalidArgument, err.Error()) } if !local { status, err := s.dialNode(nodeID) if err != nil { return nil, err } return status.Ranges(ctx, req) } output := serverpb.RangesResponse{ Ranges: make([]serverpb.RangeInfo, 0, s.stores.GetStoreCount()), } err = s.stores.VisitStores(func(store *storage.Store) error { // Use IterateRangeDescriptors to read from the engine only // because it's already exported. err := storage.IterateRangeDescriptors(store.Engine(), func(desc roachpb.RangeDescriptor) (bool, error) { rep, err := store.GetReplica(desc.RangeID) if err != nil { return true, err } status := rep.RaftStatus() var raftState string if status != nil { // We can't put the whole raft.Status object in the json output // because it contains a map with integer keys. Just extract // the most interesting bit for now. raftState = status.RaftState.String() } else { raftState = "StateDormant" } state := rep.State() output.Ranges = append(output.Ranges, serverpb.RangeInfo{ Span: serverpb.PrettySpan{ StartKey: desc.StartKey.String(), EndKey: desc.EndKey.String(), }, RaftState: raftState, State: state, }) return false, nil }) return err }) if err != nil { return nil, grpc.Errorf(codes.Internal, err.Error()) } return &output, nil }
// Ranges returns range info for the server specified func (s *statusServer) Ranges(ctx context.Context, req *serverpb.RangesRequest) (*serverpb.RangesResponse, error) { nodeID, local, err := s.parseNodeID(req.NodeId) if err != nil { return nil, grpc.Errorf(codes.InvalidArgument, err.Error()) } if !local { status, err := s.dialNode(nodeID) if err != nil { return nil, err } return status.Ranges(ctx, req) } output := serverpb.RangesResponse{ Ranges: make([]serverpb.RangeInfo, 0, s.stores.GetStoreCount()), } convertRaftStatus := func(raftStatus *raft.Status) serverpb.RaftState { var state serverpb.RaftState if raftStatus == nil { state.State = "StateDormant" return state } state.ReplicaID = raftStatus.ID state.HardState = raftStatus.HardState state.Applied = raftStatus.Applied // Grab Lead and State, which together form the SoftState. state.Lead = raftStatus.Lead state.State = raftStatus.RaftState.String() state.Progress = make(map[uint64]serverpb.RaftState_Progress) for id, progress := range raftStatus.Progress { state.Progress[id] = serverpb.RaftState_Progress{ Match: progress.Match, Next: progress.Next, Paused: progress.Paused, PendingSnapshot: progress.PendingSnapshot, State: progress.State.String(), } } return state } err = s.stores.VisitStores(func(store *storage.Store) error { // Use IterateRangeDescriptors to read from the engine only // because it's already exported. err := storage.IterateRangeDescriptors(ctx, store.Engine(), func(desc roachpb.RangeDescriptor) (bool, error) { rep, err := store.GetReplica(desc.RangeID) if err != nil { return true, err } output.Ranges = append(output.Ranges, serverpb.RangeInfo{ Span: serverpb.PrettySpan{ StartKey: desc.StartKey.String(), EndKey: desc.EndKey.String(), }, RaftState: convertRaftStatus(rep.RaftStatus()), State: rep.State(), }) return false, nil }) return err }) if err != nil { return nil, grpc.Errorf(codes.Internal, err.Error()) } return &output, nil }