func (t *ShardTree) AscendRange(start, end []byte, fn func(Shard *meta.Shard) bool) {
	startItem := &ShardItem{
		Shard: meta.Shard{Start: start},
	}
	endItem := &ShardItem{
		Shard: meta.Shard{Start: end},
	}
	t.RLock()
	t.tree.DescendRange(startItem, endItem, func(item btree.Item) bool {
		return fn(&item.(*ShardItem).Shard)
	})
	t.RUnlock()
}
AscendRange asc iterator the tree in the range [start, end) until fn returns false
package util
import (
	"bytes"
	"sync"
	"github.com/google/btree"
	"github.com/matrixorigin/matrixcube/pb/meta"
)
const (
	defaultBTreeDegree = 64
)
var (
	emptyShard meta.Shard
	itemPool   sync.Pool
)
func acquireItem() *ShardItem {
	v := itemPool.Get()
	if v == nil {
		return &ShardItem{}
	}
	return v.(*ShardItem)
}
func releaseItem(item *ShardItem) {
	itemPool.Put(item)
}
type ShardItem struct {
	Shard meta.Shard
}
type ShardTree struct {
	sync.RWMutex
	tree *btree.BTree
}
func NewShardTree() *ShardTree {
	return &ShardTree{
		tree: btree.New(defaultBTreeDegree),
	}
}
func (r *ShardItem) Less(other btree.Item) bool {
	left := r.Shard.Start
	right := other.(*ShardItem).Shard.Start
	return bytes.Compare(left, right) > 0
}
func (r *ShardItem) Contains(key []byte) bool {
	start, end := r.Shard.Start, r.Shard.End
	return bytes.Compare(key, start) >= 0 && (len(end) == 0 || bytes.Compare(key, end) < 0)
}
func (t *ShardTree) length() int {
	return t.tree.Len()
}
func (t *ShardTree) Update(shard meta.Shard) {
	t.Lock()
	item := &ShardItem{Shard: shard}
	result := t.find(shard)
	if result == nil {
		result = item
	}
	var overlaps []*ShardItem
	t.tree.DescendLessOrEqual(result, func(i btree.Item) bool {
		over := i.(*ShardItem)
		if len(shard.End) > 0 && bytes.Compare(shard.End, over.Shard.Start) <= 0 {
			return false
		}
		overlaps = append(overlaps, over)
		return true
	})
	for _, item := range overlaps {
		t.tree.Delete(item)
	}
	t.tree.ReplaceOrInsert(item)
	t.Unlock()
}
func (t *ShardTree) Remove(Shard meta.Shard) bool {
	t.Lock()
	result := t.find(Shard)
	if result == nil || result.Shard.ID != Shard.ID {
		t.Unlock()
		return false
	}
	t.tree.Delete(result)
	t.Unlock()
	return true
}
func (t *ShardTree) Ascend(fn func(Shard *meta.Shard) bool) {
	t.RLock()
	t.tree.Descend(func(item btree.Item) bool {
		return fn(&item.(*ShardItem).Shard)
	})
	t.RUnlock()
}
func (t *ShardTree) NextShard(start []byte) *meta.Shard {
	var value *ShardItem
	p := &ShardItem{
		Shard: meta.Shard{Start: start},
	}
	t.RLock()
	t.tree.DescendLessOrEqual(p, func(item btree.Item) bool {
		if bytes.Compare(item.(*ShardItem).Shard.Start, start) > 0 {
			value = item.(*ShardItem)
			return false
		}
		return true
	})
	t.RUnlock()
	if nil == value {
		return nil
	}
	return &value.Shard
}