init
commit
298e51a680
@ -0,0 +1,8 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
|
||||||
|
<serverData>
|
||||||
|
<paths name="开发机">
|
||||||
|
<serverdata>
|
||||||
|
<mappings>
|
||||||
|
<mapping local="$PROJECT_DIR$" web="/" />
|
||||||
|
</mappings>
|
||||||
|
</serverdata>
|
||||||
|
</paths>
|
||||||
|
</serverData>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/gtid.iml" filepath="$PROJECT_DIR$/.idea/gtid.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,569 @@
|
|||||||
|
package gtid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Parse(gtidDesc string) (*Gtid, error) {
|
||||||
|
return parse(gtidDesc)
|
||||||
|
}
|
||||||
|
func parse(gtidDesc string) (*Gtid, error) {
|
||||||
|
var gtid Gtid
|
||||||
|
gtid.hashMap = make(map[string]int)
|
||||||
|
gtidDesc = strings.TrimSpace(gtidDesc)
|
||||||
|
if "" == gtidDesc {
|
||||||
|
return >id, nil
|
||||||
|
}
|
||||||
|
return >id, gtid.uniform(gtidDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) uniform(gtidDesc string) error {
|
||||||
|
hashMap := make(map[string][]string)
|
||||||
|
gtidlists := strings.Split(gtidDesc, ",")
|
||||||
|
uuidLists := make([]string, 0, len(gtidlists))
|
||||||
|
for _, v := range gtidlists {
|
||||||
|
if v == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
numbers := strings.Split(v, ":")
|
||||||
|
if len(numbers) < 2 {
|
||||||
|
return fmt.Errorf("invalid format:%v", v)
|
||||||
|
}
|
||||||
|
uuid, err := g.isValidUUID(numbers[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
numbers = numbers[1:]
|
||||||
|
existsNums, ok := hashMap[uuid]
|
||||||
|
if ok {
|
||||||
|
for _, v := range existsNums {
|
||||||
|
numbers = append(numbers, v)
|
||||||
|
}
|
||||||
|
hashMap[uuid] = numbers
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hashMap[uuid] = numbers
|
||||||
|
uuidLists = append(uuidLists, uuid)
|
||||||
|
}
|
||||||
|
sort.Strings(uuidLists)
|
||||||
|
g.uuidNumbers = make([]UUIDNumber, 0, len(uuidLists))
|
||||||
|
for k, v := range uuidLists {
|
||||||
|
number, err := g.uniformNumber(hashMap[v])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
number, err = g.uniformRange(number)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
g.mu.Lock()
|
||||||
|
g.hashMap[v] = k
|
||||||
|
g.mu.Unlock()
|
||||||
|
g.uuidNumbers = append(g.uuidNumbers, UUIDNumber{
|
||||||
|
uuid: v,
|
||||||
|
intervals: number,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) reform() {
|
||||||
|
sort.Sort(SortUUID(g.uuidNumbers))
|
||||||
|
g.hashMap = make(map[string]int, len(g.uuidNumbers))
|
||||||
|
for k, v := range g.uuidNumbers {
|
||||||
|
g.uuidNumbers[k].intervals, _ = g.uniformRange(v.intervals)
|
||||||
|
g.hashMap[v.uuid] = k
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) uniformRange(rg []uuidRange) ([]uuidRange, error) {
|
||||||
|
newRg := make([]uuidRange, 0, len(rg))
|
||||||
|
sort.Sort(SortRange(rg))
|
||||||
|
var last *uuidRange = nil
|
||||||
|
for _, v := range rg {
|
||||||
|
if last != nil && v.min <= last.max+1 {
|
||||||
|
if last.max <= v.max {
|
||||||
|
last.max = v.max
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newRg = append(newRg, v)
|
||||||
|
last = &newRg[len(newRg)-1]
|
||||||
|
}
|
||||||
|
return newRg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func subRange(origin, rg []uuidRange) []uuidRange {
|
||||||
|
newRg := make([]uuidRange, 0)
|
||||||
|
sort.Sort(SortRange(rg))
|
||||||
|
sort.Sort(SortRange(origin))
|
||||||
|
for i := 0; i < len(origin); i++ {
|
||||||
|
ori := origin[i]
|
||||||
|
res := make([]uuidRange, 0)
|
||||||
|
shouldAdd := true
|
||||||
|
for _, v := range rg {
|
||||||
|
if v.min <= ori.min && v.max >= ori.max {
|
||||||
|
shouldAdd = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.max < ori.min {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v.min > ori.max {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
ur1 := uuidRange{
|
||||||
|
min: ori.min,
|
||||||
|
max: v.min - 1,
|
||||||
|
}
|
||||||
|
ur2 := uuidRange{
|
||||||
|
min: v.max + 1,
|
||||||
|
max: ori.max,
|
||||||
|
}
|
||||||
|
if ur1.max >= ur1.min {
|
||||||
|
res = append(res, ur1)
|
||||||
|
}
|
||||||
|
if ur2.max >= ur2.min {
|
||||||
|
res = append(res, ur2)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if len(res) == 0 && shouldAdd {
|
||||||
|
res = append(res, ori)
|
||||||
|
}
|
||||||
|
newRg = append(newRg, res...)
|
||||||
|
}
|
||||||
|
return newRg
|
||||||
|
}
|
||||||
|
|
||||||
|
func containRange(origin, rg []uuidRange) bool {
|
||||||
|
sort.Sort(SortRange(rg))
|
||||||
|
sort.Sort(SortRange(origin))
|
||||||
|
for i := 0; i < len(rg); i++ {
|
||||||
|
ft := rg[i]
|
||||||
|
found := false
|
||||||
|
for _, v := range origin {
|
||||||
|
if v.min <= ft.min && v.max >= ft.max {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func overlapRange(origin, rg []uuidRange) bool {
|
||||||
|
sort.Sort(SortRange(rg))
|
||||||
|
sort.Sort(SortRange(origin))
|
||||||
|
for i := 0; i < len(origin); i++ {
|
||||||
|
ori := origin[i]
|
||||||
|
for _, v := range rg {
|
||||||
|
if v.min <= ori.min && v.max >= ori.max {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if v.max < ori.min {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v.min > ori.max {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
ur1 := uuidRange{
|
||||||
|
min: ori.min,
|
||||||
|
max: v.min - 1,
|
||||||
|
}
|
||||||
|
ur2 := uuidRange{
|
||||||
|
min: v.max + 1,
|
||||||
|
max: ori.max,
|
||||||
|
}
|
||||||
|
if ur1.max >= ur1.min {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ur2.max >= ur2.min {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) uniformNumber(num []string) ([]uuidRange, error) {
|
||||||
|
rg := make([]uuidRange, 0, len(num))
|
||||||
|
for _, v := range num {
|
||||||
|
ret := uuidRange{}
|
||||||
|
if splitPos := strings.Index(v, "-"); -1 != splitPos {
|
||||||
|
firstPart := string(v[0:splitPos])
|
||||||
|
if i64, err := strconv.ParseUint(firstPart, 10, 64); nil == err {
|
||||||
|
ret.min = i64
|
||||||
|
} else {
|
||||||
|
return rg, fmt.Errorf("invalid number %v", firstPart)
|
||||||
|
}
|
||||||
|
secondPart := string(v[splitPos+1:])
|
||||||
|
if i64, err := strconv.ParseUint(secondPart, 10, 64); nil == err {
|
||||||
|
ret.max = i64
|
||||||
|
} else {
|
||||||
|
return rg, fmt.Errorf("invalid number %v", secondPart)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if i64, err := strconv.ParseUint(v, 10, 64); nil == err {
|
||||||
|
ret.min = i64
|
||||||
|
ret.max = i64
|
||||||
|
} else {
|
||||||
|
return rg, fmt.Errorf("invalid number %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rg = append(rg, ret)
|
||||||
|
}
|
||||||
|
return rg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) isValidUUID(uuid string) (string, error) {
|
||||||
|
uuid = strings.TrimSpace(strings.ToLower(strings.Replace(uuid, "-", "", -1)))
|
||||||
|
if 32 != len(uuid) {
|
||||||
|
return "", errors.New("invalid uuid" + uuid)
|
||||||
|
}
|
||||||
|
return uuid[0:8] + "-" + uuid[8:12] + "-" + uuid[12:16] + "-" + uuid[16:20] + "-" + uuid[20:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) String() (ret string) {
|
||||||
|
|
||||||
|
if g.changed {
|
||||||
|
g.mu.Lock()
|
||||||
|
g.reform()
|
||||||
|
g.mu.Unlock()
|
||||||
|
g.changed = false
|
||||||
|
}
|
||||||
|
for _, uuidNumber := range g.uuidNumbers {
|
||||||
|
s := uuidNumber.uuid
|
||||||
|
for _, interval := range uuidNumber.intervals {
|
||||||
|
if interval.min == interval.max {
|
||||||
|
s = s + ":" + strconv.FormatUint(interval.min, 10)
|
||||||
|
} else {
|
||||||
|
s = s + ":" + strconv.FormatUint(interval.min, 10) + "-" + strconv.FormatUint(interval.max, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if "" != ret {
|
||||||
|
ret = ret + ","
|
||||||
|
}
|
||||||
|
ret = ret + s
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) AddGtid(uuid string, number uint64) error {
|
||||||
|
if strings.TrimSpace(uuid) == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
uuid, err := g.isValidUUID(uuid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
g.mu.RLock()
|
||||||
|
id, ok := g.hashMap[uuid]
|
||||||
|
g.mu.RUnlock()
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
if ok {
|
||||||
|
tmp := g.uuidNumbers[id].intervals
|
||||||
|
if len(tmp) > 0 && tmp[len(tmp)-1].max+1 == number {
|
||||||
|
g.uuidNumbers[id].intervals[len(tmp)-1].max = number
|
||||||
|
} else {
|
||||||
|
g.uuidNumbers[id].intervals = append(g.uuidNumbers[id].intervals, uuidRange{
|
||||||
|
min: number,
|
||||||
|
max: number,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.uuidNumbers = append(g.uuidNumbers, UUIDNumber{
|
||||||
|
uuid: uuid,
|
||||||
|
intervals: []uuidRange{uuidRange{
|
||||||
|
min: number,
|
||||||
|
max: number,
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
g.hashMap[uuid] = len(g.uuidNumbers) - 1
|
||||||
|
}
|
||||||
|
if len(g.uuidNumbers[id].intervals) > 5000 {
|
||||||
|
g.reform()
|
||||||
|
}
|
||||||
|
g.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (g *Gtid) Add(gtidDesc string) error {
|
||||||
|
return g.add(gtidDesc)
|
||||||
|
}
|
||||||
|
func (g *Gtid) add(gtidDesc string) error {
|
||||||
|
tmpSlice := make([]UUIDNumber, 0)
|
||||||
|
gtidlists := strings.Split(gtidDesc, ",")
|
||||||
|
for _, v := range gtidlists {
|
||||||
|
numbers := strings.Split(v, ":")
|
||||||
|
if len(numbers) < 2 {
|
||||||
|
return fmt.Errorf("invalid format:%v", v)
|
||||||
|
}
|
||||||
|
uuid, err := g.isValidUUID(numbers[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
num, err := g.uniformNumber(numbers[1:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tmpSlice = append(tmpSlice, UUIDNumber{
|
||||||
|
uuid: uuid,
|
||||||
|
intervals: num,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
g.changed = true
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
for _, v := range tmpSlice {
|
||||||
|
id, ok := g.hashMap[v.uuid]
|
||||||
|
if ok {
|
||||||
|
n := g.uuidNumbers[id].intervals
|
||||||
|
n = append(n, v.intervals...)
|
||||||
|
g.uuidNumbers[id].intervals = n
|
||||||
|
} else {
|
||||||
|
g.uuidNumbers = append(g.uuidNumbers, v)
|
||||||
|
g.hashMap[v.uuid] = len(g.uuidNumbers) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(g.uuidNumbers[id].intervals) > 5000 {
|
||||||
|
g.reform()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (g *Gtid) Sub(gtidDesc string) error {
|
||||||
|
return g.sub(gtidDesc)
|
||||||
|
}
|
||||||
|
func (g *Gtid) sub(gtidDesc string) error {
|
||||||
|
if strings.TrimSpace(gtidDesc) == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
tmpSlice := make([]UUIDNumber, 0)
|
||||||
|
gtidlists := strings.Split(gtidDesc, ",")
|
||||||
|
for _, v := range gtidlists {
|
||||||
|
numbers := strings.Split(v, ":")
|
||||||
|
if len(numbers) < 2 {
|
||||||
|
return fmt.Errorf("invalid format:%v", v)
|
||||||
|
}
|
||||||
|
uuid, err := g.isValidUUID(numbers[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
num, err := g.uniformNumber(numbers[1:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tmpSlice = append(tmpSlice, UUIDNumber{
|
||||||
|
uuid: uuid,
|
||||||
|
intervals: num,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
g.changed = true
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
for _, v := range tmpSlice {
|
||||||
|
id, ok := g.hashMap[v.uuid]
|
||||||
|
if ok {
|
||||||
|
n := subRange(g.uuidNumbers[id].intervals, v.intervals)
|
||||||
|
n, _ = g.uniformRange(n)
|
||||||
|
if len(n) == 0 || (len(n) == 1 && n[0].max == 0) {
|
||||||
|
delete(g.hashMap, v.uuid)
|
||||||
|
g.uuidNumbers = append(g.uuidNumbers[:id], g.uuidNumbers[id+1:]...)
|
||||||
|
for k, v := range g.uuidNumbers {
|
||||||
|
g.hashMap[v.uuid] = k
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
g.uuidNumbers[id].intervals = n
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(g.uuidNumbers[id].intervals) > 5000 {
|
||||||
|
g.reform()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) ContainGtid(uuid string, number uint64) (bool, error) {
|
||||||
|
if strings.TrimSpace(uuid) == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
uuid, err := g.isValidUUID(uuid)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
id, ok := g.hashMap[uuid]
|
||||||
|
if ok {
|
||||||
|
if g.changed {
|
||||||
|
g.reform()
|
||||||
|
}
|
||||||
|
for _, v := range g.uuidNumbers[id].intervals {
|
||||||
|
if v.min <= number && v.max >= number {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) Contain(gtidDesc string) (bool, error) {
|
||||||
|
return g.contain(gtidDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) contain(gtidDesc string) (bool, error) {
|
||||||
|
if strings.TrimSpace(gtidDesc) == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
tmpSlice := make([]UUIDNumber, 0)
|
||||||
|
gtidlists := strings.Split(gtidDesc, ",")
|
||||||
|
for _, v := range gtidlists {
|
||||||
|
numbers := strings.Split(v, ":")
|
||||||
|
if len(numbers) < 2 {
|
||||||
|
return false, fmt.Errorf("invalid format:%v", v)
|
||||||
|
}
|
||||||
|
uuid, err := g.isValidUUID(numbers[0])
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
num, err := g.uniformNumber(numbers[1:])
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
tmpSlice = append(tmpSlice, UUIDNumber{
|
||||||
|
uuid: uuid,
|
||||||
|
intervals: num,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
for _, v := range tmpSlice {
|
||||||
|
id, ok := g.hashMap[v.uuid]
|
||||||
|
if ok {
|
||||||
|
if !containRange(g.uuidNumbers[id].intervals, v.intervals) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
func (g *Gtid) Overlap(gtidDesc string) (bool, error) {
|
||||||
|
return g.overlap(gtidDesc)
|
||||||
|
}
|
||||||
|
func (g *Gtid) overlap(gtidDesc string) (bool, error) {
|
||||||
|
if strings.TrimSpace(gtidDesc) == "" {
|
||||||
|
if g.String() == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
tmpSlice := make([]UUIDNumber, 0)
|
||||||
|
gtidlists := strings.Split(gtidDesc, ",")
|
||||||
|
for _, v := range gtidlists {
|
||||||
|
numbers := strings.Split(v, ":")
|
||||||
|
if len(numbers) < 2 {
|
||||||
|
return false, fmt.Errorf("invalid format:%v", v)
|
||||||
|
}
|
||||||
|
uuid, err := g.isValidUUID(numbers[0])
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
num, err := g.uniformNumber(numbers[1:])
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
tmpSlice = append(tmpSlice, UUIDNumber{
|
||||||
|
uuid: uuid,
|
||||||
|
intervals: num,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
for _, v := range tmpSlice {
|
||||||
|
id, ok := g.hashMap[v.uuid]
|
||||||
|
if ok {
|
||||||
|
if overlapRange(g.uuidNumbers[id].intervals, v.intervals) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) Equal(gtidDesc string) (bool, error) {
|
||||||
|
if g.String() == "" && strings.TrimSpace(gtidDesc) == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
equ, err := parse(gtidDesc)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return g.String() == equ.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) Clone() *Gtid {
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
var newGtid = &Gtid{}
|
||||||
|
newGtid.uuidNumbers = make([]UUIDNumber, len(g.uuidNumbers))
|
||||||
|
copy(newGtid.uuidNumbers, g.uuidNumbers)
|
||||||
|
newGtid.hashMap = make(map[string]int, len(g.hashMap))
|
||||||
|
for k, v := range g.hashMap {
|
||||||
|
newGtid.hashMap[k] = v
|
||||||
|
}
|
||||||
|
if g.changed {
|
||||||
|
newGtid.reform()
|
||||||
|
}
|
||||||
|
return newGtid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) EventCount() uint64 {
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
if g.changed {
|
||||||
|
g.reform()
|
||||||
|
}
|
||||||
|
var ret uint64 = 0
|
||||||
|
for _, uuidNumber := range g.uuidNumbers {
|
||||||
|
for _, interval := range uuidNumber.intervals {
|
||||||
|
ret += interval.max - interval.min + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gtid) EventList() []string {
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
if g.changed {
|
||||||
|
g.reform()
|
||||||
|
}
|
||||||
|
eventList := []string{}
|
||||||
|
for _, uuidNumber := range g.uuidNumbers {
|
||||||
|
for _, interval := range uuidNumber.intervals {
|
||||||
|
for i := interval.min; i <= interval.max; i++ {
|
||||||
|
eventList = append(eventList, fmt.Sprintf("%s:%d", uuidNumber.uuid, i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eventList
|
||||||
|
}
|
@ -0,0 +1,424 @@
|
|||||||
|
package gtid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGtidEqual(t *testing.T) {
|
||||||
|
equal, err := Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-30")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-30")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if !equal {
|
||||||
|
t.Fatalf("unexpected error should equal!")
|
||||||
|
}
|
||||||
|
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-13")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-13",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-123",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-123",
|
||||||
|
)
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-13",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-123",
|
||||||
|
)
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-123",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-13",
|
||||||
|
)
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-123",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,14b12195-39b4-11eb-b3a9-005056bf03d8:1-20",
|
||||||
|
)
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,14b12195-39b4-11eb-b3a9-005056bf03d8:1-20",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-123",
|
||||||
|
)
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if equal {
|
||||||
|
t.Fatalf("unexpected error should not equal!")
|
||||||
|
}
|
||||||
|
equal, err = Equal(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,14b12195-39b4-11eb-b3a9-005056bf03d8:1-10,14b12195-39b4-11eb-b3a9-005056bf03d8:11-15,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-123,14b12195-39b4-11eb-b3a9-005056bf03d8:16-20",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-123,14b12195-39b4-11eb-b3a9-005056bf03d8:1-20",
|
||||||
|
)
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if !equal {
|
||||||
|
t.Fatalf("unexpected error should equal!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGtidAdd(t *testing.T) {
|
||||||
|
gtid, err := Add(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:5-10,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:7",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-4,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5:7" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestGtidAdd2(t *testing.T) {
|
||||||
|
gtid, err := Parse(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:5-10,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:7")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
gtid.Add("ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-4,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5")
|
||||||
|
if gtid.String() != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5:7" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestGtid_AddGtid(t *testing.T) {
|
||||||
|
src := `14b12195-39b4-11eb-b3a9-005056bf03d8:1-16`
|
||||||
|
gtid, err := Parse(src)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = gtid.Add(`14b12195-39b4-11eb-b3a9-005056bf03d8:1-17`)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
gtid.Add(`14b12195-39b4-11eb-b3a9-005056bf03d8:19-20`)
|
||||||
|
fmt.Println(gtid.String())
|
||||||
|
if gtid.String() != `14b12195-39b4-11eb-b3a9-005056bf03d8:1-17:19-20` {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGtid_SubGtid(t *testing.T) {
|
||||||
|
src := `14b12195-39b4-11eb-b3a9-005056bf03d8:1-16`
|
||||||
|
gtid, err := Parse(src)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = gtid.sub(`14b12195-39b4-11eb-b3a9-005056bf03d8:1-12`)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
//gtid.Add(`14b12195-39b4-11eb-b3a9-005056bf03d8:19-20`)
|
||||||
|
fmt.Println(gtid.String())
|
||||||
|
if gtid.String() != `14b12195-39b4-11eb-b3a9-005056bf03d8:13-16` {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_1(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:20-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:11-12")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:20-30" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_2(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:20-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:15-40")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_3(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:20-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:15-25")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:26-30" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_4(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:20-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:15-30")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_5(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:20-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:2-29")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1:30" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_6(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:20-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-30")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_7(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10:20-30",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:5-6:25")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-4:7-10:20-24:26-30" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_8(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:20-30, ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-7, ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-9:25, ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:6")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:10:20-24:26-30,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5:7" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub_empty(t *testing.T) {
|
||||||
|
gtid, err := Sub(
|
||||||
|
"",
|
||||||
|
"")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if gtid != "" {
|
||||||
|
t.Fatalf("wrong gtid %v", gtid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Benchmark_SUB8(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Sub(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:20-30, ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-7, ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-9:25, ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:6")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Benchmark_SUB82(b *testing.B) {
|
||||||
|
p, _ := parse("ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:20-30, ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-7, ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10")
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
c := *p
|
||||||
|
c.Sub("ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-9:25, ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:6")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContain_pass(t *testing.T) {
|
||||||
|
contain, err := Contain(
|
||||||
|
"ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-7,ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-10",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-4,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if !contain {
|
||||||
|
t.Fatalf("contain should == true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContain_not_pass(t *testing.T) {
|
||||||
|
contain, err := Contain(
|
||||||
|
"ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-7,ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:2-10",
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:1-4,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if contain {
|
||||||
|
t.Fatalf("contain should == false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContain_null(t *testing.T) {
|
||||||
|
contain, err := Contain(
|
||||||
|
"",
|
||||||
|
"")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if !contain {
|
||||||
|
t.Fatalf("contain should == true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGtidOverlap_true(t *testing.T) {
|
||||||
|
ret, err := Overlap(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:10:20-24:26-30,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5:7",
|
||||||
|
"ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:4")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if !ret {
|
||||||
|
t.Fatalf("expect true, but got false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGtidOverlap_false(t *testing.T) {
|
||||||
|
ret, err := Overlap(
|
||||||
|
"ca8035ea-c5d5-11e3-8ce9-e66ccf50db66:10:20-24:26-30,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5:7",
|
||||||
|
"ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:9")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if ret {
|
||||||
|
t.Fatalf("expect false, but got true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGtidOverlap_false2(t *testing.T) {
|
||||||
|
ret, err := Overlap(
|
||||||
|
"ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-5:7",
|
||||||
|
"ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-12")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
if !ret {
|
||||||
|
t.Fatalf("expect true, but got false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGtid(t *testing.T) {
|
||||||
|
ret, err := Parse("")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
for i := 0; i < 1000000; i++ {
|
||||||
|
err := ret.AddGtid("ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb", uint64(i+1))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(ret.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGtid2(t *testing.T) {
|
||||||
|
ret, err := Parse("")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
str := ret.String()
|
||||||
|
for i := 0; i < 10000000; i++ {
|
||||||
|
gtid := "ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:" + strconv.Itoa(i+1)
|
||||||
|
str, err = Add(str, gtid)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGtid_Contain(t *testing.T) {
|
||||||
|
ret, err := Parse("ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:1-99999,ff92c4da-c5d7-11e3-8cf7-5e10e6a05cf2:1-7867")
|
||||||
|
if nil != err {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
str := ret.String()
|
||||||
|
for i := 0; i < 10000000; i++ {
|
||||||
|
//gtid := "ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb:" + strconv.Itoa(i+1)
|
||||||
|
_, err = ret.ContainGtid("ff92c4da-c5d7-11e3-8cf7-5e10e6a05cfb", uint64(i+1)) //ret.Contain(gtid)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(str == ret.String())
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package gtid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Add(gtidDesc0, gtidDesc1 string) (string, error) {
|
||||||
|
gtid, err := Parse(gtidDesc0 + "," + gtidDesc1)
|
||||||
|
if nil != err {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return gtid.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sub(gtidDesc0, gtidDesc1 string) (string, error) {
|
||||||
|
if strings.TrimSpace(gtidDesc0) == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
gtid, err := parse(gtidDesc0)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(gtidDesc1) == "" {
|
||||||
|
return gtid.String(), nil
|
||||||
|
}
|
||||||
|
err = gtid.sub(gtidDesc1)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return gtid.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Contain(gtidDesc0, gtidDesc1 string) (bool, error) {
|
||||||
|
if strings.TrimSpace(gtidDesc0) == "" {
|
||||||
|
if strings.TrimSpace(gtidDesc1) == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
gtid, err := parse(gtidDesc0)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return gtid.Contain(gtidDesc1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Overlap(gtidDesc0, gtidDesc1 string) (bool, error) {
|
||||||
|
if strings.TrimSpace(gtidDesc0) == "" {
|
||||||
|
if strings.TrimSpace(gtidDesc1) == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
gtid, err := parse(gtidDesc0)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return gtid.Overlap(gtidDesc1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Equal(gtidDesc0, gtidDesc1 string) (bool, error) {
|
||||||
|
if strings.TrimSpace(gtidDesc0) == "" {
|
||||||
|
if strings.TrimSpace(gtidDesc1) == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
gtid, err := parse(gtidDesc0)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return gtid.Equal(gtidDesc1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EventCount(gtidDesc string) (uint64, error) {
|
||||||
|
gtid, err := Parse(gtidDesc)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return gtid.EventCount(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EventList(gtidDesc string) ([]string, error) {
|
||||||
|
gtid, err := Parse(gtidDesc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return gtid.EventList(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uniform(gtidDesc string) (string, error) {
|
||||||
|
gtid, err := Parse(gtidDesc)
|
||||||
|
if err != nil {
|
||||||
|
return gtidDesc, err
|
||||||
|
}
|
||||||
|
return gtid.String(), nil
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package gtid
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type Gtid struct {
|
||||||
|
uuidNumbers []UUIDNumber
|
||||||
|
hashMap map[string]int
|
||||||
|
changed bool
|
||||||
|
mu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type UUIDNumber struct {
|
||||||
|
uuid string
|
||||||
|
intervals []uuidRange
|
||||||
|
}
|
||||||
|
|
||||||
|
type uuidRange struct {
|
||||||
|
min uint64
|
||||||
|
max uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type SortUUID []UUIDNumber
|
||||||
|
|
||||||
|
func (s SortUUID) Len() int { return len(s) }
|
||||||
|
func (s SortUUID) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
func (s SortUUID) Less(i, j int) bool { return s[i].uuid < s[j].uuid }
|
||||||
|
|
||||||
|
|
||||||
|
type SortRange []uuidRange
|
||||||
|
|
||||||
|
func (s SortRange) Len() int { return len(s) }
|
||||||
|
func (s SortRange) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
func (s SortRange) Less(i, j int) bool { return s[i].min < s[j].min }
|
Loading…
Reference in New Issue