Repository: pingcap/pd
Pull request #719 (2017-09-04 02:39:48)

server: move StoreInfo/ResourceKind to core directory.


Patch:
diff --git a/server/api/history.go b/server/api/history.go
index e5608db01..4748437bb 100644
--- a/server/api/history.go
+++ b/server/api/history.go
@@ -14,12 +14,13 @@
 package api
 
 import (
-	"github.com/juju/errors"
 	"net/http"
 	"strconv"
 
 	"github.com/gorilla/mux"
+	"github.com/juju/errors"
 	"github.com/pingcap/pd/server"
+	"github.com/pingcap/pd/server/core"
 	"github.com/unrolled/render"
 )
 
@@ -59,8 +60,8 @@ func (h *historyHandler) GetOperatorsOfKind(w http.ResponseWriter, r *http.Reque
 		h.r.JSON(w, http.StatusOK, nil)
 		return
 	}
-	kind := server.ParseResourceKind(k)
-	if kind == server.UnKnownKind {
+	kind := core.ParseResourceKind(k)
+	if kind == core.UnKnownKind {
 		h.r.JSON(w, http.StatusInternalServerError, errUnknownOperatorKind.Error())
 		return
 	}
diff --git a/server/api/store.go b/server/api/store.go
index 1d7bedaf0..2de2ba94e 100644
--- a/server/api/store.go
+++ b/server/api/store.go
@@ -24,6 +24,7 @@ import (
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/pd/pkg/typeutil"
 	"github.com/pingcap/pd/server"
+	"github.com/pingcap/pd/server/core"
 	"github.com/unrolled/render"
 )
 
@@ -57,7 +58,7 @@ type storeInfo struct {
 
 const downStateName = "Down"
 
-func newStoreInfo(store *server.StoreInfo) *storeInfo {
+func newStoreInfo(store *core.StoreInfo) *storeInfo {
 	s := &storeInfo{
 		Store: &metaStore{
 			Store:     store.Store,
diff --git a/server/balancer.go b/server/balancer.go
index 73174b19b..79088cffc 100644
--- a/server/balancer.go
+++ b/server/balancer.go
@@ -22,6 +22,7 @@ import (
 	log "github.com/Sirupsen/logrus"
 	"github.com/montanaflynn/stats"
 	"github.com/pingcap/kvproto/pkg/metapb"
+	"github.com/pingcap/pd/server/core"
 )
 
 const (
@@ -50,10 +51,10 @@ func minBalanceDiff(count uint64) float64 {
 // shouldBalance returns true if we should balance the source and target store.
 // The min balance diff provides a buffer to make the cluster stable, so that we
 // don't need to schedule very frequently.
-func shouldBalance(source, target *StoreInfo, kind ResourceKind) bool {
-	sourceCount := source.resourceCount(kind)
-	sourceScore := source.resourceScore(kind)
-	targetScore := target.resourceScore(kind)
+func shouldBalance(source, target *core.StoreInfo, kind core.ResourceKind) bool {
+	sourceCount := source.ResourceCount(kind)
+	sourceScore := source.ResourceScore(kind)
+	targetScore := target.ResourceScore(kind)
 	if targetScore >= sourceScore {
 		return false
 	}
@@ -62,12 +63,12 @@ func shouldBalance(source, target *StoreInfo, kind ResourceKind) bool {
 	return diffCount >= minBalanceDiff(sourceCount)
 }
 
-func adjustBalanceLimit(cluster *clusterInfo, kind ResourceKind) uint64 {
+func adjustBalanceLimit(cluster *clusterInfo, kind core.ResourceKind) uint64 {
 	stores := cluster.getStores()
 	counts := make([]float64, 0, len(stores))
 	for _, s := range stores {
-		if s.isUp() {
-			counts = append(counts, float64(s.resourceCount(kind)))
+		if s.IsUp() {
+			counts = append(counts, float64(s.ResourceCount(kind)))
 		}
 	}
 	limit, _ := stats.StandardDeviation(stats.Float64Data(counts))
@@ -89,7 +90,7 @@ func newBalanceLeaderScheduler(opt *scheduleOption) *balanceLeaderScheduler {
 	return &balanceLeaderScheduler{
 		opt:      opt,
 		limit:    1,
-		selector: newBalanceSelector(LeaderKind, filters),
+		selector: newBalanceSelector(core.LeaderKind, filters),
 	}
 }
 
@@ -97,8 +98,8 @@ func (l *balanceLeaderScheduler) GetName() string {
 	return "balance-leader-scheduler"
 }
 
-func (l *balanceLeaderScheduler) GetResourceKind() ResourceKind {
-	return LeaderKind
+func (l *balanceLeaderScheduler) GetResourceKind() core.ResourceKind {
+	return core.LeaderKind
 }
 
 func (l *balanceLeaderScheduler) GetResourceLimit() uint64 {
@@ -156,7 +157,7 @@ func newBalanceRegionScheduler(opt *scheduleOption) *balanceRegionScheduler {
 		rep:      opt.GetReplication(),
 		cache:    cache,
 		limit:    1,
-		selector: newBalanceSelector(RegionKind, filters),
+		selector: newBalanceSelector(core.RegionKind, filters),
 	}
 }
 
@@ -164,8 +165,8 @@ func (s *balanceRegionScheduler) GetName() string {
 	return "balance-region-scheduler"
 }
 
-func (s *balanceRegionScheduler) GetResourceKind() ResourceKind {
-	return RegionKind
+func (s *balanceRegionScheduler) GetResourceKind() core.ResourceKind {
+	return core.RegionKind
 }
 
 func (s *balanceRegionScheduler) GetResourceLimit() uint64 {
@@ -226,7 +227,7 @@ func (s *balanceRegionScheduler) transferPeer(cluster *clusterInfo, region *Regi
 	}
 	s.limit = adjustBalanceLimit(cluster, s.GetResourceKind())
 
-	return newTransferPeer(region, RegionKind, oldPeer, newPeer)
+	return newTransferPeer(region, core.RegionKind, oldPeer, newPeer)
 }
 
 // replicaChecker ensures region has the best replicas.
@@ -339,7 +340,7 @@ func (r *replicaChecker) checkDownPeer(region *RegionInfo) Operator {
 			log.Infof("lost the store %d,maybe you are recovering the PD cluster.", peer.GetStoreId())
 			return nil
 		}
-		if store.downTime() < r.opt.GetMaxStoreDownTime() {
+		if store.DownTime() < r.opt.GetMaxStoreDownTime() {
 			continue
 		}
 		if stats.GetDownSeconds() < uint64(r.opt.GetMaxStoreDownTime().Seconds()) {
@@ -357,7 +358,7 @@ func (r *replicaChecker) checkOfflinePeer(region *RegionInfo) Operator {
 			log.Infof("lost the store %d,maybe you are recovering the PD cluster.", peer.GetStoreId())
 			return nil
 		}
-		if store.isUp() {
+		if store.IsUp() {
 			continue
 		}
 
@@ -370,7 +371,7 @@ func (r *replicaChecker) checkOfflinePeer(region *RegionInfo) Operator {
 		if newPeer == nil {
 			return nil
 		}
-		return newTransferPeer(region, RegionKind, peer, newPeer)
+		return newTransferPeer(region, core.RegionKind, peer, newPeer)
 	}
 
 	return nil
@@ -393,7 +394,7 @@ func (r *replicaChecker) checkBestReplacement(region *RegionInfo) Operator {
 	if err != nil {
 		return nil
 	}
-	return newTransferPeer(region, RegionKind, oldPeer, newPeer)
+	return newTransferPeer(region, core.RegionKind, oldPeer, newPeer)
 }
 
 // RegionStat records each hot region's statistics
@@ -451,8 +452,8 @@ func (h *balanceHotRegionScheduler) GetName() string {
 	return "balance-hot-region-scheduler"
 }
 
-func (h *balanceHotRegionScheduler) GetResourceKind() ResourceKind {
-	return PriorityKind
+func (h *balanceHotRegionScheduler) GetResourceKind() core.ResourceKind {
+	return core.PriorityKind
 }
 
 func (h *balanceHotRegionScheduler) GetResourceLimit() uint64 {
@@ -471,7 +472,7 @@ func (h *balanceHotRegionScheduler) Schedule(cluster *clusterInfo) Operator {
 	srcRegion, srcPeer, destPeer := h.balanceByPeer(cluster)
 	if srcRegion != nil {
 		schedulerCounter.WithLabelValues(h.GetName(), "move_peer").Inc()
-		return newTransferPeer(srcRegion, PriorityKind, srcPeer, destPeer)
+		return newTransferPeer(srcRegion, core.PriorityKind, srcPeer, destPeer)
 	}
 
 	// balance by leader
diff --git a/server/cache.go b/server/cache.go
index 03cddf06f..3fd0aa6d5 100644
--- a/server/cache.go
+++ b/server/cache.go
@@ -23,6 +23,7 @@ import (
 	"github.com/juju/errors"
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/kvproto/pkg/pdpb"
+	"github.com/pingcap/pd/server/core"
 )
 
 var (
@@ -41,24 +42,24 @@ var (
 )
 
 type storesInfo struct {
-	stores map[uint64]*StoreInfo
+	stores map[uint64]*core.StoreInfo
 }
 
 func newStoresInfo() *storesInfo {
 	return &storesInfo{
-		stores: make(map[uint64]*StoreInfo),
+		stores: make(map[uint64]*core.StoreInfo),
 	}
 }
 
-func (s *storesInfo) getStore(storeID uint64) *StoreInfo {
+func (s *storesInfo) getStore(storeID uint64) *core.StoreInfo {
 	store, ok := s.stores[storeID]
 	if !ok {
 		return nil
 	}
-	return store.clone()
+	return store.Clone()
 }
 
-func (s *storesInfo) setStore(store *StoreInfo) {
+func (s *storesInfo) setStore(store *core.StoreInfo) {
 	s.stores[store.GetId()] = store
 }
 
@@ -67,10 +68,10 @@ func (s *storesInfo) blockStore(storeID uint64) error {
 	if !ok {
 		return errStoreNotFound(storeID)
 	}
-	if store.isBlocked() {
+	if store.IsBlocked() {
 		return errStoreIsBlocked(storeID)
 	}
-	store.block()
+	store.Block()
 	return nil
 }
 
@@ -79,13 +80,13 @@ func (s *storesInfo) unblockStore(storeID uint64) {
 	if !ok {
 		log.Fatalf("store %d is unblocked, but it is not found", storeID)
 	}
-	store.unblock()
+	store.Unblock()
 }
 
-func (s *storesInfo) getStores() []*StoreInfo {
-	stores := make([]*StoreInfo, 0, len(s.stores))
+func (s *storesInfo) getStores() []*core.StoreInfo {
+	stores := make([]*core.StoreInfo, 0, len(s.stores))
 	for _, store := range s.stores {
-		stores = append(stores, store.clone())
+		stores = append(stores, store.Clone())
 	}
 	return stores
 }
@@ -117,7 +118,7 @@ func (s *storesInfo) setRegionCount(storeID uint64, regionCount int) {
 func (s *storesInfo) totalWrittenBytes() uint64 {
 	var totalWrittenBytes uint64
 	for _, s := range s.stores {
-		if s.isUp() {
+		if s.IsUp() {
 			totalWrittenBytes += s.Stats.GetBytesWritten()
 		}
 	}
@@ -430,19 +431,19 @@ func (c *clusterInfo) putMetaLocked(meta *metapb.Cluster) error {
 	return nil
 }
 
-func (c *clusterInfo) getStore(storeID uint64) *StoreInfo {
+func (c *clusterInfo) getStore(storeID uint64) *core.StoreInfo {
 	c.RLock()
 	defer c.RUnlock()
 	return c.stores.getStore(storeID)
 }
 
-func (c *clusterInfo) putStore(store *StoreInfo) error {
+func (c *clusterInfo) putStore(store *core.StoreInfo) error {
 	c.Lock()
 	defer c.Unlock()
-	return c.putStoreLocked(store.clone())
+	return c.putStoreLocked(store.Clone())
 }
 
-func (c *clusterInfo) putStoreLocked(store *StoreInfo) error {
+func (c *clusterInfo) putStoreLocked(store *core.StoreInfo) error {
 	if c.kv != nil {
 		if err := c.kv.saveStore(store.Store); err != nil {
 			return errors.Trace(err)
@@ -464,7 +465,7 @@ func (c *clusterInfo) unblockStore(storeID uint64) {
 	c.stores.unblockStore(storeID)
 }
 
-func (c *clusterInfo) getStores() []*StoreInfo {
+func (c *clusterInfo) getStores() []*core.StoreInfo {
 	c.RLock()
 	defer c.RUnlock()
 	return c.stores.getStores()
@@ -612,10 +613,10 @@ func (c *clusterInfo) randFollowerRegion(storeID uint64) *RegionInfo {
 	return c.regions.randFollowerRegion(storeID)
 }
 
-func (c *clusterInfo) getRegionStores(region *RegionInfo) []*StoreInfo {
+func (c *clusterInfo) getRegionStores(region *RegionInfo) []*core.StoreInfo {
 	c.RLock()
 	defer c.RUnlock()
-	var stores []*StoreInfo
+	var stores []*core.StoreInfo
 	for id := range region.GetStoreIds() {
 		if store := c.stores.getStore(id); store != nil {
 			stores = append(stores, store)
@@ -624,16 +625,16 @@ func (c *clusterInfo) getRegionStores(region *RegionInfo) []*StoreInfo {
 	return stores
 }
 
-func (c *clusterInfo) getLeaderStore(region *RegionInfo) *StoreInfo {
+func (c *clusterInfo) getLeaderStore(region *RegionInfo) *core.StoreInfo {
 	c.RLock()
 	defer c.RUnlock()
 	return c.stores.getStore(region.Leader.GetStoreId())
 }
 
-func (c *clusterInfo) getFollowerStores(region *RegionInfo) []*StoreInfo {
+func (c *clusterInfo) getFollowerStores(region *RegionInfo) []*core.StoreInfo {
 	c.RLock()
 	defer c.RUnlock()
-	var stores []*StoreInfo
+	var stores []*core.StoreInfo
 	for id := range region.GetFollowers() {
 		if store := c.stores.getStore(id); store != nil {
 			stores = append(stores, store)
diff --git a/server/cluster.go b/server/cluster.go
index e78feffc3..ab68c2d8b 100644
--- a/server/cluster.go
+++ b/server/cluster.go
@@ -25,6 +25,7 @@ import (
 	"github.com/juju/errors"
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/kvproto/pkg/pdpb"
+	"github.com/pingcap/pd/server/core"
 )
 
 const (
@@ -389,7 +390,7 @@ func (c *RaftCluster) GetStores() []*metapb.Store {
 }
 
 // GetStore gets store from cluster.
-func (c *RaftCluster) GetStore(storeID uint64) (*StoreInfo, error) {
+func (c *RaftCluster) GetStore(storeID uint64) (*core.StoreInfo, error) {
 	if storeID == 0 {
 		return nil, errors.New("invalid zero store id")
 	}
@@ -427,7 +428,7 @@ func (c *RaftCluster) putStore(store *metapb.Store) error {
 	// Store address can not be the same as other stores.
 	for _, s := range cluster.getStores() {
 		// It's OK to start a new store on the same address if the old store has been removed.
-		if s.isTombstone() {
+		if s.IsTombstone() {
 			continue
 		}
 		if s.GetId() != store.GetId() && s.GetAddress() == store.GetAddress() {
@@ -438,16 +439,16 @@ func (c *RaftCluster) putStore(store *metapb.Store) error {
 	s := cluster.getStore(store.GetId())
 	if s == nil {
 		// Add a new store.
-		s = newStoreInfo(store)
+		s = core.NewStoreInfo(store)
 	} else {
 		// Update an existed store.
 		s.Address = store.Address
-		s.mergeLabels(store.Labels)
+		s.MergeLabels(store.Labels)
 	}
 
 	// Check location labels.
 	for _, k := range c.s.cfg.Replication.LocationLabels {
-		if v := s.getLabelValue(k); len(v) == 0 {
+		if v := s.GetLabelValue(k); len(v) == 0 {
 			log.Warnf("missing location label %q in store %v", k, s)
 		}
 	}
@@ -469,11 +470,11 @@ func (c *RaftCluster) RemoveStore(storeID uint64) error {
 	}
 
 	// Remove an offline store should be OK, nothing to do.
-	if store.isOffline() {
+	if store.IsOffline() {
 		return nil
 	}
 
-	if store.isTombstone() {
+	if store.IsTombstone() {
 		return errors.New("store has been removed")
 	}
 
@@ -498,11 +499,11 @@ func (c *RaftCluster) BuryStore(storeID uint64, force bool) error {
 	}
 
 	// Bury a tombstone store should be OK, nothing to do.
-	if store.isTombstone() {
+	if store.IsTombstone() {
 		return nil
 	}
 
-	if store.isUp() {
+	if store.IsUp() {
 		if !force {
 			return errors.New("store is still up, please remove store gracefully")
 		}
@@ -571,15 +572,15 @@ func (c *RaftCluster) collectMetrics() {
 		case metapb.StoreState_Tombstone:
 			storeTombstoneCount++
 		}
-		if s.isTombstone() {
+		if s.IsTombstone() {
 			continue
 		}
-		if s.downTime() >= c.coordinator.opt.GetMaxStoreDownTime() {
+		if s.DownTime() >= c.coordinator.opt.GetMaxStoreDownTime() {
 			storeDownCount++
 		}
 
 		// Store stats.
-		storageSize += s.storageSize()
+		storageSize += s.StorageSize()
 		storageCapacity += s.Stats.GetCapacity()
 
 		// Balance score.
diff --git a/server/coordinator.go b/server/coordinator.go
index 95112ff61..35c43f2fb 100644
--- a/server/coordinator.go
+++ b/server/coordinator.go
@@ -20,6 +20,7 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 	"github.com/juju/errors"
+	"github.com/pingcap/pd/server/core"
 	"golang.org/x/net/context"
 )
 
@@ -105,7 +106,7 @@ func (c *coordinator) dispatch(region *RegionInfo) {
 	}
 
 	// Check replica operator.
-	if c.limiter.operatorCount(RegionKind) >= c.opt.GetReplicaScheduleLimit() {
+	if c.limiter.operatorCount(core.RegionKind) >= c.opt.GetReplicaScheduleLimit() {
 		return
 	}
 	if op := c.checker.Check(region); op != nil {
@@ -296,10 +297,10 @@ func (c *coordinator) addOperator(op Operator) bool {
 }
 
 func isHigherPriorityOperator(new Operator, old Operator) bool {
-	if new.GetResourceKind() == AdminKind {
+	if new.GetResourceKind() == core.AdminKind {
 		return true
 	}
-	if new.GetResourceKind() == PriorityKind && old.GetResourceKind() != PriorityKind {
+	if new.GetResourceKind() == core.PriorityKind && old.GetResourceKind() != core.PriorityKind {
 		return true
 	}
 	return false
@@ -350,7 +351,7 @@ func (c *coordinator) getHistories() []Operator {
 	return operators
 }
 
-func (c *coordinator) getHistoriesOfKind(kind ResourceKind) []Operator {
+func (c *coordinator) getHistoriesOfKind(kind core.ResourceKind) []Operator {
 	c.RLock()
 	defer c.RUnlock()
 
@@ -367,12 +368,12 @@ func (c *coordinator) getHistoriesOfKind(kind ResourceKind) []Operator {
 
 type scheduleLimiter struct {
 	sync.RWMutex
-	counts map[ResourceKind]uint64
+	counts map[core.ResourceKind]uint64
 }
 
 func newScheduleLimiter() *scheduleLimiter {
 	return &scheduleLimiter{
-		counts: make(map[ResourceKind]uint64),
+		counts: make(map[core.ResourceKind]uint64),
 	}
 }
 
@@ -388,7 +389,7 @@ func (l *scheduleLimiter) removeOperator(op Operator) {
 	l.counts[op.GetResourceKind()]--
 }
 
-func (l *scheduleLimiter) operatorCount(kind ResourceKind) uint64 {
+func (l *scheduleLimiter) operatorCount(kind core.ResourceKind) uint64 {
 	l.RLock()
 	defer l.RUnlock()
 	return l.counts[kind]
diff --git a/server/core/resource_kind.go b/server/core/resource_kind.go
new file mode 100644
index 000000000..fb0322845
--- /dev/null
+++ b/server/core/resource_kind.go
@@ -0,0 +1,67 @@
+// 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 core
+
+// ResourceKind distinguishes different kinds of resources.
+type ResourceKind int
+
+const (
+	// UnKnownKind indicates the unknown kind resource
+	UnKnownKind ResourceKind = iota
+	// AdminKind indicates that specify by admin
+	AdminKind
+	// LeaderKind indicates the leader kind resource
+	LeaderKind
+	// RegionKind indicates the region kind resource
+	RegionKind
+	// PriorityKind indicates the priority kind resource
+	PriorityKind
+	// OtherKind indicates the other kind resource
+	OtherKind
+)
+
+var resourceKindToName = map[ResourceKind]string{
+	0: "unknown",
+	1: "admin",
+	2: "leader",
+	3: "region",
+	4: "priority",
+	5: "other",
+}
+
+var resourceNameToValue = map[string]ResourceKind{
+	"unknown":  UnKnownKind,
+	"admin":    AdminKind,
+	"leader":   LeaderKind,
+	"region":   RegionKind,
+	"priority": PriorityKind,
+	"other":    OtherKind,
+}
+
+func (k ResourceKind) String() string {
+	s, ok := resourceKindToName[k]
+	if ok {
+		return s
+	}
+	return resourceKindToName[UnKnownKind]
+}
+
+// ParseResourceKind convert string to ResourceKind
+func ParseResourceKind(name string) ResourceKind {
+	k, ok := resourceNameToValue[name]
+	if ok {
+		return k
+	}
+	return UnKnownKind
+}
diff --git a/server/store.go b/server/core/store.go
similarity index 69%
rename from server/store.go
rename to server/core/store.go
index a6232053a..38d88d062 100644
--- a/server/store.go
+++ b/server/core/store.go
@@ -11,7 +11,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package server
+package core
 
 import (
 	"time"
@@ -34,7 +34,8 @@ type StoreInfo struct {
 	RegionWeight    float64
 }
 
-func newStoreInfo(store *metapb.Store) *StoreInfo {
+// NewStoreInfo creates StoreInfo with meta data.
+func NewStoreInfo(store *metapb.Store) *StoreInfo {
 	return &StoreInfo{
 		Store:        store,
 		LeaderWeight: 1.0,
@@ -42,7 +43,8 @@ func newStoreInfo(store *metapb.Store) *StoreInfo {
 	}
 }
 
-func (s *StoreInfo) clone() *StoreInfo {
+// Clone creates a copy of current StoreInfo.
+func (s *StoreInfo) Clone() *StoreInfo {
 	return &StoreInfo{
 		Store:           proto.Clone(s.Store).(*metapb.Store),
 		Stats:           proto.Clone(s.Stats).(*pdpb.StoreStats),
@@ -55,31 +57,38 @@ func (s *StoreInfo) clone() *StoreInfo {
 	}
 }
 
-func (s *StoreInfo) block() {
+// Block stops balancer from selecting the store.
+func (s *StoreInfo) Block() {
 	s.blocked = true
 }
 
-func (s *StoreInfo) unblock() {
+// Unblock allows balancer to select the store.
+func (s *StoreInfo) Unblock() {
 	s.blocked = false
 }
 
-func (s *StoreInfo) isBlocked() bool {
+// IsBlocked returns if the store is blocked.
+func (s *StoreInfo) IsBlocked() bool {
 	return s.blocked
 }
 
-func (s *StoreInfo) isUp() bool {
+// IsUp checks if the store's state is Up.
+func (s *StoreInfo) IsUp() bool {
 	return s.GetState() == metapb.StoreState_Up
 }
 
-func (s *StoreInfo) isOffline() bool {
+// IsOffline checks if the store's state is Offline.
+func (s *StoreInfo) IsOffline() bool {
 	return s.GetState() == metapb.StoreState_Offline
 }
 
-func (s *StoreInfo) isTombstone() bool {
+// IsTombstone checks if the store's state is Tombstone.
+func (s *StoreInfo) IsTombstone() bool {
 	return s.GetState() == metapb.StoreState_Tombstone
 }
 
-func (s *StoreInfo) downTime() time.Duration {
+// DownTime returns the time elapsed since last heartbeat.
+func (s *StoreInfo) DownTime() time.Duration {
 	return time.Since(s.LastHeartbeatTS)
 }
 
@@ -109,18 +118,21 @@ func (s *StoreInfo) RegionScore() float64 {
 	return float64(s.RegionCount) / s.RegionWeight
 }
 
-func (s *StoreInfo) storageSize() uint64 {
+// StorageSize returns store's used storage size reported from tikv.
+func (s *StoreInfo) StorageSize() uint64 {
 	return s.Stats.GetUsedSize()
 }
 
-func (s *StoreInfo) availableRatio() float64 {
+// AvailableRatio is store's freeSpace/capacity.
+func (s *StoreInfo) AvailableRatio() float64 {
 	if s.Stats.GetCapacity() == 0 {
 		return 0
 	}
 	return float64(s.Stats.GetAvailable()) / float64(s.Stats.GetCapacity())
 }
 
-func (s *StoreInfo) resourceCount(kind ResourceKind) uint64 {
+// ResourceCount reutrns count of leader/region in the store.
+func (s *StoreInfo) ResourceCount(kind ResourceKind) uint64 {
 	switch kind {
 	case LeaderKind:
 		return s.leaderCount()
@@ -131,7 +143,8 @@ func (s *StoreInfo) resourceCount(kind ResourceKind) uint64 {
 	}
 }
 
-func (s *StoreInfo) resourceScore(kind ResourceKind) float64 {
+// ResourceScore reutrns score of leader/region in the store.
+func (s *StoreInfo) ResourceScore(kind ResourceKind) float64 {
 	switch kind {
 	case LeaderKind:
 		return s.LeaderScore()
@@ -163,7 +176,8 @@ func (s *StoreInfo) IsDown() bool {
 	return time.Now().Sub(s.LastHeartbeatTS) > defaultStoreDownTime
 }
 
-func (s *StoreInfo) getLabelValue(key string) string {
+// GetLabelValue returns a label's value (if exists).
+func (s *StoreInfo) GetLabelValue(key string) string {
 	for _, label := range s.GetLabels() {
 		if label.GetKey() == key {
 			return label.GetValue()
@@ -172,11 +186,11 @@ func (s *StoreInfo) getLabelValue(key string) string {
 	return ""
 }
 
-// compareLocation compares 2 stores' labels and returns at which level their
+// CompareLocation compares 2 stores' labels and returns at which level their
 // locations are different. It returns -1 if they are at the same location.
-func (s *StoreInfo) compareLocation(other *StoreInfo, labels []string) int {
+func (s *StoreInfo) CompareLocation(other *StoreInfo, labels []string) int {
 	for i, key := range labels {
-		v1, v2 := s.getLabelValue(key), other.getLabelValue(key)
+		v1, v2 := s.GetLabelValue(key), other.GetLabelValue(key)
 		// If label is not set, the store is considered at the same location
 		// with any other store.
 		if v1 != "" && v2 != "" && v1 != v2 {
@@ -186,7 +200,9 @@ func (s *StoreInfo) compareLocation(other *StoreInfo, labels []string) int {
 	return -1
 }
 
-func (s *StoreInfo) mergeLabels(labels []*metapb.StoreLabel) {
+// MergeLabels merges the passed in labels with origins, overriding duplicated
+// ones.
+func (s *StoreInfo) MergeLabels(labels []*metapb.StoreLabel) {
 L:
 	for _, newLabel := range labels {
 		for _, label := range s.Labels {
diff --git a/server/event.go b/server/event.go
index 514846c50..fc7af89ae 100644
--- a/server/event.go
+++ b/server/event.go
@@ -19,6 +19,7 @@ import (
 
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/kvproto/pkg/pdpb"
+	"github.com/pingcap/pd/server/core"
 )
 
 type statusType byte
@@ -156,8 +157,8 @@ func (op *splitOperator) GetRegionID() uint64 {
 	return op.Origin.GetId()
 }
 
-func (op *splitOperator) GetResourceKind() ResourceKind {
-	return OtherKind
+func (op *splitOperator) GetResourceKind() core.ResourceKind {
+	return core.OtherKind
 }
 
 func (op *splitOperator) GetState() OperatorState {
diff --git a/server/filter.go b/server/filter.go
index 4d55485a3..2bffbeafc 100644
--- a/server/filter.go
+++ b/server/filter.go
@@ -13,15 +13,17 @@
 
 package server
 
+import "github.com/pingcap/pd/server/core"
+
 // Filter is an interface to filter source and target store.
 type Filter interface {
 	// Return true if the store should not be used as a source store.
-	FilterSource(store *StoreInfo) bool
+	FilterSource(store *core.StoreInfo) bool
 	// Return true if the store should not be used as a target store.
-	FilterTarget(store *StoreInfo) bool
+	FilterTarget(store *core.StoreInfo) bool
 }
 
-func filterSource(store *StoreInfo, filters []Filter) bool {
+func filterSource(store *core.StoreInfo, filters []Filter) bool {
 	for _, filter := range filters {
 		if filter.FilterSource(store) {
 			return true
@@ -30,7 +32,7 @@ func filterSource(store *StoreInfo, filters []Filter) bool {
 	return false
 }
 
-func filterTarget(store *StoreInfo, filters []Filter) bool {
+func filterTarget(store *core.StoreInfo, filters []Filter) bool {
 	for _, filter := range filters {
 		if filter.FilterTarget(store) {
 			return true
@@ -51,12 +53,12 @@ func newExcludedFilter(sources, targets map[uint64]struct{}) *excludedFilter {
 	}
 }
 
-func (f *excludedFilter) FilterSource(store *StoreInfo) bool {
+func (f *excludedFilter) FilterSource(store *core.StoreInfo) bool {
 	_, ok := f.sources[store.GetId()]
 	return ok
 }
 
-func (f *excludedFilter) FilterTarget(store *StoreInfo) bool {
+func (f *excludedFilter) FilterTarget(store *core.StoreInfo) bool {
 	_, ok := f.targets[store.GetId()]
 	return ok
 }
@@ -67,12 +69,12 @@ func newBlockFilter() *blockFilter {
 	return &blockFilter{}
 }
 
-func (f *blockFilter) FilterSource(store *StoreInfo) bool {
-	return store.isBlocked()
+func (f *blockFilter) FilterSource(store *core.StoreInfo) bool {
+	return store.IsBlocked()
 }
 
-func (f *blockFilter) FilterTarget(store *StoreInfo) bool {
-	return store.isBlocked()
+func (f *blockFilter) FilterTarget(store *core.StoreInfo) bool {
+	return store.IsBlocked()
 }
 
 type cacheFilter struct {
@@ -83,11 +85,11 @@ func newCacheFilter(cache *idCache) *cacheFilter {
 	return &cacheFilter{cache: cache}
 }
 
-func (f *cacheFilter) FilterSource(store *StoreInfo) bool {
+func (f *cacheFilter) FilterSource(store *core.StoreInfo) bool {
 	return f.cache.get(store.GetId())
 }
 
-func (f *cacheFilter) FilterTarget(store *StoreInfo) bool {
+func (f *cacheFilter) FilterTarget(store *core.StoreInfo) bool {
 	return false
 }
 
@@ -99,15 +101,15 @@ func newStateFilter(opt *scheduleOption) *stateFilter {
 	return &stateFilter{opt: opt}
 }
 
-func (f *stateFilter) filter(store *StoreInfo) bool {
-	return !store.isUp()
+func (f *stateFilter) filter(store *core.StoreInfo) bool {
+	return !store.IsUp()
 }
 
-func (f *stateFilter) FilterSource(store *StoreInfo) bool {
+func (f *stateFilter) FilterSource(store *core.StoreInfo) bool {
 	return f.filter(store)
 }
 
-func (f *stateFilter) FilterTarget(store *StoreInfo) bool {
+func (f *stateFilter) FilterTarget(store *core.StoreInfo) bool {
 	return f.filter(store)
 }
 
@@ -119,18 +121,18 @@ func newHealthFilter(opt *scheduleOption) *healthFilter {
 	return &healthFilter{opt: opt}
 }
 
-func (f *healthFilter) filter(store *StoreInfo) bool {
+func (f *healthFilter) filter(store *core.StoreInfo) bool {
 	if store.Stats.GetIsBusy() {
 		return true
 	}
-	return store.downTime() > f.opt.GetMaxStoreDownTime()
+	return store.DownTime() > f.opt.GetMaxStoreDownTime()
 }
 
-func (f *healthFilter) FilterSource(store *StoreInfo) bool {
+func (f *healthFilter) FilterSource(store *core.StoreInfo) bool {
 	return f.filter(store)
 }
 
-func (f *healthFilter) FilterTarget(store *StoreInfo) bool {
+func (f *healthFilter) FilterTarget(store *core.StoreInfo) bool {
 	return f.filter(store)
 }
 
@@ -142,17 +144,17 @@ func newSnapshotCountFilter(opt *scheduleOption) *snapshotCountFilter {
 	return &snapshotCountFilter{opt: opt}
 }
 
-func (f *snapshotCountFilter) filter(store *StoreInfo) bool {
+func (f *snapshotCountFilter) filter(store *core.StoreInfo) bool {
 	return uint64(store.Stats.GetSendingSnapCount()) > f.opt.GetMaxSnapshotCount() ||
 		uint64(store.Stats.GetReceivingSnapCount()) > f.opt.GetMaxSnapshotCount() ||
 		uint64(store.Stats.GetApplyingSnapCount()) > f.opt.GetMaxSnapshotCount()
 }
 
-func (f *snapshotCountFilter) FilterSource(store *StoreInfo) bool {
+func (f *snapshotCountFilter) FilterSource(store *core.StoreInfo) bool {
 	return f.filter(store)
 }
 
-func (f *snapshotCountFilter) FilterTarget(store *StoreInfo) bool {
+func (f *snapshotCountFilter) FilterTarget(store *core.StoreInfo) bool {
 	return f.filter(store)
 }
 
@@ -165,23 +167,23 @@ func newStorageThresholdFilter(opt *scheduleOption) *storageThresholdFilter {
 	return &storageThresholdFilter{}
 }
 
-func (f *storageThresholdFilter) FilterSource(store *StoreInfo) bool {
+func (f *storageThresholdFilter) FilterSource(store *core.StoreInfo) bool {
 	return false
 }
 
-func (f *storageThresholdFilter) FilterTarget(store *StoreInfo) bool {
-	return store.availableRatio() < storageAvailableRatioThreshold
+func (f *storageThresholdFilter) FilterTarget(store *core.StoreInfo) bool {
+	return store.AvailableRatio() < storageAvailableRatioThreshold
 }
 
 // distinctScoreFilter ensures that distinct score will not decrease.
 type distinctScoreFilter struct {
 	rep       *Replication
-	stores    []*StoreInfo
+	stores    []*core.StoreInfo
 	safeScore float64
 }
 
-func newDistinctScoreFilter(rep *Replication, stores []*StoreInfo, source *StoreInfo) *distinctScoreFilter {
-	newStores := make([]*StoreInfo, 0, len(stores)-1)
+func newDistinctScoreFilter(rep *Replication, stores []*core.StoreInfo, source *core.StoreInfo) *distinctScoreFilter {
+	newStores := make([]*core.StoreInfo, 0, len(stores)-1)
 	for _, s := range stores {
 		if s.GetId() == source.GetId() {
 			continue
@@ -196,10 +198,10 @@ func newDistinctScoreFilter(rep *Replication, stores []*StoreInfo, source *Store
 	}
 }
 
-func (f *distinctScoreFilter) FilterSource(store *StoreInfo) bool {
+func (f *distinctScoreFilter) FilterSource(store *core.StoreInfo) bool {
 	return false
 }
 
-func (f *distinctScoreFilter) FilterTarget(store *StoreInfo) bool {
+func (f *distinctScoreFilter) FilterTarget(store *core.StoreInfo) bool {
 	return f.rep.GetDistinctScore(f.stores, store) < f.safeScore
 }
diff --git a/server/handler.go b/server/handler.go
index 868a448f2..16cef75a3 100644
--- a/server/handler.go
+++ b/server/handler.go
@@ -13,7 +13,10 @@
 
 package server
 
-import "github.com/juju/errors"
+import (
+	"github.com/juju/errors"
+	"github.com/pingcap/pd/server/core"
+)
 
 var (
 	errNotBootstrapped  = errors.New("TiKV cluster not bootstrapped, please start TiKV first")
@@ -146,21 +149,21 @@ func (h *Handler) GetOperators() ([]Operator, error) {
 
 // GetAdminOperators returns the running admin operators.
 func (h *Handler) GetAdminOperators() ([]Operator, error) {
-	return h.GetOperatorsOfKind(AdminKind)
+	return h.GetOperatorsOfKind(core.AdminKind)
 }
 
 // GetLeaderOperators returns the running leader operators.
 func (h *Handler) GetLeaderOperators() ([]Operator, error) {
-	return h.GetOperatorsOfKind(LeaderKind)
+	return h.GetOperatorsOfKind(core.LeaderKind)
 }
 
 // GetRegionOperators returns the running region operators.
 func (h *Handler) GetRegionOperators() ([]Operator, error) {
-	return h.GetOperatorsOfKind(RegionKind)
+	return h.GetOperatorsOfKind(core.RegionKind)
 }
 
 // GetOperatorsOfKind returns the running operators of the kind.
-func (h *Handler) GetOperatorsOfKind(kind ResourceKind) ([]Operator, error) {
+func (h *Handler) GetOperatorsOfKind(kind core.ResourceKind) ([]Operator, error) {
 	ops, err := h.GetOperators()
 	if err != nil {
 		return nil, errors.Trace(err)
@@ -184,7 +187,7 @@ func (h *Handler) GetHistoryOperators() ([]Operator, error) {
 }
 
 // GetHistoryOperatorsOfKind returns history operators by Kind
-func (h *Handler) GetHistoryOperatorsOfKind(kind ResourceKind) ([]Operator, error) {
+func (h *Handler) GetHistoryOperatorsOfKind(kind core.ResourceKind) ([]Operator, error) {
 	c, err := h.getCoordinator()
 	if err != nil {
 		return nil, errors.Trace(err)
diff --git a/server/kv.go b/server/kv.go
index 00297160a..a4833586c 100644
--- a/server/kv.go
+++ b/server/kv.go
@@ -26,6 +26,7 @@ import (
 	"github.com/gogo/protobuf/proto"
 	"github.com/juju/errors"
 	"github.com/pingcap/kvproto/pkg/metapb"
+	"github.com/pingcap/pd/server/core"
 	"golang.org/x/net/context"
 )
 
@@ -180,7 +181,7 @@ func (kv *kv) loadStores(stores *storesInfo, rangeLimit int64) error {
 				return errors.Trace(err)
 			}
 
-			storeInfo := newStoreInfo(store)
+			storeInfo := core.NewStoreInfo(store)
 			leaderWeight, err := kv.loadFloatWithDefaultValue(kv.storeLeaderWeightPath(storeInfo.GetId()), 1.0)
 			if err != nil {
 				return errors.Trace(err)
diff --git a/server/operator.go b/server/operator.go
index e6ef3274a..b33ab95c6 100644
--- a/server/operator.go
+++ b/server/operator.go
@@ -22,63 +22,11 @@ import (
 	"github.com/juju/errors"
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/kvproto/pkg/pdpb"
+	"github.com/pingcap/pd/server/core"
 )
 
 const maxOperatorWaitTime = 5 * time.Minute
 
-// ResourceKind distinguishes different kinds of resources.
-type ResourceKind int
-
-const (
-	// UnKnownKind indicates the unknown kind resource
-	UnKnownKind ResourceKind = iota
-	// AdminKind indicates that specify by admin
-	AdminKind
-	// LeaderKind indicates the leader kind resource
-	LeaderKind
-	// RegionKind indicates the region kind resource
-	RegionKind
-	// PriorityKind indicates the priority kind resource
-	PriorityKind
-	// OtherKind indicates the other kind resource
-	OtherKind
-)
-
-var resourceKindToName = map[ResourceKind]string{
-	0: "unknown",
-	1: "admin",
-	2: "leader",
-	3: "region",
-	4: "priority",
-	5: "other",
-}
-
-var resourceNameToValue = map[string]ResourceKind{
-	"unknown":  UnKnownKind,
-	"admin":    AdminKind,
-	"leader":   LeaderKind,
-	"region":   RegionKind,
-	"priority": PriorityKind,
-	"other":    OtherKind,
-}
-
-func (k ResourceKind) String() string {
-	s, ok := resourceKindToName[k]
-	if ok {
-		return s
-	}
-	return resourceKindToName[UnKnownKind]
-}
-
-// ParseResourceKind convert string to ResourceKind
-func ParseResourceKind(name string) ResourceKind {
-	k, ok := resourceNameToValue[name]
-	if ok {
-		return k
-	}
-	return UnKnownKind
-}
-
 // OperatorState indicates state of the operator
 type OperatorState int
 
@@ -146,7 +94,7 @@ func (o *OperatorState) UnmarshalJSON(text []byte) error {
 // Operator is an interface to schedule region.
 type Operator interface {
 	GetRegionID() uint64
-	GetResourceKind() ResourceKind
+	GetResourceKind() core.ResourceKind
 	GetState() OperatorState
 	SetState(OperatorState)
 	GetName() string
@@ -184,8 +132,8 @@ func (op *adminOperator) GetRegionID() uint64 {
 	return op.Region.GetId()
 }
 
-func (op *adminOperator) GetResourceKind() ResourceKind {
-	return AdminKind
+func (op *adminOperator) GetResourceKind() core.ResourceKind {
+	return core.AdminKind
 }
 
 func (op *adminOperator) GetState() OperatorState {
@@ -228,17 +176,17 @@ func (op *adminOperator) Do(region *RegionInfo) (*pdpb.RegionHeartbeatResponse,
 
 type regionOperator struct {
 	sync.RWMutex `json:"-"`
-	Name         string        `json:"name"`
-	Start        time.Time     `json:"start"`
-	Region       *RegionInfo   `json:"region"`
-	End          time.Time     `json:"end"`
-	Index        int           `json:"index"`
-	Ops          []Operator    `json:"ops"`
-	Kind         ResourceKind  `json:"kind"`
-	State        OperatorState `json:"state"`
+	Name         string            `json:"name"`
+	Start        time.Time         `json:"start"`
+	Region       *RegionInfo       `json:"region"`
+	End          time.Time         `json:"end"`
+	Index        int               `json:"index"`
+	Ops          []Operator        `json:"ops"`
+	Kind         core.ResourceKind `json:"kind"`
+	State        OperatorState     `json:"state"`
 }
 
-func newRegionOperator(region *RegionInfo, kind ResourceKind, ops ...Operator) *regionOperator {
+func newRegionOperator(region *RegionInfo, kind core.ResourceKind, ops ...Operator) *regionOperator {
 	// Do some check here, just fatal because it must be bug.
 	if len(ops) == 0 {
 		log.Fatalf("[region %d] new region operator with no ops", region.GetId())
@@ -266,7 +214,7 @@ func (op *regionOperator) GetRegionID() uint64 {
 	return op.Region.GetId()
 }
 
-func (op *regionOperator) GetResourceKind() ResourceKind {
+func (op *regionOperator) GetResourceKind() core.ResourceKind {
 	return op.Kind
 }
 
@@ -361,8 +309,8 @@ func (op *changePeerOperator) GetRegionID() uint64 {
 	return op.RegionID
 }
 
-func (op *changePeerOperator) GetResourceKind() ResourceKind {
-	return RegionKind
+func (op *changePeerOperator) GetResourceKind() core.ResourceKind {
+	return core.RegionKind
 }
 
 func (op *changePeerOperator) GetState() OperatorState {
@@ -446,8 +394,8 @@ func (op *transferLeaderOperator) GetRegionID() uint64 {
 	return op.RegionID
 }
 
-func (op *transferLeaderOperator) GetResourceKind() ResourceKind {
-	return LeaderKind
+func (op *transferLeaderOperator) GetResourceKind() core.ResourceKind {
+	return core.LeaderKind
 }
 
 func (op *transferLeaderOperator) GetState() OperatorState {
diff --git a/server/replication.go b/server/replication.go
index 4bb2d7ef9..0a7606285 100644
--- a/server/replication.go
+++ b/server/replication.go
@@ -16,6 +16,8 @@ package server
 import (
 	"math"
 	"sync/atomic"
+
+	"github.com/pingcap/pd/server/core"
 )
 
 const replicaBaseScore = 100
@@ -59,7 +61,7 @@ func (r *Replication) GetLocationLabels() []string {
 
 // GetDistinctScore returns the score that the other is distinct from the stores.
 // A higher score means the other store is more different from the existed stores.
-func (r *Replication) GetDistinctScore(stores []*StoreInfo, other *StoreInfo) float64 {
+func (r *Replication) GetDistinctScore(stores []*core.StoreInfo, other *core.StoreInfo) float64 {
 	score := float64(0)
 	locationLabels := r.GetLocationLabels()
 
@@ -67,7 +69,7 @@ func (r *Replication) GetDistinctScore(stores []*StoreInfo, other *StoreInfo) fl
 		if s.GetId() == other.GetId() {
 			continue
 		}
-		if index := s.compareLocation(other, locationLabels); index != -1 {
+		if index := s.CompareLocation(other, locationLabels); index != -1 {
 			score += math.Pow(replicaBaseScore, float64(len(locationLabels)-index-1))
 		}
 	}
@@ -78,7 +80,7 @@ func (r *Replication) GetDistinctScore(stores []*StoreInfo, other *StoreInfo) fl
 // Returns 0 if store A is as good as store B.
 // Returns 1 if store A is better than store B.
 // Returns -1 if store B is better than store A.
-func compareStoreScore(storeA *StoreInfo, scoreA float64, storeB *StoreInfo, scoreB float64) int {
+func compareStoreScore(storeA *core.StoreInfo, scoreA float64, storeB *core.StoreInfo, scoreB float64) int {
 	// The store with higher score is better.
 	if scoreA > scoreB {
 		return 1
diff --git a/server/scheduler.go b/server/scheduler.go
index b1954ce43..31de0f371 100644
--- a/server/scheduler.go
+++ b/server/scheduler.go
@@ -20,12 +20,13 @@ import (
 	log "github.com/Sirupsen/logrus"
 	"github.com/juju/errors"
 	"github.com/pingcap/kvproto/pkg/metapb"
+	"github.com/pingcap/pd/server/core"
 )
 
 // Scheduler is an interface to schedule resources.
 type Scheduler interface {
 	GetName() string
-	GetResourceKind() ResourceKind
+	GetResourceKind() core.ResourceKind
 	GetResourceLimit() uint64
 	Prepare(cluster *clusterInfo) error
 	Cleanup(cluster *clusterInfo)
@@ -51,8 +52,8 @@ func (s *grantLeaderScheduler) GetName() string {
 	return s.name
 }
 
-func (s *grantLeaderScheduler) GetResourceKind() ResourceKind {
-	return LeaderKind
+func (s *grantLeaderScheduler) GetResourceKind() core.ResourceKind {
+	return core.LeaderKind
 }
 
 func (s *grantLeaderScheduler) GetResourceLimit() uint64 {
@@ -103,8 +104,8 @@ func (s *evictLeaderScheduler) GetName() string {
 	return s.name
 }
 
-func (s *evictLeaderScheduler) GetResourceKind() ResourceKind {
-	return LeaderKind
+func (s *evictLeaderScheduler) GetResourceKind() core.ResourceKind {
+	return core.LeaderKind
 }
 
 func (s *evictLeaderScheduler) GetResourceLimit() uint64 {
@@ -157,8 +158,8 @@ func (s *shuffleLeaderScheduler) GetName() string {
 	return "shuffle-leader-scheduler"
 }
 
-func (s *shuffleLeaderScheduler) GetResourceKind() ResourceKind {
-	return LeaderKind
+func (s *shuffleLeaderScheduler) GetResourceKind() core.ResourceKind {
+	return core.LeaderKind
 }
 
 func (s *shuffleLeaderScheduler) GetResourceLimit() uint64 {
@@ -224,8 +225,8 @@ func (s *shuffleRegionScheduler) GetName() string {
 	return "shuffle-region-scheduler"
 }
 
-func (s *shuffleRegionScheduler) GetResourceKind() ResourceKind {
-	return RegionKind
+func (s *shuffleRegionScheduler) GetResourceKind() core.ResourceKind {
+	return core.RegionKind
 }
 
 func (s *shuffleRegionScheduler) GetResourceLimit() uint64 {
@@ -252,12 +253,12 @@ func (s *shuffleRegionScheduler) Schedule(cluster *clusterInfo) Operator {
 	}
 
 	schedulerCounter.WithLabelValues(s.GetName(), "new_operator").Inc()
-	return newTransferPeer(region, RegionKind, oldPeer, newPeer)
+	return newTransferPeer(region, core.RegionKind, oldPeer, newPeer)
 }
 
 func newAddPeer(region *RegionInfo, peer *metapb.Peer) Operator {
 	addPeer := newAddPeerOperator(region.GetId(), peer)
-	return newRegionOperator(region, RegionKind, addPeer)
+	return newRegionOperator(region, core.RegionKind, addPeer)
 }
 
 func newRemovePeer(region *RegionInfo, peer *metapb.Peer) Operator {
@@ -265,14 +266,14 @@ func newRemovePeer(region *RegionInfo, peer *metapb.Peer) Operator {
 	if region.Leader != nil && region.Leader.GetId() == peer.GetId() {
 		if follower := region.GetFollower(); follower != nil {
 			transferLeader := newTransferLeaderOperator(region.GetId(), region.Leader, follower)
-			return newRegionOperator(region, RegionKind, transferLeader, removePeer)
+			return newRegionOperator(region, core.RegionKind, transferLeader, removePeer)
 		}
 		return nil
 	}
-	return newRegionOperator(region, RegionKind, removePeer)
+	return newRegionOperator(region, core.RegionKind, removePeer)
 }
 
-func newTransferPeer(region *RegionInfo, kind ResourceKind, oldPeer, newPeer *metapb.Peer) Operator {
+func newTransferPeer(region *RegionInfo, kind core.ResourceKind, oldPeer, newPeer *metapb.Peer) Operator {
 	addPeer := newAddPeerOperator(region.GetId(), newPeer)
 	removePeer := newRemovePeerOperator(region.GetId(), oldPeer)
 	if region.Leader != nil && region.Leader.GetId() == oldPeer.GetId() {
@@ -288,12 +289,12 @@ func newTransferPeer(region *RegionInfo, kind ResourceKind, oldPeer, newPeer *me
 
 func newPriorityTransferLeader(region *RegionInfo, newLeader *metapb.Peer) Operator {
 	transferLeader := newTransferLeaderOperator(region.GetId(), region.Leader, newLeader)
-	return newRegionOperator(region, PriorityKind, transferLeader)
+	return newRegionOperator(region, core.PriorityKind, transferLeader)
 }
 
 func newTransferLeader(region *RegionInfo, newLeader *metapb.Peer) Operator {
 	transferLeader := newTransferLeaderOperator(region.GetId(), region.Leader, newLeader)
-	return newRegionOperator(region, LeaderKind, transferLeader)
+	return newRegionOperator(region, core.LeaderKind, transferLeader)
 }
 
 // scheduleAddPeer schedules a new peer.
diff --git a/server/selector.go b/server/selector.go
index a6f32d575..ef3cb9614 100644
--- a/server/selector.go
+++ b/server/selector.go
@@ -13,50 +13,54 @@
 
 package server
 
-import "math/rand"
+import (
+	"math/rand"
+
+	"github.com/pingcap/pd/server/core"
+)
 
 // Selector is an interface to select source and target store to schedule.
 type Selector interface {
-	SelectSource(stores []*StoreInfo, filters ...Filter) *StoreInfo
-	SelectTarget(stores []*StoreInfo, filters ...Filter) *StoreInfo
+	SelectSource(stores []*core.StoreInfo, filters ...Filter) *core.StoreInfo
+	SelectTarget(stores []*core.StoreInfo, filters ...Filter) *core.StoreInfo
 }
 
 type balanceSelector struct {
-	kind    ResourceKind
+	kind    core.ResourceKind
 	filters []Filter
 }
 
-func newBalanceSelector(kind ResourceKind, filters []Filter) *balanceSelector {
+func newBalanceSelector(kind core.ResourceKind, filters []Filter) *balanceSelector {
 	return &balanceSelector{
 		kind:    kind,
 		filters: filters,
 	}
 }
 
-func (s *balanceSelector) SelectSource(stores []*StoreInfo, filters ...Filter) *StoreInfo {
+func (s *balanceSelector) SelectSource(stores []*core.StoreInfo, filters ...Filter) *core.StoreInfo {
 	filters = append(filters, s.filters...)
 
-	var result *StoreInfo
+	var result *core.StoreInfo
 	for _, store := range stores {
 		if filterSource(store, filters) {
 			continue
 		}
-		if result == nil || result.resourceScore(s.kind) < store.resourceScore(s.kind) {
+		if result == nil || result.ResourceScore(s.kind) < store.ResourceScore(s.kind) {
 			result = store
 		}
 	}
 	return result
 }
 
-func (s *balanceSelector) SelectTarget(stores []*StoreInfo, filters ...Filter) *StoreInfo {
+func (s *balanceSelector) SelectTarget(stores []*core.StoreInfo, filters ...Filter) *core.StoreInfo {
 	filters = append(filters, s.filters...)
 
-	var result *StoreInfo
+	var result *core.StoreInfo
 	for _, store := range stores {
 		if filterTarget(store, filters) {
 			continue
 		}
-		if result == nil || result.resourceScore(s.kind) > store.resourceScore(s.kind) {
+		if result == nil || result.ResourceScore(s.kind) > store.ResourceScore(s.kind) {
 			result = store
 		}
 	}
@@ -64,12 +68,12 @@ func (s *balanceSelector) SelectTarget(stores []*StoreInfo, filters ...Filter) *
 }
 
 type replicaSelector struct {
-	regionStores []*StoreInfo
+	regionStores []*core.StoreInfo
 	rep          *Replication
 	filters      []Filter
 }
 
-func newReplicaSelector(regionStores []*StoreInfo, rep *Replication, filters ...Filter) Selector {
+func newReplicaSelector(regionStores []*core.StoreInfo, rep *Replication, filters ...Filter) Selector {
 	return &replicaSelector{
 		regionStores: regionStores,
 		rep:          rep,
@@ -77,9 +81,9 @@ func newReplicaSelector(regionStores []*StoreInfo, rep *Replication, filters ...
 	}
 }
 
-func (s *replicaSelector) SelectSource(stores []*StoreInfo, filters ...Filter) *StoreInfo {
+func (s *replicaSelector) SelectSource(stores []*core.StoreInfo, filters ...Filter) *core.StoreInfo {
 	var (
-		best      *StoreInfo
+		best      *core.StoreInfo
 		bestScore float64
 	)
 	for _, store := range stores {
@@ -97,9 +101,9 @@ func (s *replicaSelector) SelectSource(stores []*StoreInfo, filters ...Filter) *
 	return best
 }
 
-func (s *replicaSelector) SelectTarget(stores []*StoreInfo, filters ...Filter) *StoreInfo {
+func (s *replicaSelector) SelectTarget(stores []*core.StoreInfo, filters ...Filter) *core.StoreInfo {
 	var (
-		best      *StoreInfo
+		best      *core.StoreInfo
 		bestScore float64
 	)
 	for _, store := range stores {
@@ -125,17 +129,17 @@ func newRandomSelector(filters []Filter) *randomSelector {
 	return &randomSelector{filters: filters}
 }
 
-func (s *randomSelector) Select(stores []*StoreInfo) *StoreInfo {
+func (s *randomSelector) Select(stores []*core.StoreInfo) *core.StoreInfo {
 	if len(stores) == 0 {
 		return nil
 	}
 	return stores[rand.Int()%len(stores)]
 }
 
-func (s *randomSelector) SelectSource(stores []*StoreInfo, filters ...Filter) *StoreInfo {
+func (s *randomSelector) SelectSource(stores []*core.StoreInfo, filters ...Filter) *core.StoreInfo {
 	filters = append(filters, s.filters...)
 
-	var candidates []*StoreInfo
+	var candidates []*core.StoreInfo
 	for _, store := range stores {
 		if filterSource(store, filters) {
 			continue
@@ -145,10 +149,10 @@ func (s *randomSelector) SelectSource(stores []*StoreInfo, filters ...Filter) *S
 	return s.Select(candidates)
 }
 
-func (s *randomSelector) SelectTarget(stores []*StoreInfo, filters ...Filter) *StoreInfo {
+func (s *randomSelector) SelectTarget(stores []*core.StoreInfo, filters ...Filter) *core.StoreInfo {
 	filters = append(filters, s.filters...)
 
-	var candidates []*StoreInfo
+	var candidates []*core.StoreInfo
 	for _, store := range stores {
 		if filterTarget(store, filters) {
 			continue


Test patch:
diff --git a/server/api/store_test.go b/server/api/store_test.go
index 8bd689431..e1c4d55fd 100644
--- a/server/api/store_test.go
+++ b/server/api/store_test.go
@@ -25,6 +25,7 @@ import (
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/kvproto/pkg/pdpb"
 	"github.com/pingcap/pd/server"
+	"github.com/pingcap/pd/server/core"
 )
 
 var _ = Suite(&testStoreSuite{})
@@ -229,7 +230,7 @@ func (s *testStoreSuite) TestUrlStoreFilter(c *C) {
 }
 
 func (s *testStoreSuite) TestDownState(c *C) {
-	store := &server.StoreInfo{
+	store := &core.StoreInfo{
 		Store: &metapb.Store{
 			State: metapb.StoreState_Up,
 		},
diff --git a/server/balancer_test.go b/server/balancer_test.go
index 4d273e723..d01f0f547 100644
--- a/server/balancer_test.go
+++ b/server/balancer_test.go
@@ -20,6 +20,7 @@ import (
 	. "github.com/pingcap/check"
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/kvproto/pkg/pdpb"
+	"github.com/pingcap/pd/server/core"
 )
 
 type testClusterInfo struct {
@@ -58,7 +59,7 @@ func (c *testClusterInfo) setStoreBusy(storeID uint64, busy bool) {
 }
 
 func (c *testClusterInfo) addLeaderStore(storeID uint64, leaderCount int) {
-	store := newStoreInfo(&metapb.Store{Id: storeID})
+	store := core.NewStoreInfo(&metapb.Store{Id: storeID})
 	store.Stats = &pdpb.StoreStats{}
 	store.LastHeartbeatTS = time.Now()
 	store.LeaderCount = leaderCount
@@ -66,7 +67,7 @@ func (c *testClusterInfo) addLeaderStore(storeID uint64, leaderCount int) {
 }
 
 func (c *testClusterInfo) addRegionStore(storeID uint64, regionCount int) {
-	store := newStoreInfo(&metapb.Store{Id: storeID})
+	store := core.NewStoreInfo(&metapb.Store{Id: storeID})
 	store.Stats = &pdpb.StoreStats{}
 	store.LastHeartbeatTS = time.Now()
 	store.RegionCount = regionCount
@@ -220,7 +221,7 @@ func (s *testBalanceSpeedSuite) testBalanceSpeed(c *C, tests []testBalanceSpeedC
 		tc.addLeaderStore(2, int(t.targetCount))
 		source := cluster.getStore(1)
 		target := cluster.getStore(2)
-		c.Assert(shouldBalance(source, target, LeaderKind), Equals, t.expectedResult)
+		c.Assert(shouldBalance(source, target, core.LeaderKind), Equals, t.expectedResult)
 	}
 
 	for _, t := range tests {
@@ -228,7 +229,7 @@ func (s *testBalanceSpeedSuite) testBalanceSpeed(c *C, tests []testBalanceSpeedC
 		tc.addRegionStore(2, int(t.targetCount))
 		source := cluster.getStore(1)
 		target := cluster.getStore(2)
-		c.Assert(shouldBalance(source, target, RegionKind), Equals, t.expectedResult)
+		c.Assert(shouldBalance(source, target, core.RegionKind), Equals, t.expectedResult)
 	}
 }
 
@@ -240,11 +241,11 @@ func (s *testBalanceSpeedSuite) TestBalanceLimit(c *C) {
 	tc.addLeaderStore(3, 30)
 
 	// StandDeviation is sqrt((10^2+0+10^2)/3).
-	c.Assert(adjustBalanceLimit(cluster, LeaderKind), Equals, uint64(math.Sqrt(200.0/3.0)))
+	c.Assert(adjustBalanceLimit(cluster, core.LeaderKind), Equals, uint64(math.Sqrt(200.0/3.0)))
 
 	tc.setStoreOffline(1)
 	// StandDeviation is sqrt((5^2+5^2)/2).
-	c.Assert(adjustBalanceLimit(cluster, LeaderKind), Equals, uint64(math.Sqrt(50.0/2.0)))
+	c.Assert(adjustBalanceLimit(cluster, core.LeaderKind), Equals, uint64(math.Sqrt(50.0/2.0)))
 }
 
 var _ = Suite(&testBalanceLeaderSchedulerSuite{})
diff --git a/server/cache_test.go b/server/cache_test.go
index 2b10c5d7e..1ff8fde60 100644
--- a/server/cache_test.go
+++ b/server/cache_test.go
@@ -21,6 +21,7 @@ import (
 	. "github.com/pingcap/check"
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/kvproto/pkg/pdpb"
+	"github.com/pingcap/pd/server/core"
 )
 
 var _ = Suite(&testStoresInfoSuite{})
@@ -39,13 +40,13 @@ func checkStaleRegion(origin *metapb.Region, region *metapb.Region) error {
 }
 
 // Create n stores (0..n).
-func newTestStores(n uint64) []*StoreInfo {
-	stores := make([]*StoreInfo, 0, n)
+func newTestStores(n uint64) []*core.StoreInfo {
+	stores := make([]*core.StoreInfo, 0, n)
 	for i := uint64(0); i < n; i++ {
 		store := &metapb.Store{
 			Id: i,
 		}
-		stores = append(stores, newStoreInfo(store))
+		stores = append(stores, core.NewStoreInfo(store))
 	}
 	return stores
 }
@@ -62,10 +63,10 @@ func (s *testStoresInfoSuite) TestStores(c *C) {
 		c.Assert(cache.getStore(i), DeepEquals, stores[i])
 		c.Assert(cache.getStoreCount(), Equals, int(i+1))
 		c.Assert(cache.blockStore(i), IsNil)
-		c.Assert(cache.getStore(i).isBlocked(), IsTrue)
+		c.Assert(cache.getStore(i).IsBlocked(), IsTrue)
 		c.Assert(cache.blockStore(i), NotNil)
 		cache.unblockStore(i)
-		c.Assert(cache.getStore(i).isBlocked(), IsFalse)
+		c.Assert(cache.getStore(i).IsBlocked(), IsFalse)
 	}
 	c.Assert(cache.getStoreCount(), Equals, int(n))
 
diff --git a/server/coordinator_test.go b/server/coordinator_test.go
index bd077a1ae..7abb97b49 100644
--- a/server/coordinator_test.go
+++ b/server/coordinator_test.go
@@ -20,25 +20,26 @@ import (
 	"github.com/pingcap/kvproto/pkg/metapb"
 	"github.com/pingcap/kvproto/pkg/pdpb"
 	"github.com/pingcap/pd/pkg/testutil"
+	"github.com/pingcap/pd/server/core"
 )
 
 type testOperator struct {
 	RegionID uint64
-	Kind     ResourceKind
+	Kind     core.ResourceKind
 	State    OperatorState
 }
 
-func newTestOperator(regionID uint64, kind ResourceKind) Operator {
+func newTestOperator(regionID uint64, kind core.ResourceKind) Operator {
 	region := newRegionInfo(&metapb.Region{Id: regionID}, nil)
 	op := &testOperator{RegionID: regionID, Kind: kind, State: OperatorRunning}
 	return newRegionOperator(region, kind, op)
 }
 
-func (op *testOperator) GetRegionID() uint64           { return op.RegionID }
-func (op *testOperator) GetResourceKind() ResourceKind { return op.Kind }
-func (op *testOperator) GetState() OperatorState       { return op.State }
-func (op *testOperator) SetState(state OperatorState)  { op.State = state }
-func (op *testOperator) GetName() string               { return "test" }
+func (op *testOperator) GetRegionID() uint64                { return op.RegionID }
+func (op *testOperator) GetResourceKind() core.ResourceKind { return op.Kind }
+func (op *testOperator) GetState() OperatorState            { return op.State }
+func (op *testOperator) SetState(state OperatorState)       { op.State = state }
+func (op *testOperator) GetName() string                    { return "test" }
 func (op *testOperator) Do(region *RegionInfo) (*pdpb.RegionHeartbeatResponse, bool) {
 	return nil, false
 }
@@ -55,13 +56,13 @@ func (s *testCoordinatorSuite) TestBasic(c *C) {
 	co := newCoordinator(cluster, opt, hbStreams)
 	l := co.limiter
 
-	op1 := newTestOperator(1, LeaderKind)
+	op1 := newTestOperator(1, core.LeaderKind)
 	co.addOperator(op1)
 	c.Assert(l.operatorCount(op1.GetResourceKind()), Equals, uint64(1))
 	c.Assert(co.getOperator(1).GetRegionID(), Equals, op1.GetRegionID())
 
 	// Region 1 already has an operator, cannot add another one.
-	op2 := newTestOperator(1, RegionKind)
+	op2 := newTestOperator(1, core.RegionKind)
 	co.addOperator(op2)
 	c.Assert(l.operatorCount(op2.GetResourceKind()), Equals, uint64(0))
 
@@ -412,24 +413,24 @@ type testScheduleLimiterSuite struct{}
 
 func (s *testScheduleLimiterSuite) TestOperatorCount(c *C) {
 	l := newScheduleLimiter()
-	c.Assert(l.operatorCount(LeaderKind), Equals, uint64(0))
-	c.Assert(l.operatorCount(RegionKind), Equals, uint64(0))
+	c.Assert(l.operatorCount(core.LeaderKind), Equals, uint64(0))
+	c.Assert(l.operatorCount(core.RegionKind), Equals, uint64(0))
 
-	leaderOP := newTestOperator(1, LeaderKind)
+	leaderOP := newTestOperator(1, core.LeaderKind)
 	l.addOperator(leaderOP)
-	c.Assert(l.operatorCount(LeaderKind), Equals, uint64(1))
+	c.Assert(l.operatorCount(core.LeaderKind), Equals, uint64(1))
 	l.addOperator(leaderOP)
-	c.Assert(l.operatorCount(LeaderKind), Equals, uint64(2))
+	c.Assert(l.operatorCount(core.LeaderKind), Equals, uint64(2))
 	l.removeOperator(leaderOP)
-	c.Assert(l.operatorCount(LeaderKind), Equals, uint64(1))
+	c.Assert(l.operatorCount(core.LeaderKind), Equals, uint64(1))
 
-	regionOP := newTestOperator(1, RegionKind)
+	regionOP := newTestOperator(1, core.RegionKind)
 	l.addOperator(regionOP)
-	c.Assert(l.operatorCount(RegionKind), Equals, uint64(1))
+	c.Assert(l.operatorCount(core.RegionKind), Equals, uint64(1))
 	l.addOperator(regionOP)
-	c.Assert(l.operatorCount(RegionKind), Equals, uint64(2))
+	c.Assert(l.operatorCount(core.RegionKind), Equals, uint64(2))
 	l.removeOperator(regionOP)
-	c.Assert(l.operatorCount(RegionKind), Equals, uint64(1))
+	c.Assert(l.operatorCount(core.RegionKind), Equals, uint64(1))
 }
 
 var _ = Suite(&testScheduleControllerSuite{})
@@ -461,11 +462,11 @@ func (s *testScheduleControllerSuite) TestController(c *C) {
 	lb.limit = 2
 	// count = 0
 	c.Assert(sc.AllowSchedule(), IsTrue)
-	op1 := newTestOperator(1, LeaderKind)
+	op1 := newTestOperator(1, core.LeaderKind)
 	c.Assert(co.addOperator(op1), IsTrue)
 	// count = 1
 	c.Assert(sc.AllowSchedule(), IsTrue)
-	op2 := newTestOperator(2, LeaderKind)
+	op2 := newTestOperator(2, core.LeaderKind)
 	c.Assert(co.addOperator(op2), IsTrue)
 	// count = 2
 	c.Assert(sc.AllowSchedule(), IsFalse)
@@ -474,7 +475,7 @@ func (s *testScheduleControllerSuite) TestController(c *C) {
 	c.Assert(sc.AllowSchedule(), IsTrue)
 
 	// add a PriorityKind operator will remove old operator
-	op3 := newTestOperator(2, PriorityKind)
+	op3 := newTestOperator(2, core.PriorityKind)
 	c.Assert(co.addOperator(op1), IsTrue)
 	c.Assert(sc.AllowSchedule(), IsFalse)
 	c.Assert(co.addOperator(op3), IsTrue)
@@ -484,7 +485,7 @@ func (s *testScheduleControllerSuite) TestController(c *C) {
 	// add a AdminKind operator will remove old operator
 	c.Assert(co.addOperator(op2), IsTrue)
 	c.Assert(sc.AllowSchedule(), IsFalse)
-	op4 := newTestOperator(2, AdminKind)
+	op4 := newTestOperator(2, core.AdminKind)
 	c.Assert(co.addOperator(op4), IsTrue)
 	c.Assert(sc.AllowSchedule(), IsTrue)
 }
diff --git a/server/core/resource_kind_test.go b/server/core/resource_kind_test.go
new file mode 100644
index 000000000..dfbac7d68
--- /dev/null
+++ b/server/core/resource_kind_test.go
@@ -0,0 +1,64 @@
+// 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 core
+
+import (
+	"testing"
+
+	. "github.com/pingcap/check"
+)
+
+func TestCore(t *testing.T) {
+	TestingT(t)
+}
+
+var _ = Suite(&testResouceKindSuite{})
+
+type testResouceKindSuite struct{}
+
+func (s *testResouceKindSuite) TestString(c *C) {
+	tbl := []struct {
+		value ResourceKind
+		name  string
+	}{
+		{UnKnownKind, "unknown"},
+		{AdminKind, "admin"},
+		{LeaderKind, "leader"},
+		{RegionKind, "region"},
+		{PriorityKind, "priority"},
+		{OtherKind, "other"},
+		{ResourceKind(404), "unknown"},
+	}
+	for _, t := range tbl {
+		c.Assert(t.value.String(), Equals, t.name)
+	}
+}
+
+func (s *testResouceKindSuite) TestParseResouceKind(c *C) {
+	tbl := []struct {
+		name  string
+		value ResourceKind
+	}{
+		{"unknown", UnKnownKind},
+		{"admin", AdminKind},
+		{"leader", LeaderKind},
+		{"region", RegionKind},
+		{"priority", PriorityKind},
+		{"other", OtherKind},
+		{"test", UnKnownKind},
+	}
+	for _, t := range tbl {
+		c.Assert(ParseResourceKind(t.name), Equals, t.value)
+	}
+}
diff --git a/server/operator_test.go b/server/operator_test.go
index 287fa9b5c..f5bcfe92d 100644
--- a/server/operator_test.go
+++ b/server/operator_test.go
@@ -21,46 +21,6 @@ import (
 	"github.com/pingcap/kvproto/pkg/pdpb"
 )
 
-var _ = Suite(&testResouceKindSuite{})
-
-type testResouceKindSuite struct{}
-
-func (s *testResouceKindSuite) TestString(c *C) {
-	tbl := []struct {
-		value ResourceKind
-		name  string
-	}{
-		{UnKnownKind, "unknown"},
-		{AdminKind, "admin"},
-		{LeaderKind, "leader"},
-		{RegionKind, "region"},
-		{PriorityKind, "priority"},
-		{OtherKind, "other"},
-		{ResourceKind(404), "unknown"},
-	}
-	for _, t := range tbl {
-		c.Assert(t.value.String(), Equals, t.name)
-	}
-}
-
-func (s *testResouceKindSuite) TestParseResouceKind(c *C) {
-	tbl := []struct {
-		name  string
-		value ResourceKind
-	}{
-		{"unknown", UnKnownKind},
-		{"admin", AdminKind},
-		{"leader", LeaderKind},
-		{"region", RegionKind},
-		{"priority", PriorityKind},
-		{"other", OtherKind},
-		{"test", UnKnownKind},
-	}
-	for _, t := range tbl {
-		c.Assert(ParseResourceKind(t.name), Equals, t.value)
-	}
-}
-
 var _ = Suite(&testOperatorSuite{})
 
 type testOperatorSuite struct{}
diff --git a/server/replication_test.go b/server/replication_test.go
index ec073c324..36bd168fa 100644
--- a/server/replication_test.go
+++ b/server/replication_test.go
@@ -13,7 +13,10 @@
 
 package server
 
-import . "github.com/pingcap/check"
+import (
+	. "github.com/pingcap/check"
+	"github.com/pingcap/pd/server/core"
+)
 
 func newTestReplication(maxReplicas int, locationLabels ...string) *Replication {
 	cfg := &ReplicationConfig{
@@ -36,7 +39,7 @@ func (s *testReplicationSuite) TestDistinctScore(c *C) {
 	racks := []string{"r1", "r2", "r3"}
 	hosts := []string{"h1", "h2", "h3"}
 
-	var stores []*StoreInfo
+	var stores []*core.StoreInfo
 	for i, zone := range zones {
 		for j, rack := range racks {
 			for k, host := range hosts {
diff --git a/server/testutil.go b/server/testutil.go
index 782d83899..d61b86701 100644
--- a/server/testutil.go
+++ b/server/testutil.go
@@ -21,7 +21,7 @@ import (
 	"time"
 
 	"github.com/coreos/etcd/embed"
-	. "github.com/pingcap/check"
+	"github.com/pingcap/check"
 	"github.com/pingcap/pd/pkg/testutil"
 	"github.com/pingcap/pd/pkg/typeutil"
 )
@@ -35,11 +35,11 @@ func cleanServer(cfg *Config) {
 }
 
 // NewTestServer creates a pd server for testing.
-func NewTestServer(c *C) (*Config, *Server, CleanupFunc) {
+func NewTestServer(c *check.C) (*Config, *Server, CleanupFunc) {
 	cfg := NewTestSingleConfig()
 	s, err := CreateServer(cfg, nil)
-	c.Assert(err, IsNil)
-	c.Assert(s.Run(), IsNil)
+	c.Assert(err, check.IsNil)
+	c.Assert(s.Run(), check.IsNil)
 
 	cleanup := func() {
 		s.Close()