❷ 第二种方法的代码如下(以[]byte类型的key建立的树为例):_groutine_bskeyCsWrFunc是一个驻留协程,用于处理节点如何获取,顺序执行。
case d, ok := <-__global_bskeyCsWr_chan__:
if ok {
switch d.wr {
case P:
if d.cs != nil && d.spr != nil {
p, selfi := d.cs.bskeyParent(d.spr, d.f)
__global_bskeyCsWr_Pre_chan__ <- &keyPre{p, selfi}
continue
}
__global_bskeyCsWr_Pre_chan__ <- nil
case L:
if d.cs != nil && d.pa != nil && d.spr != nil {
__global_bskeyCsWr_LRIre_chan__ <- d.cs.bskeyLeft(d.pa, d.spr, d.f)
continue
}
__global_bskeyCsWr_LRIre_chan__ <- nil
case R:
if d.cs != nil && d.pa != nil && d.spr != nil {
__global_bskeyCsWr_LRIre_chan__ <- d.cs.bskeyRight(d.pa, d.spr, d.f)
continue
}
__global_bskeyCsWr_LRIre_chan__ <- nil
case I:
if d.cs != nil && d.ci >= CHUNKINDEXIGNORE && d.spr != nil {
__global_bskeyCsWr_LRIre_chan__ <- d.cs.bskeyI(d.ci, d.spr, d.f)
continue
}
__global_bskeyCsWr_LRIre_chan__ <- nil
}
}
func (cs *BsTr) bskeyParent(spr *SpireReturn, f *os.File) (*BsTr, int) {
var i int
pa := cs.chunk[PARENT]
flag := spr.flag
if pa == nil {//父节点为nil
var cse *BsTr
var uris []int
left := cs.chunk[LEFT]
if left != nil {//左兄弟不为nil,获取左兄弟节点到树根的索引路径(孩子节点在父节点的位置索引形成的路径)
if flag&Unique == Unique {
uris, cse = left.bskeyUpRouteIndexs(spr.sp)
} else {
uris, cse = left.bskeyUpRouteIndexsNotUnique(spr.sp)
}
//从左兄弟节点的关系中查找当前节点的父节点。(注意:左兄弟节点的父节点不一定是当前节点的父节点)
pa = cs.bskeyFindParentFromLeftInMem(cse, uris)
}
if pa == nil {
right := cs.chunk[RIGHT]
if right != nil {//右兄弟不为nil,获取右兄弟节点到树根的索引路径(孩子节点在父节点的位置索引形成的路径)
if flag&Unique == Unique {
uris, cse = right.bskeyUpRouteIndexs(spr.sp)
} else {
uris, cse = right.bskeyUpRouteIndexsNotUnique(spr.sp)
}
//从右兄弟节点的关系中查找当前节点的父节点。(注意:右兄弟节点的父节点不一定是当前节点的父节点)
pa = cs.bskeyFindParentFromRightInMem(cse, uris)
}
}
//将找到的父节点赋给当前节点的父索引位置
cs.chunk[PARENT] = pa
}
if cs.chunk[PARENT] == nil {//如果当前节点的父节点依然为nil,则从磁盘读入页面。
if cs.offs[PARENT] != -1 && f != nil {
cs.chunk[PARENT] = cs.getPage(cs.offs[PARENT], f)
}
}
//set positon of cs in parent
csp := cs.chunk[PARENT]
if csp != nil {//如果获取父节点成功,则获取当前节点在父节点的索引位置
if flag&Unique == Unique {
i = cs.bskeyChildIndexInParentWith(csp)
} else {
i = cs.bskeyChildIndexInParentNotUniqueWith(csp)
}
//说明当前节点是父节点的最大节点
if i == len(csp.chunk) {
i -= 1
}
if i > 0 {
//设置好父子关系
csp.chunk[i] = cs
}
}
return csp, i
}
//从左兄弟节点获取当前节点的父节点
//uris是左兄弟节点到树根的索引路径
func (cs *BsTr) bskeyFindParentFromLeftInMem(lee *BsTr, uris []int) *BsTr {
// must not exists this problem
// because all entry in Mem
// if cs.isEntry(){
// return nil
// }
pa := cs.chunk[PARENT]
le := cs.chunk[LEFT]
if pa == nil {
if len(uris) == 0 {
return nil
}
//try find parent from left
//沿着索引路径一层一层找
if le != nil {
lpa := le.chunk[PARENT]
if lpa != nil {
var i int
var otmpc *BsTr
tmpc := le
//先判断索引路径是否一直在最左
for ; i < len(uris); i++ {
if uris[i] < len(tmpc.chunk[PARENT].chunk)-1 {
break
}
tmpc = tmpc.chunk[PARENT]
}
//demonstrate all uris[i] = len(tmpc.chunk)-1, all is rightest.
if i == len(uris) || (tmpc == lee && lee.isEntry()) {
tmpc = tmpc.chunk[RIGHT]
if tmpc == nil {
return nil
}
i -= 1
if i < 0 {
return nil
}
} else {
if i == 0 {
cs.chunk[PARENT] = lpa
lpa.chunk[uris[i]+1] = cs
return lpa
}
otmpc = tmpc
tmpc = tmpc.chunk[PARENT].chunk[uris[i]+1]
if tmpc == nil {
i -= 1
if i < 0 {
return nil
}
tmpc = otmpc.chunk[RIGHT]
}
}
for k := 1; k < i; {
if tmpc == nil {
i -= 1
if i < 1 {
return nil
}
otmpc = otmpc.chunk[len(otmpc.chunk)-1]
tmpc = otmpc.chunk[RIGHT]
k = 1
continue
}
tmpc = tmpc.chunk[CHUNKINDEXIGNORE]
k++
}
if tmpc != nil {
cs.chunk[PARENT] = tmpc
if tmpc.chunk[CHUNKINDEXIGNORE] == nil {
if tmpc.offs[CHUNKINDEXIGNORE] != cs.offset {
panic("")
}
tmpc.chunk[CHUNKINDEXIGNORE] = cs
} else {
if tmpc.chunk[CHUNKINDEXIGNORE] != cs {
log.Println(tmpc.chunk[CHUNKINDEXIGNORE])
log.Println(cs)
}
}
}
return tmpc
}
}
}
return pa
}
//从右兄弟节点获取当前节点的父节点
//uris是右兄弟节点到树根的索引路径
func (cs *BsTr) bskeyFindParentFromRightInMem(ree *BsTr, uris []int) *BsTr {
pa := cs.chunk[PARENT]
ri := cs.chunk[RIGHT]
if pa == nil {
if len(uris) == 0 {
return nil
}
//try find parent from right
//沿着索引路径一层一层找
if ri != nil {
rpa := ri.chunk[PARENT]
if rpa != nil {
var i int
var otmpc *BsTr
tmpc := ri
//先判断索引路径是否一直在最右
for ; i < len(uris); i++ {
if uris[i] > CHUNKINDEXIGNORE {
break
}
tmpc = tmpc.chunk[PARENT]
}
if i == len(uris) || (tmpc == ree && ree.isEntry()) {
tmpc = tmpc.chunk[LEFT]
if tmpc == nil {
return nil
}
i -= 1
if i < 0 {
return nil
}
} else {
if i == 0 {
cs.chunk[PARENT] = rpa
rpa.chunk[uris[i]-1] = cs
return rpa
}
otmpc = tmpc
tmpc = tmpc.chunk[PARENT].chunk[uris[i]-1]
if tmpc == nil {
i -= 1
if i < 0 {
return nil
}
tmpc = otmpc.chunk[LEFT]
}
}
//i==0 and uris[0] > CHUNKINDEXIGNORE was processed
for k := 1; k < i; {
if tmpc == nil {
i -= 1
if i < 1 {
return nil
}
otmpc = otmpc.chunk[CHUNKINDEXIGNORE]
tmpc = otmpc.chunk[LEFT]
k = 1
continue
}
tmpc = tmpc.chunk[len(tmpc.chunk)-1]
k++
}
if tmpc != nil {
cs.chunk[PARENT] = tmpc
if tmpc.chunk[len(tmpc.chunk)-1] == nil {
if tmpc.offs[len(tmpc.chunk)-1] != cs.offset {
log.Println("")
}
tmpc.chunk[len(tmpc.chunk)-1] = cs
} else {
if tmpc.chunk[len(tmpc.chunk)-1] != cs {
log.Println(tmpc.chunk[len(tmpc.chunk)-1])
log.Println(cs)
}
}
}
return tmpc
}
}
}
return pa
}
//获取左兄弟节点
func (cs *BsTr) bskeyLeft(pa *BsTr, spr *SpireReturn, f *os.File) *BsTr {
left := cs.chunk[LEFT]
if left == nil {
//如果当前节点为入口,则直接返回nil
//因为所有的入口及其左右兄弟关系都已经载入内存
if cs.isEntry() {
return nil
}
flag := spr.flag
var cse *BsTr
var uris []int
//获取当前节点的索引路径,以及入口
if flag&Unique == Unique {
uris, cse = cs.bskeyUpRouteIndexs(spr.sp)
} else {
uris, cse = cs.bskeyUpRouteIndexsNotUnique(spr.sp)
}
//在索引路径中查找左兄弟节点
left = cs.bskeyFindLeftInMem(pa, cse, uris)
if left == nil {
leo := cs.offs[LEFT]
if leo != -1 && f != nil {
left = cs.getPage(leo, f)
if left == nil || left.IsEmptyFast() {
left = cs.getPage(leo, f)
log.Println("Error page.")
}
left.chunk[RIGHT] = cs
cs.chunk[LEFT] = left
//build left--parent relation
//but parent of left may be nil in Mem
//获取左兄弟节点的父节点,并设置父子关系
left.bskeyFindParentFromRightInMem(cse, uris)
}
}
}
return left
}
//在内存中获取左兄弟节点
func (cs *BsTr) bskeyFindLeftInMem(pa *BsTr, cse *BsTr, uris []int) *BsTr {
le := cs.chunk[LEFT]
if le == nil {
if len(uris) == 0 {
return nil
}
// if cs.isEntry() || pa.isSpire() {
// return nil
// }
var i int
var otmpc *BsTr
tmpc := cs
//判断当前节点的索引路径是否一直在左
//一直在左的话,左兄弟节点一定不是当前节点的亲兄弟
for i = 0; i < len(uris); i++ {
if uris[i] > CHUNKINDEXIGNORE { //find in route
break
}
tmpc = tmpc.chunk[PARENT]
}
//在索引路径一层一层查找
//如果i == len(uris) || (tmpc == cse && cse.isEntry()),说明已经到了入口,则可以立即获取左兄弟节点
//此处获取的非当前节点的左兄弟节点,而是非最左情况下的那个节点的左兄弟节点
if i == len(uris) || (tmpc == cse && cse.isEntry()) {
tmpc = tmpc.chunk[LEFT]
if tmpc == nil {
return nil
}
i -= 1
if i < 0 {
return nil
}
} else {
//说明当前节点的父节点就是左兄弟节点的父节点
if i == 0 {
le = pa.chunk[uris[i]-1]
if le != nil {
le.chunk[PARENT] = pa
cs.chunk[LEFT] = le
le.chunk[RIGHT] = cs
}
return le
}
otmpc = tmpc
tmpc = tmpc.chunk[PARENT].chunk[uris[i]-1]
if tmpc == nil {
i -= 1
if i < 0 {
return nil
}
tmpc = otmpc.chunk[LEFT]
}
}
//从索引路径中的第一个非最左节点开始,一层一层往下查找
for k := 1; k < i; {
if tmpc == nil {
i -= 1
if i < 1 {
return nil
}
otmpc = otmpc.chunk[CHUNKINDEXIGNORE]
tmpc = otmpc.chunk[LEFT]
k = 1
continue
}
tmpc = tmpc.chunk[len(tmpc.chunk)-1]
k++
}
if tmpc == nil {
return nil
}
le = tmpc.chunk[len(tmpc.chunk)-1]
if le != nil {
if tmpc.offs[len(tmpc.chunk)-1] != le.offset {
log.Println("")
}
le.chunk[PARENT] = tmpc
cs.chunk[LEFT] = le
le.chunk[RIGHT] = cs
}
return le
}
return le
}
//获取右兄弟节点
func (cs *BsTr) bskeyRight(pa *BsTr, spr *SpireReturn, f *os.File) *BsTr {
right := cs.chunk[RIGHT]
if right == nil {
if cs.isEntry() {
return nil
}
flag := spr.flag
var cse *BsTr
var uris []int
if flag&Unique == Unique {
uris, cse = cs.bskeyUpRouteIndexs(spr.sp)
} else {
uris, cse = cs.bskeyUpRouteIndexsNotUnique(spr.sp)
}
right = cs.bskeyFindRightInMem(pa, cse, uris)
if right == nil {
rio := cs.offs[RIGHT]
if rio != -1 && f != nil {
right = cs.getPage(rio, f)
if right == nil || right.IsEmptyFast() {
//return nil
right = cs.getPage(rio, f)
log.Println("Error page.")
}
right.chunk[LEFT] = cs
cs.chunk[RIGHT] = right
//build right--parent relation
//but parent of right may be nil in Mem
right.bskeyFindParentFromLeftInMem(cse, uris)
}
}
}
return right
}
//在内存中获取右兄弟节点
func (cs *BsTr) bskeyFindRightInMem(pa *BsTr, cse *BsTr, uris []int) *BsTr {
ri := cs.chunk[RIGHT]
if ri == nil {
if len(uris) == 0 {
return nil
}
var i int
var otmpc *BsTr
tmpc := cs
//找到第一个在索引路径中非最右的节点
for i = 0; i < len(uris); i++ {
if uris[i] < len(tmpc.chunk[PARENT].chunk)-1 { //find in route
break
}
tmpc = tmpc.chunk[PARENT]
}
if i == len(uris) || (tmpc == cse && cse.isEntry()) {
tmpc = tmpc.chunk[RIGHT]
if tmpc == nil {
return nil
}
i -= 1
if i < 0 {
return nil
}
} else {
if i == 0 {
ri = pa.chunk[uris[i]+1]
if ri != nil {
ri.chunk[PARENT] = pa
cs.chunk[RIGHT] = ri
ri.chunk[LEFT] = cs
}
return ri
}
otmpc = tmpc
tmpc = tmpc.chunk[PARENT].chunk[uris[i]+1]
if tmpc == nil {
i -= 1
if i < 0 {
return nil
}
tmpc = otmpc.chunk[RIGHT]
}
}
for k := 1; k < i; {
if tmpc == nil {
i -= 1
if i < 1 {
return nil
}
otmpc = otmpc.chunk[len(otmpc.chunk)-1]
tmpc = otmpc.chunk[RIGHT]
k = 1
continue
}
tmpc = tmpc.chunk[CHUNKINDEXIGNORE]
k++
}
if tmpc == nil {
return nil
}
ri = tmpc.chunk[CHUNKINDEXIGNORE]
if ri != nil {
if tmpc.offs[CHUNKINDEXIGNORE] != ri.offset {
log.Println("")
}
ri.chunk[PARENT] = tmpc
cs.chunk[RIGHT] = ri
ri.chunk[LEFT] = cs
}
return ri
}
return ri
}
//获取第i个孩子节点
func (cs *BsTr) bskeyI(i int, spr *SpireReturn, f *os.File) *BsTr {
if i > len(cs.chunk) {
return nil
}
//从左节点获取第i个孩子节点
ci := cs.bskeyFindIFromLeftInMem(i, spr)
if ci == nil {
//从左节点获取不成功,则从右节点获取第i个孩子节点
ci = cs.bskeyFindIFromRightInMem(i, spr)
}
if ci == nil {
//如果内存找不到,则从磁盘读取
ci = cs.HeavyI(i, f)
} else {
if ci.chunk[PARENT] == nil {
//找到了,并且父节点为nil的情况下,获取父节点,并设置好父子关系
var ni int
ci.chunk[PARENT], ni = ci.bskeyParent(spr, f)
if ni != i {
panic("")
}
ci.chunk[PARENT].chunk[i] = ci
}
}
return ci
}
//通过当前节点的右兄弟节点的关系查找第i个孩子节点
func (cs *BsTr) bskeyFindIFromRightInMem(i int, spr *SpireReturn) *BsTr {
ci := cs.chunk[i]
if ci == nil {
var cse *BsTr
var uris []int
if spr.flag&Unique == Unique {
uris, cse = cs.bskeyUpRouteIndexs(spr.sp)
} else {
uris, cse = cs.bskeyUpRouteIndexsNotUnique(spr.sp)
}
if i < len(cs.chunk)-1 { //不是最大孩子节点
if cs.chunk[i+1] != nil {//通过第i个孩子节点的右兄弟节点来获取
ci = cs.chunk[i+1].bskeyFindLeftInMem(cs, cse, append([]int{i + 1}, uris...))
}
} else {
cr := cs.bskeyFindRightInMem(cs.chunk[PARENT], cse, uris)
//通过当前节点的右兄弟节点来获取孩子节点,孩子节点只能是当前节点的最大节点
if cr != nil && cr.isNode() && (len(cr.chunk) > CHUNKINDEXIGNORE) && cr.chunk[CHUNKINDEXIGNORE] != nil {
cir := cr.chunk[CHUNKINDEXIGNORE]
if cir.chunk[LEFT] != nil {
ci = cir.chunk[LEFT]
}
}
}
if ci != nil && ci.chunk[PARENT] == nil {
cs.chunk[i] = ci
ci.chunk[PARENT] = cs
}
}
return ci
}
//通过当前节点的左兄弟节点的关系查找第i个孩子节点
func (cs *BsTr) bskeyFindIFromLeftInMem(i int, spr *SpireReturn) *BsTr {
ci := cs.chunk[i]
if ci == nil {
var cse *BsTr
var uris []int
if spr.flag&Unique == Unique {
uris, cse = cs.bskeyUpRouteIndexs(spr.sp)
} else {
uris, cse = cs.bskeyUpRouteIndexsNotUnique(spr.sp)
}
if i > CHUNKINDEXIGNORE {//不是最小孩子节点
if cs.chunk[i-1] != nil {//通过第i个孩子节点的左兄弟节点来获取
ci = cs.chunk[i-1].bskeyFindRightInMem(cs, cse, append([]int{i - 1}, uris...))
}
} else {
cl := cs.bskeyFindLeftInMem(cs.chunk[PARENT], cse, uris)
//通过当前节点的左兄弟节点来获取孩子节点,孩子节点只能是当前节点的最小节点
if cl != nil && cl.isNode() && (len(cl.chunk) > CHUNKINDEXIGNORE) && cl.chunk[len(cl.chunk)-1] != nil {
cil := cl.chunk[len(cl.chunk)-1]
if cil.chunk[RIGHT] != nil {
ci = cil.chunk[RIGHT]
}
}
}
if ci != nil && ci.chunk[PARENT] == nil {
cs.chunk[i] = ci
ci.chunk[PARENT] = cs
}
}
return ci
}