Commit 10829bb0 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 67547ab1
...@@ -223,11 +223,12 @@ func TestSetGet0(t *testing.T) { ...@@ -223,11 +223,12 @@ func TestSetGet0(t *testing.T) {
} }
func TestSetGet1(t *testing.T) { func TestSetGet1(t *testing.T) {
const N = 40000 //const N = 40000
//const N = 21 //const N = 21
//const N = 41 //const N = 41
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314159} { const N = 320
//for _, x := range []int{0x314159} { //for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314159} {
for _, x := range []int{0x314159} {
//for _, x := range []int{0} { //for _, x := range []int{0} {
r := TreeNew(cmp) r := TreeNew(cmp)
set := r.Set set := r.Set
...@@ -246,7 +247,7 @@ func TestSetGet1(t *testing.T) { ...@@ -246,7 +247,7 @@ func TestSetGet1(t *testing.T) {
for i, k := range a { for i, k := range a {
v, ok := r.Get(k) v, ok := r.Get(k)
if !ok { if !ok {
t.Fatal(i, k, v, ok) t.Fatal(i, k, v, ok) // XXX bug here
} }
if g, e := v.(int), k^x; g != e { if g, e := v.(int), k^x; g != e {
...@@ -272,7 +273,7 @@ func TestSetGet1(t *testing.T) { ...@@ -272,7 +273,7 @@ func TestSetGet1(t *testing.T) {
} }
if g, e := v.(int), k^x+42; g != e { if g, e := v.(int), k^x+42; g != e {
t.Fatal(i, g, e) // XXX bug here t.Fatal(i, g, e)
} }
k |= 1 k |= 1
......
...@@ -39,10 +39,10 @@ type btTpool struct{ sync.Pool } ...@@ -39,10 +39,10 @@ type btTpool struct{ sync.Pool }
func (p *btTpool) get(cmp Cmp) *Tree { func (p *btTpool) get(cmp Cmp) *Tree {
x := p.Get().(*Tree) x := p.Get().(*Tree)
x.cmp = cmp x.cmp = cmp
x.hitIdx = -1 //x.hitIdx = -1
x.hitPi = -1 //x.hitPi = -1
x.hitMinKMInf = true //x.hitMinKMInf = true
x.hitMaxKInf = true //x.hitMaxKInf = true
return x return x
} }
...@@ -104,15 +104,18 @@ type ( ...@@ -104,15 +104,18 @@ type (
// last data page which Set/Put/Delete/XXX recheck modified // last data page which Set/Put/Delete/XXX recheck modified
// XXX naming // XXX naming
hit *d hit *d
hitIdx int hitIdx int
hitP *x hitKmin xkey
hitPi int hitKmax xkey
hitMinK interface{} /*K*/ //hitP *x
hitMinKMInf bool // whether hitMinK = -∞ //hitPi int
hitMaxK interface{} /*K*/
hitMaxKInf bool // whether hitMaxK = +∞ //hitMinK interface{} /*K*/
//hitMinKMInf bool // whether hitMinK = -∞
//hitMaxK interface{} /*K*/
//hitMaxKInf bool // whether hitMaxK = +∞
} }
xe struct { // x element xe struct { // x element
...@@ -124,6 +127,16 @@ type ( ...@@ -124,6 +127,16 @@ type (
c int c int
x [2*kx + 2]xe x [2*kx + 2]xe
} }
xkey struct { // key + whether value is present
k interface {} /*K*/
kset bool // if not set - k not present
}
keyrange struct { // key range [kmin, kmax)
kmin xkey // if not set = -∞
kmax xkey // if not set = +∞
}
) )
var ( // R/O zero values var ( // R/O zero values
...@@ -150,6 +163,11 @@ func clr(q interface{}) { ...@@ -150,6 +163,11 @@ func clr(q interface{}) {
} }
} }
func (xk *xkey) set(k interface{} /*K*/) {
xk.k = k
xk.kset = true
}
// -------------------------------------------------------------------------- x // -------------------------------------------------------------------------- x
func newX(ch0 interface{}) *x { func newX(ch0 interface{}) *x {
...@@ -447,7 +465,7 @@ func (t *Tree) hitFind(k interface{} /*K*/) (i int, ok bool) { ...@@ -447,7 +465,7 @@ func (t *Tree) hitFind(k interface{} /*K*/) (i int, ok bool) {
// return -1, false // return -1, false
// } // }
if !(t.hitMaxKInf || t.cmp(k, t.hitMaxK) < 0) { if !(t.hitKmax.kset && t.cmp(k, t.hitKmax.k) < 0) {
return -1, false return -1, false
} }
...@@ -469,7 +487,7 @@ func (t *Tree) hitFind(k interface{} /*K*/) (i int, ok bool) { ...@@ -469,7 +487,7 @@ func (t *Tree) hitFind(k interface{} /*K*/) (i int, ok bool) {
// return -1, false // return -1, false
// } // }
if !(t.hitMinKMInf || t.cmp(k, t.hitMinK) >= 0) { if !(t.hitKmin.kset && t.cmp(k, t.hitKmin.k) >= 0) {
return -1, false return -1, false
} }
...@@ -548,7 +566,7 @@ func (t *Tree) Len() int { ...@@ -548,7 +566,7 @@ func (t *Tree) Len() int {
return t.c return t.c
} }
func (t *Tree) overflow(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} /*V*/) { func (t *Tree) overflow(p *x, q *d, pi, i int, hitKmaxPrev xkey, k interface{} /*K*/, v interface{} /*V*/) {
t.ver++ t.ver++
l, r := p.siblings(pi) l, r := p.siblings(pi)
...@@ -556,34 +574,45 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{ ...@@ -556,34 +574,45 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{
l.mvL(q, 1) l.mvL(q, 1)
t.insert(q, i-1, k, v) t.insert(q, i-1, k, v)
p.x[pi-1].k = q.d[0].k p.x[pi-1].k = q.d[0].k
t.hitP = p t.hitKmin.set(q.d[0].k)
t.hitPi = pi
t.checkHitP(q) //t.hitP = p // minK = q.d[0].k (= p.x[pi-1].k)
//t.hitPi = pi
//t.checkHitP(q)
return return
} }
if r != nil && r.c < 2*kd { if r != nil && r.c < 2*kd {
t.hitP = p //t.hitP = p
if i < 2*kd { if i < 2*kd {
q.mvR(r, 1) q.mvR(r, 1)
t.insert(q, i, k, v) t.insert(q, i, k, v)
p.x[pi].k = r.d[0].k p.x[pi].k = r.d[0].k
t.hitPi = pi t.hitKmax.set(r.d[0].k)
t.checkHitP(q) //t.hitPi = pi // maxK = r.d[0].k (= p.x[pi].k)
//t.checkHitP(q)
return return
} }
t.insert(r, 0, k, v) t.insert(r, 0, k, v)
p.x[pi].k = k p.x[pi].k = k
t.hitPi = pi + 1
t.checkHitP(r) t.hitKmin.set(k)
if p.x[t.hitPi].ch != r { kmax := hitKmaxPrev
panic(p.x) if pi + 1 < p.c { // means < ∞
kmax.set(p.x[pi+1].k)
} }
t.hitKmax = kmax
//t.hitPi = pi + 1
//t.checkHitP(r)
//if p.x[t.hitPi].ch != r {
// panic(p.x)
//}
return return
} }
t.split(p, q, pi, i, k, v) t.split(p, q, pi, i, hitKmaxPrev, k, v)
} }
// Seek returns an Enumerator positioned on an item such that k >= item's key. // Seek returns an Enumerator positioned on an item such that k >= item's key.
...@@ -641,13 +670,13 @@ func (t *Tree) SeekLast() (e *Enumerator, err error) { ...@@ -641,13 +670,13 @@ func (t *Tree) SeekLast() (e *Enumerator, err error) {
// Set sets the value associated with k. // Set sets the value associated with k.
func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) { func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
//dbg("--- PRE Set(%v, %v)\t(%v @%d, [%v/%v, %v/%v), %v @%d)\n%s", k, v, t.hit, t.hitIdx, t.hitMinKMInf, t.hitMinK, t.hitMaxKInf, t.hitMaxK, t.hitP, t.hitPi, t.dump()) dbg("--- PRE Set(%v, %v)\t(%v @%d, [%v, %v))\n%s", k, v, t.hit, t.hitIdx, t.hitKmin, t.hitKmax, t.dump())
//defer func() { defer func() {
// //if r := recover(); r != nil { //if r := recover(); r != nil {
// // panic(r) // panic(r)
// //} //}
// dbg("--- POST\n%s\n====\n", t.dump()) dbg("--- POST\n%s\n====\n", t.dump())
//}() }()
// check if we can do the update nearby previous change // check if we can do the update nearby previous change
i, ok := t.hitFind(k) i, ok := t.hitFind(k)
...@@ -691,10 +720,12 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) { ...@@ -691,10 +720,12 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
return return
} }
var minK, maxK interface{} /*K*/ // XXX max key limiting found hit range var hitKmin, hitKmax xkey // initially [-∞, +∞)
minKMInf, maxKInf := true, true // if there will be no limiting factors ... XXX var hitKmaxPrev xkey // hitKmax state @ prev iter
for { for {
hitKmaxPrev = hitKmax // XXX here? - recheck
i, ok = t.find(q, k) i, ok = t.find(q, k)
switch x := q.(type) { switch x := q.(type) {
case *x: case *x:
...@@ -710,54 +741,42 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) { ...@@ -710,54 +741,42 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
p = x p = x
q = p.x[pi].ch q = p.x[pi].ch
if pi > 0 { if pi > 0 { // XXX also check < p.c ?
minK = p.x[pi-1].k hitKmin.set(p.x[pi-1].k)
minKMInf = false
} }
if pi < p.c { if pi < p.c {
maxK = p.x[pi].k hitKmax.set(p.x[pi].k)
maxKInf = false
} }
if minK != nil && minKMInf { if !((hitKmin.k != nil) == hitKmin.kset) {
dbg("MINK WRONG", pi, minK) dbg("MINK WRONG", pi, hitKmin)
panic(minK) panic(0)
} }
if maxK != nil && maxKInf { if !((hitKmax.k != nil) == hitKmax.kset) {
dbg("MAXK WRONG", pi, maxK) dbg("MAXK WRONG", pi, hitKmax)
panic(maxK) panic(0)
} }
case *d: case *d:
// data page found - perform the update // data page found - perform the update
t.hitKmin = hitKmin
t.hitKmax = hitKmax
switch { switch {
case ok: case ok:
//dbg("ok") //dbg("ok")
x.d[i].v = v x.d[i].v = v
t.hit, t.hitIdx = x, i t.hit, t.hitIdx = x, i
t.hitP, t.hitPi = p, pi
t.hitMinK = minK
t.hitMinKMInf = minKMInf
t.hitMaxK = maxK
t.hitMaxKInf = maxKInf
case x.c < 2*kd: case x.c < 2*kd:
//dbg("insert") //dbg("insert")
t.insert(x, i, k, v) t.insert(x, i, k, v)
t.hitP, t.hitPi = p, pi
t.hitMinK = minK
t.hitMinKMInf = minKMInf
t.hitMaxK = maxK
t.hitMaxKInf = maxKInf
default: default:
//dbg("overflow") //dbg("overflow")
t.overflow(p, x, pi, i, k, v) // NOTE overflow will correct hit-range as needed
t.hitMinK = minK t.overflow(p, x, pi, i, hitKmaxPrev, k, v)
t.hitMinKMInf = minKMInf
t.hitMaxK = maxK
t.hitMaxKInf = maxKInf
} }
return return
...@@ -843,13 +862,15 @@ func (t *Tree) Put(k interface{} /*K*/, upd func(oldV interface{} /*V*/, exists ...@@ -843,13 +862,15 @@ func (t *Tree) Put(k interface{} /*K*/, upd func(oldV interface{} /*V*/, exists
case x.c < 2*kd: case x.c < 2*kd:
t.insert(x, i, k, newV) t.insert(x, i, k, newV)
default: default:
t.overflow(p, x, pi, i, k, newV) //t.overflow(p, x, pi, i, k, newV)
panic("TODO")
} }
return return
} }
} }
} }
/*
func (t *Tree) checkHitP(q *d) { func (t *Tree) checkHitP(q *d) {
p := t.hitP p := t.hitP
pi := t.hitPi pi := t.hitPi
...@@ -862,8 +883,9 @@ func (t *Tree) checkHitP(q *d) { ...@@ -862,8 +883,9 @@ func (t *Tree) checkHitP(q *d) {
panic(0) panic(0)
} }
} }
*/
func (t *Tree) split(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} /*V*/) { func (t *Tree) split(p *x, q *d, pi, i int, hitKmaxPrev xkey, k interface{} /*K*/, v interface{} /*V*/) {
t.ver++ t.ver++
r := btDPool.Get().(*d) r := btDPool.Get().(*d)
if q.n != nil { if q.n != nil {
...@@ -889,16 +911,24 @@ func (t *Tree) split(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} / ...@@ -889,16 +911,24 @@ func (t *Tree) split(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} /
pi = 0 pi = 0
t.r = p t.r = p
} }
t.hitP = p //t.hitP = p
if i > kd { if i > kd {
t.insert(r, i-kd, k, v) t.insert(r, i-kd, k, v)
t.hitPi = pi + 1 t.hitKmin.set(p.x[pi].k)
t.checkHitP(r) kmax := hitKmaxPrev
if pi + 1 < p.c {
kmax.set(p.x[pi+1].k)
}
t.hitKmax = kmax
//t.hitPi = pi + 1 // minK = p.x[pi].k; maxK = derive-up(p.x[pi+1].k)
//t.checkHitP(r)
} else { } else {
t.insert(q, i, k, v) t.insert(q, i, k, v)
t.hitPi = pi t.hitKmax.set(r.d[0].k)
t.checkHitP(q) //t.hitPi = pi // maxK = r.d[0].k (= p.x[pi].k XXX recheck)
//t.checkHitP(q)
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment