Skip to content

Commit

Permalink
server/api: add the api to show the regions in subtree by type (#8101)
Browse files Browse the repository at this point in the history
close #8100

server/api: add the api to show the regions in subtree by type

Signed-off-by: nolouch <nolouch@gmail.com>

Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com>
  • Loading branch information
nolouch and ti-chi-bot[bot] authored Apr 30, 2024
1 parent aae410f commit 6e3cac7
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 2 deletions.
54 changes: 54 additions & 0 deletions pkg/core/region.go
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,60 @@ func (r *RegionsInfo) GetStoreRegions(storeID uint64) []*RegionInfo {
return regions
}

// SubTreeRegionType is the type of sub tree region.
type SubTreeRegionType string

const (
// AllInSubTree is all sub trees.
AllInSubTree SubTreeRegionType = "all"
// LeaderInSubTree is the leader sub tree.
LeaderInSubTree SubTreeRegionType = "leader"
// FollowerInSubTree is the follower sub tree.
FollowerInSubTree SubTreeRegionType = "follower"
// LearnerInSubTree is the learner sub tree.
LearnerInSubTree SubTreeRegionType = "learner"
// WitnessInSubTree is the witness sub tree.
WitnessInSubTree SubTreeRegionType = "witness"
// PendingPeerInSubTree is the pending peer sub tree.
PendingPeerInSubTree SubTreeRegionType = "pending"
)

// GetStoreRegions gets all RegionInfo with a given storeID
func (r *RegionsInfo) GetStoreRegionsByTypeInSubTree(storeID uint64, typ SubTreeRegionType) ([]*RegionInfo, error) {
r.st.RLock()
var regions []*RegionInfo
switch typ {
case LeaderInSubTree:
if leaders, ok := r.leaders[storeID]; ok {
regions = leaders.scanRanges()
}
case FollowerInSubTree:
if followers, ok := r.followers[storeID]; ok {
regions = followers.scanRanges()
}
case LearnerInSubTree:
if learners, ok := r.learners[storeID]; ok {
regions = learners.scanRanges()
}
case WitnessInSubTree:
if witnesses, ok := r.witnesses[storeID]; ok {
regions = witnesses.scanRanges()
}
case PendingPeerInSubTree:
if pendingPeers, ok := r.pendingPeers[storeID]; ok {
regions = pendingPeers.scanRanges()
}
case AllInSubTree:
r.st.RUnlock()
return r.GetStoreRegions(storeID), nil
default:
return nil, errors.Errorf("unknown sub tree region type %v", typ)
}

r.st.RUnlock()
return regions, nil
}

// GetStoreLeaderRegionSize get total size of store's leader regions
func (r *RegionsInfo) GetStoreLeaderRegionSize(storeID uint64) int64 {
r.st.RLock()
Expand Down
2 changes: 2 additions & 0 deletions pkg/response/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type StoreStatus struct {
RegionSize int64 `json:"region_size"`
LearnerCount int `json:"learner_count,omitempty"`
WitnessCount int `json:"witness_count,omitempty"`
PendingPeerCount int `json:"pending_peer_count,omitempty"`
SlowScore uint64 `json:"slow_score,omitempty"`
SlowTrend *SlowTrend `json:"slow_trend,omitempty"`
SendingSnapCount uint32 `json:"sending_snap_count,omitempty"`
Expand Down Expand Up @@ -117,6 +118,7 @@ func BuildStoreInfo(opt *sc.ScheduleConfig, store *core.StoreInfo) *StoreInfo {
SlowTrend: slowTrend,
SendingSnapCount: store.GetSendingSnapCount(),
ReceivingSnapCount: store.GetReceivingSnapCount(),
PendingPeerCount: store.GetPendingPeerCount(),
IsBusy: store.IsBusy(),
},
}
Expand Down
12 changes: 11 additions & 1 deletion server/api/region.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,17 @@ func (h *regionsHandler) GetStoreRegions(w http.ResponseWriter, r *http.Request)
h.rd.JSON(w, http.StatusBadRequest, err.Error())
return
}
regions := rc.GetStoreRegions(uint64(id))
// get type from query
typ := r.URL.Query().Get("type")
if len(typ) == 0 {
typ = string(core.AllInSubTree)
}

regions, err := rc.GetStoreRegionsByTypeInSubTree(uint64(id), core.SubTreeRegionType(typ))
if err != nil {
h.rd.JSON(w, http.StatusBadRequest, err.Error())
return
}
b, err := response.MarshalRegionsInfoJSON(r.Context(), regions)
if err != nil {
h.rd.JSON(w, http.StatusInternalServerError, err.Error())
Expand Down
5 changes: 5 additions & 0 deletions server/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,11 @@ func (c *RaftCluster) GetStoreRegions(storeID uint64) []*core.RegionInfo {
return c.core.GetStoreRegions(storeID)
}

// GetStoreRegions returns all regions' information with a given storeID.
func (c *RaftCluster) GetStoreRegionsByType(storeID uint64) []*core.RegionInfo {
return c.core.GetStoreRegions(storeID)
}

// RandLeaderRegions returns some random regions that has leader on the store.
func (c *RaftCluster) RandLeaderRegions(storeID uint64, ranges []core.KeyRange) []*core.RegionInfo {
return c.core.RandLeaderRegions(storeID, ranges)
Expand Down
3 changes: 3 additions & 0 deletions tools/pd-ctl/pdctl/command/region_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ func NewRegionWithStoreCommand() *cobra.Command {
Short: "show the regions of a specific store",
Run: showRegionWithStoreCommandFunc,
}
r.Flags().String("type", "all", "the type of the regions, could be 'all', 'leader', 'learner' or 'pending'")
return r
}

Expand All @@ -496,6 +497,8 @@ func showRegionWithStoreCommandFunc(cmd *cobra.Command, args []string) {
}
storeID := args[0]
prefix := regionsStorePrefix + "/" + storeID
flagType := cmd.Flag("type")
prefix += "?type=" + flagType.Value.String()
r, err := doRequest(cmd, prefix, http.MethodGet, http.Header{})
if err != nil {
cmd.Printf("Failed to get regions with the given storeID: %s\n", err)
Expand Down
12 changes: 11 additions & 1 deletion tools/pd-ctl/tests/region/region_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ func TestRegion(t *testing.T) {
)
defer cluster.Destroy()

getRegionsByType := func(storeID uint64, regionType core.SubTreeRegionType) []*core.RegionInfo {
regions, _ := leaderServer.GetRaftCluster().GetStoreRegionsByTypeInSubTree(storeID, regionType)
return regions
}

var testRegionsCases = []struct {
args []string
expect []*core.RegionInfo
Expand All @@ -118,7 +123,12 @@ func TestRegion(t *testing.T) {
{[]string{"region", "sibling", "2"}, leaderServer.GetAdjacentRegions(leaderServer.GetRegionInfoByID(2))},
// region store <store_id> command
{[]string{"region", "store", "1"}, leaderServer.GetStoreRegions(1)},
{[]string{"region", "store", "1"}, []*core.RegionInfo{r1, r2, r3, r4}},
{[]string{"region", "store", "1", "--type=leader"}, getRegionsByType(1, core.LeaderInSubTree)},
{[]string{"region", "store", "1", "--type=follower"}, getRegionsByType(1, core.FollowerInSubTree)},
{[]string{"region", "store", "1", "--type=learner"}, getRegionsByType(1, core.LearnerInSubTree)},
{[]string{"region", "store", "1", "--type=witness"}, getRegionsByType(1, core.WitnessInSubTree)},
{[]string{"region", "store", "1", "--type=pending"}, getRegionsByType(1, core.PendingPeerInSubTree)},
{[]string{"region", "store", "1", "--type=all"}, []*core.RegionInfo{r1, r2, r3, r4}},
// region check extra-peer command
{[]string{"region", "check", "extra-peer"}, []*core.RegionInfo{r1}},
// region check miss-peer command
Expand Down

0 comments on commit 6e3cac7

Please sign in to comment.