forked from pingcap/br
/
range.go
100 lines (90 loc) · 3.11 KB
/
range.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0.
package restore
import (
"bytes"
"github.com/pingcap/errors"
"github.com/pingcap/kvproto/pkg/import_sstpb"
"github.com/pingcap/kvproto/pkg/metapb"
"github.com/pingcap/log"
"github.com/pingcap/tidb/tablecodec"
"go.uber.org/zap"
berrors "github.com/pingcap/br/pkg/errors"
"github.com/pingcap/br/pkg/logutil"
"github.com/pingcap/br/pkg/rtree"
)
// SortRanges checks if the range overlapped and sort them.
func SortRanges(ranges []rtree.Range, rewriteRules *RewriteRules) ([]rtree.Range, error) {
rangeTree := rtree.NewRangeTree()
for _, rg := range ranges {
if rewriteRules != nil {
startID := tablecodec.DecodeTableID(rg.StartKey)
endID := tablecodec.DecodeTableID(rg.EndKey)
var rule *import_sstpb.RewriteRule
if startID == endID {
rg.StartKey, rule = replacePrefix(rg.StartKey, rewriteRules)
if rule == nil {
log.Warn("cannot find rewrite rule", logutil.Key("key", rg.StartKey))
} else {
log.Debug(
"rewrite start key",
logutil.Key("key", rg.StartKey), logutil.RewriteRule(rule))
}
rg.EndKey, rule = replacePrefix(rg.EndKey, rewriteRules)
if rule == nil {
log.Warn("cannot find rewrite rule", logutil.Key("key", rg.EndKey))
} else {
log.Debug(
"rewrite end key",
logutil.Key("key", rg.EndKey),
logutil.RewriteRule(rule))
}
} else {
log.Warn("table id does not match",
logutil.Key("startKey", rg.StartKey),
logutil.Key("endKey", rg.EndKey),
zap.Int64("startID", startID),
zap.Int64("endID", endID))
return nil, errors.Annotate(berrors.ErrRestoreTableIDMismatch, "table id mismatch")
}
}
if out := rangeTree.InsertRange(rg); out != nil {
log.Error("insert ranges overlapped",
logutil.Key("startKeyOut", out.StartKey),
logutil.Key("endKeyOut", out.EndKey),
logutil.Key("startKeyIn", rg.StartKey),
logutil.Key("endKeyIn", rg.EndKey))
return nil, errors.Annotatef(berrors.ErrRestoreInvalidRange, "ranges overlapped")
}
}
sortedRanges := rangeTree.GetSortedRanges()
return sortedRanges, nil
}
// RegionInfo includes a region and the leader of the region.
type RegionInfo struct {
Region *metapb.Region
Leader *metapb.Peer
}
// ContainsInterior returns whether the region contains the given key, and also
// that the key does not fall on the boundary (start key) of the region.
func (region *RegionInfo) ContainsInterior(key []byte) bool {
return bytes.Compare(key, region.Region.GetStartKey()) > 0 &&
(len(region.Region.GetEndKey()) == 0 ||
bytes.Compare(key, region.Region.GetEndKey()) < 0)
}
// RewriteRules contains rules for rewriting keys of tables.
type RewriteRules struct {
Table []*import_sstpb.RewriteRule
Data []*import_sstpb.RewriteRule
}
// Append append its argument to this rewrite rules.
func (r *RewriteRules) Append(other RewriteRules) {
r.Data = append(r.Data, other.Data...)
r.Table = append(r.Table, other.Table...)
}
// EmptyRewriteRule make a new, empty rewrite rule.
func EmptyRewriteRule() *RewriteRules {
return &RewriteRules{
Table: []*import_sstpb.RewriteRule{},
Data: []*import_sstpb.RewriteRule{},
}
}