Rev 3814: Set up failing tests for _copy_revision_texts, _copy_inventory_texts, and _copy_text_texts. in http://bzr.arbash-meinel.com/branches/bzr/1.9-dev/pack_retry_153786

John Arbash Meinel john at arbash-meinel.com
Sat Oct 25 16:31:01 BST 2008


At http://bzr.arbash-meinel.com/branches/bzr/1.9-dev/pack_retry_153786

------------------------------------------------------------
revno: 3814
revision-id: john at arbash-meinel.com-20081025153055-u56eg6vkslmzx6qs
parent: john at arbash-meinel.com-20081025024257-sbi10z5ddf6rc93r
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: pack_retry_153786
timestamp: Sat 2008-10-25 10:30:55 -0500
message:
  Set up failing tests for _copy_revision_texts, _copy_inventory_texts, and _copy_text_texts.
-------------- next part --------------
=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py	2008-10-25 02:40:12 +0000
+++ b/bzrlib/repofmt/pack_repo.py	2008-10-25 15:30:55 +0000
@@ -814,16 +814,20 @@
                 record_index += 1
 
     def _copy_nodes_graph(self, index_map, writer, write_index,
-        readv_group_iter, total_items, output_lines=False):
+        readv_group_iter, total_items, output_lines=False, completed_keys=None):
         """Copy knit nodes between packs.
 
         :param output_lines: Return lines present in the copied data as
             an iterator of line,version_id.
+        :param completed_keys: If set to a list, we will fill it with the keys
+            that have been successfully written to the target repository. This
+            is used in case there is a fault and we need to restart.
         """
         pb = ui.ui_factory.nested_progress_bar()
         try:
             for result in self._do_copy_nodes_graph(index_map, writer,
-                write_index, output_lines, pb, readv_group_iter, total_items):
+                write_index, output_lines, pb, readv_group_iter, total_items,
+                completed_keys=completed_keys):
                 yield result
         except Exception:
             # Python 2.4 does not permit try:finally: in a generator.
@@ -833,7 +837,7 @@
             pb.finished()
 
     def _do_copy_nodes_graph(self, index_map, writer, write_index,
-        output_lines, pb, readv_group_iter, total_items):
+        output_lines, pb, readv_group_iter, total_items, completed_keys=None):
         # for record verification
         knit = KnitVersionedFiles(None, None)
         # for line extraction when requested (inventories only)
@@ -841,6 +845,10 @@
             factory = KnitPlainFactory()
         record_index = 0
         pb.update("Copied record", record_index, total_items)
+        if completed_keys is None:
+            completed_keys_append = None
+        else:
+            completed_keys_append = completed_keys.append
         for index, readv_vector, node_vector in readv_group_iter:
             # copy the data
             transport, path = index_map[index]
@@ -863,6 +871,8 @@
                     df.close()
                 pos, size = writer.add_bytes_record(raw_data, names)
                 write_index.add_node(key, eol_flag + "%d %d" % (pos, size), references)
+                if completed_keys_append is not None:
+                    completed_keys_append(key)
                 pb.update("Copied record", record_index)
                 record_index += 1
 

=== modified file 'bzrlib/tests/test_repository.py'
--- a/bzrlib/tests/test_repository.py	2008-10-25 00:38:53 +0000
+++ b/bzrlib/tests/test_repository.py	2008-10-25 15:30:55 +0000
@@ -1042,8 +1042,86 @@
 class TestPacker(TestCaseWithTransport):
     """Tests for the packs repository Packer class."""
 
-    # To date, this class has been factored out and nothing new added to it;
-    # thus there are not yet any tests.
+    def make_repo_with_three_packs(self):
+        tree = self.make_branch_and_tree('.')
+        tree.lock_write()
+        self.addCleanup(tree.unlock)
+        self.build_tree(['f'])
+        tree.add('f', 'f-id')
+        revs = []
+        revs.append(tree.commit('one'))
+        revs.append(tree.commit('two'))
+        revs.append(tree.commit('three'))
+        return tree.branch.repository, revs
+
+    def munge_transport_readv(self, pack_obj, call_obj):
+        """Change pack_obj's transport so it triggers a callable."""
+        orig_readv = pack_obj.pack_transport.readv
+        def failing_readv(relpath, *args, **kwargs):
+            # Fail when we try to read. We would *like* to fail after reading a
+            # bit, but that runs into concurrancy issues depending on the
+            # platform
+            print 'activating'
+            call_obj()
+            for count, val in enumerate(orig_readv(relpath, *args, **kwargs)):
+                yield val
+        pack_obj.pack_transport.readv = failing_readv
+
+    def munge_function_to_trigger(self, obj, attr, pack_obj, call_obj):
+        """Update a function so that it munges readv() when called.
+
+        :param obj: The object we want to have modified
+        :param attr: The attribute we want to trigger the change in readv
+        :param pack_obj: The pack object whose readv will be munged
+        :param call_obj: A callable, which will be called during readv
+        """
+        print 'munging %s' % (attr,)
+        orig_func = getattr(obj, attr)
+        def munging_func(*args, **kwargs):
+            self.munge_transport_readv(pack_obj, call_obj)
+            return orig_func(*args, **kwargs)
+        setattr(obj, attr, munging_func)
+
+    def setup_retry_function(self, attr):
+        repo, revs = self.make_repo_with_three_packs()
+        alt_repo = repository.Repository.open('.')
+        alt_repo.lock_write()
+        self.addCleanup(alt_repo.unlock)
+
+        packer = pack_repo.Packer(repo._pack_collection,
+                                  repo._pack_collection.packs,
+                                  '.testpack')
+        self.munge_function_to_trigger(packer, attr,
+                                       packer.packs[1], alt_repo.pack)
+        return packer
+
+    def test__copy_revision_texts_retries(self):
+        packer = self.setup_retry_function('_copy_revision_texts')
+        packer.pack()
+
+    def test__copy_inventory_texts_retries(self):
+        packer = self.setup_retry_function('_copy_inventory_texts')
+        packer.pack()
+
+    def test__copy_text_texts_retries(self):
+        packer = self.setup_retry_function('_copy_text_texts')
+        packer.pack()
+
+    def test__copy_signature_texts_retries(self):
+        return # there isn't a separate _copy_signature_texts function yet
+        repo, revs = self.make_repo_with_three_packs()
+        alt_repo = repository.Repository.open('.')
+        alt_repo.lock_write()
+        self.addCleanup(alt_repo.unlock)
+
+        packer = pack_repo.Packer(repo._pack_collection,
+                                  repo._pack_collection.packs,
+                                  '.testpack')
+        # Munge the middle pack so that while reading, it triggers a
+        # full-repack from the other repository
+        self.munge_function_to_trigger(packer, '_copy_signature_texts',
+                                       packer.packs[1], alt_repo.pack)
+        packer.pack()
 
 
 class TestOptimisingPacker(TestCaseWithTransport):



More information about the bazaar-commits mailing list