Skip to content

Commit

Permalink
Merge branch 'master' into route
Browse files Browse the repository at this point in the history
  • Loading branch information
ti-chi-bot[bot] committed Jul 3, 2023
2 parents ad159a3 + 5f7236f commit 33fef9e
Show file tree
Hide file tree
Showing 22 changed files with 420 additions and 95 deletions.
17 changes: 17 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,20 @@ coverage:
# basic
target: auto
threshold: 3%

comment:
layout: "header, diff, flags"
behavior: default
require_changes: false

flag_management:
default_rules: # the rules that will be followed for any flag added, generally
carryforward: true
statuses:
- type: project
target: 85%
- type: patch
target: 85%

ignore:
- tests/** # integration test cases or tools.
5 changes: 0 additions & 5 deletions errors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -606,11 +606,6 @@ error = '''
invalid group settings, please check the group name, priority and the number of resources
'''

["PD:resourcemanager:ErrResourceGroupAlreadyExists"]
error = '''
the %s resource group already exists
'''

["PD:schedule:ErrCreateOperator"]
error = '''
unable to create operator, %s
Expand Down
7 changes: 3 additions & 4 deletions pkg/errs/errno.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,7 @@ var (

// Resource Manager errors
var (
ErrResourceGroupAlreadyExists = errors.Normalize("the %s resource group already exists", errors.RFCCodeText("PD:resourcemanager:ErrResourceGroupAlreadyExists"))
ErrResourceGroupNotExists = errors.Normalize("the %s resource group does not exist", errors.RFCCodeText("PD:resourcemanager:ErrGroupNotExists"))
ErrDeleteReservedGroup = errors.Normalize("cannot delete reserved group", errors.RFCCodeText("PD:resourcemanager:ErrDeleteReservedGroup"))
ErrInvalidGroup = errors.Normalize("invalid group settings, please check the group name, priority and the number of resources", errors.RFCCodeText("PD:resourcemanager:ErrInvalidGroup"))
ErrResourceGroupNotExists = errors.Normalize("the %s resource group does not exist", errors.RFCCodeText("PD:resourcemanager:ErrGroupNotExists"))
ErrDeleteReservedGroup = errors.Normalize("cannot delete reserved group", errors.RFCCodeText("PD:resourcemanager:ErrDeleteReservedGroup"))
ErrInvalidGroup = errors.Normalize("invalid group settings, please check the group name, priority and the number of resources", errors.RFCCodeText("PD:resourcemanager:ErrInvalidGroup"))
)
4 changes: 0 additions & 4 deletions pkg/keyspace/keyspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,6 @@ func (manager *Manager) LoadKeyspace(name string) (*keyspacepb.KeyspaceMeta, err
if meta == nil {
return ErrKeyspaceNotFound
}
meta.Id = id
return nil
})
return meta, err
Expand All @@ -397,9 +396,6 @@ func (manager *Manager) LoadKeyspaceByID(spaceID uint32) (*keyspacepb.KeyspaceMe
}
return nil
})
if meta != nil {
meta.Id = spaceID
}
return meta, err
}

Expand Down
16 changes: 14 additions & 2 deletions pkg/keyspace/tso_keyspace_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,17 @@ func buildSplitKeyspaces(
oldSplit = append(oldSplit, keyspace)
}
}
return oldSplit, new, nil
// If newNum != len(newKeyspaceMap), it means the provided new keyspace list contains
// duplicate keyspaces, and we need to dedup them (https://github.com/tikv/pd/issues/6687);
// otherwise, we can just return the old split and new keyspace list.
if newNum == len(newKeyspaceMap) {
return oldSplit, new, nil
}
newSplit := make([]uint32, 0, len(newKeyspaceMap))
for keyspace := range newKeyspaceMap {
newSplit = append(newSplit, keyspace)
}
return oldSplit, newSplit, nil
}
// Split according to the start and end keyspace ID.
if startKeyspaceID == 0 && endKeyspaceID == 0 {
Expand All @@ -634,7 +644,9 @@ func buildSplitKeyspaces(
)
for _, keyspace := range old {
if keyspace == utils.DefaultKeyspaceID {
return nil, nil, ErrModifyDefaultKeyspace
// The source keyspace group must be the default keyspace group and we always keep the default
// keyspace in the default keyspace group.
continue
}
if startKeyspaceID <= keyspace && keyspace <= endKeyspaceID {
newSplit = append(newSplit, keyspace)
Expand Down
41 changes: 41 additions & 0 deletions pkg/keyspace/tso_keyspace_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,27 +483,68 @@ func TestBuildSplitKeyspaces(t *testing.T) {
new: []uint32{6},
err: ErrKeyspaceNotInKeyspaceGroup,
},
{
old: []uint32{1, 2},
new: []uint32{2, 2},
expectedOld: []uint32{1},
expectedNew: []uint32{2},
},
{
old: []uint32{0, 1, 2, 3, 4, 5},
startKeyspaceID: 2,
endKeyspaceID: 4,
expectedOld: []uint32{0, 1, 5},
expectedNew: []uint32{2, 3, 4},
},
{
old: []uint32{0, 1, 2, 3, 4, 5},
startKeyspaceID: 0,
endKeyspaceID: 4,
expectedOld: []uint32{0, 5},
expectedNew: []uint32{1, 2, 3, 4},
},
{
old: []uint32{1, 2, 3, 4, 5},
startKeyspaceID: 2,
endKeyspaceID: 4,
expectedOld: []uint32{1, 5},
expectedNew: []uint32{2, 3, 4},
},
{
old: []uint32{1, 2, 3, 4, 5},
startKeyspaceID: 5,
endKeyspaceID: 6,
expectedOld: []uint32{1, 2, 3, 4},
expectedNew: []uint32{5},
},
{
old: []uint32{1, 2, 3, 4, 5},
startKeyspaceID: 2,
endKeyspaceID: 6,
expectedOld: []uint32{1},
expectedNew: []uint32{2, 3, 4, 5},
},
{
old: []uint32{1, 2, 3, 4, 5},
startKeyspaceID: 1,
endKeyspaceID: 1,
expectedOld: []uint32{2, 3, 4, 5},
expectedNew: []uint32{1},
},
{
old: []uint32{1, 2, 3, 4, 5},
startKeyspaceID: 0,
endKeyspaceID: 6,
expectedOld: []uint32{},
expectedNew: []uint32{1, 2, 3, 4, 5},
},
{
old: []uint32{1, 2, 3, 4, 5},
startKeyspaceID: 7,
endKeyspaceID: 10,
expectedOld: []uint32{1, 2, 3, 4, 5},
expectedNew: []uint32{},
},
{
old: []uint32{1, 2, 3, 4, 5},
err: ErrKeyspaceNotInKeyspaceGroup,
Expand Down
35 changes: 25 additions & 10 deletions pkg/keyspace/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func MaskKeyspaceID(id uint32) uint32 {
return id & 0xFF
}

// makeKeyRanges encodes keyspace ID to correct LabelRule data.
// RegionBound represents the region boundary of the given keyspace.
// For a keyspace with id ['a', 'b', 'c'], it has four boundaries:
//
// Lower bound for raw mode: ['r', 'a', 'b', 'c']
Expand All @@ -147,23 +147,38 @@ func MaskKeyspaceID(id uint32) uint32 {
// And shares upper bound with keyspace with id ['a', 'b', 'c + 1'].
// These repeated bound will not cause any problem, as repetitive bound will be ignored during rangeListBuild,
// but provides guard against hole in keyspace allocations should it occur.
func makeKeyRanges(id uint32) []interface{} {
type RegionBound struct {
RawLeftBound []byte
RawRightBound []byte
TxnLeftBound []byte
TxnRightBound []byte
}

// MakeRegionBound constructs the correct region boundaries of the given keyspace.
func MakeRegionBound(id uint32) *RegionBound {
keyspaceIDBytes := make([]byte, 4)
nextKeyspaceIDBytes := make([]byte, 4)
binary.BigEndian.PutUint32(keyspaceIDBytes, id)
binary.BigEndian.PutUint32(nextKeyspaceIDBytes, id+1)
rawLeftBound := hex.EncodeToString(codec.EncodeBytes(append([]byte{'r'}, keyspaceIDBytes[1:]...)))
rawRightBound := hex.EncodeToString(codec.EncodeBytes(append([]byte{'r'}, nextKeyspaceIDBytes[1:]...)))
txnLeftBound := hex.EncodeToString(codec.EncodeBytes(append([]byte{'x'}, keyspaceIDBytes[1:]...)))
txnRightBound := hex.EncodeToString(codec.EncodeBytes(append([]byte{'x'}, nextKeyspaceIDBytes[1:]...)))
return &RegionBound{
RawLeftBound: codec.EncodeBytes(append([]byte{'r'}, keyspaceIDBytes[1:]...)),
RawRightBound: codec.EncodeBytes(append([]byte{'r'}, nextKeyspaceIDBytes[1:]...)),
TxnLeftBound: codec.EncodeBytes(append([]byte{'x'}, keyspaceIDBytes[1:]...)),
TxnRightBound: codec.EncodeBytes(append([]byte{'x'}, nextKeyspaceIDBytes[1:]...)),
}
}

// makeKeyRanges encodes keyspace ID to correct LabelRule data.
func makeKeyRanges(id uint32) []interface{} {
regionBound := MakeRegionBound(id)
return []interface{}{
map[string]interface{}{
"start_key": rawLeftBound,
"end_key": rawRightBound,
"start_key": hex.EncodeToString(regionBound.RawLeftBound),
"end_key": hex.EncodeToString(regionBound.RawRightBound),
},
map[string]interface{}{
"start_key": txnLeftBound,
"end_key": txnRightBound,
"start_key": hex.EncodeToString(regionBound.TxnLeftBound),
"end_key": hex.EncodeToString(regionBound.TxnRightBound),
},
}
}
Expand Down
8 changes: 2 additions & 6 deletions pkg/mcs/resourcemanager/server/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ func (m *Manager) Init(ctx context.Context) {
}

// AddResourceGroup puts a resource group.
// NOTE: AddResourceGroup should also be idempotent because tidb depends
// on this retry mechanism.
func (m *Manager) AddResourceGroup(grouppb *rmpb.ResourceGroup) error {
// Check the name.
if len(grouppb.Name) == 0 || len(grouppb.Name) > 32 {
Expand All @@ -163,12 +165,6 @@ func (m *Manager) AddResourceGroup(grouppb *rmpb.ResourceGroup) error {
if grouppb.GetPriority() > 16 {
return errs.ErrInvalidGroup
}
m.RLock()
_, ok := m.groups[grouppb.Name]
m.RUnlock()
if ok {
return errs.ErrResourceGroupAlreadyExists.FastGenByArgs(grouppb.Name)
}
group := FromProtoResourceGroup(grouppb)
m.Lock()
defer m.Unlock()
Expand Down
43 changes: 43 additions & 0 deletions pkg/timerpool/pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Note: This file is copied from https://go-review.googlesource.com/c/go/+/276133

package timerpool

import (
"sync"
"time"
)

// GlobalTimerPool is a global pool for reusing *time.Timer.
var GlobalTimerPool TimerPool

// TimerPool is a wrapper of sync.Pool which caches *time.Timer for reuse.
type TimerPool struct {
pool sync.Pool
}

// Get returns a timer with a given duration.
func (tp *TimerPool) Get(d time.Duration) *time.Timer {
if v := tp.pool.Get(); v != nil {
timer := v.(*time.Timer)
timer.Reset(d)
return timer
}
return time.NewTimer(d)
}

// Put tries to call timer.Stop() before putting it back into pool,
// if the timer.Stop() returns false (it has either already expired or been stopped),
// have a shot at draining the channel with residual time if there is one.
func (tp *TimerPool) Put(timer *time.Timer) {
if !timer.Stop() {
select {
case <-timer.C:
default:
}
}
tp.pool.Put(timer)
}
70 changes: 70 additions & 0 deletions pkg/timerpool/pool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Note: This file is copied from https://go-review.googlesource.com/c/go/+/276133

package timerpool

import (
"testing"
"time"
)

func TestTimerPool(t *testing.T) {
var tp TimerPool

for i := 0; i < 100; i++ {
timer := tp.Get(20 * time.Millisecond)

select {
case <-timer.C:
t.Errorf("timer expired too early")
continue
default:
}

select {
case <-time.After(100 * time.Millisecond):
t.Errorf("timer didn't expire on time")
case <-timer.C:
}

tp.Put(timer)
}
}

const timeout = 10 * time.Millisecond

func BenchmarkTimerUtilization(b *testing.B) {
b.Run("TimerWithPool", func(b *testing.B) {
for i := 0; i < b.N; i++ {
t := GlobalTimerPool.Get(timeout)
GlobalTimerPool.Put(t)
}
})
b.Run("TimerWithoutPool", func(b *testing.B) {
for i := 0; i < b.N; i++ {
t := time.NewTimer(timeout)
t.Stop()
}
})
}

func BenchmarkTimerPoolParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
t := GlobalTimerPool.Get(timeout)
GlobalTimerPool.Put(t)
}
})
}

func BenchmarkTimerNativeParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
t := time.NewTimer(timeout)
t.Stop()
}
})
}

0 comments on commit 33fef9e

Please sign in to comment.