more stuff that doesn't work
This commit is contained in:
parent
1f1edeb23f
commit
eb78bc7a51
1 changed files with 154 additions and 51 deletions
|
|
@ -4,11 +4,26 @@
|
||||||
## Can also use a page manager for allocations. The page manager be used
|
## Can also use a page manager for allocations. The page manager be used
|
||||||
## to off load pages to a file system or to send it over the wire.
|
## to off load pages to a file system or to send it over the wire.
|
||||||
|
|
||||||
|
## Todo:
|
||||||
|
## - Add logic to deal with the fact that keys do not have to be unique.
|
||||||
|
## - Ranged queries
|
||||||
|
## - Make it generic and low level
|
||||||
|
## - Support for external nodes and a page cache
|
||||||
|
|
||||||
const
|
const
|
||||||
M = 4 # max children per B-tree node = M-1
|
M = 4 # max children per B-tree node = M-1
|
||||||
# (must be even and greater than 2)
|
# (must be even and greater than 2)
|
||||||
Mhalf = M div 2
|
Mhalf = M div 2
|
||||||
|
|
||||||
|
SupportFullTableScan = true
|
||||||
|
SupportDuplicateKeys = true
|
||||||
|
|
||||||
|
## Due to the fact that leaves are shared among multiple BTrees the following
|
||||||
|
## fields in a Node are downright impossible:
|
||||||
|
## - parent
|
||||||
|
## - next
|
||||||
|
## - prev
|
||||||
|
|
||||||
type
|
type
|
||||||
Key = string
|
Key = string
|
||||||
Val = string
|
Val = string
|
||||||
|
|
@ -24,6 +39,12 @@ type
|
||||||
root: Node
|
root: Node
|
||||||
height: int ## height
|
height: int ## height
|
||||||
n: int ## number of key-value pairs
|
n: int ## number of key-value pairs
|
||||||
|
CmpKind {.pure.} = enum
|
||||||
|
eq, le, lt, ge, gt, neq
|
||||||
|
Cursor = object
|
||||||
|
n: Node
|
||||||
|
i, dir: int
|
||||||
|
up: seq[(Node, int)]
|
||||||
|
|
||||||
proc newBTree(): BTree = BTree(root: Node(m: 0, isInternal: false))
|
proc newBTree(): BTree = BTree(root: Node(m: 0, isInternal: false))
|
||||||
|
|
||||||
|
|
@ -42,6 +63,86 @@ proc search(x: Node, key: Key, ht: int): Val =
|
||||||
if j+1 == x.m or less(key, x.keys[j+1]):
|
if j+1 == x.m or less(key, x.keys[j+1]):
|
||||||
return search(x.links[j], key, ht-1)
|
return search(x.links[j], key, ht-1)
|
||||||
|
|
||||||
|
proc `=~`(i: int; k: CmpKind): bool =
|
||||||
|
## check if the result of 'cmp' matches what was requested by 'k':
|
||||||
|
case k
|
||||||
|
of CmpKind.eq: i == 0
|
||||||
|
of CmpKind.le: i <= 0
|
||||||
|
of CmpKind.lt: i < 0
|
||||||
|
of CmpKind.ge: i >= 0
|
||||||
|
of CmpKind.gt: i > 0
|
||||||
|
of CmpKind.neq: i != 0
|
||||||
|
|
||||||
|
proc canPrune(i: int; k: CmpKind): bool =
|
||||||
|
case k
|
||||||
|
of CmpKind.eq:
|
||||||
|
# we demand equality so if bigger, we can prune:
|
||||||
|
i > 0
|
||||||
|
of CmpKind.le:
|
||||||
|
i > 0
|
||||||
|
of CmpKind.lt: i >= 0
|
||||||
|
of CmpKind.ge: i < 0
|
||||||
|
of CmpKind.gt: i <= 0
|
||||||
|
of CmpKind.neq: i != 0
|
||||||
|
|
||||||
|
proc startingPoint(x: Node; key: Key; kind: CmpKind): Cursor =
|
||||||
|
if x.isInternal:
|
||||||
|
for j in 0 ..< x.m:
|
||||||
|
if j+1 == x.m or cmp(key, x.keys[j+1]) =~ kind:
|
||||||
|
return startingPoint(x.links[j], key, kind)
|
||||||
|
else:
|
||||||
|
for j in 0 ..< x.m:
|
||||||
|
let cmpRes = cmp(key, x.keys[j])
|
||||||
|
if cmpRes =~ kind: return Cursor(n: x, i: j)
|
||||||
|
|
||||||
|
proc dos(x: Node; key: Key; kind: CmpKind; withKey: proc(k: Key; v: Val)) =
|
||||||
|
if not x.isInternal:
|
||||||
|
echo "came here"
|
||||||
|
for j in 0 ..< x.m:
|
||||||
|
if cmp(key, x.keys[j]) =~ kind:
|
||||||
|
withKey(x.keys[j+1], x.vals[j])
|
||||||
|
else:
|
||||||
|
for j in 0 ..< x.m-1:
|
||||||
|
let cmpRes = cmp(key, x.keys[j+1])
|
||||||
|
echo "came here B ", canPrune(cmpRes, kind)
|
||||||
|
if not canPrune(cmpRes, kind): #cmpRes =~ kind:
|
||||||
|
dos(x.links[j], key, kind, withKey)
|
||||||
|
#if canPrune(cmpRes, kind): return
|
||||||
|
# XXX j+1==x.m case?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
proc init(x: Node): Cursor =
|
||||||
|
result.up = @[]
|
||||||
|
result.i = 0
|
||||||
|
var it = x
|
||||||
|
while it.isInternal:
|
||||||
|
result.up.add((it, 0))
|
||||||
|
it = it.links[0]
|
||||||
|
result.n = it
|
||||||
|
|
||||||
|
proc next(c: var Cursor) =
|
||||||
|
assert c.n != nil
|
||||||
|
if c.i >= c.n.m:
|
||||||
|
# current leaf exhausted, pick the next one:
|
||||||
|
if c.up.len > 0:
|
||||||
|
(c.n, c.i) = c.up.pop()
|
||||||
|
|
||||||
|
inc c.i
|
||||||
|
var u = 1
|
||||||
|
while c.i > c.n.m or c.n.isInternal:
|
||||||
|
if c.up.len > 0:
|
||||||
|
(c.n, c.i) = c.up[c.up.len - u]
|
||||||
|
else:
|
||||||
|
c.n = nil
|
||||||
|
return
|
||||||
|
assert(c.n == nil or not c.n.isInternal)
|
||||||
|
|
||||||
|
proc atEnd(c: Cursor): bool = c.n == nil
|
||||||
|
|
||||||
|
proc getKey(c: Cursor): Key = discard
|
||||||
|
proc getVal(c: Cursor): Val = discard
|
||||||
|
|
||||||
proc get(t: BTree; key: Key): Val = search(t.root, key, t.height)
|
proc get(t: BTree; key: Key): Val = search(t.root, key, t.height)
|
||||||
|
|
||||||
proc copyHalf(h, result: Node; offset: int) =
|
proc copyHalf(h, result: Node; offset: int) =
|
||||||
|
|
@ -187,6 +288,7 @@ proc `$`(b: BTree): string =
|
||||||
result = ""
|
result = ""
|
||||||
toString(b.root, b.height, "", result)
|
toString(b.root, b.height, "", result)
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
proc main =
|
proc main =
|
||||||
var st = newBTree()
|
var st = newBTree()
|
||||||
st.put("www.cs.princeton.edu", "abc")
|
st.put("www.cs.princeton.edu", "abc")
|
||||||
|
|
@ -231,7 +333,7 @@ proc main =
|
||||||
when true:
|
when true:
|
||||||
var b1 = newBTree()
|
var b1 = newBTree()
|
||||||
var b2 = newBTree()
|
var b2 = newBTree()
|
||||||
const iters = 60_000
|
const iters = 10 #60_000
|
||||||
for i in 1..iters:
|
for i in 1..iters:
|
||||||
b2 = b2.putPs($i, $(iters - i))
|
b2 = b2.putPs($i, $(iters - i))
|
||||||
b1.put($i, $(iters - i))
|
b1.put($i, $(iters - i))
|
||||||
|
|
@ -241,5 +343,6 @@ proc main =
|
||||||
echo i, "th iteration; got ", x, ", but expected ", iters - i
|
echo i, "th iteration; got ", x, ", but expected ", iters - i
|
||||||
echo b2.n, " = ", b1.n
|
echo b2.n, " = ", b1.n
|
||||||
echo b2.height, " = ", b1.height
|
echo b2.height, " = ", b1.height
|
||||||
|
dos(b1.root, "5", CmpKind.eq, proc(k: Key; v: Val) = echo("k ", k, " = ", v))
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue