func (s *StoresStats) FilterUnhealthyStore(cluster core.StoreSetInformer) {
	s.Lock()
	defer s.Unlock()
	for storeID := range s.rollingStoresStats {
		store := cluster.GetStore(storeID)
		if store.IsTombstone() || store.IsUnhealthy() || store.IsPhysicallyDestroyed() {
			delete(s.rollingStoresStats, storeID)
		}
	}
}
FilterUnhealthyStore filter unhealthy store
package statistics
import (
	"sync"
	"time"
	"github.com/pingcap/kvproto/pkg/pdpb"
	"github.com/pingcap/log"
	"github.com/tikv/pd/pkg/movingaverage"
	"github.com/tikv/pd/server/core"
	"go.uber.org/zap"
)
const (
	storeStatsRollingWindowsSize = 3
	RegionsStatsObserveInterval = 30 * time.Second
	RegionsStatsRollingWindowsSize = 9
)
type StoresStats struct {
	sync.RWMutex
	rollingStoresStats map[uint64]*RollingStoreStats
}
func NewStoresStats() *StoresStats {
	return &StoresStats{
		rollingStoresStats: make(map[uint64]*RollingStoreStats),
	}
}
func (s *StoresStats) RemoveRollingStoreStats(storeID uint64) {
	s.Lock()
	defer s.Unlock()
	delete(s.rollingStoresStats, storeID)
}
func (s *StoresStats) GetRollingStoreStats(storeID uint64) *RollingStoreStats {
	s.RLock()
	defer s.RUnlock()
	return s.rollingStoresStats[storeID]
}
func (s *StoresStats) GetOrCreateRollingStoreStats(storeID uint64) *RollingStoreStats {
	s.Lock()
	defer s.Unlock()
	ret, ok := s.rollingStoresStats[storeID]
	if !ok {
		ret = newRollingStoreStats()
		s.rollingStoresStats[storeID] = ret
	}
	return ret
}
func (s *StoresStats) Observe(storeID uint64, stats *pdpb.StoreStats) {
	rollingStoreStat := s.GetOrCreateRollingStoreStats(storeID)
	rollingStoreStat.Observe(stats)
}
func (s *StoresStats) ObserveRegionsStats(storeIDs []uint64, writeBytesRates, writeKeysRates []float64) {
	for i, storeID := range storeIDs {
		rollingStoreStat := s.GetOrCreateRollingStoreStats(storeID)
		rollingStoreStat.ObserveRegionsStats(writeBytesRates[i], writeKeysRates[i])
	}
}
func (s *StoresStats) Set(storeID uint64, stats *pdpb.StoreStats) {
	rollingStoreStat := s.GetOrCreateRollingStoreStats(storeID)
	rollingStoreStat.Set(stats)
}
func (s *StoresStats) SetRegionsStats(storeIDs []uint64, writeBytesRates, writeKeysRates []float64) {
	for i, storeID := range storeIDs {
		rollingStoreStat := s.GetOrCreateRollingStoreStats(storeID)
		rollingStoreStat.SetRegionsStats(writeBytesRates[i], writeKeysRates[i])
	}
}
func (s *StoresStats) GetStoresLoads() map[uint64][]float64 {
	s.RLock()
	defer s.RUnlock()
	res := make(map[uint64][]float64, len(s.rollingStoresStats))
	for storeID, stats := range s.rollingStoresStats {
		for i := StoreStatKind(0); i < StoreStatCount; i++ {
			res[storeID] = append(res[storeID], stats.GetLoad(i))
		}
	}
	return res
}