From 8edf2787fca77df7e17e25267f0e18d81667bedd Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Sun, 26 Feb 2006 13:10:43 +0000 Subject: Add a new cache.metadata_overlay module that layers a writable cache over a readonly cache. svn path=/main/trunk/; revision=2792 --- pym/cache/metadata_overlay.py | 91 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 pym/cache/metadata_overlay.py diff --git a/pym/cache/metadata_overlay.py b/pym/cache/metadata_overlay.py new file mode 100644 index 000000000..557855a52 --- /dev/null +++ b/pym/cache/metadata_overlay.py @@ -0,0 +1,91 @@ +# 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_"] -- cgit v1.2.3-1-g7c22