<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package faketikv

import (
	"context"
	"fmt"
	"math/rand"
	"sort"

	"github.com/juju/errors"
	"github.com/pingcap/kvproto/pkg/metapb"
	"github.com/pingcap/pd/pkg/faketikv/cases"
	"github.com/pingcap/pd/pkg/faketikv/simutil"
	"github.com/pingcap/pd/server/core"
)

// ClusterInfo records all cluster information.
type ClusterInfo struct {
	conf *cases.Conf
	*core.RegionsInfo
	Nodes map[uint64]*Node
}

// NewClusterInfo creates the initialized cluster with config.
func NewClusterInfo(pdAddr string, conf *cases.Conf) (*ClusterInfo, error) {
	cluster := &ClusterInfo{
		conf:        conf,
		RegionsInfo: core.NewRegionsInfo(),
		Nodes:       make(map[uint64]*Node),
	}

	for _, store := range conf.Stores {
		node, err := NewNode(store.ID, fmt.Sprintf("mock:://tikv-%d", store.ID), pdAddr)
		if err != nil {
			return nil, errors.Trace(err)
		}
		node.clusterInfo = cluster
		cluster.Nodes[store.ID] = node
	}

	splitKeys := generateKeys(len(conf.Regions) - 1)
	for i, region := range conf.Regions {
		meta := &metapb.Region{
			Id:          region.ID,
			Peers:       region.Peers,
			RegionEpoch: &metapb.RegionEpoch{ConfVer: 1, Version: 1},
		}
		if i > 0 {
			meta.StartKey = []byte(splitKeys[i-1])
		}
		if i < len(conf.Regions)-1 {
			meta.EndKey = []byte(splitKeys[i])
		}
		regionInfo := core.NewRegionInfo(meta, region.Leader)
		regionInfo.ApproximateSize = region.Size
		cluster.RegionsInfo.SetRegion(regionInfo)
	}

	return cluster, nil
}

// GetBootstrapInfo returns a valid bootstrap store and region.
func (c *ClusterInfo) GetBootstrapInfo() (*metapb.Store, *metapb.Region, error) {
	region := c.RegionsInfo.RandRegion()
	if region == nil {
		return nil, nil, errors.New("no region found for bootstrap")
	}
	if region.Leader == nil {
		return nil, nil, errors.New("bootstrap region has no leader")
	}
	store := c.Nodes[region.Leader.GetStoreId()]
	if store == nil {
		return nil, nil, errors.Errorf("bootstrap store %v not found", region.Leader.GetStoreId())
	}
	region.StartKey, region.EndKey = []byte(""), []byte("")
	region.RegionEpoch = &metapb.RegionEpoch{}
	region.Peers = []*metapb.Peer{region.Leader}
	return store.Store, region.Region, nil
}

func (c *ClusterInfo) nodeHealth(storeID uint64) bool {
	n, ok := c.Nodes[storeID]
	if !ok {
		return false
	}
<commit_msg>faketikv: fix the overlap problem when getting the bootstrap region (#1090)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package faketikv

import (
	"context"
	"fmt"
	"math/rand"
	"sort"

	"github.com/juju/errors"
	"github.com/pingcap/kvproto/pkg/metapb"
	"github.com/pingcap/pd/pkg/faketikv/cases"
	"github.com/pingcap/pd/pkg/faketikv/simutil"
	"github.com/pingcap/pd/server/core"
)

// ClusterInfo records all cluster information.
type ClusterInfo struct {
	conf *cases.Conf
	*core.RegionsInfo
	Nodes map[uint64]*Node
}

// NewClusterInfo creates the initialized cluster with config.
func NewClusterInfo(pdAddr string, conf *cases.Conf) (*ClusterInfo, error) {
	cluster := &ClusterInfo{
		conf:        conf,
		RegionsInfo: core.NewRegionsInfo(),
		Nodes:       make(map[uint64]*Node),
	}

	for _, store := range conf.Stores {
		node, err := NewNode(store.ID, fmt.Sprintf("mock:://tikv-%d", store.ID), pdAddr)
		if err != nil {
			return nil, errors.Trace(err)
		}
		node.clusterInfo = cluster
		cluster.Nodes[store.ID] = node
	}

	splitKeys := generateKeys(len(conf.Regions) - 1)
	for i, region := range conf.Regions {
		meta := &metapb.Region{
			Id:          region.ID,
			Peers:       region.Peers,
			RegionEpoch: &metapb.RegionEpoch{ConfVer: 1, Version: 1},
		}
		if i > 0 {
			meta.StartKey = []byte(splitKeys[i-1])
		}
		if i < len(conf.Regions)-1 {
			meta.EndKey = []byte(splitKeys[i])
		}
		regionInfo := core.NewRegionInfo(meta, region.Leader)
		regionInfo.ApproximateSize = region.Size
		cluster.RegionsInfo.SetRegion(regionInfo)
	}

	return cluster, nil
}

// GetBootstrapInfo returns a valid bootstrap store and region.
func (c *ClusterInfo) GetBootstrapInfo() (*metapb.Store, *metapb.Region, error) {
	origin := c.RegionsInfo.RandRegion()
	if origin == nil {
		return nil, nil, errors.New("no region found for bootstrap")
	}
	region := origin.Clone()
	if region.Leader == nil {
		return nil, nil, errors.New("bootstrap region has no leader")
	}
	store := c.Nodes[region.Leader.GetStoreId()]
	if store == nil {
		return nil, nil, errors.Errorf("bootstrap store %v not found", region.Leader.GetStoreId())
	}
	region.StartKey, region.EndKey = []byte(""), []byte("")
	region.RegionEpoch = &metapb.RegionEpoch{}
	region.Peers = []*metapb.Peer{region.Leader}
	return store.Store, region.Region, nil
}

func (c *ClusterInfo) nodeHealth(storeID uint64) bool {
	n, ok := c.Nodes[storeID]
	if !ok {
		return false
	}

{'fraction_non_alphanumeric': 0.13604610548375828, 'fraction_numerical': 0.007684247293049249, 'mean_word_length': 3.8045302013422817, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4496629', 'n_tokens_mistral': 2067, 'n_tokens_neox': 1950, 'n_words': 522}