summaryrefslogtreecommitdiffstats
path: root/pym/portage/dbapi
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-10-24 23:59:31 -0700
committerZac Medico <zmedico@gentoo.org>2012-10-25 01:23:33 -0700
commite440548da95775019dc89bb612f8049240eed4e9 (patch)
treedaf33f8cb22fcd632b418307bc8482371518a7e9 /pym/portage/dbapi
parentf48625c547398ee5f92d33e16b1a837c3c595ae9 (diff)
downloadportage-e440548da95775019dc89bb612f8049240eed4e9.tar.gz
portage-e440548da95775019dc89bb612f8049240eed4e9.tar.bz2
portage-e440548da95775019dc89bb612f8049240eed4e9.zip
dblink: add hooks to sync disk for bug #439584
Diffstat (limited to 'pym/portage/dbapi')
-rw-r--r--pym/portage/dbapi/vartree.py59
1 files changed, 58 insertions, 1 deletions
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 46afea572..cb7b39b02 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -1486,6 +1486,7 @@ class dblink(object):
self._contents_inodes = None
self._contents_basenames = None
self._linkmap_broken = False
+ self._device_path_map = {}
self._hardlink_merge_map = {}
self._hash_key = (self._eroot, self.mycpv)
self._protect_obj = None
@@ -1533,7 +1534,11 @@ class dblink(object):
"""
Remove this entry from the database
"""
- if not os.path.exists(self.dbdir):
+ try:
+ os.lstat(self.dbdir)
+ except OSError as e:
+ if e.errno not in (errno.ENOENT, errno.ENOTDIR, errno.ESTALE):
+ raise
return
# Check validity of self.dbdir before attempting to remove it.
@@ -1550,6 +1555,14 @@ class dblink(object):
pass
self.vartree.dbapi._remove(self)
+ # Use self.dbroot since we need an existing path for syncfs.
+ try:
+ self._merged_path(self.dbroot, os.lstat(self.dbroot))
+ except OSError:
+ pass
+
+ self._post_merge_sync()
+
def clearcontents(self):
"""
For a given db entry (self), erase the CONTENTS values.
@@ -2135,6 +2148,12 @@ class dblink(object):
self._eerror("postrm",
["Could not chmod or unlink '%s': %s" % \
(file_name, ose)])
+ else:
+ try:
+ self._merged_path(file_name, lstatobj)
+ except OSError:
+ pass
+
finally:
if bsd_chflags and pflags != 0:
# Restore the parent flags we saved before unlinking
@@ -4048,6 +4067,7 @@ class dblink(object):
try:
self.delete()
_movefile(self.dbtmpdir, self.dbpkgdir, mysettings=self.settings)
+ self._merged_path(self.dbpkgdir, os.lstat(self.dbpkgdir))
finally:
self.unlockdb()
@@ -4163,6 +4183,7 @@ class dblink(object):
# For gcc upgrades, preserved libs have to be removed after the
# the library path has been updated.
self._prune_plib_registry()
+ self._post_merge_sync()
return os.EX_OK
@@ -4412,6 +4433,12 @@ class dblink(object):
mymtime = movefile(mysrc, mydest, newmtime=thismtime,
sstat=mystat, mysettings=self.settings,
encoding=_encodings['merge'])
+
+ try:
+ self._merged_path(mydest, os.lstat(mydest))
+ except OSError:
+ pass
+
if mymtime != None:
showMessage(">>> %s -> %s\n" % (mydest, myto))
if sys.hexversion >= 0x3030000:
@@ -4511,6 +4538,12 @@ class dblink(object):
os.chmod(mydest, mystat[0])
os.chown(mydest, mystat[4], mystat[5])
showMessage(">>> %s/\n" % mydest)
+
+ try:
+ self._merged_path(mydest, os.lstat(mydest))
+ except OSError:
+ pass
+
outfile.write("dir "+myrealdest+"\n")
# recurse and merge this directory
if self.mergeme(srcroot, destroot, outfile, secondhand,
@@ -4610,6 +4643,11 @@ class dblink(object):
hardlink_candidates.append(mydest)
zing = ">>>"
+ try:
+ self._merged_path(mydest, os.lstat(mydest))
+ except OSError:
+ pass
+
if mymtime != None:
if sys.hexversion >= 0x3030000:
outfile.write("obj "+myrealdest+" "+mymd5+" "+str(mymtime // 1000000000)+"\n")
@@ -4625,6 +4663,12 @@ class dblink(object):
sstat=mystat, mysettings=self.settings,
encoding=_encodings['merge']) is not None:
zing = ">>>"
+
+ try:
+ self._merged_path(mydest, os.lstat(mydest))
+ except OSError:
+ pass
+
else:
return 1
if stat.S_ISFIFO(mymode):
@@ -4633,6 +4677,19 @@ class dblink(object):
outfile.write("dev %s\n" % myrealdest)
showMessage(zing + " " + mydest + "\n")
+ def _merged_path(self, path, lstatobj):
+ previous_path = self._device_path_map.get(lstatobj.st_dev)
+ if previous_path is None or len(path) < len(previous_path):
+ self._device_path_map[lstatobj.st_dev] = path
+
+ def _post_merge_sync(self):
+ """
+ Call this after merge or unmerge, in order to sync relevant files to
+ disk and avoid data-loss in the event of a power failure. This method
+ does nothing if FEATURES=merge-sync is disabled.
+ """
+ pass
+
def merge(self, mergeroot, inforoot, myroot=None, myebuild=None, cleanup=0,
mydbapi=None, prev_mtimes=None, counter=None):
"""