# Copyright 2005-2010 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # Author(s): Brian Harring (ferringb@gentoo.org) from __future__ import absolute_import try: import anydbm as anydbm_module 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: import pickle from portage import _unicode_encode from portage import os import sys from portage.cache import fs_template from portage.cache import cache_errors class database(fs_template.FsBased): validation_chf = 'md5' chf_types = ('md5', 'mtime') autocommits = True cleanse_keys = True serialize_eclasses = False def __init__(self, *args, **config): super(database,self).__init__(*args, **config) default_db = config.get("dbtype","anydbm") if not default_db.startswith("."): default_db = '.' + default_db 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, mode, self._perms) except anydbm_module.error: # XXX handle this at some point try: self._ensure_dirs() self._ensure_dirs(self._db_path) except (OSError, IOError) as e: raise cache_errors.InitializationError(self.__class__, e) # try again if failed try: if self.__db == None: # dbm.open() will not work with bytes in python-3.1: # TypeError: can't concat bytes to str 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): # 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. return pickle.loads(self.__db[_unicode_encode(cpv)]) def _setitem(self, cpv, values): self.__db[_unicode_encode(cpv)] = pickle.dumps(values,pickle.HIGHEST_PROTOCOL) def _delitem(self, cpv): del self.__db[cpv] def __iter__(self): return iter(list(self.__db.keys())) def __contains__(self, cpv): return cpv in self.__db def __del__(self): if "__db" in self.__dict__ and self.__db != None: self.__db.sync() self.__db.close() if sys.hexversion >= 0x3000000: items = iteritems