Rev 3759: Test unmapping with one child left but multiple keys. in http://people.ubuntu.com/~robertc/baz2.0/repository

Robert Collins robertc at robertcollins.net
Wed Nov 12 00:39:04 GMT 2008


At http://people.ubuntu.com/~robertc/baz2.0/repository

------------------------------------------------------------
revno: 3759
revision-id: robertc at robertcollins.net-20081112003855-ay7xhc5xhgx3bwt4
parent: robertc at robertcollins.net-20081111100253-hx2ndctrnwilr62i
parent: andrew.bennetts at canonical.com-20081111070622-14i0n8g8meqo4yl8
committer: Robert Collins <robertc at robertcollins.net>
branch nick: repository
timestamp: Wed 2008-11-12 11:38:55 +1100
message:
  Test unmapping with one child left but multiple keys.
modified:
  bzrlib/chk_map.py              chk_map.py-20081001014447-ue6kkuhofvdecvxa-1
  bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
  bzrlib/tests/test_chk_map.py   test_chk_map.py-20081001014447-ue6kkuhofvdecvxa-2
    ------------------------------------------------------------
    revno: 3756.1.6
    revision-id: andrew.bennetts at canonical.com-20081111070622-14i0n8g8meqo4yl8
    parent: andrew.bennetts at canonical.com-20081111043629-ojx8u4wob9kwuatt
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: chk
    timestamp: Tue 2008-11-11 17:06:22 +1000
    message:
      Make fetch much much faster.  Adds CHKMap.copy_to(other_store)
    modified:
      bzrlib/chk_map.py              chk_map.py-20081001014447-ue6kkuhofvdecvxa-1
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
      bzrlib/tests/test_chk_map.py   test_chk_map.py-20081001014447-ue6kkuhofvdecvxa-2
=== modified file 'bzrlib/chk_map.py'
--- a/bzrlib/chk_map.py	2008-11-11 06:02:49 +0000
+++ b/bzrlib/chk_map.py	2008-11-12 00:38:55 +0000
@@ -74,6 +74,20 @@
                 self.map(new, value)
         return self._save()
 
+    def copy_to(self, store):
+        """Copy all of the refs from this map into store."""
+        root_key = self.key()
+        if root_key in store.get_parent_map([root_key]):
+            # Target already has the content, return
+            return
+        self._ensure_root()
+        keys = self._root_node.refs()
+        present_keys = store.get_parent_map(keys)
+        missing_keys = [key for key in keys if key not in present_keys]
+        missing_keys.append(root_key)
+        store.insert_record_stream(self._store.get_record_stream(
+            missing_keys, 'unordered', False))
+
     def _ensure_root(self):
         """Ensure that the root node is an object not a key."""
         if type(self._root_node) == tuple:
@@ -634,26 +648,10 @@
         else:
             # Stash the returned node
             self._items[serialised_key] = unmapped
-        if len(self) == 1:
+        if len(self._items) == 1:
             # this node is no longer needed:
             return self._items.values()[0]
         return self
-        prefix, node_details = child.map(store, key, value)
-        if len(node_details) == 1:
-            # child may have shrunk, or might be the same.
-            self._len = self._len - old_len + len(child)
-            self._items[serialised_key] = child
-            return self.unique_serialised_prefix(), [("", self)]
-        # child has overflown - create a new intermediate node.
-        # XXX: This is where we might want to try and expand our depth
-        # to refer to more bytes of every child (which would give us
-        # multiple pointers to child nodes, but less intermediate nodes)
-        child = self._new_child(serialised_key, InternalNode)
-        for split, node in node_details:
-            child.add_node(split, node)
-        self._len = self._len - old_len + len(child)
-        return self.unique_serialised_prefix(), [("", self)]
-
 
 
 class RootNode(Node):

=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py	2008-10-22 06:40:59 +0000
+++ b/bzrlib/inventory.py	2008-11-11 07:06:22 +0000
@@ -1441,12 +1441,18 @@
         result = CHKInventory()
         result.revision_id = inventory.revision_id
         result.root_id = inventory.root.file_id
