Rev 3772: Add a --raw output for dump-btree. in http://bzr.arbash-meinel.com/branches/bzr/1.8-dev/dump_btree

John Arbash Meinel john at arbash-meinel.com
Wed Oct 8 22:52:04 BST 2008


At http://bzr.arbash-meinel.com/branches/bzr/1.8-dev/dump_btree

------------------------------------------------------------
revno: 3772
revision-id: john at arbash-meinel.com-20081008215137-wu18nhhorncyon50
parent: john at arbash-meinel.com-20081008204023-z1u32sjby509wl12
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dump_btree
timestamp: Wed 2008-10-08 16:51:37 -0500
message:
  Add a --raw output for dump-btree.
  
  This does the minimum it can, so that we can dump out the
  raw bytes in a meaningful manner.
-------------- next part --------------
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2008-10-08 20:40:23 +0000
+++ b/bzrlib/builtins.py	2008-10-08 21:51:37 +0000
@@ -29,6 +29,7 @@
 from bzrlib import (
     bugtracker,
     bundle,
+    btree_index,
     bzrdir,
     delta,
     config,
@@ -269,24 +270,70 @@
     #       rather than only going through iter_all_entries. However, this is
     #       good enough for a start
     hidden = True
+    encoding_type = 'exact'
     takes_args = ['path']
-
-    def run(self, path):
-        from bzrlib import btree_index
-
+    takes_options = [Option('raw', help='Write the uncompressed bytes out,'
+                                        ' rather than the parsed tuples'),
+                    ]
+
+    def run(self, path, raw=False):
         dirname, basename = osutils.split(path)
         t = transport.get_transport(dirname)
+        if raw:
+            self._dump_raw_bytes(t, basename)
+        else:
+            self._dump_entries(t, basename)
+
+    def _get_index_and_bytes(self, trans, basename):
+        """Create a BTreeGraphIndex and raw bytes."""
+        bt = btree_index.BTreeGraphIndex(trans, basename, None)
+        bytes = trans.get_bytes(basename)
+        bt._file = cStringIO.StringIO(bytes)
+        bt._size = len(bytes)
+        return bt, bytes
+
+    def _dump_raw_bytes(self, trans, basename):
+        import zlib
+
+        # We need to parse at least the root node.
+        # This is because the first page of every row starts with an
+        # uncompressed header.
+        bt, bytes = self._get_index_and_bytes(trans, basename)
+        root_node = bt._get_root_node()
+        for row_idx, row_start in enumerate(bt._row_offsets[:-1]):
+            if row_idx == 0:
+                self.outf.write('Root node:\n')
+            elif row_idx < len(bt._row_lengths):
+                self.outf.write('\nInternal Row %d:\n' % (row_idx,))
+            else:
+                self.outf.write('\nLeaf Row %d:\n' % (row_idx,))
+            # Should we do something to ensure all pages are 'back-to-back'?
+            # And we aren't skipping data in the middle?
+            for page_idx in xrange(0, bt._row_lengths[row_idx]):
+                start_idx = bt._row_offsets[row_idx] + page_idx
+                start_offset = start_idx * btree_index._PAGE_SIZE
+                finish_offset = min(start_offset + btree_index._PAGE_SIZE,
+                                    len(bytes))
+                page_bytes = bytes[start_offset:finish_offset]
+                if row_idx == 0 and page_idx == 0:
+                    header_end, data = bt._parse_header_from_bytes(page_bytes)
+                    self.outf.write(page_bytes[:header_end])
+                    page_bytes = data
+                self.outf.write('\nPage %d (row: %d, offset: %d)\n'
+                                % (start_idx, row_idx, page_idx))
+                decomp_bytes = zlib.decompress(page_bytes)
+                self.outf.write(decomp_bytes)
+                self.outf.write('\n')
+
+    def _dump_entries(self, trans, basename):
         try:
-            st = t.stat(basename)
+            st = trans.stat(basename)
         except errors.TransportNotPossible:
             # We can't stat, so we'll fake it because we have to do the 'get()'
             # anyway.
-            bt = btree_index.BTreeGraphIndex(t, basename, None)
-            bytes = t.get_bytes(basename)
-            bt._file = cStringIO.StringIO(bytes)
-            bt._size = len(bytes)
+            bt, _ = self._get_index_and_bytes(trans, basename)
         else:
-            bt = btree_index.BTreeGraphIndex(t, basename, st.st_size)
+            bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
         for node in bt.iter_all_entries():
             # Node is made up of:
             # (index, key, value, [references])

=== modified file 'bzrlib/tests/blackbox/test_dump_btree.py'
--- a/bzrlib/tests/blackbox/test_dump_btree.py	2008-10-08 20:40:23 +0000
+++ b/bzrlib/tests/blackbox/test_dump_btree.py	2008-10-08 21:51:37 +0000
@@ -59,3 +59,22 @@
             "(('test', 'key2'), 'value2', ((('ref', 'entry2'),),))\n"
             "(('test2', 'key3'), 'value3', ((('ref', 'entry3'),),))\n",
             out)
+
+    def test_dump_btree_raw_smoke(self):
+        self.create_sample_btree_index()
+        out, err = self.run_bzr('dump-btree test.btree --raw')
+        self.assertEqualDiff(
+            'Root node:\n'
+            'B+Tree Graph Index 2\n'
+            'node_ref_lists=1\n'
+            'key_elements=2\n'
+            'len=3\n'
+            'row_lengths=1\n'
+            '\n'
+            'Page 0 (row: 0, offset: 0)\n'
+            'type=leaf\n'
+            'test\0key1\0ref\0entry\0value\n'
+            'test\0key2\0ref\0entry2\0value2\n'
+            'test2\0key3\0ref\0entry3\0value3\n'
+            '\n',
+            out)



More information about the bazaar-commits mailing list