func NewExcludedFilter(scope string, sources, targets map[uint64]struct{}) Filter {
	return &excludedFilter{
		scope:   scope,
		sources: sources,
		targets: targets,
	}
}
NewExcludedFilter creates a Filter that filters all specified stores.
package filter
import (
	"fmt"
	"strconv"
	"github.com/golang/protobuf/proto"
	"github.com/pingcap/kvproto/pkg/metapb"
	"github.com/pingcap/log"
	"github.com/tikv/pd/pkg/slice"
	"github.com/tikv/pd/server/config"
	"github.com/tikv/pd/server/core"
	"github.com/tikv/pd/server/core/storelimit"
	"github.com/tikv/pd/server/schedule/opt"
	"github.com/tikv/pd/server/schedule/placement"
	"go.uber.org/zap"
)
func SelectSourceStores(stores []*core.StoreInfo, filters []Filter, opt *config.PersistOptions) []*core.StoreInfo {
	return filterStoresBy(stores, func(s *core.StoreInfo) bool {
		return slice.AllOf(filters, func(i int) bool {
			if !filters[i].Source(opt, s) {
				sourceID := strconv.FormatUint(s.GetID(), 10)
				targetID := ""
				filterCounter.WithLabelValues("filter-source", s.GetAddress(),
					sourceID, filters[i].Scope(), filters[i].Type(), sourceID, targetID).Inc()
				return false
			}
			return true
		})
	})
}
func SelectTargetStores(stores []*core.StoreInfo, filters []Filter, opt *config.PersistOptions) []*core.StoreInfo {
	return filterStoresBy(stores, func(s *core.StoreInfo) bool {
		return slice.AllOf(filters, func(i int) bool {
			filter := filters[i]
			if !filter.Target(opt, s) {
				cfilter, ok := filter.(comparingFilter)
				targetID := strconv.FormatUint(s.GetID(), 10)
				sourceID := ""
				if ok {
					sourceID = strconv.FormatUint(cfilter.GetSourceStoreID(), 10)
				}
				filterCounter.WithLabelValues("filter-target", s.GetAddress(),
					targetID, filters[i].Scope(), filters[i].Type(), sourceID, targetID).Inc()
				return false
			}
			return true
		})
	})
}
func filterStoresBy(stores []*core.StoreInfo, keepPred func(*core.StoreInfo) bool) (selected []*core.StoreInfo) {
	for _, s := range stores {
		if keepPred(s) {
			selected = append(selected, s)
		}
	}
	return
}
type Filter interface {
	Scope() string
	Type() string
	Source(opt *config.PersistOptions, store *core.StoreInfo) bool
	Target(opt *config.PersistOptions, store *core.StoreInfo) bool
}
type comparingFilter interface {
	Filter
	GetSourceStoreID() uint64
}
func Source(opt *config.PersistOptions, store *core.StoreInfo, filters []Filter) bool {
	storeAddress := store.GetAddress()
	storeID := strconv.FormatUint(store.GetID(), 10)
	for _, filter := range filters {
		if !filter.Source(opt, store) {
			sourceID := storeID
			targetID := ""
			filterCounter.WithLabelValues("filter-source", storeAddress,
				sourceID, filter.Scope(), filter.Type(), sourceID, targetID).Inc()
			return false
		}
	}
	return true
}
func Target(opt *config.PersistOptions, store *core.StoreInfo, filters []Filter) bool {
	storeAddress := store.GetAddress()
	storeID := strconv.FormatUint(store.GetID(), 10)
	for _, filter := range filters {
		if !filter.Target(opt, store) {
			cfilter, ok := filter.(comparingFilter)
			targetID := storeID
			sourceID := ""
			if ok {
				sourceID = strconv.FormatUint(cfilter.GetSourceStoreID(), 10)
			}
			filterCounter.WithLabelValues("filter-target", storeAddress,
				targetID, filter.Scope(), filter.Type(), sourceID, targetID).Inc()
			return false
		}
	}
	return true
}
type excludedFilter struct {
	scope   string
	sources map[uint64]struct{}
	targets map[uint64]struct{}
}