From a12de8508f3406954abe9048ba7231343a5a70b9 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Sun, 26 Dec 2010 13:22:38 -0800 Subject: [PATCH] anydbm: use gdbm "u" flag for concurrent writers This will fix bug #53607. --- pym/portage/cache/anydbm.py | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/pym/portage/cache/anydbm.py b/pym/portage/cache/anydbm.py index 1cf3775eb..1d56b1458 100644 --- a/pym/portage/cache/anydbm.py +++ b/pym/portage/cache/anydbm.py @@ -9,6 +9,20 @@ try: except ImportError: # python 3.x import dbm as anydbm_module + +try: + import dbm.gnu as gdbm +except ImportError: + try: + import gdbm + except ImportError: + gdbm = None + +try: + from dbm import whichdb +except ImportError: + from whichdb import whichdb + try: import cPickle as pickle except ImportError: @@ -35,11 +49,15 @@ class database(fs_template.FsBased): self._db_path = os.path.join(self.location, fs_template.gen_label(self.location, self.label)+default_db) self.__db = None + mode = "w" + if whichdb(self._db_path) in ("dbm.gnu", "gdbm"): + # Allow multiple concurrent writers (see bug #53607). + mode += "u" try: # dbm.open() will not work with bytes in python-3.1: # TypeError: can't concat bytes to str self.__db = anydbm_module.open(self._db_path, - 'w', self._perms) + mode, self._perms) except anydbm_module.error: # XXX handle this at some point try: @@ -53,14 +71,22 @@ class database(fs_template.FsBased): if self.__db == None: # dbm.open() will not work with bytes in python-3.1: # TypeError: can't concat bytes to str - self.__db = anydbm_module.open(self._db_path, - 'c', self._perms) + if gdbm is None: + self.__db = anydbm_module.open(self._db_path, + "c", self._perms) + else: + # Prefer gdbm type if available, since it allows + # multiple concurrent writers (see bug #53607). + self.__db = gdbm.open(self._db_path, + "cu", self._perms) except anydbm_module.error as e: raise cache_errors.InitializationError(self.__class__, e) self._ensure_access(self._db_path) def iteritems(self): - return iter(self.__db.items()) + # dbm doesn't implement items() + for k in self.__db.keys(): + yield (k, self[k]) def _getitem(self, cpv): # we override getitem because it's just a cpickling of the data handed in. -- 2.26.2