-        result.id_to_entry = chk_map.CHKMap(chk_store, None)
-        delta = []
-        for path, entry in inventory.iter_entries():
-            delta.append((None, entry.file_id, result._entry_to_bytes(entry)))
-        result.id_to_entry.apply_delta(delta)
-        result.id_to_entry._save()
+        if isinstance(inventory, CHKInventory):
+            inventory.id_to_entry.copy_to(chk_store)
+            result.id_to_entry = chk_map.CHKMap(chk_store,
+                                                inventory.id_to_entry.key())
+        else:
+            result.id_to_entry = chk_map.CHKMap(chk_store, None)
+            delta = []
+            for path, entry in inventory.iter_entries():
+                delta.append((None, entry.file_id,
+                              result._entry_to_bytes(entry)))
+            result.id_to_entry.apply_delta(delta)
+            result.id_to_entry._save()
         return result
 
     def __getitem__(self, file_id):

=== modified file 'bzrlib/tests/test_chk_map.py'
--- a/bzrlib/tests/test_chk_map.py	2008-11-11 06:02:49 +0000
+++ b/bzrlib/tests/test_chk_map.py	2008-11-12 00:38:55 +0000
@@ -212,6 +212,56 @@
         self.assertEqual([key], leaf_node.serialise(chkmap._store))
 
 
+class TestCaseWithTwoStores(TestCaseWithTransport):
+
+    def _make_chk_bytes(self, path):
+        repo = self.make_repository(path, format="development3")
+        repo.lock_write()
+        self.addCleanup(repo.unlock)
+        repo.start_write_group()
+        self.addCleanup(repo.abort_write_group)
+        return repo.chk_bytes
+
+    def make_chk_bytes(self):
+        chk_bytes1 = self._make_chk_bytes('a')
+        chk_bytes2 = self._make_chk_bytes('b')
+        return chk_bytes1, chk_bytes2
+
+
+class TestChkMapCopyTo(TestCaseWithTwoStores):
+
+    def disable_insert(self, store):
+        def add_lines_fail(*args, **kwargs):
+            self.fail('We should not need to add any content')
+        def insert_record_stream_fail(*args, **kwargs):
+            self.fail('We should not need to insert any content')
+        store.add_lines = add_lines_fail
+        store.insert_record_stream = insert_record_stream_fail
+
+    def test_to_self(self):
+        chk_bytes1, chk_bytes2 = self.make_chk_bytes()
+        root_key = CHKMap.from_dict(chk_bytes1, {'key': 'value'})
+        chkmap = CHKMap(chk_bytes1, root_key)
+        self.disable_insert(chk_bytes1)
+
+    def test_simple(self):
+        chk_bytes1, chk_bytes2 = self.make_chk_bytes()
+        root_key = CHKMap.from_dict(chk_bytes1, {'key': 'value'})
+        chkmap = CHKMap(chk_bytes1, root_key)
+        chkmap.copy_to(chk_bytes2)
+        newmap = CHKMap(chk_bytes2, root_key)
+        self.assertEqual(chkmap.key(), newmap.key())
+        self.assertEqual({'key': 'value'}, dict(newmap.iteritems()))
+
+    def test_target_has_root(self):
+        chk_bytes1, chk_bytes2 = self.make_chk_bytes()
+        root_key = CHKMap.from_dict(chk_bytes1, {'key': 'value'})
+        chkmap = CHKMap(chk_bytes1, root_key)
+        CHKMap.from_dict(chk_bytes2, {'key': 'value'})
+        self.disable_insert(chk_bytes2)
+        chkmap.copy_to(chk_bytes2)
+
+
 class TestRootNode(TestCaseWithTransport):
 
     def test__current_size(self):
@@ -749,6 +799,20 @@
         self.assertEqual([keys[-1]], keys)
         self.assertEqual(('sha1:d3f06fc03d8f50845894d8d04cc5a3f47e62948d',), keys[-1])
 
+    def test_unmap_k1_from_k1_k22_k23_gives_k22_k23_tree_new(self):
+        chkmap = self._get_map(
+            {('k1',):'foo', ('k22',):'bar', ('k23',): 'quux'}, maximum_size=10)
+        # Check we have the expected tree.
+        self.assertEqual(('sha1:d68cd97c95e847d3dc58c05537aa5fdcdf2cf5da',),
+            chkmap._root_node)
+        chkmap._ensure_root()
+        node = chkmap._root_node
+        k2_ptr = node._items['k2']
+        # unmapping k21 should give us a root, with k22 and k23 as direct
+        # children, and should not have needed to page in the subtree.
+        result = node.unmap(chkmap._store, ('k1',))
+        self.assertEqual(k2_ptr, result)
+
     def test_unmap_second_last_shrinks_to_other_branch(self):
         # unmapping the second last child of an internal node downgrades it to
         # a leaf node.




More information about the bazaar-commits mailing list