Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
fe0f712e
Commit
fe0f712e
authored
Apr 18, 2017
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
X storage/fs1/fsb: regenerate @x/bulkload
parent
91340c7a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
534 additions
and
165 deletions
+534
-165
t/neo/storage/fs1/fsb/fsbtree.go
t/neo/storage/fs1/fsb/fsbtree.go
+533
-164
t/neo/storage/fs1/fsb/fsbtree_util.go
t/neo/storage/fs1/fsb/fsbtree_util.go
+1
-1
No files found.
t/neo/storage/fs1/fsb/fsbtree.go
View file @
fe0f712e
// DO NOT EDIT - AUTOGENERATED (by gen-fsbtree from github.com/cznic/b
aaaa43c
)
// DO NOT EDIT - AUTOGENERATED (by gen-fsbtree from github.com/cznic/b
4efd872
)
// KEY=zodb.Oid VALUE=int64
// ---- 8< ----
...
...
@@ -19,6 +19,8 @@ import (
const
(
kx
=
32
//TODO benchmark tune this number if using custom key/value type(s).
kd
=
32
//TODO benchmark tune this number if using custom key/value type(s).
//kx = 2
//kd = 2
)
func
init
()
{
...
...
@@ -42,6 +44,8 @@ type btTpool struct{ sync.Pool }
func
(
p
*
btTpool
)
get
()
*
Tree
{
x
:=
p
.
Get
()
.
(
*
Tree
)
x
.
hitDi
=
-
1
x
.
hitPi
=
-
1
return
x
}
...
...
@@ -99,6 +103,22 @@ type (
last
*
d
r
interface
{}
ver
int64
// information about last data page which Set/Put/Delete accessed
hitD
*
d
// data page & pos of last write access
hitDi
int
hitP
*
x
// parent & pos for data page (= nil/-1 if no parent)
hitPi
int
hitKmin
zodb
.
Oid
// hitD allowed key range is [hitKmin, hitKmax)
hitKmax
zodb
.
Oid
hitPKmin
zodb
.
Oid
// ----//--- for hitP
hitPKmax
zodb
.
Oid
hitKminSet
bool
// whether corresponding hitK* value is set
hitKmaxSet
bool
// if value is not set it is treated as ±∞ depending on context
hitPKminSet
bool
hitPKmaxSet
bool
}
xe
struct
{
// x element
...
...
@@ -136,6 +156,11 @@ func clr(q interface{}) {
}
}
func
(
t
*
Tree
)
setHitKmin
(
k
zodb
.
Oid
)
{
t
.
hitKmin
=
k
;
t
.
hitKminSet
=
true
}
func
(
t
*
Tree
)
setHitKmax
(
k
zodb
.
Oid
)
{
t
.
hitKmax
=
k
;
t
.
hitKmaxSet
=
true
}
func
(
t
*
Tree
)
setHitPKmin
(
k
zodb
.
Oid
)
{
t
.
hitPKmin
=
k
;
t
.
hitPKminSet
=
true
}
func
(
t
*
Tree
)
setHitPKmax
(
k
zodb
.
Oid
)
{
t
.
hitPKmax
=
k
;
t
.
hitPKmaxSet
=
true
}
// -------------------------------------------------------------------------- x
func
newX
(
ch0
interface
{})
*
x
{
...
...
@@ -212,6 +237,9 @@ func (t *Tree) Clear() {
clr
(
t
.
r
)
t
.
c
,
t
.
first
,
t
.
last
,
t
.
r
=
0
,
nil
,
nil
,
nil
t
.
hitD
,
t
.
hitDi
,
t
.
hitP
,
t
.
hitPi
=
nil
,
-
1
,
nil
,
-
1
t
.
hitKmin
,
t
.
hitKmax
,
t
.
hitPKmin
,
t
.
hitPKmax
=
zk
,
zk
,
zk
,
zk
t
.
hitKminSet
,
t
.
hitKmaxSet
,
t
.
hitPKminSet
,
t
.
hitPKmaxSet
=
false
,
false
,
false
,
false
t
.
ver
++
}
...
...
@@ -286,6 +314,63 @@ func (t *Tree) catX(p, q, r *x, pi int) {
// Delete removes the k's KV pair, if it exists, in which case Delete returns
// true.
func
(
t
*
Tree
)
Delete
(
k
zodb
.
Oid
)
(
ok
bool
)
{
//dbg("--- PRE Delete(%v)\t; %v @%d, [%v, %v) pk: [%v, %v)\n%s", k, t.hitD, t.hitDi, t.hitKmin, t.hitKmax, t.hitPKmin, t.hitPKmax, t.dump())
//defer t.checkHit(k, opDel)
//defer func() {
// dbg("--- POST\n%s\n====\n", t.dump())
//}()
// check if we can do the delete nearby previous change
i
,
ok
:=
t
.
hitFind
(
k
)
if
i
>=
0
{
dd
:=
t
.
hitD
switch
{
case
!
ok
:
// tried to delete last or element past max k in hitD
// see also "extract rule" below
if
i
>=
dd
.
c
{
i
--
}
t
.
hitDi
=
i
return
false
case
dd
.
c
>
kd
:
t
.
extract
(
dd
,
i
)
// extract rule for t.hitDi
if
t
.
hitDi
>=
dd
.
c
{
t
.
hitDi
--
}
return
true
// here: need to extract / underflow but we have to check: if underflowing
// would cause upper level underflow (underflowX) -> we cannot extract /
// underflow here - need to do the usual scan from root to underflow index pages.
default
:
p
,
pi
:=
t
.
hitP
,
t
.
hitPi
if
p
!=
nil
&&
p
.
c
<
kx
&&
p
!=
t
.
r
{
break
}
t
.
extract
(
dd
,
i
)
if
p
!=
nil
{
// NOTE underflow corrects hit D,Di, P,Pi, Kmin, Kmax as needed
t
.
underflow
(
p
,
dd
,
pi
)
}
else
if
t
.
c
==
0
{
t
.
Clear
()
}
// extract rule for t.hitDi
if
t
.
hitD
!=
nil
&&
t
.
hitDi
>=
t
.
hitD
.
c
{
t
.
hitDi
--
}
return
true
}
}
// data page not quickly found - search and descent from root
pi
:=
-
1
var
p
*
x
q
:=
t
.
r
...
...
@@ -293,45 +378,72 @@ func (t *Tree) Delete(k zodb.Oid) (ok bool) {
return
false
}
t
.
hitKminSet
,
t
.
hitKmaxSet
=
false
,
false
// initially [-∞, +∞)
t
.
hitPKminSet
,
t
.
hitPKmaxSet
=
false
,
false
for
{
var
i
int
i
,
ok
=
t
.
find
(
q
,
k
)
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
<
kx
&&
q
!=
t
.
r
{
x
,
i
=
t
.
underflowX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
p
=
x
q
=
x
.
x
[
pi
]
.
ch
ok
=
false
continue
case
*
d
:
t
.
extract
(
x
,
i
)
if
x
.
c
>=
kd
{
return
true
switch
x
:=
q
.
(
type
)
{
case
*
x
:
i
,
ok
:=
t
.
findX
(
x
,
k
)
if
ok
{
i
++
}
if
x
.
c
<
kx
&&
q
!=
t
.
r
{
// NOTE underflowX corrects hit Kmin and Kmax as needed
x
,
i
=
t
.
underflowX
(
p
,
x
,
pi
,
i
)
}
t
.
hitPKmin
=
t
.
hitKmin
t
.
hitPKmax
=
t
.
hitKmax
t
.
hitPKminSet
=
t
.
hitKminSet
t
.
hitPKmaxSet
=
t
.
hitKmaxSet
p
=
x
pi
=
i
q
=
x
.
x
[
pi
]
.
ch
if
pi
>
0
{
// k=-∞ @-1
t
.
setHitKmin
(
p
.
x
[
pi
-
1
]
.
k
)
}
if
pi
<
p
.
c
{
// k=+∞ @p.c
t
.
setHitKmax
(
p
.
x
[
pi
]
.
k
)
}
case
*
d
:
i
,
ok
:=
t
.
find
(
x
,
k
)
// data page found - perform the delete
t
.
hitP
=
p
t
.
hitPi
=
pi
if
!
ok
{
t
.
hitD
=
x
if
i
>=
x
.
c
{
// tried to delete last or element past max k in hitD
i
--
}
t
.
hitDi
=
i
return
false
}
t
.
extract
(
x
,
i
)
if
x
.
c
<
kd
{
if
q
!=
t
.
r
{
// NOTE underflow corrects hit D,Di, P,Pi, Kmin, Kmax as needed
t
.
underflow
(
p
,
x
,
pi
)
}
else
if
t
.
c
==
0
{
t
.
Clear
()
}
return
true
}
}
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
<
kx
&&
q
!=
t
.
r
{
x
,
i
=
t
.
underflowX
(
p
,
x
,
pi
,
i
)
// extract rule for t.hitDi
if
t
.
hitD
!=
nil
&&
t
.
hitDi
>=
t
.
hitD
.
c
{
t
.
hitDi
--
}
pi
=
i
p
=
x
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
return
false
return
true
}
}
}
...
...
@@ -345,45 +457,104 @@ func (t *Tree) extract(q *d, i int) { // (r int64) {
}
q
.
d
[
q
.
c
]
=
zde
// GC
t
.
c
--
t
.
hitD
=
q
// NOTE extract users - in the end - must decrement t.hitDi if t.hitDi == t.hitD.c
// we are not doing it right here because unaltered position is
// required in case merging a right sibling data page will be needed.
t
.
hitDi
=
i
return
}
func
(
t
*
Tree
)
find
(
q
interface
{},
k
zodb
.
Oid
)
(
i
int
,
ok
bool
)
{
var
mk
zodb
.
Oid
func
(
t
*
Tree
)
findX
(
x
*
x
,
k
zodb
.
Oid
)
(
i
int
,
ok
bool
)
{
l
:=
0
switch
x
:=
q
.
(
type
)
{
case
*
x
:
h
:=
x
.
c
-
1
for
l
<=
h
{
m
:=
(
l
+
h
)
>>
1
mk
=
x
.
x
[
m
]
.
k
switch
cmp
:=
oidCmp
(
k
,
mk
);
{
case
cmp
>
0
:
l
=
m
+
1
case
cmp
==
0
:
return
m
,
true
default
:
h
=
m
-
1
}
h
:=
x
.
c
-
1
for
l
<=
h
{
m
:=
(
l
+
h
)
>>
1
switch
cmp
:=
oidCmp
(
k
,
x
.
x
[
m
]
.
k
);
{
case
cmp
>
0
:
l
=
m
+
1
case
cmp
==
0
:
return
m
,
true
default
:
h
=
m
-
1
}
case
*
d
:
h
:=
x
.
c
-
1
for
l
<=
h
{
m
:=
(
l
+
h
)
>>
1
mk
=
x
.
d
[
m
]
.
k
switch
cmp
:=
oidCmp
(
k
,
mk
);
{
case
cmp
>
0
:
l
=
m
+
1
case
cmp
==
0
:
return
m
,
true
default
:
h
=
m
-
1
}
}
return
l
,
false
}
func
(
t
*
Tree
)
find
(
x
*
d
,
k
zodb
.
Oid
)
(
i
int
,
ok
bool
)
{
l
:=
0
h
:=
x
.
c
-
1
for
l
<=
h
{
m
:=
(
l
+
h
)
>>
1
switch
cmp
:=
oidCmp
(
k
,
x
.
d
[
m
]
.
k
);
{
case
cmp
>
0
:
l
=
m
+
1
case
cmp
==
0
:
return
m
,
true
default
:
h
=
m
-
1
}
}
return
l
,
false
}
// hitFind returns position for k in previously hit data page
// if k should not reside in hit range: -1, false is returned
// otherwise returns are:
// - i: index corresponding to data entry in t.hitD with min(k' : k <= k')
// - ok: whether k' == k
func
(
t
*
Tree
)
hitFind
(
k
zodb
.
Oid
)
(
i
int
,
ok
bool
)
{
// DEBUG: enable this to test how slow path computes hit{Kmin,Kmax} on all keys
//return -1, false
hit
:=
t
.
hitD
if
hit
==
nil
{
return
-
1
,
false
}
i
=
t
.
hitDi
var
h
int
switch
cmp
:=
oidCmp
(
k
,
hit
.
d
[
i
]
.
k
);
{
case
cmp
>
0
:
if
t
.
hitKmaxSet
&&
oidCmp
(
k
,
t
.
hitKmax
)
>=
0
{
// >= hitKmax
return
-
1
,
false
}
// NOTE we are ok if i+1=hit.c -> hit.c will be returned
i
,
h
=
i
+
1
,
hit
.
c
-
1
case
cmp
<
0
:
if
t
.
hitKminSet
&&
oidCmp
(
k
,
t
.
hitKmin
)
<
0
{
// < hitKmin
return
-
1
,
false
}
// NOTE we are ok if i-1=-1 -> 0 will be returned
i
,
h
=
0
,
i
-
1
default
:
return
i
,
true
}
for
i
<=
h
{
m
:=
(
i
+
h
)
>>
1
switch
cmp
:=
oidCmp
(
k
,
hit
.
d
[
m
]
.
k
);
{
case
cmp
>
0
:
i
=
m
+
1
case
cmp
==
0
:
return
m
,
true
default
:
h
=
m
-
1
}
}
return
i
,
false
}
// First returns the first item of the tree in the key collating order, or
// (zero-value, zero-value) if the tree is empty.
func
(
t
*
Tree
)
First
()
(
k
zodb
.
Oid
,
v
int64
)
{
...
...
@@ -403,21 +574,20 @@ func (t *Tree) Get(k zodb.Oid) (v int64, ok bool) {
}
for
{
var
i
int
if
i
,
ok
=
t
.
find
(
q
,
k
);
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
return
x
.
d
[
i
]
.
v
,
true
}
}
switch
x
:=
q
.
(
type
)
{
case
*
x
:
i
,
ok
:=
t
.
findX
(
x
,
k
)
if
ok
{
i
++
}
q
=
x
.
x
[
i
]
.
ch
default
:
return
case
*
d
:
i
,
ok
:=
t
.
find
(
x
,
k
)
if
ok
{
return
x
.
d
[
i
]
.
v
,
true
}
return
v
,
ok
}
}
}
...
...
@@ -432,6 +602,8 @@ func (t *Tree) insert(q *d, i int, k zodb.Oid, v int64) *d {
q
.
c
=
c
q
.
d
[
i
]
.
k
,
q
.
d
[
i
]
.
v
=
k
,
v
t
.
c
++
t
.
hitD
=
q
t
.
hitDi
=
i
return
q
}
...
...
@@ -458,6 +630,8 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k zodb.Oid, v int64) {
l
.
mvL
(
q
,
1
)
t
.
insert
(
q
,
i
-
1
,
k
,
v
)
p
.
x
[
pi
-
1
]
.
k
=
q
.
d
[
0
]
.
k
t
.
setHitKmin
(
q
.
d
[
0
]
.
k
)
//t.hitPi = pi already pre-set this way
return
}
...
...
@@ -466,11 +640,22 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k zodb.Oid, v int64) {
q
.
mvR
(
r
,
1
)
t
.
insert
(
q
,
i
,
k
,
v
)
p
.
x
[
pi
]
.
k
=
r
.
d
[
0
]
.
k
t
.
setHitKmax
(
r
.
d
[
0
]
.
k
)
//t.hitPi = pi already pre-set this way
return
}
t
.
insert
(
r
,
0
,
k
,
v
)
p
.
x
[
pi
]
.
k
=
k
t
.
setHitKmin
(
k
)
if
pi
+
1
<
p
.
c
{
// k=+∞ @p.c
t
.
setHitKmax
(
p
.
x
[
pi
+
1
]
.
k
)
}
else
{
t
.
hitKmax
=
t
.
hitPKmax
t
.
hitKmaxSet
=
t
.
hitPKmaxSet
}
t
.
hitPi
=
pi
+
1
return
}
...
...
@@ -488,22 +673,17 @@ func (t *Tree) Seek(k zodb.Oid) (e *Enumerator, ok bool) {
}
for
{
var
i
int
if
i
,
ok
=
t
.
find
(
q
,
k
);
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
return
btEPool
.
get
(
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
),
true
}
}
switch
x
:=
q
.
(
type
)
{
case
*
x
:
i
,
ok
:=
t
.
findX
(
x
,
k
)
if
ok
{
i
++
}
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
return
btEPool
.
get
(
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
),
false
i
,
ok
:=
t
.
find
(
x
,
k
)
return
btEPool
.
get
(
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
),
ok
}
}
}
...
...
@@ -532,11 +712,43 @@ func (t *Tree) SeekLast() (e *Enumerator, err error) {
// Set sets the value associated with k.
func
(
t
*
Tree
)
Set
(
k
zodb
.
Oid
,
v
int64
)
{
//dbg("--- PRE Set(%v, %v)\n%s", k, v, t.dump())
//dbg("--- PRE Set(%v, %v)\t; %v @%d, [%v, %v) pk: [%v, %v)\n%s", k, v, t.hitD, t.hitDi, t.hitKmin, t.hitKmax, t.hitPKmin, t.hitPKmax, t.dump())
//defer t.checkHit(k, opSet)
//defer func() {
// dbg("--- POST\n%s\n====\n", t.dump())
//}()
// check if we can do the update nearby previous change
i
,
ok
:=
t
.
hitFind
(
k
)
if
i
>=
0
{
dd
:=
t
.
hitD
switch
{
case
ok
:
dd
.
d
[
i
]
.
v
=
v
t
.
hitDi
=
i
return
case
dd
.
c
<
2
*
kd
:
t
.
insert
(
dd
,
i
,
k
,
v
)
return
// here: need to overflow but we have to check: if overflowing would
// cause upper level overflow (splitX) -> we cannot overflow here -
// - need to do the usual scan from root to split index pages.
default
:
p
,
pi
:=
t
.
hitP
,
t
.
hitPi
if
p
!=
nil
&&
p
.
c
>
2
*
kx
{
break
}
// NOTE overflow corrects hit Kmin, Kmax and Pi as needed
t
.
overflow
(
p
,
dd
,
pi
,
i
,
k
,
v
)
return
}
}
// data page not quickly found - search and descent from root
pi
:=
-
1
var
p
*
x
q
:=
t
.
r
...
...
@@ -546,39 +758,59 @@ func (t *Tree) Set(k zodb.Oid, v int64) {
return
}
for
{
i
,
ok
:=
t
.
find
(
q
,
k
)
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
>
2
*
kx
{
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
p
=
x
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
x
.
d
[
i
]
.
v
=
v
}
return
}
t
.
hitKminSet
,
t
.
hitKmaxSet
=
false
,
false
// initially [-∞, +∞)
t
.
hitPKminSet
,
t
.
hitPKmaxSet
=
false
,
false
for
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
i
,
ok
:=
t
.
findX
(
x
,
k
)
if
ok
{
i
++
}
if
x
.
c
>
2
*
kx
{
// NOTE splitX corrects hit Kmin and Kmax as needed
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
t
.
hitPKmin
=
t
.
hitKmin
t
.
hitPKmax
=
t
.
hitKmax
t
.
hitPKminSet
=
t
.
hitKminSet
t
.
hitPKmaxSet
=
t
.
hitKmaxSet
p
=
x
q
=
x
.
x
[
i
]
.
ch
pi
=
i
q
=
p
.
x
[
pi
]
.
ch
if
pi
>
0
{
// k=-∞ @-1
t
.
setHitKmin
(
p
.
x
[
pi
-
1
]
.
k
)
}
if
pi
<
p
.
c
{
// k=+∞ @p.c
t
.
setHitKmax
(
p
.
x
[
pi
]
.
k
)
}
case
*
d
:
i
,
ok
:=
t
.
find
(
x
,
k
)
// data page found - perform the update
t
.
hitP
=
p
t
.
hitPi
=
pi
switch
{
case
ok
:
x
.
d
[
i
]
.
v
=
v
t
.
hitD
,
t
.
hitDi
=
x
,
i
case
x
.
c
<
2
*
kd
:
t
.
insert
(
x
,
i
,
k
,
v
)
default
:
// NOTE overflow corrects hit Kmin, Kmax and Pi as needed
t
.
overflow
(
p
,
x
,
pi
,
i
,
k
,
v
)
}
return
}
}
...
...
@@ -597,6 +829,7 @@ func (t *Tree) Set(k zodb.Oid, v int64) {
//
// modulo the differing return values.
func
(
t
*
Tree
)
Put
(
k
zodb
.
Oid
,
upd
func
(
oldV
int64
,
exists
bool
)
(
newV
int64
,
write
bool
))
(
oldV
int64
,
written
bool
)
{
//defer func () { t.checkHit(k, opPut(written)) }()
pi
:=
-
1
var
p
*
x
q
:=
t
.
r
...
...
@@ -613,50 +846,131 @@ func (t *Tree) Put(k zodb.Oid, upd func(oldV int64, exists bool) (newV int64, wr
return
}
for
{
i
,
ok
:=
t
.
find
(
q
,
k
)
if
ok
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
>
2
*
kx
{
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
p
=
x
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
oldV
=
x
.
d
[
i
]
.
v
newV
,
written
=
upd
(
oldV
,
true
)
if
!
written
{
return
// check if we can do the update nearby previous change
i
,
ok
:=
t
.
hitFind
(
k
)
if
i
>=
0
{
dd
:=
t
.
hitD
switch
{
case
ok
:
oldV
=
dd
.
d
[
i
]
.
v
newV
,
written
=
upd
(
oldV
,
true
)
if
written
{
dd
.
d
[
i
]
.
v
=
newV
}
t
.
hitDi
=
i
return
case
dd
.
c
<
2
*
kd
:
newV
,
written
=
upd
(
newV
,
false
)
if
written
{
t
.
insert
(
dd
,
i
,
k
,
newV
)
}
else
{
t
.
hitDi
=
i
// if it was only Get landed past max key - adjust it to valid entry
if
t
.
hitDi
>=
dd
.
c
{
t
.
hitDi
--
}
}
return
// here: need to overflow but we have to check: if overflowing would
// cause upper level overflow (splitX) -> we cannot overflow here -
// - need to do the usual scan from root to split index pages.
default
:
p
,
pi
:=
t
.
hitP
,
t
.
hitPi
if
p
!=
nil
&&
p
.
c
>
2
*
kx
{
break
}
newV
,
written
=
upd
(
newV
,
false
)
x
.
d
[
i
]
.
v
=
newV
if
written
{
// NOTE overflow corrects hit Kmin, Kmax and Pi as needed
t
.
overflow
(
p
,
dd
,
pi
,
i
,
k
,
newV
)
}
else
{
t
.
hitDi
=
i
// see about "valid entry" ^^^
if
t
.
hitDi
>=
dd
.
c
{
t
.
hitDi
--
}
}
return
}
}
// data page not quickly found - search and descent from root
t
.
hitKminSet
,
t
.
hitKmaxSet
=
false
,
false
// initially [-∞, +∞)
t
.
hitPKminSet
,
t
.
hitPKmaxSet
=
false
,
false
for
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
i
,
ok
:=
t
.
findX
(
x
,
k
)
if
ok
{
i
++
}
if
x
.
c
>
2
*
kx
{
// NOTE splitX corrects hit Kmin and Kmax as needed
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
t
.
hitPKmin
=
t
.
hitKmin
t
.
hitPKmax
=
t
.
hitKmax
t
.
hitPKminSet
=
t
.
hitKminSet
t
.
hitPKmaxSet
=
t
.
hitKmaxSet
p
=
x
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
// new KV pair
newV
,
written
=
upd
(
newV
,
false
)
if
!
written
{
return
pi
=
i
q
=
p
.
x
[
pi
]
.
ch
if
pi
>
0
{
// k=-∞ @-1
t
.
setHitKmin
(
p
.
x
[
pi
-
1
]
.
k
)
}
if
pi
<
p
.
c
{
// k=+∞ @p.c
t
.
setHitKmax
(
p
.
x
[
pi
]
.
k
)
}
case
*
d
:
i
,
ok
:=
t
.
find
(
x
,
k
)
// data page found - perform the update
t
.
hitP
=
p
t
.
hitPi
=
pi
switch
{
case
x
.
c
<
2
*
kd
:
t
.
insert
(
x
,
i
,
k
,
newV
)
case
ok
:
oldV
=
x
.
d
[
i
]
.
v
newV
,
written
=
upd
(
oldV
,
true
)
if
written
{
x
.
d
[
i
]
.
v
=
newV
}
t
.
hitD
,
t
.
hitDi
=
x
,
i
default
:
t
.
overflow
(
p
,
x
,
pi
,
i
,
k
,
newV
)
newV
,
written
=
upd
(
newV
,
false
)
if
!
written
{
t
.
hitD
,
t
.
hitDi
=
x
,
i
// see about "valid entry" ^^^
if
t
.
hitDi
>=
x
.
c
{
t
.
hitDi
--
}
break
}
switch
{
case
x
.
c
<
2
*
kd
:
t
.
insert
(
x
,
i
,
k
,
newV
)
default
:
// NOTE overflow corrects hit Kmin, Kmax and Pi as needed
t
.
overflow
(
p
,
x
,
pi
,
i
,
k
,
newV
)
}
}
return
}
}
...
...
@@ -680,21 +994,32 @@ func (t *Tree) split(p *x, q *d, pi, i int, k zodb.Oid, v int64) {
}
q
.
c
=
kd
r
.
c
=
kd
var
done
bool
if
i
>
kd
{
done
=
true
t
.
insert
(
r
,
i
-
kd
,
k
,
v
)
}
if
pi
>=
0
{
p
.
insert
(
pi
,
r
.
d
[
0
]
.
k
,
r
)
}
else
{
t
.
r
=
newX
(
q
)
.
insert
(
0
,
r
.
d
[
0
]
.
k
,
r
)
}
if
done
{
return
p
=
newX
(
q
)
.
insert
(
0
,
r
.
d
[
0
]
.
k
,
r
)
pi
=
0
t
.
r
=
p
t
.
hitP
=
p
t
.
hitPi
=
pi
}
t
.
insert
(
q
,
i
,
k
,
v
)
if
i
>
kd
{
t
.
insert
(
r
,
i
-
kd
,
k
,
v
)
t
.
setHitKmin
(
p
.
x
[
pi
]
.
k
)
if
pi
+
1
<
p
.
c
{
// k=+∞ @p.c
t
.
setHitKmax
(
p
.
x
[
pi
+
1
]
.
k
)
}
else
{
t
.
hitKmax
=
t
.
hitPKmax
t
.
hitKmaxSet
=
t
.
hitPKmaxSet
}
t
.
hitPi
=
pi
+
1
}
else
{
t
.
insert
(
q
,
i
,
k
,
v
)
t
.
setHitKmax
(
r
.
d
[
0
]
.
k
)
//t.hitPi = pi already pre-set this way
}
}
func
(
t
*
Tree
)
splitX
(
p
*
x
,
q
*
x
,
pi
int
,
i
int
)
(
*
x
,
int
)
{
...
...
@@ -705,36 +1030,31 @@ func (t *Tree) splitX(p *x, q *x, pi int, i int) (*x, int) {
r
.
c
=
kx
if
pi
>=
0
{
p
.
insert
(
pi
,
q
.
x
[
kx
]
.
k
,
r
)
q
.
x
[
kx
]
.
k
=
zk
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
switch
{
case
i
<
kx
:
return
q
,
i
case
i
==
kx
:
return
p
,
pi
default
:
// i > kx
return
r
,
i
-
kx
-
1
}
}
else
{
p
=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
k
,
r
)
pi
=
0
t
.
r
=
p
}
nr
:=
newX
(
q
)
.
insert
(
0
,
q
.
x
[
kx
]
.
k
,
r
)
t
.
r
=
nr
q
.
x
[
kx
]
.
k
=
zk
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
switch
{
case
i
<
kx
:
return
q
,
i
case
i
==
kx
:
return
nr
,
0
default
:
// i > kx
return
r
,
i
-
kx
-
1
if
i
>
kx
{
q
=
r
i
-=
kx
+
1
t
.
setHitKmin
(
p
.
x
[
pi
]
.
k
)
if
pi
+
1
<
p
.
c
{
// k=+∞ @p.c
t
.
setHitKmax
(
p
.
x
[
pi
+
1
]
.
k
)
}
else
{
t
.
hitKmax
=
t
.
hitPKmax
t
.
hitKmaxSet
=
t
.
hitPKmaxSet
}
}
else
{
t
.
setHitKmax
(
p
.
x
[
pi
]
.
k
)
}
return
q
,
i
}
func
(
t
*
Tree
)
underflow
(
p
*
x
,
q
*
d
,
pi
int
)
{
...
...
@@ -744,22 +1064,56 @@ func (t *Tree) underflow(p *x, q *d, pi int) {
if
l
!=
nil
&&
l
.
c
+
q
.
c
>=
2
*
kd
{
l
.
mvR
(
q
,
1
)
p
.
x
[
pi
-
1
]
.
k
=
q
.
d
[
0
]
.
k
t
.
setHitKmin
(
q
.
d
[
0
]
.
k
)
//t.hitPi = pi already pre-set this way
t
.
hitDi
+=
1
return
}
if
r
!=
nil
&&
q
.
c
+
r
.
c
>=
2
*
kd
{
q
.
mvL
(
r
,
1
)
p
.
x
[
pi
]
.
k
=
r
.
d
[
0
]
.
k
t
.
setHitKmax
(
r
.
d
[
0
]
.
k
)
//t.hitPi = pi already pre-set this way
// hitDi stays the same
r
.
d
[
r
.
c
]
=
zde
// GC
return
}
if
l
!=
nil
{
t
.
cat
(
p
,
l
,
q
,
pi
-
1
)
t
.
hitD
=
l
t
.
hitDi
+=
l
.
c
pi
--
t
.
cat
(
p
,
l
,
q
,
pi
)
t
.
hitKmin
=
t
.
hitPKmin
t
.
hitKminSet
=
t
.
hitPKminSet
// XXX move vvv under else ? (but vs t.r == l)
if
t
.
r
==
l
{
// cat removed p
t
.
hitP
=
nil
t
.
hitPi
=
-
1
}
else
{
if
pi
>
0
{
// k=-∞ @-1
t
.
setHitKmin
(
p
.
x
[
pi
-
1
]
.
k
)
}
t
.
hitPi
=
pi
}
return
}
t
.
cat
(
p
,
q
,
r
,
pi
)
// hitD/hitDi stays unchanged
t
.
hitKmax
=
t
.
hitPKmax
t
.
hitKmaxSet
=
t
.
hitPKmaxSet
// XXX move vvv under else ? (but vs t.r == q)
if
t
.
r
==
q
{
// cat removed p
t
.
hitP
=
nil
t
.
hitPi
=
-
1
}
else
{
if
pi
<
p
.
c
{
// k=+∞ @p.c
t
.
setHitKmax
(
p
.
x
[
pi
]
.
k
)
}
//t.hitPi = pi already pre-set this way
}
}
func
(
t
*
Tree
)
underflowX
(
p
*
x
,
q
*
x
,
pi
int
,
i
int
)
(
*
x
,
int
)
{
...
...
@@ -784,6 +1138,7 @@ func (t *Tree) underflowX(p *x, q *x, pi int, i int) (*x, int) {
i
++
l
.
c
--
p
.
x
[
pi
-
1
]
.
k
=
l
.
x
[
l
.
c
]
.
k
t
.
setHitKmin
(
l
.
x
[
l
.
c
]
.
k
)
return
q
,
i
}
...
...
@@ -792,6 +1147,7 @@ func (t *Tree) underflowX(p *x, q *x, pi int, i int) (*x, int) {
q
.
c
++
q
.
x
[
q
.
c
]
.
ch
=
r
.
x
[
0
]
.
ch
p
.
x
[
pi
]
.
k
=
r
.
x
[
0
]
.
k
t
.
setHitKmax
(
r
.
x
[
0
]
.
k
)
copy
(
r
.
x
[
:
],
r
.
x
[
1
:
r
.
c
])
r
.
c
--
rc
:=
r
.
c
...
...
@@ -803,12 +1159,25 @@ func (t *Tree) underflowX(p *x, q *x, pi int, i int) (*x, int) {
if
l
!=
nil
{
i
+=
l
.
c
+
1
t
.
catX
(
p
,
l
,
q
,
pi
-
1
)
pi
--
t
.
catX
(
p
,
l
,
q
,
pi
)
q
=
l
if
t
.
r
!=
q
&&
pi
>
0
{
// k=+∞ @p.c
t
.
setHitKmin
(
p
.
x
[
pi
-
1
]
.
k
)
}
else
{
t
.
hitKmin
=
t
.
hitPKmin
t
.
hitKminSet
=
t
.
hitPKminSet
}
return
q
,
i
}
t
.
catX
(
p
,
q
,
r
,
pi
)
if
t
.
r
!=
q
&&
pi
<
p
.
c
{
// k=+∞ @p.c
t
.
setHitKmax
(
p
.
x
[
pi
]
.
k
)
}
else
{
t
.
hitKmax
=
t
.
hitPKmax
t
.
hitKmaxSet
=
t
.
hitPKmaxSet
}
return
q
,
i
}
...
...
t/neo/storage/fs1/fsb/fsbtree_util.go
View file @
fe0f712e
// DO NOT EDIT - AUTOGENERATED (by gen-fsbtree from github.com/cznic/b
aaaa43c
)
// DO NOT EDIT - AUTOGENERATED (by gen-fsbtree from github.com/cznic/b
4efd872
)
// ---- 8< ----
package
fsb
import
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment