Rev 4543: Teach CHKInventory.path2id to avoid loading inventory entries. in http://bazaar.launchpad.net/~lifeless/bzr/apply-inventory-delta

Robert Collins robertc at robertcollins.net
Fri Jul 17 03:11:27 BST 2009


At http://bazaar.launchpad.net/~lifeless/bzr/apply-inventory-delta

------------------------------------------------------------
revno: 4543
revision-id: robertc at robertcollins.net-20090717021123-s5gg4kje2g07qnio
parent: robertc at robertcollins.net-20090717020426-xz7uaj0uzgykemu4
committer: Robert Collins <robertc at robertcollins.net>
branch nick: apply-inventory-delta
timestamp: Fri 2009-07-17 12:11:23 +1000
message:
  Teach CHKInventory.path2id to avoid loading inventory entries.
=== modified file 'NEWS'
--- a/NEWS	2009-07-16 23:28:49 +0000
+++ b/NEWS	2009-07-17 02:11:23 +0000
@@ -57,6 +57,10 @@
 Internals
 *********
 
+* ``CHKInventory.path2id`` uses the parent_id to basename hash to avoid
+  reading the entries along the path, reducing work to lookup ids from
+  paths. (Robert Collins)
+
 * ``CHKMap.apply_delta`` now raises ``InconsistentDelta`` if a delta adds
   as new a key which was already mapped. (Robert Collins)
 

=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py	2009-07-17 02:04:26 +0000
+++ b/bzrlib/inventory.py	2009-07-17 02:11:23 +0000
@@ -1480,6 +1480,7 @@
         self._fileid_to_entry_cache = {}
         self._path_to_fileid_cache = {}
         self._search_key_name = search_key_name
+        self.root_id = None
 
     def __eq__(self, other):
         """Compare two sets by comparing their contents."""
@@ -2014,11 +2015,34 @@
 
     def path2id(self, name):
         """See CommonInventory.path2id()."""
+        # TODO: perhaps support negative hits?
         result = self._path_to_fileid_cache.get(name, None)
-        if result is None:
-            result = CommonInventory.path2id(self, name)
-            self._path_to_fileid_cache[name] = result
-        return result
+        if result is not None:
+            return result
+        if isinstance(name, basestring):
+            names = osutils.splitpath(name)
+        else:
+            names = name
+        current_id = self.root_id
+        if current_id is None:
+            return None
+        parent_id_index = self.parent_id_basename_to_file_id
+        for basename in names:
+            # TODO: Cache each path we figure out in this function.
+            basename_utf8 = basename.encode('utf8')
+            key_filter = [(current_id, basename_utf8)]
+            file_id = None
+            for (parent_id, name_utf8), file_id in parent_id_index.iteritems(
+                key_filter=key_filter):
+                if parent_id != current_id or name_utf8 != basename_utf8:
+                    raise errors.BzrError("corrupt inventory  lookup! "
+                        "%r %r %r %r" % (parent_id, current_id, name_utf8,
+                        basename_utf8))
+            if file_id is None:
+                return None
+            current_id = file_id
+        self._path_to_fileid_cache[name] = current_id
+        return current_id
 
     def to_lines(self):
         """Serialise the inventory to lines."""




More information about the bazaar-commits mailing list