Commit 8c6d44a3 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 553ef8bf
...@@ -25,8 +25,8 @@ It is primarily used to verify ΔBTail in wcfs. ...@@ -25,8 +25,8 @@ It is primarily used to verify ΔBTail in wcfs.
- `Tree` represents a tree node. - `Tree` represents a tree node.
- `Bucket` represents a bucket node. - `Bucket` represents a bucket node.
- `StructureOf` returns internal structure of a BTree represented as Tree and - `StructureOf` returns internal structure of ZODB BTree represented as Tree
Bucket nodes. and Bucket nodes.
- `Restructure` XXX - `Restructure` XXX
- `AllStructs` XXX - `AllStructs` XXX
...@@ -129,17 +129,13 @@ class Tree(object): ...@@ -129,17 +129,13 @@ class Tree(object):
s += _indent(' '*4, str(ch)) s += _indent(' '*4, str(ch))
s += ")" s += ")"
return s return s
__repr__ = __str__ __repr__ = __str__
#def __repr__(t):
# return 'R'+str(t)
# TODO def graphviz() -> str for graphviz
# Bucket represents a bucket node. # Bucket represents a bucket node.
class Bucket(object): class Bucket(object):
# .keyv () of keys # .keyv () of keys
def __init__(b, *keyv): # XXX *keyv -> keyv ? def __init__(b, *keyv):
_assertIncv(keyv) _assertIncv(keyv)
b.keyv = tuple(keyv) b.keyv = tuple(keyv)
...@@ -154,7 +150,6 @@ class Bucket(object): ...@@ -154,7 +150,6 @@ class Bucket(object):
def __str__(b): def __str__(b):
return "B(" + ','.join(['%s' % _ for _ in b.keyv]) + ")" return "B(" + ','.join(['%s' % _ for _ in b.keyv]) + ")"
__repr__ = __str__ __repr__ = __str__
...@@ -190,6 +185,103 @@ def StructureOf(node): ...@@ -190,6 +185,103 @@ def StructureOf(node):
panic("unknown node type %r" % typ) panic("unknown node type %r" % typ)
# Restructure reorganizes BTree instance (not Tree) according to new structure.
def Restructure(tree, newStructure):
assert istree(tree)
assert isinstance(newStructure, Tree)
1/0
# AllStructs generates subset of all possible BTree structures for BTrees with
# specified keys and btree depth up-to maxdepth. Each tree node is split by
# up-to maxsplit points.
def AllStructs(keys, maxdepth, maxsplit): # -> i[] of Tree
assert isinstance(maxdepth, int); assert maxdepth >= 0
assert isinstance(maxsplit, int); assert maxsplit >= 0
ks = set(keys)
for k in keys:
assert isinstance(k, int)
assert k in ks # no duplicates
ks.remove(k)
keyv = list(keys)
keyv.sort()
# initial [lo, hi) covering keys and such that split points will be there withing +-1 of min/max key
#klo = -inf
#khi = +inf
if len(keyv) > 0:
klo = keyv[0] - 1 - 1
khi = keyv[-1] + 1 + 1 # hi is ")", not "]"
else:
# XXX ok? (should be -inf,+inf)
klo = 0
khi = 0
for tree in _allStructs(klo, khi, keyv, maxdepth, maxsplit):
yield tree
def _allStructs(klo, khi, keyv, maxdepth, maxsplit):
assert klo <= khi
_assertIncv(keyv)
if len(keyv) > 0:
assert klo <= keyv[0]
assert keyv[-1] < khi
#print('_allStructs [%s, %s) keyv: %r, maxdepth=%d, maxsplit=%d' %
# (klo, khi, keyv, maxdepth, maxsplit))
for nsplit in range(0, maxsplit+1):
for ksplitv in _iterSplitByN(klo, khi, nsplit):
# ksplitv = [klo, s1, s2, ..., sN, khi]
#print('ksplitv: %r' % ksplitv)
# emit Tree -> Buckets
children = []
for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi)
children.append(Bucket(*_keyvSliceBy(keyv, xlo, xhi)))
yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN)
# emit Tree -> Trees -> ...
if maxdepth == 0:
continue
ichildrenv = [] # of _allStructs for each child link
for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi)
ichildrenv.append( _allStructs(
xlo, xhi, _keyvSliceBy(keyv, xlo, xhi), maxdepth - 1, maxsplit))
for children in itertools.product(*ichildrenv):
yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN)
# _keyvSliceBy returns [] of keys from keyv : k ∈ [klo, khi)
def _keyvSliceBy(keyv, klo, khi):
assert klo <= khi
_assertIncv(keyv)
return list([k for k in keyv if (klo <= k < khi)])
# _iterSplitByN iterates through all nsplit splitting of [lo, hi) range.
# hi > lo
# XXX nsplit > ...
# lo < si < hi
# si < s_{i+1}
#
# XXX remove lo and hi from the output?
def _iterSplitByN(lo, hi, nsplit): # -> i[] of [lo, s1, s2, ..., sn, hi)
assert lo <= hi
assert nsplit >= 0
if nsplit == 0:
yield [lo, hi]
return
for s in range(lo+1, hi): # [lo+1, hi-1]
for tail in _iterSplitByN(s, hi, nsplit-1):
yield [lo] + tail
# ---- topology encoding ----
# TopoEncode returns topology encoding for internal structure of the tree. # TopoEncode returns topology encoding for internal structure of the tree.
# #
# See top-level docstring for description of topology encoding. # See top-level docstring for description of topology encoding.
...@@ -209,30 +301,6 @@ def TopoEncode(tree): ...@@ -209,30 +301,6 @@ def TopoEncode(tree):
tnodev.append(tnode) tnodev.append(tnode)
topo += '-'.join(tnodev) topo += '-'.join(tnodev)
"""
queue = [tree, '/']
while 1:
x = queue.pop(0)
if x == '/':
if len(queue) == 0:
break # it was last '/'
topo += '/'
queue.append('/') # add / after all queued nodes of next layer
continue
node = x
assert isinstance(node, (Tree, Bucket))
tnode = ('T' if isinstance(node, Tree) else 'B') + \
(','.join(['%d' % _ for _ in node.keyv]))
if len(topo) != 0 and topo[-1] != '/':
topo += '-'
topo += tnode
if isinstance(node, Tree):
queue += node.children
"""
if 1: # make sure that every topology we emit, can be loaded back if 1: # make sure that every topology we emit, can be loaded back
t2 = TopoDecode(topo) t2 = TopoDecode(topo)
if t2 != tree: if t2 != tree:
...@@ -313,100 +381,6 @@ def TopoDecode(text): ...@@ -313,100 +381,6 @@ def TopoDecode(text):
return root return root
# Restructure reorganizes BTree instance (not Tree) according to new structure.
def Restructure(tree, newStructure):
assert istree(tree)
assert isinstance(newStructure, Tree)
1/0
# AllStructs generates subset of all possible BTree structures for BTrees with
# specified keys and btree depth up-to maxdepth. Each tree node is split by
# up-to maxsplit points.
def AllStructs(keys, maxdepth, maxsplit): # -> i[] of Tree
assert isinstance(maxdepth, int); assert maxdepth >= 0
assert isinstance(maxsplit, int); assert maxsplit >= 0
ks = set(keys)
for k in keys:
assert isinstance(k, int)
assert k in ks # no duplicates
ks.remove(k)
keyv = list(keys)
keyv.sort()
# initial [lo, hi) covering keys and such that split points will be there withing +-1 of min/max key
#klo = -inf
#khi = +inf
if len(keyv) > 0:
klo = keyv[0] - 1 - 1
khi = keyv[-1] + 1 + 1 # hi is ")", not "]"
else:
# XXX ok? (should be -inf,+inf)
klo = 0
khi = 0
for tree in _allStructs(klo, khi, keyv, maxdepth, maxsplit):
yield tree
def _allStructs(klo, khi, keyv, maxdepth, maxsplit):
assert klo <= khi
_assertIncv(keyv)
if len(keyv) > 0:
assert klo <= keyv[0]
assert keyv[-1] < khi
#print('_allStructs [%s, %s) keyv: %r, maxdepth=%d, maxsplit=%d' %
# (klo, khi, keyv, maxdepth, maxsplit))
for nsplit in range(0, maxsplit+1):
for ksplitv in _iterSplitByN(klo, khi, nsplit):
# ksplitv = [klo, s1, s2, ..., sN, khi]
#print('ksplitv: %r' % ksplitv)
# emit Tree -> Buckets
children = []
for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi)
children.append(Bucket(*_keyvSliceBy(keyv, xlo, xhi)))
yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN)
# emit Tree -> Trees -> ...
if maxdepth == 0:
continue
ichildrenv = [] # of _allStructs for each child link
for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi)
ichildrenv.append( _allStructs(
xlo, xhi, _keyvSliceBy(keyv, xlo, xhi), maxdepth - 1, maxsplit))
for children in itertools.product(*ichildrenv):
yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN)
# _keyvSliceBy returns [] of keys from keyv : k ∈ [klo, khi)
def _keyvSliceBy(keyv, klo, khi):
assert klo <= khi
_assertIncv(keyv)
return list([k for k in keyv if (klo <= k < khi)])
# _iterSplitByN iterates through all nsplit splitting of [lo, hi) range.
# hi > lo
# XXX nsplit > ...
# lo < si < hi
# si < s_{i+1}
#
# XXX remove lo and hi from the output?
def _iterSplitByN(lo, hi, nsplit): # -> i[] of [lo, s1, s2, ..., sn, hi)
assert lo <= hi
assert nsplit >= 0
if nsplit == 0:
yield [lo, hi]
return
for s in range(lo+1, hi): # [lo+1, hi-1]
for tail in _iterSplitByN(s, hi, nsplit-1):
yield [lo] + tail
# ---- misc ---- # ---- misc ----
# _indent returns text with each line of it indented with prefix. # _indent returns text with each line of it indented with prefix.
......
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