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
1
Issues
1
List
Boards
Labels
Milestones
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
neoppod
Commits
89162ce1
Commit
89162ce1
authored
Feb 02, 2017
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
e797c2fe
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
948 additions
and
0 deletions
+948
-0
t/neo/storage/fs1/b/fsbtree.go
t/neo/storage/fs1/b/fsbtree.go
+933
-0
t/neo/storage/fs1/b/gen-fsbtree
t/neo/storage/fs1/b/gen-fsbtree
+15
-0
No files found.
t/neo/storage/fs1/b/fsbtree.go
0 → 100644
View file @
89162ce1
// DO NOT EDIT - AUTOGENERATED (by gen-fsbtree from github.com/cznic/b bcff30a)
// KEY=Oid VALUE=uint64
// ---- 8< ----
// Copyright 2014 The b Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
b
import
(
"fmt"
"io"
"sync"
)
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).
)
func
init
()
{
if
kd
<
1
{
panic
(
fmt
.
Errorf
(
"kd %d: out of range"
,
kd
))
}
if
kx
<
2
{
panic
(
fmt
.
Errorf
(
"kx %d: out of range"
,
kx
))
}
}
var
(
btDPool
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
d
{}
}}
btEPool
=
btEpool
{
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
Enumerator
{}
}}}
btTPool
=
btTpool
{
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
Tree
{}
}}}
btXPool
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
x
{}
}}
)
type
btTpool
struct
{
sync
.
Pool
}
func
(
p
*
btTpool
)
get
(
cmp
Cmp
)
*
Tree
{
x
:=
p
.
Get
()
.
(
*
Tree
)
x
.
cmp
=
cmp
return
x
}
type
btEpool
struct
{
sync
.
Pool
}
func
(
p
*
btEpool
)
get
(
err
error
,
hit
bool
,
i
int
,
k
Oid
,
q
*
d
,
t
*
Tree
,
ver
int64
)
*
Enumerator
{
x
:=
p
.
Get
()
.
(
*
Enumerator
)
x
.
err
,
x
.
hit
,
x
.
i
,
x
.
k
,
x
.
q
,
x
.
t
,
x
.
ver
=
err
,
hit
,
i
,
k
,
q
,
t
,
ver
return
x
}
type
(
// Cmp compares a and b. Return value is:
//
// < 0 if a < b
// 0 if a == b
// > 0 if a > b
//
Cmp
func
(
a
,
b
Oid
)
int
d
struct
{
// data page
c
int
d
[
2
*
kd
+
1
]
de
n
*
d
p
*
d
}
de
struct
{
// d element
k
Oid
v
uint64
}
// Enumerator captures the state of enumerating a tree. It is returned
// from the Seek* methods. The enumerator is aware of any mutations
// made to the tree in the process of enumerating it and automatically
// resumes the enumeration at the proper key, if possible.
//
// However, once an Enumerator returns io.EOF to signal "no more
// items", it does no more attempt to "resync" on tree mutation(s). In
// other words, io.EOF from an Enumerator is "sticky" (idempotent).
Enumerator
struct
{
err
error
hit
bool
i
int
k
Oid
q
*
d
t
*
Tree
ver
int64
}
// Tree is a B+tree.
Tree
struct
{
c
int
cmp
Cmp
first
*
d
last
*
d
r
interface
{}
ver
int64
}
xe
struct
{
// x element
ch
interface
{}
k
Oid
}
x
struct
{
// index page
c
int
x
[
2
*
kx
+
2
]
xe
}
)
var
(
// R/O zero values
zd
d
zde
de
ze
Enumerator
zk
Oid
zt
Tree
zx
x
zxe
xe
)
func
clr
(
q
interface
{})
{
switch
x
:=
q
.
(
type
)
{
case
*
x
:
for
i
:=
0
;
i
<=
x
.
c
;
i
++
{
// Ch0 Sep0 ... Chn-1 Sepn-1 Chn
clr
(
x
.
x
[
i
]
.
ch
)
}
*
x
=
zx
btXPool
.
Put
(
x
)
case
*
d
:
*
x
=
zd
btDPool
.
Put
(
x
)
}
}
// -------------------------------------------------------------------------- x
func
newX
(
ch0
interface
{})
*
x
{
r
:=
btXPool
.
Get
()
.
(
*
x
)
r
.
x
[
0
]
.
ch
=
ch0
return
r
}
func
(
q
*
x
)
extract
(
i
int
)
{
q
.
c
--
if
i
<
q
.
c
{
copy
(
q
.
x
[
i
:
],
q
.
x
[
i
+
1
:
q
.
c
+
1
])
q
.
x
[
q
.
c
]
.
ch
=
q
.
x
[
q
.
c
+
1
]
.
ch
q
.
x
[
q
.
c
]
.
k
=
zk
// GC
q
.
x
[
q
.
c
+
1
]
=
zxe
// GC
}
}
func
(
q
*
x
)
insert
(
i
int
,
k
Oid
,
ch
interface
{})
*
x
{
c
:=
q
.
c
if
i
<
c
{
q
.
x
[
c
+
1
]
.
ch
=
q
.
x
[
c
]
.
ch
copy
(
q
.
x
[
i
+
2
:
],
q
.
x
[
i
+
1
:
c
])
q
.
x
[
i
+
1
]
.
k
=
q
.
x
[
i
]
.
k
}
c
++
q
.
c
=
c
q
.
x
[
i
]
.
k
=
k
q
.
x
[
i
+
1
]
.
ch
=
ch
return
q
}
func
(
q
*
x
)
siblings
(
i
int
)
(
l
,
r
*
d
)
{
if
i
>=
0
{
if
i
>
0
{
l
=
q
.
x
[
i
-
1
]
.
ch
.
(
*
d
)
}
if
i
<
q
.
c
{
r
=
q
.
x
[
i
+
1
]
.
ch
.
(
*
d
)
}
}
return
}
// -------------------------------------------------------------------------- d
func
(
l
*
d
)
mvL
(
r
*
d
,
c
int
)
{
copy
(
l
.
d
[
l
.
c
:
],
r
.
d
[
:
c
])
copy
(
r
.
d
[
:
],
r
.
d
[
c
:
r
.
c
])
l
.
c
+=
c
r
.
c
-=
c
}
func
(
l
*
d
)
mvR
(
r
*
d
,
c
int
)
{
copy
(
r
.
d
[
c
:
],
r
.
d
[
:
r
.
c
])
copy
(
r
.
d
[
:
c
],
l
.
d
[
l
.
c
-
c
:
])
r
.
c
+=
c
l
.
c
-=
c
}
// ----------------------------------------------------------------------- Tree
// TreeNew returns a newly created, empty Tree. The compare function is used
// for key collation.
func
TreeNew
(
cmp
Cmp
)
*
Tree
{
return
btTPool
.
get
(
cmp
)
}
// Clear removes all K/V pairs from the tree.
func
(
t
*
Tree
)
Clear
()
{
if
t
.
r
==
nil
{
return
}
clr
(
t
.
r
)
t
.
c
,
t
.
first
,
t
.
last
,
t
.
r
=
0
,
nil
,
nil
,
nil
t
.
ver
++
}
// Close performs Clear and recycles t to a pool for possible later reuse. No
// references to t should exist or such references must not be used afterwards.
func
(
t
*
Tree
)
Close
()
{
t
.
Clear
()
*
t
=
zt
btTPool
.
Put
(
t
)
}
func
(
t
*
Tree
)
cat
(
p
*
x
,
q
,
r
*
d
,
pi
int
)
{
t
.
ver
++
q
.
mvL
(
r
,
r
.
c
)
if
r
.
n
!=
nil
{
r
.
n
.
p
=
q
}
else
{
t
.
last
=
q
}
q
.
n
=
r
.
n
*
r
=
zd
btDPool
.
Put
(
r
)
if
p
.
c
>
1
{
p
.
extract
(
pi
)
p
.
x
[
pi
]
.
ch
=
q
return
}
switch
x
:=
t
.
r
.
(
type
)
{
case
*
x
:
*
x
=
zx
btXPool
.
Put
(
x
)
case
*
d
:
*
x
=
zd
btDPool
.
Put
(
x
)
}
t
.
r
=
q
}
func
(
t
*
Tree
)
catX
(
p
,
q
,
r
*
x
,
pi
int
)
{
t
.
ver
++
q
.
x
[
q
.
c
]
.
k
=
p
.
x
[
pi
]
.
k
copy
(
q
.
x
[
q
.
c
+
1
:
],
r
.
x
[
:
r
.
c
])
q
.
c
+=
r
.
c
+
1
q
.
x
[
q
.
c
]
.
ch
=
r
.
x
[
r
.
c
]
.
ch
*
r
=
zx
btXPool
.
Put
(
r
)
if
p
.
c
>
1
{
p
.
c
--
pc
:=
p
.
c
if
pi
<
pc
{
p
.
x
[
pi
]
.
k
=
p
.
x
[
pi
+
1
]
.
k
copy
(
p
.
x
[
pi
+
1
:
],
p
.
x
[
pi
+
2
:
pc
+
1
])
p
.
x
[
pc
]
.
ch
=
p
.
x
[
pc
+
1
]
.
ch
p
.
x
[
pc
]
.
k
=
zk
// GC
p
.
x
[
pc
+
1
]
.
ch
=
nil
// GC
}
return
}
switch
x
:=
t
.
r
.
(
type
)
{
case
*
x
:
*
x
=
zx
btXPool
.
Put
(
x
)
case
*
d
:
*
x
=
zd
btDPool
.
Put
(
x
)
}
t
.
r
=
q
}
// Delete removes the k's KV pair, if it exists, in which case Delete returns
// true.
func
(
t
*
Tree
)
Delete
(
k
Oid
)
(
ok
bool
)
{
pi
:=
-
1
var
p
*
x
q
:=
t
.
r
if
q
==
nil
{
return
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
}
if
q
!=
t
.
r
{
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
)
}
pi
=
i
p
=
x
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
return
false
}
}
}
func
(
t
*
Tree
)
extract
(
q
*
d
,
i
int
)
{
// (r uint64) {
t
.
ver
++
//r = q.d[i].v // prepared for Extract
q
.
c
--
if
i
<
q
.
c
{
copy
(
q
.
d
[
i
:
],
q
.
d
[
i
+
1
:
q
.
c
+
1
])
}
q
.
d
[
q
.
c
]
=
zde
// GC
t
.
c
--
return
}
func
(
t
*
Tree
)
find
(
q
interface
{},
k
Oid
)
(
i
int
,
ok
bool
)
{
var
mk
Oid
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
:=
t
.
cmp
(
k
,
mk
);
{
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
:=
t
.
cmp
(
k
,
mk
);
{
case
cmp
>
0
:
l
=
m
+
1
case
cmp
==
0
:
return
m
,
true
default
:
h
=
m
-
1
}
}
}
return
l
,
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
Oid
,
v
uint64
)
{
if
q
:=
t
.
first
;
q
!=
nil
{
q
:=
&
q
.
d
[
0
]
k
,
v
=
q
.
k
,
q
.
v
}
return
}
// Get returns the value associated with k and true if it exists. Otherwise Get
// returns (zero-value, false).
func
(
t
*
Tree
)
Get
(
k
Oid
)
(
v
uint64
,
ok
bool
)
{
q
:=
t
.
r
if
q
==
nil
{
return
}
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
:
q
=
x
.
x
[
i
]
.
ch
default
:
return
}
}
}
func
(
t
*
Tree
)
insert
(
q
*
d
,
i
int
,
k
Oid
,
v
uint64
)
*
d
{
t
.
ver
++
c
:=
q
.
c
if
i
<
c
{
copy
(
q
.
d
[
i
+
1
:
],
q
.
d
[
i
:
c
])
}
c
++
q
.
c
=
c
q
.
d
[
i
]
.
k
,
q
.
d
[
i
]
.
v
=
k
,
v
t
.
c
++
return
q
}
// Last returns the last item of the tree in the key collating order, or
// (zero-value, zero-value) if the tree is empty.
func
(
t
*
Tree
)
Last
()
(
k
Oid
,
v
uint64
)
{
if
q
:=
t
.
last
;
q
!=
nil
{
q
:=
&
q
.
d
[
q
.
c
-
1
]
k
,
v
=
q
.
k
,
q
.
v
}
return
}
// Len returns the number of items in the tree.
func
(
t
*
Tree
)
Len
()
int
{
return
t
.
c
}
func
(
t
*
Tree
)
overflow
(
p
*
x
,
q
*
d
,
pi
,
i
int
,
k
Oid
,
v
uint64
)
{
t
.
ver
++
l
,
r
:=
p
.
siblings
(
pi
)
if
l
!=
nil
&&
l
.
c
<
2
*
kd
&&
i
!=
0
{
l
.
mvL
(
q
,
1
)
t
.
insert
(
q
,
i
-
1
,
k
,
v
)
p
.
x
[
pi
-
1
]
.
k
=
q
.
d
[
0
]
.
k
return
}
if
r
!=
nil
&&
r
.
c
<
2
*
kd
{
if
i
<
2
*
kd
{
q
.
mvR
(
r
,
1
)
t
.
insert
(
q
,
i
,
k
,
v
)
p
.
x
[
pi
]
.
k
=
r
.
d
[
0
]
.
k
return
}
t
.
insert
(
r
,
0
,
k
,
v
)
p
.
x
[
pi
]
.
k
=
k
return
}
t
.
split
(
p
,
q
,
pi
,
i
,
k
,
v
)
}
// Seek returns an Enumerator positioned on an item such that k >= item's key.
// ok reports if k == item.key The Enumerator's position is possibly after the
// last item in the tree.
func
(
t
*
Tree
)
Seek
(
k
Oid
)
(
e
*
Enumerator
,
ok
bool
)
{
q
:=
t
.
r
if
q
==
nil
{
e
=
btEPool
.
get
(
nil
,
false
,
0
,
k
,
nil
,
t
,
t
.
ver
)
return
}
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
:
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
return
btEPool
.
get
(
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
),
false
}
}
}
// SeekFirst returns an enumerator positioned on the first KV pair in the tree,
// if any. For an empty tree, err == io.EOF is returned and e will be nil.
func
(
t
*
Tree
)
SeekFirst
()
(
e
*
Enumerator
,
err
error
)
{
q
:=
t
.
first
if
q
==
nil
{
return
nil
,
io
.
EOF
}
return
btEPool
.
get
(
nil
,
true
,
0
,
q
.
d
[
0
]
.
k
,
q
,
t
,
t
.
ver
),
nil
}
// SeekLast returns an enumerator positioned on the last KV pair in the tree,
// if any. For an empty tree, err == io.EOF is returned and e will be nil.
func
(
t
*
Tree
)
SeekLast
()
(
e
*
Enumerator
,
err
error
)
{
q
:=
t
.
last
if
q
==
nil
{
return
nil
,
io
.
EOF
}
return
btEPool
.
get
(
nil
,
true
,
q
.
c
-
1
,
q
.
d
[
q
.
c
-
1
]
.
k
,
q
,
t
,
t
.
ver
),
nil
}
// Set sets the value associated with k.
func
(
t
*
Tree
)
Set
(
k
Oid
,
v
uint64
)
{
//dbg("--- PRE Set(%v, %v)\n%s", k, v, t.dump())
//defer func() {
// dbg("--- POST\n%s\n====\n", t.dump())
//}()
pi
:=
-
1
var
p
*
x
q
:=
t
.
r
if
q
==
nil
{
z
:=
t
.
insert
(
btDPool
.
Get
()
.
(
*
d
),
0
,
k
,
v
)
t
.
r
,
t
.
first
,
t
.
last
=
z
,
z
,
z
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
}
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
>
2
*
kx
{
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
p
=
x
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
switch
{
case
x
.
c
<
2
*
kd
:
t
.
insert
(
x
,
i
,
k
,
v
)
default
:
t
.
overflow
(
p
,
x
,
pi
,
i
,
k
,
v
)
}
return
}
}
}
// Put combines Get and Set in a more efficient way where the tree is walked
// only once. The upd(ater) receives (old-value, true) if a KV pair for k
// exists or (zero-value, false) otherwise. It can then return a (new-value,
// true) to create or overwrite the existing value in the KV pair, or
// (whatever, false) if it decides not to create or not to update the value of
// the KV pair.
//
// tree.Set(k, v) call conceptually equals calling
//
// tree.Put(k, func(Oid, bool){ return v, true })
//
// modulo the differing return values.
func
(
t
*
Tree
)
Put
(
k
Oid
,
upd
func
(
oldV
uint64
,
exists
bool
)
(
newV
uint64
,
write
bool
))
(
oldV
uint64
,
written
bool
)
{
pi
:=
-
1
var
p
*
x
q
:=
t
.
r
var
newV
uint64
if
q
==
nil
{
// new KV pair in empty tree
newV
,
written
=
upd
(
newV
,
false
)
if
!
written
{
return
}
z
:=
t
.
insert
(
btDPool
.
Get
()
.
(
*
d
),
0
,
k
,
newV
)
t
.
r
,
t
.
first
,
t
.
last
=
z
,
z
,
z
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
}
x
.
d
[
i
]
.
v
=
newV
}
return
}
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
>
2
*
kx
{
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
p
=
x
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
// new KV pair
newV
,
written
=
upd
(
newV
,
false
)
if
!
written
{
return
}
switch
{
case
x
.
c
<
2
*
kd
:
t
.
insert
(
x
,
i
,
k
,
newV
)
default
:
t
.
overflow
(
p
,
x
,
pi
,
i
,
k
,
newV
)
}
return
}
}
}
func
(
t
*
Tree
)
split
(
p
*
x
,
q
*
d
,
pi
,
i
int
,
k
Oid
,
v
uint64
)
{
t
.
ver
++
r
:=
btDPool
.
Get
()
.
(
*
d
)
if
q
.
n
!=
nil
{
r
.
n
=
q
.
n
r
.
n
.
p
=
r
}
else
{
t
.
last
=
r
}
q
.
n
=
r
r
.
p
=
q
copy
(
r
.
d
[
:
],
q
.
d
[
kd
:
2
*
kd
])
for
i
:=
range
q
.
d
[
kd
:
]
{
q
.
d
[
kd
+
i
]
=
zde
}
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
}
t
.
insert
(
q
,
i
,
k
,
v
)
}
func
(
t
*
Tree
)
splitX
(
p
*
x
,
q
*
x
,
pi
int
,
i
int
)
(
*
x
,
int
)
{
t
.
ver
++
r
:=
btXPool
.
Get
()
.
(
*
x
)
copy
(
r
.
x
[
:
],
q
.
x
[
kx
+
1
:
])
q
.
c
=
kx
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
}
}
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
}
}
func
(
t
*
Tree
)
underflow
(
p
*
x
,
q
*
d
,
pi
int
)
{
t
.
ver
++
l
,
r
:=
p
.
siblings
(
pi
)
if
l
!=
nil
&&
l
.
c
+
q
.
c
>=
2
*
kd
{
l
.
mvR
(
q
,
1
)
p
.
x
[
pi
-
1
]
.
k
=
q
.
d
[
0
]
.
k
return
}
if
r
!=
nil
&&
q
.
c
+
r
.
c
>=
2
*
kd
{
q
.
mvL
(
r
,
1
)
p
.
x
[
pi
]
.
k
=
r
.
d
[
0
]
.
k
r
.
d
[
r
.
c
]
=
zde
// GC
return
}
if
l
!=
nil
{
t
.
cat
(
p
,
l
,
q
,
pi
-
1
)
return
}
t
.
cat
(
p
,
q
,
r
,
pi
)
}
func
(
t
*
Tree
)
underflowX
(
p
*
x
,
q
*
x
,
pi
int
,
i
int
)
(
*
x
,
int
)
{
t
.
ver
++
var
l
,
r
*
x
if
pi
>=
0
{
if
pi
>
0
{
l
=
p
.
x
[
pi
-
1
]
.
ch
.
(
*
x
)
}
if
pi
<
p
.
c
{
r
=
p
.
x
[
pi
+
1
]
.
ch
.
(
*
x
)
}
}
if
l
!=
nil
&&
l
.
c
>
kx
{
q
.
x
[
q
.
c
+
1
]
.
ch
=
q
.
x
[
q
.
c
]
.
ch
copy
(
q
.
x
[
1
:
],
q
.
x
[
:
q
.
c
])
q
.
x
[
0
]
.
ch
=
l
.
x
[
l
.
c
]
.
ch
q
.
x
[
0
]
.
k
=
p
.
x
[
pi
-
1
]
.
k
q
.
c
++
i
++
l
.
c
--
p
.
x
[
pi
-
1
]
.
k
=
l
.
x
[
l
.
c
]
.
k
return
q
,
i
}
if
r
!=
nil
&&
r
.
c
>
kx
{
q
.
x
[
q
.
c
]
.
k
=
p
.
x
[
pi
]
.
k
q
.
c
++
q
.
x
[
q
.
c
]
.
ch
=
r
.
x
[
0
]
.
ch
p
.
x
[
pi
]
.
k
=
r
.
x
[
0
]
.
k
copy
(
r
.
x
[
:
],
r
.
x
[
1
:
r
.
c
])
r
.
c
--
rc
:=
r
.
c
r
.
x
[
rc
]
.
ch
=
r
.
x
[
rc
+
1
]
.
ch
r
.
x
[
rc
]
.
k
=
zk
r
.
x
[
rc
+
1
]
.
ch
=
nil
return
q
,
i
}
if
l
!=
nil
{
i
+=
l
.
c
+
1
t
.
catX
(
p
,
l
,
q
,
pi
-
1
)
q
=
l
return
q
,
i
}
t
.
catX
(
p
,
q
,
r
,
pi
)
return
q
,
i
}
// ----------------------------------------------------------------- Enumerator
// Close recycles e to a pool for possible later reuse. No references to e
// should exist or such references must not be used afterwards.
func
(
e
*
Enumerator
)
Close
()
{
*
e
=
ze
btEPool
.
Put
(
e
)
}
// Next returns the currently enumerated item, if it exists and moves to the
// next item in the key collation order. If there is no item to return, err ==
// io.EOF is returned.
func
(
e
*
Enumerator
)
Next
()
(
k
Oid
,
v
uint64
,
err
error
)
{
if
err
=
e
.
err
;
err
!=
nil
{
return
}
if
e
.
ver
!=
e
.
t
.
ver
{
f
,
hit
:=
e
.
t
.
Seek
(
e
.
k
)
if
!
e
.
hit
&&
hit
{
if
err
=
f
.
next
();
err
!=
nil
{
return
}
}
*
e
=
*
f
f
.
Close
()
}
if
e
.
q
==
nil
{
e
.
err
,
err
=
io
.
EOF
,
io
.
EOF
return
}
if
e
.
i
>=
e
.
q
.
c
{
if
err
=
e
.
next
();
err
!=
nil
{
return
}
}
i
:=
e
.
q
.
d
[
e
.
i
]
k
,
v
=
i
.
k
,
i
.
v
e
.
k
,
e
.
hit
=
k
,
false
e
.
next
()
return
}
func
(
e
*
Enumerator
)
next
()
error
{
if
e
.
q
==
nil
{
e
.
err
=
io
.
EOF
return
io
.
EOF
}
switch
{
case
e
.
i
<
e
.
q
.
c
-
1
:
e
.
i
++
default
:
if
e
.
q
,
e
.
i
=
e
.
q
.
n
,
0
;
e
.
q
==
nil
{
e
.
err
=
io
.
EOF
}
}
return
e
.
err
}
// Prev returns the currently enumerated item, if it exists and moves to the
// previous item in the key collation order. If there is no item to return, err
// == io.EOF is returned.
func
(
e
*
Enumerator
)
Prev
()
(
k
Oid
,
v
uint64
,
err
error
)
{
if
err
=
e
.
err
;
err
!=
nil
{
return
}
if
e
.
ver
!=
e
.
t
.
ver
{
f
,
hit
:=
e
.
t
.
Seek
(
e
.
k
)
if
!
e
.
hit
&&
hit
{
if
err
=
f
.
prev
();
err
!=
nil
{
return
}
}
*
e
=
*
f
f
.
Close
()
}
if
e
.
q
==
nil
{
e
.
err
,
err
=
io
.
EOF
,
io
.
EOF
return
}
if
e
.
i
>=
e
.
q
.
c
{
if
err
=
e
.
next
();
err
!=
nil
{
return
}
}
i
:=
e
.
q
.
d
[
e
.
i
]
k
,
v
=
i
.
k
,
i
.
v
e
.
k
,
e
.
hit
=
k
,
false
e
.
prev
()
return
}
func
(
e
*
Enumerator
)
prev
()
error
{
if
e
.
q
==
nil
{
e
.
err
=
io
.
EOF
return
io
.
EOF
}
switch
{
case
e
.
i
>
0
:
e
.
i
--
default
:
if
e
.
q
=
e
.
q
.
p
;
e
.
q
==
nil
{
e
.
err
=
io
.
EOF
break
}
e
.
i
=
e
.
q
.
c
-
1
}
return
e
.
err
}
t/neo/storage/fs1/b/gen-fsbtree
0 → 100755
View file @
89162ce1
#!/bin/sh -e
# generate b.Tree with compile-time KEY & VALUE
b
=
github.com/cznic/b
Bdir
=
`
go list
-f
'{{.Dir}}'
$b
`
Brev
=
`
cd
$Bdir
&&
git describe
--always
`
out
=
fsbtree.go
KEY
=
Oid
VALUE
=
uint64
echo
"// DO NOT EDIT - AUTOGENERATED (by gen-fsbtree from
$b
$Brev
)"
>
$out
echo
"// KEY=
$KEY
VALUE=
$VALUE
"
>>
$out
echo
"// ---- 8< ----"
>>
$out
echo
>>
$out
make
-s
-C
$Bdir
generic |sed
-e
's/KEY/Oid/g'
-e
's/VALUE/uint64/g'
>>
$out
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