Optimized dbg*.py tree generation/rendering by deduplicating edges
Optimizing a script? This might sound premature, but the tree rendering was, uh, quite slow for any decently sized (>1024) btree. The main reason is that tree generation is quite hacky in places, repeatedly spitting out multiple copies of the inner node's rbyd trees for example. Rather than rewrite the tree generation implementation to be smarter, this just changes all edge representations to namedtuples (which may reduce memory pressure a bit), and collects them into a Python set. This has the effect of deduplicating generated edges efficiently, and improved the rendering performance significantly. --- I also considered memoizing rbyd tree, but dropped the idea since the current renderer performs well enough.
This commit is contained in:
+98
-92
@@ -177,6 +177,10 @@ def tagrepr(tag, w, size, off=None):
|
|||||||
else:
|
else:
|
||||||
return '0x%04x w%d %d' % (tag, w, size)
|
return '0x%04x w%d %d' % (tag, w, size)
|
||||||
|
|
||||||
|
# this type is used for tree representations
|
||||||
|
TBranch = co.namedtuple('TBranch', 'a, b, d, c')
|
||||||
|
|
||||||
|
# our core rbyd type
|
||||||
class Rbyd:
|
class Rbyd:
|
||||||
def __init__(self, block, data, rev, off, trunk, weight):
|
def __init__(self, block, data, rev, off, trunk, weight):
|
||||||
self.block = block
|
self.block = block
|
||||||
@@ -444,21 +448,21 @@ class Rbyd:
|
|||||||
t_depth = max((alt['h']+1 for alt in alts.values()), default=0)
|
t_depth = max((alt['h']+1 for alt in alts.values()), default=0)
|
||||||
|
|
||||||
# convert to more general tree representation
|
# convert to more general tree representation
|
||||||
tree = []
|
tree = set()
|
||||||
for j, alt in alts.items():
|
for j, alt in alts.items():
|
||||||
# note all non-trunk edges should be black
|
# note all non-trunk edges should be black
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': alt['nft'],
|
a=alt['nft'],
|
||||||
'b': alt['nft'],
|
b=alt['nft'],
|
||||||
'd': t_depth-1 - alt['h'],
|
d=t_depth-1 - alt['h'],
|
||||||
'c': alt['c'],
|
c=alt['c'],
|
||||||
})
|
))
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': alt['nft'],
|
a=alt['nft'],
|
||||||
'b': alt['ft'],
|
b=alt['ft'],
|
||||||
'd': t_depth-1 - alt['h'],
|
d=t_depth-1 - alt['h'],
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
return tree, t_depth
|
return tree, t_depth
|
||||||
|
|
||||||
@@ -566,7 +570,7 @@ def main(disk, roots=None, *,
|
|||||||
bdepths[d] = max(bdepths.get(d, 0), rdepth)
|
bdepths[d] = max(bdepths.get(d, 0), rdepth)
|
||||||
|
|
||||||
# find all branches
|
# find all branches
|
||||||
tree = []
|
tree = set()
|
||||||
root = None
|
root = None
|
||||||
branches = {}
|
branches = {}
|
||||||
bid = -1
|
bid = -1
|
||||||
@@ -588,45 +592,47 @@ def main(disk, roots=None, *,
|
|||||||
# note we adjust our bid/rids to be left-leaning,
|
# note we adjust our bid/rids to be left-leaning,
|
||||||
# this allows a global order and make tree rendering quite
|
# this allows a global order and make tree rendering quite
|
||||||
# a bit easier
|
# a bit easier
|
||||||
for i in range(len(rtree)):
|
rtree_ = set()
|
||||||
a_rid, a_tag = rtree[i]['a']
|
for branch in rtree:
|
||||||
b_rid, b_tag = rtree[i]['b']
|
a_rid, a_tag = branch.a
|
||||||
|
b_rid, b_tag = branch.b
|
||||||
_, _, _, a_w, _, _, _, _ = rbyd.lookup(a_rid, 0)
|
_, _, _, a_w, _, _, _, _ = rbyd.lookup(a_rid, 0)
|
||||||
_, _, _, b_w, _, _, _, _ = rbyd.lookup(b_rid, 0)
|
_, _, _, b_w, _, _, _, _ = rbyd.lookup(b_rid, 0)
|
||||||
rtree[i] = {
|
rtree_.add(TBranch(
|
||||||
'a': (a_rid-(a_w-1), a_tag),
|
a=(a_rid-(a_w-1), a_tag),
|
||||||
'b': (b_rid-(b_w-1), b_tag),
|
b=(b_rid-(b_w-1), b_tag),
|
||||||
'd': rtree[i]['d'],
|
d=branch.d,
|
||||||
'c': rtree[i]['c'],
|
c=branch.c,
|
||||||
}
|
))
|
||||||
|
rtree = rtree_
|
||||||
|
|
||||||
# connect our branch to the rbyd's root
|
# connect our branch to the rbyd's root
|
||||||
if leaf is not None:
|
if leaf is not None:
|
||||||
root = min(rtree,
|
root = min(rtree,
|
||||||
key=lambda branch: branch['d'],
|
key=lambda branch: branch.d,
|
||||||
default=None)
|
default=None)
|
||||||
|
|
||||||
if root is not None:
|
if root is not None:
|
||||||
r_rid, r_tag = root['a']
|
r_rid, r_tag = root.a
|
||||||
else:
|
else:
|
||||||
r_rid, r_tag = rid-(w-1), tags[0][0]
|
r_rid, r_tag = rid-(w-1), tags[0][0]
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': leaf,
|
a=leaf,
|
||||||
'b': (bid-rid+r_rid, d, r_rid, r_tag),
|
b=(bid-rid+r_rid, d, r_rid, r_tag),
|
||||||
'd': d_-1,
|
d=d_-1,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
for branch in rtree:
|
for branch in rtree:
|
||||||
# map rbyd branches into our btree space
|
# map rbyd branches into our btree space
|
||||||
a_rid, a_tag = branch['a']
|
a_rid, a_tag = branch.a
|
||||||
b_rid, b_tag = branch['b']
|
b_rid, b_tag = branch.b
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (bid-rid+a_rid, d, a_rid, a_tag),
|
a=(bid-rid+a_rid, d, a_rid, a_tag),
|
||||||
'b': (bid-rid+b_rid, d, b_rid, b_tag),
|
b=(bid-rid+b_rid, d, b_rid, b_tag),
|
||||||
'd': branch['d'] + d_ + bdepths.get(d, 0)-rdepth,
|
d=branch.d + d_ + bdepths.get(d, 0)-rdepth,
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
})
|
))
|
||||||
|
|
||||||
d_ += max(bdepths.get(d, 0), 1)
|
d_ += max(bdepths.get(d, 0), 1)
|
||||||
leaf = (bid-(w-1), d, rid-(w-1), TAG_BTREE)
|
leaf = (bid-(w-1), d, rid-(w-1), TAG_BTREE)
|
||||||
@@ -634,49 +640,49 @@ def main(disk, roots=None, *,
|
|||||||
# remap branches to leaves if we aren't showing inner branches
|
# remap branches to leaves if we aren't showing inner branches
|
||||||
if not args.get('inner'):
|
if not args.get('inner'):
|
||||||
# step through each layer backwards
|
# step through each layer backwards
|
||||||
b_depth = max((branch['a'][1]+1 for branch in tree), default=0)
|
b_depth = max((branch.a[1]+1 for branch in tree), default=0)
|
||||||
|
|
||||||
# keep track of the original tree to find the original bids,
|
# keep track of the original bids, unfortunately because we
|
||||||
# unfortunately because we store the bids in the branches we
|
# store the bids in the branches we overwrite these
|
||||||
# overwrite these
|
tree = {(branch.b[0] - branch.b[2], branch) for branch in tree}
|
||||||
tree_ = tree.copy()
|
|
||||||
|
|
||||||
for bd in reversed(range(b_depth-1)):
|
for bd in reversed(range(b_depth-1)):
|
||||||
# find leaf-roots at this level
|
# find leaf-roots at this level
|
||||||
roots = {}
|
roots = {}
|
||||||
for branch_, branch in zip(tree_, tree):
|
for bid, branch in tree:
|
||||||
bid = branch['b'][0] - branch['b'][2]
|
|
||||||
# choose the highest node as the root
|
# choose the highest node as the root
|
||||||
if (branch_['b'][1] == b_depth-1
|
if (branch.b[1] == b_depth-1
|
||||||
and (bid not in roots
|
and (bid not in roots
|
||||||
or branch_['d'] < roots[bid]['d'])):
|
or branch.d < roots[bid].d)):
|
||||||
roots[bid] = branch_
|
roots[bid] = branch
|
||||||
|
|
||||||
# remap branches to leaf-roots
|
# remap branches to leaf-roots
|
||||||
tree__ = []
|
tree_ = set()
|
||||||
for branch_ in tree_:
|
for bid, branch in tree:
|
||||||
if branch_['a'][1] == bd and branch_['a'][0] in roots:
|
if branch.a[1] == bd and branch.a[0] in roots:
|
||||||
branch_ = {
|
branch = TBranch(
|
||||||
'a': roots[branch_['a'][0]]['b'],
|
a=roots[branch.a[0]].b,
|
||||||
'b': branch_['b'],
|
b=branch.b,
|
||||||
'd': branch_['d'],
|
d=branch.d,
|
||||||
'c': branch_['c'],
|
c=branch.c,
|
||||||
}
|
)
|
||||||
if branch_['b'][1] == bd and branch_['b'][0] in roots:
|
if branch.b[1] == bd and branch.b[0] in roots:
|
||||||
branch_ = {
|
branch = TBranch(
|
||||||
'a': branch_['a'],
|
a=branch.a,
|
||||||
'b': roots[branch_['b'][0]]['b'],
|
b=roots[branch.b[0]].b,
|
||||||
'd': branch_['d'],
|
d=branch.d,
|
||||||
'c': branch_['c'],
|
c=branch.c,
|
||||||
}
|
)
|
||||||
tree__.append(branch_)
|
tree_.add((bid, branch))
|
||||||
tree_ = tree__
|
tree = tree_
|
||||||
tree = tree_
|
|
||||||
|
# strip out bids
|
||||||
|
tree = {branch for _, branch in tree}
|
||||||
|
|
||||||
# precompute B-trees if requested
|
# precompute B-trees if requested
|
||||||
elif args.get('btree'):
|
elif args.get('btree'):
|
||||||
# find all branches
|
# find all branches
|
||||||
tree = []
|
tree = set()
|
||||||
root = None
|
root = None
|
||||||
branches = {}
|
branches = {}
|
||||||
bid = -1
|
bid = -1
|
||||||
@@ -724,18 +730,18 @@ def main(disk, roots=None, *,
|
|||||||
root = b
|
root = b
|
||||||
a = root
|
a = root
|
||||||
|
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': a,
|
a=a,
|
||||||
'b': b,
|
b=b,
|
||||||
'd': d,
|
d=d,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
a = b
|
a = b
|
||||||
|
|
||||||
# common tree renderer
|
# common tree renderer
|
||||||
if args.get('tree') or args.get('btree'):
|
if args.get('tree') or args.get('btree'):
|
||||||
# find the max depth from the tree
|
# find the max depth from the tree
|
||||||
t_depth = max((branch['d']+1 for branch in tree), default=0)
|
t_depth = max((branch.d+1 for branch in tree), default=0)
|
||||||
if t_depth > 0:
|
if t_depth > 0:
|
||||||
t_width = 2*t_depth + 2
|
t_width = 2*t_depth + 2
|
||||||
|
|
||||||
@@ -745,27 +751,27 @@ def main(disk, roots=None, *,
|
|||||||
|
|
||||||
def branchrepr(x, d, was):
|
def branchrepr(x, d, was):
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if branch['d'] == d and branch['b'] == x:
|
if branch.d == d and branch.b == x:
|
||||||
if any(branch['d'] == d and branch['a'] == x
|
if any(branch.d == d and branch.a == x
|
||||||
for branch in tree):
|
for branch in tree):
|
||||||
return '+-', branch['c'], branch['c']
|
return '+-', branch.c, branch.c
|
||||||
elif any(branch['d'] == d
|
elif any(branch.d == d
|
||||||
and x > min(branch['a'], branch['b'])
|
and x > min(branch.a, branch.b)
|
||||||
and x < max(branch['a'], branch['b'])
|
and x < max(branch.a, branch.b)
|
||||||
for branch in tree):
|
for branch in tree):
|
||||||
return '|-', branch['c'], branch['c']
|
return '|-', branch.c, branch.c
|
||||||
elif branch['a'] < branch['b']:
|
elif branch.a < branch.b:
|
||||||
return '\'-', branch['c'], branch['c']
|
return '\'-', branch.c, branch.c
|
||||||
else:
|
else:
|
||||||
return '.-', branch['c'], branch['c']
|
return '.-', branch.c, branch.c
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if branch['d'] == d and branch['a'] == x:
|
if branch.d == d and branch.a == x:
|
||||||
return '+ ', branch['c'], None
|
return '+ ', branch.c, None
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if (branch['d'] == d
|
if (branch.d == d
|
||||||
and x > min(branch['a'], branch['b'])
|
and x > min(branch.a, branch.b)
|
||||||
and x < max(branch['a'], branch['b'])):
|
and x < max(branch.a, branch.b)):
|
||||||
return '| ', branch['c'], was
|
return '| ', branch.c, was
|
||||||
if was:
|
if was:
|
||||||
return '--', was, was
|
return '--', was, was
|
||||||
return ' ', None, None
|
return ' ', None, None
|
||||||
|
|||||||
+249
-243
@@ -186,6 +186,10 @@ def tagrepr(tag, w, size, off=None):
|
|||||||
else:
|
else:
|
||||||
return '0x%04x w%d %d' % (tag, w, size)
|
return '0x%04x w%d %d' % (tag, w, size)
|
||||||
|
|
||||||
|
# this type is used for tree representations
|
||||||
|
TBranch = co.namedtuple('TBranch', 'a, b, d, c')
|
||||||
|
|
||||||
|
# our core rbyd type
|
||||||
class Rbyd:
|
class Rbyd:
|
||||||
def __init__(self, block, data, rev, off, trunk, weight):
|
def __init__(self, block, data, rev, off, trunk, weight):
|
||||||
self.block = block
|
self.block = block
|
||||||
@@ -453,21 +457,21 @@ class Rbyd:
|
|||||||
t_depth = max((alt['h']+1 for alt in alts.values()), default=0)
|
t_depth = max((alt['h']+1 for alt in alts.values()), default=0)
|
||||||
|
|
||||||
# convert to more general tree representation
|
# convert to more general tree representation
|
||||||
tree = []
|
tree = set()
|
||||||
for j, alt in alts.items():
|
for j, alt in alts.items():
|
||||||
# note all non-trunk edges should be black
|
# note all non-trunk edges should be black
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': alt['nft'],
|
a=alt['nft'],
|
||||||
'b': alt['nft'],
|
b=alt['nft'],
|
||||||
'd': t_depth-1 - alt['h'],
|
d=t_depth-1 - alt['h'],
|
||||||
'c': alt['c'],
|
c=alt['c'],
|
||||||
})
|
))
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': alt['nft'],
|
a=alt['nft'],
|
||||||
'b': alt['ft'],
|
b=alt['ft'],
|
||||||
'd': t_depth-1 - alt['h'],
|
d=t_depth-1 - alt['h'],
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
return tree, t_depth
|
return tree, t_depth
|
||||||
|
|
||||||
@@ -544,7 +548,7 @@ class Rbyd:
|
|||||||
bdepths[d] = max(bdepths.get(d, 0), rdepth)
|
bdepths[d] = max(bdepths.get(d, 0), rdepth)
|
||||||
|
|
||||||
# find all branches
|
# find all branches
|
||||||
tree = []
|
tree = set()
|
||||||
root = None
|
root = None
|
||||||
branches = {}
|
branches = {}
|
||||||
bid = -1
|
bid = -1
|
||||||
@@ -566,45 +570,47 @@ class Rbyd:
|
|||||||
# note we adjust our bid/rids to be left-leaning,
|
# note we adjust our bid/rids to be left-leaning,
|
||||||
# this allows a global order and make tree rendering quite
|
# this allows a global order and make tree rendering quite
|
||||||
# a bit easier
|
# a bit easier
|
||||||
for i in range(len(rtree)):
|
rtree_ = set()
|
||||||
a_rid, a_tag = rtree[i]['a']
|
for branch in rtree:
|
||||||
b_rid, b_tag = rtree[i]['b']
|
a_rid, a_tag = branch.a
|
||||||
|
b_rid, b_tag = branch.b
|
||||||
_, _, _, a_w, _, _, _, _ = rbyd.lookup(a_rid, 0)
|
_, _, _, a_w, _, _, _, _ = rbyd.lookup(a_rid, 0)
|
||||||
_, _, _, b_w, _, _, _, _ = rbyd.lookup(b_rid, 0)
|
_, _, _, b_w, _, _, _, _ = rbyd.lookup(b_rid, 0)
|
||||||
rtree[i] = {
|
rtree_.add(TBranch(
|
||||||
'a': (a_rid-(a_w-1), a_tag),
|
a=(a_rid-(a_w-1), a_tag),
|
||||||
'b': (b_rid-(b_w-1), b_tag),
|
b=(b_rid-(b_w-1), b_tag),
|
||||||
'd': rtree[i]['d'],
|
d=branch.d,
|
||||||
'c': rtree[i]['c'],
|
c=branch.c,
|
||||||
}
|
))
|
||||||
|
rtree = rtree_
|
||||||
|
|
||||||
# connect our branch to the rbyd's root
|
# connect our branch to the rbyd's root
|
||||||
if leaf is not None:
|
if leaf is not None:
|
||||||
root = min(rtree,
|
root = min(rtree,
|
||||||
key=lambda branch: branch['d'],
|
key=lambda branch: branch.d,
|
||||||
default=None)
|
default=None)
|
||||||
|
|
||||||
if root is not None:
|
if root is not None:
|
||||||
r_rid, r_tag = root['a']
|
r_rid, r_tag = root.a
|
||||||
else:
|
else:
|
||||||
r_rid, r_tag = rid-(w-1), tags[0][0]
|
r_rid, r_tag = rid-(w-1), tags[0][0]
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': leaf,
|
a=leaf,
|
||||||
'b': (bid-rid+r_rid, d, r_rid, r_tag),
|
b=(bid-rid+r_rid, d, r_rid, r_tag),
|
||||||
'd': d_-1,
|
d=d_-1,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
for branch in rtree:
|
for branch in rtree:
|
||||||
# map rbyd branches into our btree space
|
# map rbyd branches into our btree space
|
||||||
a_rid, a_tag = branch['a']
|
a_rid, a_tag = branch.a
|
||||||
b_rid, b_tag = branch['b']
|
b_rid, b_tag = branch.b
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (bid-rid+a_rid, d, a_rid, a_tag),
|
a=(bid-rid+a_rid, d, a_rid, a_tag),
|
||||||
'b': (bid-rid+b_rid, d, b_rid, b_tag),
|
b=(bid-rid+b_rid, d, b_rid, b_tag),
|
||||||
'd': branch['d'] + d_ + bdepths.get(d, 0)-rdepth,
|
d=branch.d + d_ + bdepths.get(d, 0)-rdepth,
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
})
|
))
|
||||||
|
|
||||||
d_ += max(bdepths.get(d, 0), 1)
|
d_ += max(bdepths.get(d, 0), 1)
|
||||||
leaf = (bid-(w-1), d, rid-(w-1), TAG_BTREE)
|
leaf = (bid-(w-1), d, rid-(w-1), TAG_BTREE)
|
||||||
@@ -612,52 +618,52 @@ class Rbyd:
|
|||||||
# remap branches to leaves if we aren't showing inner branches
|
# remap branches to leaves if we aren't showing inner branches
|
||||||
if not inner:
|
if not inner:
|
||||||
# step through each layer backwards
|
# step through each layer backwards
|
||||||
b_depth = max((branch['a'][1]+1 for branch in tree), default=0)
|
b_depth = max((branch.a[1]+1 for branch in tree), default=0)
|
||||||
|
|
||||||
# keep track of the original tree to find the original bids,
|
# keep track of the original bids, unfortunately because we
|
||||||
# unfortunately because we store the bids in the branches we
|
# store the bids in the branches we overwrite these
|
||||||
# overwrite these
|
tree = {(branch.b[0] - branch.b[2], branch) for branch in tree}
|
||||||
tree_ = tree.copy()
|
|
||||||
|
|
||||||
for bd in reversed(range(b_depth-1)):
|
for bd in reversed(range(b_depth-1)):
|
||||||
# find leaf-roots at this level
|
# find leaf-roots at this level
|
||||||
roots = {}
|
roots = {}
|
||||||
for branch_, branch in zip(tree_, tree):
|
for bid, branch in tree:
|
||||||
bid = branch['b'][0] - branch['b'][2]
|
|
||||||
# choose the highest node as the root
|
# choose the highest node as the root
|
||||||
if (branch_['b'][1] == b_depth-1
|
if (branch.b[1] == b_depth-1
|
||||||
and (bid not in roots
|
and (bid not in roots
|
||||||
or branch_['d'] < roots[bid]['d'])):
|
or branch.d < roots[bid].d)):
|
||||||
roots[bid] = branch_
|
roots[bid] = branch
|
||||||
|
|
||||||
# remap branches to leaf-roots
|
# remap branches to leaf-roots
|
||||||
tree__ = []
|
tree_ = set()
|
||||||
for branch_ in tree_:
|
for bid, branch in tree:
|
||||||
if branch_['a'][1] == bd and branch_['a'][0] in roots:
|
if branch.a[1] == bd and branch.a[0] in roots:
|
||||||
branch_ = {
|
branch = TBranch(
|
||||||
'a': roots[branch_['a'][0]]['b'],
|
a=roots[branch.a[0]].b,
|
||||||
'b': branch_['b'],
|
b=branch.b,
|
||||||
'd': branch_['d'],
|
d=branch.d,
|
||||||
'c': branch_['c'],
|
c=branch.c,
|
||||||
}
|
)
|
||||||
if branch_['b'][1] == bd and branch_['b'][0] in roots:
|
if branch.b[1] == bd and branch.b[0] in roots:
|
||||||
branch_ = {
|
branch = TBranch(
|
||||||
'a': branch_['a'],
|
a=branch.a,
|
||||||
'b': roots[branch_['b'][0]]['b'],
|
b=roots[branch.b[0]].b,
|
||||||
'd': branch_['d'],
|
d=branch.d,
|
||||||
'c': branch_['c'],
|
c=branch.c,
|
||||||
}
|
)
|
||||||
tree__.append(branch_)
|
tree_.add((bid, branch))
|
||||||
tree_ = tree__
|
tree = tree_
|
||||||
tree = tree_
|
|
||||||
|
|
||||||
return tree, max((branch['d']+1 for branch in tree), default=0)
|
# strip out bids
|
||||||
|
tree = {branch for _, branch in tree}
|
||||||
|
|
||||||
|
return tree, max((branch.d+1 for branch in tree), default=0)
|
||||||
|
|
||||||
# btree B-tree generation for debugging
|
# btree B-tree generation for debugging
|
||||||
def btree_btree(self, f, block_size, depth=None, *,
|
def btree_btree(self, f, block_size, depth=None, *,
|
||||||
inner=False):
|
inner=False):
|
||||||
# find all branches
|
# find all branches
|
||||||
tree = []
|
tree = set()
|
||||||
root = None
|
root = None
|
||||||
branches = {}
|
branches = {}
|
||||||
bid = -1
|
bid = -1
|
||||||
@@ -705,15 +711,15 @@ class Rbyd:
|
|||||||
root = b
|
root = b
|
||||||
a = root
|
a = root
|
||||||
|
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': a,
|
a=a,
|
||||||
'b': b,
|
b=b,
|
||||||
'd': d,
|
d=d,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
a = b
|
a = b
|
||||||
|
|
||||||
return tree, max((branch['d']+1 for branch in tree), default=0)
|
return tree, max((branch.d+1 for branch in tree), default=0)
|
||||||
|
|
||||||
|
|
||||||
def main(disk, mroots=None, *,
|
def main(disk, mroots=None, *,
|
||||||
@@ -815,7 +821,7 @@ def main(disk, mroots=None, *,
|
|||||||
t_width = 0
|
t_width = 0
|
||||||
if args.get('tree'):
|
if args.get('tree'):
|
||||||
# compute mroot chain "tree", prefix our actual mtree with this
|
# compute mroot chain "tree", prefix our actual mtree with this
|
||||||
tree = []
|
tree = set()
|
||||||
d_ = 0
|
d_ = 0
|
||||||
mroot_ = Rbyd.fetch(f, block_size, mroots)
|
mroot_ = Rbyd.fetch(f, block_size, mroots)
|
||||||
for d in it.count():
|
for d in it.count():
|
||||||
@@ -829,30 +835,30 @@ def main(disk, mroots=None, *,
|
|||||||
# connect branch to our root
|
# connect branch to our root
|
||||||
if d > 0:
|
if d > 0:
|
||||||
root = min(rtree,
|
root = min(rtree,
|
||||||
key=lambda branch: branch['d'],
|
key=lambda branch: branch.d,
|
||||||
default=None)
|
default=None)
|
||||||
|
|
||||||
if root:
|
if root:
|
||||||
r_rid, r_tag = root['a']
|
r_rid, r_tag = root.a
|
||||||
else:
|
else:
|
||||||
_, r_rid, r_tag, _, _, _, _, _ = mroot_.lookup(-1, 0x10)
|
_, r_rid, r_tag, _, _, _, _, _ = mroot_.lookup(-1, 0x10)
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (-1, d-1, 0, -1, TAG_MROOT),
|
a=(-1, d-1, 0, -1, TAG_MROOT),
|
||||||
'b': (-1, d, 0, r_rid, r_tag),
|
b=(-1, d, 0, r_rid, r_tag),
|
||||||
'd': d_-1,
|
d=d_-1,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
# map the tree into our metadata space
|
# map the tree into our metadata space
|
||||||
for branch in rtree:
|
for branch in rtree:
|
||||||
a_rid, a_tag = branch['a']
|
a_rid, a_tag = branch.a
|
||||||
b_rid, b_tag = branch['b']
|
b_rid, b_tag = branch.b
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (-1, d, 0, a_rid, a_tag),
|
a=(-1, d, 0, a_rid, a_tag),
|
||||||
'b': (-1, d, 0, b_rid, b_tag),
|
b=(-1, d, 0, b_rid, b_tag),
|
||||||
'd': d_ + branch['d'],
|
d=d_ + branch.d,
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
})
|
))
|
||||||
d_ += rdepth
|
d_ += rdepth
|
||||||
|
|
||||||
# fetch the next mroot
|
# fetch the next mroot
|
||||||
@@ -869,30 +875,30 @@ def main(disk, mroots=None, *,
|
|||||||
|
|
||||||
# connect branch to our root
|
# connect branch to our root
|
||||||
root = min(rtree,
|
root = min(rtree,
|
||||||
key=lambda branch: branch['d'],
|
key=lambda branch: branch.d,
|
||||||
default=None)
|
default=None)
|
||||||
|
|
||||||
if root:
|
if root:
|
||||||
r_rid, r_tag = root['a']
|
r_rid, r_tag = root.a
|
||||||
else:
|
else:
|
||||||
_, r_rid, r_tag, _, _, _, _, _ = mdir.lookup(-1, 0x10)
|
_, r_rid, r_tag, _, _, _, _, _ = mdir.lookup(-1, 0x10)
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (-1, d, 0, -1, TAG_MDIR),
|
a=(-1, d, 0, -1, TAG_MDIR),
|
||||||
'b': (0, 0, 0, r_rid, r_tag),
|
b=(0, 0, 0, r_rid, r_tag),
|
||||||
'd': d_-1,
|
d=d_-1,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
# map the tree into our metadata space
|
# map the tree into our metadata space
|
||||||
for branch in rtree:
|
for branch in rtree:
|
||||||
a_rid, a_tag = branch['a']
|
a_rid, a_tag = branch.a
|
||||||
b_rid, b_tag = branch['b']
|
b_rid, b_tag = branch.b
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (0, 0, 0, a_rid, a_tag),
|
a=(0, 0, 0, a_rid, a_tag),
|
||||||
'b': (0, 0, 0, b_rid, b_tag),
|
b=(0, 0, 0, b_rid, b_tag),
|
||||||
'd': d_ + branch['d'],
|
d=d_ + branch.d,
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
})
|
))
|
||||||
|
|
||||||
# compute the mtree's rbyd-tree if there is one
|
# compute the mtree's rbyd-tree if there is one
|
||||||
if mtree:
|
if mtree:
|
||||||
@@ -902,26 +908,26 @@ def main(disk, mroots=None, *,
|
|||||||
inner=args.get('inner'))
|
inner=args.get('inner'))
|
||||||
|
|
||||||
# connect a branch to the root of the tree
|
# connect a branch to the root of the tree
|
||||||
root = min(tree_, key=lambda branch: branch['d'], default=None)
|
root = min(tree_, key=lambda branch: branch.d, default=None)
|
||||||
if root:
|
if root:
|
||||||
r_bid, r_bd, r_rid, r_tag = root['a']
|
r_bid, r_bd, r_rid, r_tag = root.a
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (-1, d, 0, -1, TAG_BTREE),
|
a=(-1, d, 0, -1, TAG_BTREE),
|
||||||
'b': (r_bid, r_bd, r_rid, 0, r_tag),
|
b=(r_bid, r_bd, r_rid, 0, r_tag),
|
||||||
'd': d_-1,
|
d=d_-1,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
# map the tree into our metadata space
|
# map the tree into our metadata space
|
||||||
for branch in tree_:
|
for branch in tree_:
|
||||||
a_bid, a_bd, a_rid, a_tag = branch['a']
|
a_bid, a_bd, a_rid, a_tag = branch.a
|
||||||
b_bid, b_bd, b_rid, b_tag = branch['b']
|
b_bid, b_bd, b_rid, b_tag = branch.b
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (a_bid, a_bd, a_rid, 0, a_tag),
|
a=(a_bid, a_bd, a_rid, 0, a_tag),
|
||||||
'b': (b_bid, b_bd, b_rid, 0, b_tag),
|
b=(b_bid, b_bd, b_rid, 0, b_tag),
|
||||||
'd': d_ + branch['d'],
|
d=d_ + branch.d,
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
})
|
))
|
||||||
|
|
||||||
# find the max depth of each mdir to nicely align trees
|
# find the max depth of each mdir to nicely align trees
|
||||||
# TODO memoize
|
# TODO memoize
|
||||||
@@ -983,90 +989,90 @@ def main(disk, mroots=None, *,
|
|||||||
# connect the root to the mtree
|
# connect the root to the mtree
|
||||||
branch = max(
|
branch = max(
|
||||||
(branch for branch in tree
|
(branch for branch in tree
|
||||||
if branch['b'][0] == mid-(w-1)),
|
if branch.b[0] == mid-(w-1)),
|
||||||
key=lambda branch: branch['d'],
|
key=lambda branch: branch.d,
|
||||||
default=None)
|
default=None)
|
||||||
if branch:
|
if branch:
|
||||||
root = min(rtree,
|
root = min(rtree,
|
||||||
key=lambda branch: branch['d'],
|
key=lambda branch: branch.d,
|
||||||
default=None)
|
default=None)
|
||||||
if root:
|
if root:
|
||||||
r_rid, r_tag = root['a']
|
r_rid, r_tag = root.a
|
||||||
else:
|
else:
|
||||||
_, r_rid, r_tag, _, _, _, _, _ = (
|
_, r_rid, r_tag, _, _, _, _, _ = (
|
||||||
mdir_.lookup(-1, 0x10))
|
mdir_.lookup(-1, 0x10))
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': branch['b'],
|
a=branch.b,
|
||||||
'b': (mid-(w-1), len(path), 0, r_rid, r_tag),
|
b=(mid-(w-1), len(path), 0, r_rid, r_tag),
|
||||||
'd': d_ + tdepth,
|
d=d_ + tdepth,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
# map the tree into our metadata space
|
# map the tree into our metadata space
|
||||||
for branch in rtree:
|
for branch in rtree:
|
||||||
a_rid, a_tag = branch['a']
|
a_rid, a_tag = branch.a
|
||||||
b_rid, b_tag = branch['b']
|
b_rid, b_tag = branch.b
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (mid-(w-1), len(path), 0, a_rid, a_tag),
|
a=(mid-(w-1), len(path), 0, a_rid, a_tag),
|
||||||
'b': (mid-(w-1), len(path), 0, b_rid, b_tag),
|
b=(mid-(w-1), len(path), 0, b_rid, b_tag),
|
||||||
'd': (d_ + tdepth + 1
|
d=(d_ + tdepth + 1
|
||||||
+ branch['d'] + mdepth-rdepth),
|
+ branch.d + mdepth-rdepth),
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
})
|
))
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner branches
|
# remap branches to leaves if we aren't showing inner branches
|
||||||
if not args.get('inner'):
|
if not args.get('inner'):
|
||||||
# step through each layer backwards
|
# step through each layer backwards
|
||||||
b_depth = max((branch['a'][1]+1 for branch in tree),
|
b_depth = max((branch.a[1]+1 for branch in tree), default=0)
|
||||||
default=0)
|
|
||||||
|
|
||||||
# keep track of the original tree to find the original bids,
|
# keep track of the original bids, unfortunately because we
|
||||||
# unfortunately because we store the bids in the branches we
|
# store the bids in the branches we overwrite these
|
||||||
# overwrite these
|
tree = {(branch.b[0] - branch.b[2], branch)
|
||||||
tree_ = tree.copy()
|
for branch in tree}
|
||||||
|
|
||||||
for bd in reversed(range(b_depth-1)):
|
for bd in reversed(range(b_depth-1)):
|
||||||
# find leaf-roots at this level
|
# find leaf-roots at this level
|
||||||
roots = {}
|
roots = {}
|
||||||
for branch_, branch in zip(tree_, tree):
|
for bid, branch in tree:
|
||||||
bid = branch['b'][0] - branch['b'][2]
|
|
||||||
# choose the highest node as the root
|
# choose the highest node as the root
|
||||||
if (branch_['b'][1] == b_depth-1
|
if (branch.b[1] == b_depth-1
|
||||||
and (bid not in roots
|
and (bid not in roots
|
||||||
or branch_['d'] < roots[bid]['d'])):
|
or branch.d < roots[bid].d)):
|
||||||
roots[bid] = branch_
|
roots[bid] = branch
|
||||||
|
|
||||||
# remap branches to leaf-roots
|
# remap branches to leaf-roots
|
||||||
tree__ = []
|
tree_ = set()
|
||||||
for branch_ in tree_:
|
for bid, branch in tree:
|
||||||
# note we ignore mroot branches, we don't collapse
|
# note we ignore mroot branches, we don't collapse
|
||||||
# normally these
|
# normally these
|
||||||
if (branch_['a'][0] != -1
|
if (branch.a[0] != -1
|
||||||
and branch_['a'][1] == bd
|
and branch.a[1] == bd
|
||||||
and branch_['a'][0] in roots):
|
and branch.a[0] in roots):
|
||||||
branch_ = {
|
branch = TBranch(
|
||||||
'a': roots[branch_['a'][0]]['b'],
|
a=roots[branch.a[0]].b,
|
||||||
'b': branch_['b'],
|
b=branch.b,
|
||||||
'd': branch_['d'],
|
d=branch.d,
|
||||||
'c': branch_['c'],
|
c=branch.c,
|
||||||
}
|
)
|
||||||
if (branch_['b'][0] != -1
|
if (branch.b[0] != -1
|
||||||
and branch_['b'][1] == bd
|
and branch.b[1] == bd
|
||||||
and branch_['b'][0] in roots):
|
and branch.b[0] in roots):
|
||||||
branch_ = {
|
branch = TBranch(
|
||||||
'a': branch_['a'],
|
a=branch.a,
|
||||||
'b': roots[branch_['b'][0]]['b'],
|
b=roots[branch.b[0]].b,
|
||||||
'd': branch_['d'],
|
d=branch.d,
|
||||||
'c': branch_['c'],
|
c=branch.c,
|
||||||
}
|
)
|
||||||
tree__.append(branch_)
|
tree_.add((bid, branch))
|
||||||
tree_ = tree__
|
tree = tree_
|
||||||
tree = tree_
|
|
||||||
|
# strip out bids
|
||||||
|
tree = {branch for _, branch in tree}
|
||||||
|
|
||||||
# precompute B-tree if requested
|
# precompute B-tree if requested
|
||||||
elif args.get('btree'):
|
elif args.get('btree'):
|
||||||
# compute mroot chain "tree", prefix our actual mtree with this
|
# compute mroot chain "tree", prefix our actual mtree with this
|
||||||
tree = []
|
tree = set()
|
||||||
mroot_ = Rbyd.fetch(f, block_size, mroots)
|
mroot_ = Rbyd.fetch(f, block_size, mroots)
|
||||||
for d in it.count():
|
for d in it.count():
|
||||||
# corrupted?
|
# corrupted?
|
||||||
@@ -1077,12 +1083,12 @@ def main(disk, mroots=None, *,
|
|||||||
if d > 0:
|
if d > 0:
|
||||||
done, rid, tag, w, j, _, data, _ = mroot_.lookup(-1, 0x10)
|
done, rid, tag, w, j, _, data, _ = mroot_.lookup(-1, 0x10)
|
||||||
if not done:
|
if not done:
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (-1, d-1, 0, -1, TAG_MROOT),
|
a=(-1, d-1, 0, -1, TAG_MROOT),
|
||||||
'b': (-1, d, 0, rid, tag),
|
b=(-1, d, 0, rid, tag),
|
||||||
'd': 0,
|
d=0,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
# fetch the next mroot
|
# fetch the next mroot
|
||||||
done, rid, tag, w, j, _, data, _ = mroot_.lookup(-1, TAG_MROOT)
|
done, rid, tag, w, j, _, data, _ = mroot_.lookup(-1, TAG_MROOT)
|
||||||
@@ -1097,12 +1103,12 @@ def main(disk, mroots=None, *,
|
|||||||
# connect branch to our first tag
|
# connect branch to our first tag
|
||||||
done, rid, tag, w, j, _, data, _ = mdir.lookup(-1, 0x10)
|
done, rid, tag, w, j, _, data, _ = mdir.lookup(-1, 0x10)
|
||||||
if not done:
|
if not done:
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (-1, d, 0, -1, TAG_MDIR),
|
a=(-1, d, 0, -1, TAG_MDIR),
|
||||||
'b': (0, 0, 0, rid, tag),
|
b=(0, 0, 0, rid, tag),
|
||||||
'd': 0,
|
d=0,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
# compute the mtree's B-tree if there is one
|
# compute the mtree's B-tree if there is one
|
||||||
if mtree:
|
if mtree:
|
||||||
@@ -1112,26 +1118,26 @@ def main(disk, mroots=None, *,
|
|||||||
inner=args.get('inner'))
|
inner=args.get('inner'))
|
||||||
|
|
||||||
# connect a branch to the root of the tree
|
# connect a branch to the root of the tree
|
||||||
root = min(tree_, key=lambda branch: branch['d'], default=None)
|
root = min(tree_, key=lambda branch: branch.d, default=None)
|
||||||
if root:
|
if root:
|
||||||
r_bid, r_bd, r_rid, r_tag = root['a']
|
r_bid, r_bd, r_rid, r_tag = root.a
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (-1, d, 0, -1, TAG_BTREE),
|
a=(-1, d, 0, -1, TAG_BTREE),
|
||||||
'b': (r_bid, r_bd, r_rid, 0, r_tag),
|
b=(r_bid, r_bd, r_rid, 0, r_tag),
|
||||||
'd': 0,
|
d=0,
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
# map the tree into our metadata space
|
# map the tree into our metadata space
|
||||||
for branch in tree_:
|
for branch in tree_:
|
||||||
a_bid, a_bd, a_rid, a_tag = branch['a']
|
a_bid, a_bd, a_rid, a_tag = branch.a
|
||||||
b_bid, b_bd, b_rid, b_tag = branch['b']
|
b_bid, b_bd, b_rid, b_tag = branch.b
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': (a_bid, a_bd, a_rid, 0, a_tag),
|
a=(a_bid, a_bd, a_rid, 0, a_tag),
|
||||||
'b': (b_bid, b_bd, b_rid, 0, b_tag),
|
b=(b_bid, b_bd, b_rid, 0, b_tag),
|
||||||
'd': 1 + branch['d'],
|
d=1 + branch.d,
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
})
|
))
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner branches
|
# remap branches to leaves if we aren't showing inner branches
|
||||||
if not args.get('inner'):
|
if not args.get('inner'):
|
||||||
@@ -1166,31 +1172,31 @@ def main(disk, mroots=None, *,
|
|||||||
done, rid, tag, _, j, d, data, _ = (
|
done, rid, tag, _, j, d, data, _ = (
|
||||||
mdir_.lookup(-1, 0x10))
|
mdir_.lookup(-1, 0x10))
|
||||||
|
|
||||||
tree_ = []
|
tree_ = set()
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if branch['a'][0] == mid-(w-1):
|
if branch.a[0] == mid-(w-1):
|
||||||
a_bid, a_bd, _, _, _ = branch['a']
|
a_bid, a_bd, _, _, _ = branch.a
|
||||||
branch = {
|
branch = TBranch(
|
||||||
'a': (a_bid, a_bd+1, 0, rid, tag),
|
a=(a_bid, a_bd+1, 0, rid, tag),
|
||||||
'b': branch['b'],
|
b=branch.b,
|
||||||
'd': branch['d'],
|
d=branch.d,
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
}
|
)
|
||||||
if branch['b'][0] == mid-(w-1):
|
if branch.b[0] == mid-(w-1):
|
||||||
b_bid, b_bd, _, _, _ = branch['b']
|
b_bid, b_bd, _, _, _ = branch.b
|
||||||
branch = {
|
branch = TBranch(
|
||||||
'a': branch['a'],
|
a=branch.a,
|
||||||
'b': (b_bid, b_bd+1, 0, rid, tag),
|
b=(b_bid, b_bd+1, 0, rid, tag),
|
||||||
'd': branch['d'],
|
d=branch.d,
|
||||||
'c': branch['c'],
|
c=branch.c,
|
||||||
}
|
)
|
||||||
tree_.append(branch)
|
tree_.add(branch)
|
||||||
tree = tree_
|
tree = tree_
|
||||||
|
|
||||||
# common tree renderer
|
# common tree renderer
|
||||||
if args.get('tree') or args.get('btree'):
|
if args.get('tree') or args.get('btree'):
|
||||||
# find the max depth from the tree
|
# find the max depth from the tree
|
||||||
t_depth = max((branch['d']+1 for branch in tree), default=0)
|
t_depth = max((branch.d+1 for branch in tree), default=0)
|
||||||
if t_depth > 0:
|
if t_depth > 0:
|
||||||
t_width = 2*t_depth + 2
|
t_width = 2*t_depth + 2
|
||||||
|
|
||||||
@@ -1200,27 +1206,27 @@ def main(disk, mroots=None, *,
|
|||||||
|
|
||||||
def branchrepr(x, d, was):
|
def branchrepr(x, d, was):
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if branch['d'] == d and branch['b'] == x:
|
if branch.d == d and branch.b == x:
|
||||||
if any(branch['d'] == d and branch['a'] == x
|
if any(branch.d == d and branch.a == x
|
||||||
for branch in tree):
|
for branch in tree):
|
||||||
return '+-', branch['c'], branch['c']
|
return '+-', branch.c, branch.c
|
||||||
elif any(branch['d'] == d
|
elif any(branch.d == d
|
||||||
and x > min(branch['a'], branch['b'])
|
and x > min(branch.a, branch.b)
|
||||||
and x < max(branch['a'], branch['b'])
|
and x < max(branch.a, branch.b)
|
||||||
for branch in tree):
|
for branch in tree):
|
||||||
return '|-', branch['c'], branch['c']
|
return '|-', branch.c, branch.c
|
||||||
elif branch['a'] < branch['b']:
|
elif branch.a < branch.b:
|
||||||
return '\'-', branch['c'], branch['c']
|
return '\'-', branch.c, branch.c
|
||||||
else:
|
else:
|
||||||
return '.-', branch['c'], branch['c']
|
return '.-', branch.c, branch.c
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if branch['d'] == d and branch['a'] == x:
|
if branch.d == d and branch.a == x:
|
||||||
return '+ ', branch['c'], None
|
return '+ ', branch.c, None
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if (branch['d'] == d
|
if (branch.d == d
|
||||||
and x > min(branch['a'], branch['b'])
|
and x > min(branch.a, branch.b)
|
||||||
and x < max(branch['a'], branch['b'])):
|
and x < max(branch.a, branch.b)):
|
||||||
return '| ', branch['c'], was
|
return '| ', branch.c, was
|
||||||
if was:
|
if was:
|
||||||
return '--', was, was
|
return '--', was, was
|
||||||
return ' ', None, None
|
return ' ', None, None
|
||||||
|
|||||||
+31
-30
@@ -660,24 +660,25 @@ def dbg_tree(data, block_size, rev, trunk, weight, *,
|
|||||||
t_depth = max((alt['h']+1 for alt in alts.values()), default=0)
|
t_depth = max((alt['h']+1 for alt in alts.values()), default=0)
|
||||||
|
|
||||||
# convert to more general tree representation
|
# convert to more general tree representation
|
||||||
tree = []
|
TBranch = co.namedtuple('TBranch', 'a, b, d, c')
|
||||||
|
tree = set()
|
||||||
for j, alt in alts.items():
|
for j, alt in alts.items():
|
||||||
# note all non-trunk edges should be black
|
# note all non-trunk edges should be black
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': alt['nft'],
|
a=alt['nft'],
|
||||||
'b': alt['nft'],
|
b=alt['nft'],
|
||||||
'd': t_depth-1 - alt['h'],
|
d=t_depth-1 - alt['h'],
|
||||||
'c': alt['c'],
|
c=alt['c'],
|
||||||
})
|
))
|
||||||
tree.append({
|
tree.add(TBranch(
|
||||||
'a': alt['nft'],
|
a=alt['nft'],
|
||||||
'b': alt['ft'],
|
b=alt['ft'],
|
||||||
'd': t_depth-1 - alt['h'],
|
d=t_depth-1 - alt['h'],
|
||||||
'c': 'b',
|
c='b',
|
||||||
})
|
))
|
||||||
|
|
||||||
# find the max depth from the tree
|
# find the max depth from the tree
|
||||||
t_depth = max((branch['d']+1 for branch in tree), default=0)
|
t_depth = max((branch.d+1 for branch in tree), default=0)
|
||||||
if t_depth > 0:
|
if t_depth > 0:
|
||||||
t_width = 2*t_depth + 2
|
t_width = 2*t_depth + 2
|
||||||
|
|
||||||
@@ -687,27 +688,27 @@ def dbg_tree(data, block_size, rev, trunk, weight, *,
|
|||||||
|
|
||||||
def branchrepr(x, d, was):
|
def branchrepr(x, d, was):
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if branch['d'] == d and branch['b'] == x:
|
if branch.d == d and branch.b == x:
|
||||||
if any(branch['d'] == d and branch['a'] == x
|
if any(branch.d == d and branch.a == x
|
||||||
for branch in tree):
|
for branch in tree):
|
||||||
return '+-', branch['c'], branch['c']
|
return '+-', branch.c, branch.c
|
||||||
elif any(branch['d'] == d
|
elif any(branch.d == d
|
||||||
and x > min(branch['a'], branch['b'])
|
and x > min(branch.a, branch.b)
|
||||||
and x < max(branch['a'], branch['b'])
|
and x < max(branch.a, branch.b)
|
||||||
for branch in tree):
|
for branch in tree):
|
||||||
return '|-', branch['c'], branch['c']
|
return '|-', branch.c, branch.c
|
||||||
elif branch['a'] < branch['b']:
|
elif branch.a < branch.b:
|
||||||
return '\'-', branch['c'], branch['c']
|
return '\'-', branch.c, branch.c
|
||||||
else:
|
else:
|
||||||
return '.-', branch['c'], branch['c']
|
return '.-', branch.c, branch.c
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if branch['d'] == d and branch['a'] == x:
|
if branch.d == d and branch.a == x:
|
||||||
return '+ ', branch['c'], None
|
return '+ ', branch.c, None
|
||||||
for branch in tree:
|
for branch in tree:
|
||||||
if (branch['d'] == d
|
if (branch.d == d
|
||||||
and x > min(branch['a'], branch['b'])
|
and x > min(branch.a, branch.b)
|
||||||
and x < max(branch['a'], branch['b'])):
|
and x < max(branch.a, branch.b)):
|
||||||
return '| ', branch['c'], was
|
return '| ', branch.c, was
|
||||||
if was:
|
if was:
|
||||||
return '--', was, was
|
return '--', was, was
|
||||||
return ' ', None, None
|
return ' ', None, None
|
||||||
|
|||||||
Reference in New Issue
Block a user