12596 compressed repository files not upgraded to new format automatically in127
authorShawn Walker <srw@sun.com>
Tue, 10 Nov 2009 18:24:21 -0600
changeset 1485 6aeae7c6ca4c
parent 1484 6a2660b61eb4
child 1486 5e4dedd85187
12596 compressed repository files not upgraded to new format automatically
src/modules/file_layout/file_manager.py
src/tests/api/t_file_manager.py
src/tests/baseline.txt
--- a/src/modules/file_layout/file_manager.py	Tue Nov 10 15:42:33 2009 -0700
+++ b/src/modules/file_layout/file_manager.py	Tue Nov 10 18:24:21 2009 -0600
@@ -131,7 +131,7 @@
         def set_read_only(self):
                 """Make the FileManager read only."""
                 self.readonly = True
-                        
+
         def __select_path(self, hashval, check_existence):
                 """Find the path to the file with name hashval.
 
@@ -216,26 +216,36 @@
                         raise NeedToModifyReadOnlyFileManager(hashval)
                 cur_full_path, dest_full_path = \
                     self.__select_path(hashval, True)
-                if cur_full_path == dest_full_path:
-                        return
-                if cur_full_path:
+
+                if cur_full_path and cur_full_path != dest_full_path:
+                        # The file is stored in an old location and needs to be
+                        # moved to a new location.  To prevent disruption of
+                        # service or other race conditions, rename the source
+                        # file into the old place first.
                         try:
-                                portable.remove(src_path)
+                                portable.rename(src_path, cur_full_path)
                         except EnvironmentError, e:
                                 if e.errno == errno.EACCES or \
                                     e.errno == errno.EROFS:
                                         raise FMPermissionsException(e.filename)
                                 raise
                         src_path = cur_full_path
+
                 p_dir = os.path.dirname(dest_full_path)
                 try:
+                        # Ensure that the destination's parent directory exists.
                         if not os.path.exists(p_dir):
                                 os.makedirs(p_dir)
+
+                        # Move the file into place.
                         portable.rename(src_path, dest_full_path)
                 except EnvironmentError, e:
                         if e.errno == errno.EACCES or e.errno == errno.EROFS:
                                 raise FMPermissionsException(e.filename)
                         raise
+
+                # Attempt to remove the parent directory of the file's original
+                # location to ensure empty directories aren't left behind.
                 if cur_full_path:
                         try:
                                 os.removedirs(os.path.dirname(cur_full_path))
@@ -248,7 +258,6 @@
                                         raise FMPermissionsException(e.filename)
                                 else:
                                         raise
-                return
 
         def remove(self, hashval):
                 """This function removes the file associated with the name
@@ -272,7 +281,6 @@
                                         raise FMPermissionsException(e.filename)
                                 else:
                                         raise
-                return
 
         def walk(self):
                 """Generate all the hashes of all files known."""
--- a/src/tests/api/t_file_manager.py	Tue Nov 10 15:42:33 2009 -0700
+++ b/src/tests/api/t_file_manager.py	Tue Nov 10 18:24:21 2009 -0600
@@ -23,9 +23,9 @@
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 
+import errno
 import os
 import shutil
-import stat
 import sys
 import tempfile
 import unittest
@@ -61,12 +61,14 @@
         def old_hash(s):
                 return os.path.join(s[0:2], s[2:8], s)
 
-        def touch_old_file(self, s):
+        def touch_old_file(self, s, data=None):
+                if data is None:
+                        data = s
                 p = os.path.join(self.__test_dir, self.old_hash(s))
                 if not os.path.exists(os.path.dirname(p)):
                         os.makedirs(os.path.dirname(p))
                 fh = open(p, "wb")
-                fh.write(s)
+                fh.write(data)
                 fh.close()
                 return p
 
@@ -107,7 +109,7 @@
 
                 t = tempfile.gettempdir()
                 no_dir = os.path.join(t, "not_exist")
-                
+
                 self.check_exception(file_manager.FileManager,
                     file_manager.NeedToModifyReadOnlyFileManager,
                     ["create", no_dir], no_dir, readonly=True)
@@ -159,7 +161,7 @@
                 # Finally, remove file stored in the old location for the next
                 # few tests.
                 p1 = self.touch_old_file(hash1)
