| # Copyright 1999-2006 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| # $Header: $ |
| |
| import time |
| if not hasattr(__builtins__, "set"): |
| from sets import Set as set |
| import template |
| from flat_hash import database as db_rw |
| from metadata import database as db_ro |
| |
| class database(template.database): |
| |
| autocommits = True |
| serialize_eclasses = False |
| |
| def __init__(self, location, label, auxdbkeys, **config): |
| super(database, self).__init__(location, label, auxdbkeys) |
| self.db_rw = db_rw(location, label, auxdbkeys, **config) |
| self.db_ro = db_ro(label,"metadata/cache",auxdbkeys) |
| |
| def __getitem__(self, cpv): |
| """funnel whiteout validation through here, since value needs to be fetched""" |
| try: |
| value = self.db_rw[cpv] |
| except KeyError: |
| return self.db_ro[cpv] # raises a KeyError when necessary |
| if self._is_whiteout(value): |
| if self._is_whiteout_valid(cpv, value): |
| raise KeyError(cpv) |
| else: |
| del self.db_rw[cpv] |
| return self.db_ro[cpv] # raises a KeyError when necessary |
| else: |
| return value |
| |
| def _setitem(self, name, values): |
| try: |
| value_ro = self.db_ro[name] |
| if self._are_values_identical(value_ro,values): |
| # we have matching values in the underlying db_ro |
| # so it is unnecessary to store data in db_rw |
| try: |
| del self.db_rw[name] # delete unwanted whiteout when necessary |
| except KeyError: |
| pass |
| except KeyError: |
| self.db_rw[name] = values |
| |
| def _delitem(self, cpv): |
| value = self[cpv] # validates whiteout and/or raises a KeyError when necessary |
| if self.db_ro.has_key(cpv): |
| self.db_rw[cpv] = self._create_whiteout(value) |
| else: |
| del self.db_rw[cpv] |
| |
| def has_key(self, cpv): |
| try: |
| self[cpv] # validates whiteout when necessary |
| except KeyError: |
| return False |
| return True |
| |
| def iterkeys(self): |
| s = set() |
| for cpv in self.db_rw.iterkeys(): |
| if self.has_key(cpv): # validates whiteout when necessary |
| yield cpv |
| # set includes whiteouts so they won't be yielded later |
| s.add(cpv) |
| for cpv in self.db_ro.iterkeys(): |
| if cpv not in s: |
| yield cpv |
| |
| def _is_whiteout(self, value): |
| return value["EAPI"] == "whiteout" |
| |
| def _create_whiteout(self, value): |
| return {"EAPI":"whiteout","_eclasses_":value["_eclasses_"],"_mtime_":value["_mtime_"]} |
| |
| def _is_whiteout_valid(self, name, value_rw): |
| try: |
| value_ro = self.db_ro[name] |
| return self._are_values_identical(value_rw,value_ro) |
| except KeyError: |
| return False |
| |
| def _are_values_identical(self, value1, value2): |
| if long(value1["_mtime_"]) != long(value2["_mtime_"]): |
| return False |
| return value1["_eclasses_"] == value2["_eclasses_"] |