89 lines
2.9 KiB
Go
89 lines
2.9 KiB
Go
package core
|
||
|
||
const minNLen = 16
|
||
|
||
// TransactionGroup 事务分组
|
||
type TransactionGroup struct {
|
||
N int //总共分了多少个组
|
||
Group [][][2]string //分组的结果
|
||
Rely map[string]int //存储依赖关系
|
||
}
|
||
|
||
// NewGroup 新建分组
|
||
func NewGroup() *TransactionGroup {
|
||
//每个元素都是一个包含两个字符串的数组切片
|
||
buf1 := make([][][2]string, minNLen)
|
||
buf2 := make(map[string]int)
|
||
return &TransactionGroup{
|
||
N: 1,
|
||
Group: buf1,
|
||
Rely: buf2,
|
||
}
|
||
}
|
||
|
||
// resizeGroup 对分组大小进行扩容
|
||
// 切片 g.Group 扩展为原始长度的两倍,并将原始切片的内容复制到新创建的切片中
|
||
func (g *TransactionGroup) resizeGroup() {
|
||
newBuf := make([][][2]string, g.N<<1)
|
||
copy(newBuf, g.Group[:])
|
||
g.Group = newBuf
|
||
|
||
}
|
||
|
||
func (g *TransactionGroup) GroupTransactionsByDeps(table [][2]string) {
|
||
for _, t := range table {
|
||
g.AddEdge(t[0], t[1])
|
||
}
|
||
}
|
||
|
||
// AddEdge 新加分组,t1、t2是存在依赖关系的两个事务
|
||
func (g *TransactionGroup) AddEdge(t1, t2 string) {
|
||
// 新元素入队之前,当队列长度等于缓存区长度时,缓存区长度重设为两个队列长度
|
||
if g.N >= len(g.Group)*8/10 {
|
||
g.resizeGroup()
|
||
}
|
||
//当事务t1和事务t2都没进行分组时,将t1和t2加入到一个新的分组中
|
||
if g.Rely[t1] == 0 && g.Rely[t2] == 0 {
|
||
g.Rely[t1], g.Rely[t2] = g.N, g.N
|
||
g.Group[g.N] = append(g.Group[g.N], [2]string{t1, t2})
|
||
g.N++
|
||
} else if g.Rely[t1] > 0 && g.Rely[t2] == 0 { //如果t1已经分组,但是t2还没分组,则将t2加入到t1分组
|
||
g.Rely[t2] = g.Rely[t1]
|
||
g.Group[g.Rely[t1]] = append(g.Group[g.Rely[t1]], [2]string{t1, t2})
|
||
} else if g.Rely[t1] == 0 && g.Rely[t2] > 0 { //如果t2已经分组,但是t1还没分组,则将t1加入到t2分组
|
||
g.Rely[t1] = g.Rely[t2]
|
||
g.Group[g.Rely[t2]] = append(g.Group[g.Rely[t2]], [2]string{t1, t2})
|
||
} else if g.Rely[t1] == g.Rely[t2] { //事务t1和t2都已经分组,并且分到了同一个组中
|
||
g.Group[g.Rely[t1]] = append(g.Group[g.Rely[t1]], [2]string{t1, t2})
|
||
} else { //事务t1和t2都已经分组,但是分到了不同的组中
|
||
//记录t2的分组
|
||
temp := g.Rely[t2]
|
||
//将t2组中的事务和t1组中的事务合并
|
||
g.Group[g.Rely[t1]] = append(g.Group[g.Rely[t1]], g.Group[g.Rely[t2]]...)
|
||
g.Group[g.Rely[t1]] = append(g.Group[g.Rely[t1]], [2]string{t1, t2})
|
||
//将t2的分组改为t1的分组
|
||
for _, txs := range g.Group[temp] {
|
||
for _, tx := range txs {
|
||
g.Rely[tx] = g.Rely[t1]
|
||
}
|
||
}
|
||
g.Group[temp] = nil
|
||
}
|
||
}
|
||
|
||
func DeepCopyGroup(group *TransactionGroup) *TransactionGroup {
|
||
buf := make([][][2]string, len(group.Group))
|
||
for i, arr := range group.Group {
|
||
buf[i] = make([][2]string, len(arr))
|
||
for j, subArr := range arr {
|
||
buf[i][j] = [2]string{subArr[0], subArr[1]}
|
||
}
|
||
}
|
||
copyMap := make(map[string]int)
|
||
for key, value := range group.Rely {
|
||
copyMap[key] = value
|
||
}
|
||
|
||
return &TransactionGroup{N: group.N, Group: buf, Rely: copyMap}
|
||
}
|