scripts: Reworked tracebd.py, needs cleanup
It's a mess but it's working. Still a number of TODOs to cleanup...
This adopts all of the changes in dbgbmap.py/dbgbmapd3.py, block
grouping, nested curves, Canvas, Attrs, etc:
- Like dbgbmap.py, we now group by block first before applying space
filling curves, using nested space filling curves to render byte-level
operations.
Python's ft.lru_cache really shines here.
The previous behavior is still available via -u/--contiguous
- Adopted most features in dbgbmap.py, so --to-scale, -t/--tiny, custom
--title strings, etc.
- Adopted Attrs so now chars/coloring can be customized with
-./--add-char, -,/--add-wear-char, -C/--add-color,
-G/--add-wear-color.
- Renamed -R/--reset -> --volatile, which is a much better name.
- Wear is now colored cyan -> white -> read, which is a bit more
visually interesting. And we're not using cyan in any scripts yet.
In addition to the new stuff, there were a few simplifications:
- We no longer support sub-char -n/--lines with -:/--dots or
-⣿/--braille. Too complicated, required Canvas state hacks to get
working, and wasn't super useful.
We probably want to avoid doing too much cleverness with -:/--dots and
-⣿/--braille since we can't color sub-chars.
- Dropped -@/--blocks byte-level range stuff. This was just not worth
the amount of complexity it added. -@/--blocks is now limited to
simple block ranges. High-level scripts should stick to high-level
options.
- No fancy/complicated Bmap class. The bmap object is just a dict of
TraceBlocks which contain RangeSets for relevant operations.
Actually the new RangeSet class deserves a mention but this commit
message is probably already too long.
RangeSet is a decently efficient set of, well, ranges, that can be
merged and queried. In a lower-level language it should be implemented
as a binary tree, but in Python we're just using a sorted list because
we're probably not going to be able to beat O(n) list operations.
- Wear is tracked at the block level, no reason to overcomplicate this.
- We no longer resize based on new info. Instead we either expect a
-b/--block-size argument or wait until first bd init call.
We can probably drop the block size in BD_TRACE statements now, but
that's a TODO item.
- Instead of one amalgamated regex, we use string searches to figure out
the bd op and then smaller regexes to parse. Lesson learned here:
Python's string search is very fast (compared to regex).
- We do _not_ support labels on blocks like we do in treemap.py/
codemap.py. It's less useful here and would just be more hassle.
I also tried to reorganize main a bit to mirror the simple two-main
approach in dbgbmap.py and other ascii-rendering scripts, but it's a bit
difficult here since trace info is very stateful. Building up main
functions in the main main function seemed to work well enough:
main -+-> main_ -> trace__ (main thread)
'-> draw_ -> draw__ (daemon thread)
---
You may note some weirdness going on with flags. That's me trying to
avoid upcoming flag conflicts.
I think we want -n/--lines in more scripts, now that it's relatively
self-contained, but this conflicts with -n/--namespace-depth in
codemap[d3].py, and risks conflict with -N/--notes in csv.py which may
end up with namespace-related functionality in the future.
I ended up hijacking -_, but this conflicted with -_/--add-line-char in
plot.py, but that's ok because we also want a common "secondary char"
flag for wear in tracebd.py... Long story short I ended up moving a
bunch of flags around:
- added -n/--lines
- -n/--namespace-depth -> -_/--namespace-depth
- -N/--notes -> -N/--notes
- -./--add-char -> -./--add-char
- -_/--add-line-char -> -,/--add-line-char
- added -,/--add-wear-char
- -C/--color -> -C/--add-color
- added -> -G/--add-wear-color
Worth it? Dunno.
This commit is contained in:
+35
-30
@@ -4721,23 +4721,25 @@ def main(disk, output, mroots=None, *,
|
||||
corrupted = not bool(lfs)
|
||||
|
||||
# if we can't figure out the block_count, guess
|
||||
block_size_ = block_size
|
||||
block_count_ = block_count
|
||||
if block_count is None:
|
||||
if lfs.config.geometry is not None:
|
||||
block_count = lfs.config.geometry.block_count
|
||||
block_count_ = lfs.config.geometry.block_count
|
||||
else:
|
||||
f.seek(0, os.SEEK_END)
|
||||
block_count = mt.ceil(f.tell() / block_size)
|
||||
block_count_ = mt.ceil(f_.tell() / block_size)
|
||||
|
||||
# flatten blocks, default to all blocks
|
||||
blocks = list(
|
||||
range(blocks.start or 0, blocks.stop or block_count)
|
||||
blocks_ = list(
|
||||
range(blocks.start or 0, blocks.stop or block_count_)
|
||||
if isinstance(blocks, slice)
|
||||
else range(blocks, blocks+1)
|
||||
if blocks
|
||||
else range(block_count))
|
||||
else range(block_count_))
|
||||
|
||||
# traverse the filesystem and create a block map
|
||||
bmap = {b: BmapBlock(b, 'unused') for b in blocks}
|
||||
bmap = {b: BmapBlock(b, 'unused') for b in blocks_}
|
||||
for child, path in lfs.traverse(
|
||||
mtree_only=mtree_only,
|
||||
path=True):
|
||||
@@ -4779,21 +4781,21 @@ def main(disk, output, mroots=None, *,
|
||||
else:
|
||||
bmap[b] = BmapBlock(b, 'conflict',
|
||||
[bmap[b].value, child],
|
||||
range(block_size))
|
||||
range(block_size_))
|
||||
corrupted = True
|
||||
|
||||
# corrupt metadata?
|
||||
elif (not no_ckmeta
|
||||
and isinstance(child, (Mdir, Rbyd))
|
||||
and not child):
|
||||
bmap[b] = BmapBlock(b, 'corrupt', child, range(block_size))
|
||||
bmap[b] = BmapBlock(b, 'corrupt', child, range(block_size_))
|
||||
corrupted = True
|
||||
|
||||
# corrupt data?
|
||||
elif (not no_ckdata
|
||||
and isinstance(child, Bptr)
|
||||
and not child):
|
||||
bmap[b] = BmapBlock(b, 'corrupt', child, range(block_size))
|
||||
bmap[b] = BmapBlock(b, 'corrupt', child, range(block_size_))
|
||||
corrupted = True
|
||||
|
||||
# normal block
|
||||
@@ -4838,41 +4840,44 @@ def main(disk, output, mroots=None, *,
|
||||
y__ += mt.ceil(FONT_SIZE * 1.3)
|
||||
height__ -= min(mt.ceil(FONT_SIZE * 1.3), height__)
|
||||
|
||||
# figure out block_cols/block_rows
|
||||
# figure out block_cols_/block_rows_
|
||||
if block_cols is not None and block_rows is not None:
|
||||
pass
|
||||
block_cols_ = block_cols
|
||||
block_rows_ = block_rows
|
||||
elif block_rows is not None:
|
||||
block_cols = mt.ceil(len(bmap) / block_rows)
|
||||
block_cols_ = mt.ceil(len(bmap) / block_rows)
|
||||
block_rows_ = block_rows
|
||||
elif block_cols is not None:
|
||||
block_rows = mt.ceil(len(bmap) / block_cols)
|
||||
block_cols_ = block_cols
|
||||
block_rows_ = mt.ceil(len(bmap) / block_cols)
|
||||
else:
|
||||
# divide by 2 until we hit our target ratio, this works
|
||||
# well for things that are often powers-of-two
|
||||
block_cols = 1
|
||||
block_rows = len(bmap)
|
||||
while (abs(((width__/(block_cols * 2))
|
||||
/ (height__/mt.ceil(block_rows / 2)))
|
||||
block_cols_ = 1
|
||||
block_rows_ = len(bmap)
|
||||
while (abs(((width__/(block_cols_ * 2))
|
||||
/ (height__/mt.ceil(block_rows_ / 2)))
|
||||
- block_ratio)
|
||||
< abs(((width__/block_cols)
|
||||
/ (height__/block_rows)))
|
||||
< abs(((width__/block_cols_)
|
||||
/ (height__/block_rows_)))
|
||||
- block_ratio):
|
||||
block_cols *= 2
|
||||
block_rows = mt.ceil(block_rows / 2)
|
||||
block_cols_ *= 2
|
||||
block_rows_ = mt.ceil(block_rows_ / 2)
|
||||
|
||||
block_width = width__ / block_cols
|
||||
block_height = height__ / block_rows
|
||||
block_width_ = width__ / block_cols_
|
||||
block_height_ = height__ / block_rows_
|
||||
|
||||
# assign block locations based on block_rows/block_cols and the
|
||||
# requested space filling curve
|
||||
# assign block locations based on block_rows_/block_cols_ and
|
||||
# the requested space filling curve
|
||||
for (x, y), b in zip(
|
||||
(hilbert_curve if hilbert
|
||||
else lebesgue_curve if lebesgue
|
||||
else naive_curve)(block_cols, block_rows),
|
||||
else naive_curve)(block_cols_, block_rows_),
|
||||
sorted(bmap.values())):
|
||||
b.x = x__ + (x * block_width)
|
||||
b.y = y__ + (y * block_height)
|
||||
b.width = block_width
|
||||
b.height = block_height
|
||||
b.x = x__ + (x * block_width_)
|
||||
b.y = y__ + (y * block_height_)
|
||||
b.width = block_width_
|
||||
b.height = block_height_
|
||||
|
||||
# apply top padding
|
||||
if x == 0:
|
||||
|
||||
Reference in New Issue
Block a user