-                p2 = self.touch_old_file(hash2)
+                self.touch_old_file(hash2)
                 self.assert_(os.path.isfile(p1))
                 self.assert_(os.path.isdir(os.path.dirname(p1)))
                 self.assertEqual(fm.lookup(hash1),
@@ -182,18 +184,10 @@
                 self.assert_(not os.path.exists(p4))
                 self.assert_(not os.path.exists(os.path.dirname(p4)))
 
-                # Test that inserting a file already in the file manager just
-                # moves the old file if necessary.
                 p3 = self.touch_old_file(hash3)
                 self.assert_(os.path.isfile(p3))
                 self.assert_(os.path.isdir(os.path.dirname(p3)))
-                
-                rh3_fd, raw_hash_3_loc = tempfile.mkstemp(dir=self.__test_dir)
-                rh3_fh = os.fdopen(rh3_fd, "w")
-                rh3_fh.write("foo")
-                rh3_fh.close()
-                
-                fm.insert(hash3, raw_hash_3_loc)
+                fm.insert(hash3, p3)
 
                 self.assert_(not os.path.exists(p3))
                 self.assert_(not os.path.exists(os.path.dirname(p3)))
@@ -236,7 +230,7 @@
                 self.assert_(not os.path.exists(v0_hash3_loc))
                 self.assert_(not os.path.exists(os.path.dirname(v0_hash3_loc)))
                 self.assert_(os.path.isfile(fm.lookup(hash1)))
-                
+
                 rh2_fd, raw_hash_2_loc = tempfile.mkstemp(dir=self.__test_dir)
                 rh2_fh = os.fdopen(rh2_fd, "w")
                 rh2_fh.write(hash2)
@@ -279,19 +273,19 @@
                 l1 = layout.V1Layout()
 
                 # Populate the managed location using the v0 layout.
-                for hash in (hash1, hash2, hash3, hash4):
-                        self.touch_old_file(hash)
+                for fhash in (hash1, hash2, hash3, hash4):
+                        self.touch_old_file(fhash)
 
                 # Migrate it to the v1 layout.
                 fm = file_manager.FileManager(self.__test_dir, False)
-                for hash in fm.walk():
-                        self.assertEqual(fm.lookup(hash),
-                            os.path.join(self.__test_dir, l1.lookup(hash)))
+                for fhash in fm.walk():
+                        self.assertEqual(fm.lookup(fhash),
+                            os.path.join(self.__test_dir, l1.lookup(fhash)))
 
                 # After migration verify that no v0 parent directories remain.
-                for hash in fm.walk():
+                for fhash in fm.walk():
                         self.assertFalse(os.path.exists(os.path.dirname(
-                            os.path.join(self.__test_dir, l0.lookup(hash)))))
+                            os.path.join(self.__test_dir, l0.lookup(fhash)))))
 
                 # Re-create the FileManager using v0 as the preferred layout.
                 fm = file_manager.FileManager(self.__test_dir, False,
@@ -299,7 +293,52 @@
 
                 # Test that looking up a file stored under the v1 layout is
                 # correctly moved to the v0 layout.
-                for hash in fm.walk():
-                        self.assertEqual(fm.lookup(hash),
-                            os.path.join(self.__test_dir, l0.lookup(hash)))
+                for fhash in fm.walk():
+                        self.assertEqual(fm.lookup(fhash),
+                            os.path.join(self.__test_dir, l0.lookup(fhash)))
+
+        def test_3_replace(self):
+                """Verify that insert will replace an existing file even though
+                the hashval is the same."""
+
+                # Verify that reverse layout migration works as expected.
+                hash1 = "584b6ab7d7eb446938a02e57101c3a2fecbfb3cb"
+                hash2 = "584b6ab7d7eb446938a02e57101c3a2fecbfb3cc"
+                hash3 = "994b6ab7d7eb446938a02e57101c3a2fecbfb3cc"
+                hash4 = "cc1f76cdad188714d1c3b92a4eebb4ec7d646166"
+
+                l1 = layout.V1Layout()
+
+                # Populate the managed location using the v0 layout.
+                for fhash in (hash1, hash2, hash3, hash4):
+                        self.touch_old_file(fhash, data="old-%s" % fhash)
 
+                # Migrate it to the v1 layout and verify that each
+                # file contains the expected data.
+                fm = file_manager.FileManager(self.__test_dir, False)
+                for fhash in fm.walk():
+                        loc = fm.lookup(fhash)
+                        self.assertEqual(loc, os.path.join(self.__test_dir,
+                            l1.lookup(fhash)))
+
+                        f = open(loc, "rb")
+                        self.assertEqual(f.read(), "old-%s" % fhash)
+                        f.close()
+
+                # Now replace each file using the old hashnames and verify
+                # that the each contains the expected data.
+                for fhash in fm.walk():
+                        loc = os.path.join(self.__test_dir, l1.lookup(fhash))
+                        self.assertTrue(os.path.exists(loc))
+
+                        npath = os.path.join(self.__test_dir, "new-%s" % fhash)
+                        nfile = open(npath, "wb")
+                        nfile.write("new-%s" % fhash)
+                        nfile.close()
+                        fm.insert(fhash, npath)
+
+                        loc = fm.lookup(fhash)
+                        f = open(loc, "rb")
+                        self.assertEqual(f.read(), "new-%s" % fhash)
+                        f.close()
+
--- a/src/tests/baseline.txt	Tue Nov 10 15:42:33 2009 -0700
+++ b/src/tests/baseline.txt	Tue Nov 10 18:24:21 2009 -0600
@@ -31,6 +31,7 @@
 api.t_elf.py TestElf.test_is_elf_object|pass
 api.t_file_manager.py TestFileManager.test_1|pass
 api.t_file_manager.py TestFileManager.test_2_reverse|pass
+api.t_file_manager.py TestFileManager.test_3_replace|pass
 api.t_filter.py TestFilter.test_01_debug_i386|pass
 api.t_filter.py TestFilter.test_02_nondebug_i386|pass
 api.t_filter.py TestFilter.test_03_i386|pass