Rev 4414: Prototype an alternative way to handle 'first commit' in http://bazaar.launchpad.net/~jameinel/bzr/1.16-chk-direct

John Arbash Meinel john at arbash-meinel.com
Fri Jun 5 22:10:51 BST 2009


At http://bazaar.launchpad.net/~jameinel/bzr/1.16-chk-direct

------------------------------------------------------------
revno: 4414
revision-id: john at arbash-meinel.com-20090605211029-1mc1tejpgyj7ww8g
parent: pqm at pqm.ubuntu.com-20090605081039-abvojdsxjbg5i4ff
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 1.16-chk-direct
timestamp: Fri 2009-06-05 16:10:29 -0500
message:
  Prototype an alternative way to handle 'first commit'
  So far it is just as slow, because we still call .map() for every object.
  However, it at least gives us a route to make things better.
-------------- next part --------------
=== modified file 'bzrlib/chk_map.py'
--- a/bzrlib/chk_map.py	2009-05-13 21:59:57 +0000
+++ b/bzrlib/chk_map.py	2009-06-05 21:10:29 +0000
@@ -98,6 +98,19 @@
         else:
             self._root_node = self._node_key(root_key)
 
+    def apply_insert_delta(self, delta):
+        """Apply a delta that only inserts items.
+
+        :param delta: An iterable of old_key, new_key, new_value tuples.
+            all old_key entries must be None, and all new_key entries must not
+            be None.
+        """
+        for old, new, value in delta:
+            assert old is None
+            assert new is not None
+            self.map(new, value)
+        return self._save()
+
     def apply_delta(self, delta):
         """Apply a delta to the map.
 
@@ -1165,6 +1178,7 @@
         :return: An iterable of (prefix, node) tuples. prefix is a byte
             prefix for reaching node.
         """
+        import pdb; pdb.set_trace()
         if offset >= self._node_width:
             for node in self._items.values():
                 for result in node._split(offset):

=== modified file 'bzrlib/repofmt/groupcompress_repo.py'
--- a/bzrlib/repofmt/groupcompress_repo.py	2009-06-03 01:43:22 +0000
+++ b/bzrlib/repofmt/groupcompress_repo.py	2009-06-05 21:10:29 +0000
@@ -674,6 +674,54 @@
         return self._inventory_add_lines(revision_id, parents,
             inv_lines, check_content=False)
 
+    def _get_null_inventory(self):
+        serializer = self._format._serializer
+        null_inv = inventory.CHKInventory(serializer.search_key_name)
+        search_key_func = chk_map.search_key_registry.get(
+                            serializer.search_key_name)
+        null_inv.id_to_entry = chk_map.CHKMap(self.chk_bytes,
+            None, search_key_func)
+        null_inv.id_to_entry._root_node.set_maximum_size(
+            serializer.maximum_size)
+        null_inv.parent_id_basename_to_file_id = chk_map.CHKMap(
+            self.chk_bytes, None, search_key_func)
+        null_inv.parent_id_basename_to_file_id._root_node.set_maximum_size(
+            serializer.maximum_size)
+        null_inv.parent_id_basename_to_file_id._root_node._key_width = 2
+        null_inv.root_id = None
+        return null_inv
+
+    def _apply_delta_to_null_inv(self, new_inv, delta, new_revision_id):
+        """This will mutate new_inv directly.
+
+        This is a simplified form of create_by_apply_delta which knows that all
+        the old values must be None, so everything is a create.
+        """
+        new_inv.revision_id = new_revision_id
+        entry_to_bytes = new_inv._entry_to_bytes
+        assert new_inv.parent_id_basename_to_file_id is not None
+        id_to_entry_delta = []
+        parent_id_basename_delta = []
+        for old_path, new_path, file_id, entry in delta:
+            assert old_path is None
+            assert new_path is not None
+            # file id changes
+            if new_path == '':
+                new_inv.root_id = file_id
+                parent_id_basename_key = '', ''
+            else:
+                utf8_entry_name = entry.name.encode('utf-8')
+                parent_id_basename_key = (entry.parent_id, utf8_entry_name)
+            new_value = entry_to_bytes(entry)
+            # Update caches. It's worth doing this whether
+            # we're propagating the old caches or not.
+            ## result._path_to_fileid_cache[new_path] = file_id
+            id_to_entry_delta.append((None, (file_id,), new_value))
+            parent_id_basename_delta.append(
+                (None, parent_id_basename_key, file_id))
+        new_inv.id_to_entry.apply_insert_delta(id_to_entry_delta)
+        new_inv.parent_id_basename_to_file_id.apply_insert_delta(parent_id_basename_delta)
+
     def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
                                parents, basis_inv=None, propagate_caches=False):
         """Add a new inventory expressed as a delta against another revision.
@@ -699,24 +747,30 @@
             repository format specific) of the serialized inventory, and the
             resulting inventory.
         """
-        if basis_revision_id == _mod_revision.NULL_REVISION:
-            return KnitPackRepository.add_inventory_by_delta(self,
-                basis_revision_id, delta, new_revision_id, parents)
         if not self.is_in_write_group():
             raise AssertionError("%r not in write group" % (self,))
         _mod_revision.check_not_reserved_id(new_revision_id)
-        basis_tree = self.revision_tree(basis_revision_id)
-        basis_tree.lock_read()
-        try:
-            if basis_inv is None:
+        basis_tree = None
+        if basis_inv is None:
+            if basis_revision_id == _mod_revision.NULL_REVISION:
+                new_inv = self._get_null_inventory()
+                self._apply_delta_to_null_inv(new_inv, delta, new_revision_id)
+                inv_lines = new_inv.to_lines()
+                return self._inventory_add_lines(new_revision_id, parents,
+                    inv_lines, check_content=False), new_inv
+            else:
+                basis_tree = self.revision_tree(basis_revision_id)
+                basis_tree.lock_read()
                 basis_inv = basis_tree.inventory
+        try:
             result = basis_inv.create_by_apply_delta(delta, new_revision_id,
                 propagate_caches=propagate_caches)
             inv_lines = result.to_lines()
             return self._inventory_add_lines(new_revision_id, parents,
                 inv_lines, check_content=False), result
         finally:
-            basis_tree.unlock()
+            if basis_tree is not None:
+                basis_tree.unlock()
 
     def _iter_inventories(self, revision_ids):
         """Iterate over many inventory objects."""



More information about the bazaar-commits mailing list