-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Brian Harring wrote: > You need white outs here (lifting a unionfs term); this won't actually > change state in any way if you're trying to delete a bad entry from > the underlying metadata cache.
I've implemented whiteouts so that items can now be deleted properly. The whiteouts themselves are stored inside the existing writable database (self.db_rw) in order to avoid the need for an additional storage area (similar to unionfs whiteouts which are implemented as hidden files). The whiteouts (if they exist) are validated on access and removed if necessary. A whiteout is considered invalid if it's _mtime_ and _eclasses_ are not exactly equal to underlying database entry that it erases (or the underlying database entry no longer exists). This should cause whiteouts to be automatically invalidated whenever the underlying cache changes. > Aside from that, the label trick is icky. ;) Well yeah, but that was the only obvious way that I could see to implement the module within the existing framework. I think we should modify the framework to allow for a more appealing alternative. Zac -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (GNU/Linux) iD8DBQFD3JMf/ejvha5XGaMRAitfAKDrw2C09xIzDyMZ6nVNHdIU1K1l3wCeLvIi hD4yWTjTdRtPQyuAQQ6TtFc= =Yr2K -----END PGP SIGNATURE-----
# Copyright: 2006 Gentoo Foundation # Author(s): Zac Medico ([EMAIL PROTECTED]) # License: GPL2 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): 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] if long(value_rw["_mtime_"]) != long(value_ro["_mtime_"]): return False return value_rw["_eclasses_"] == value_ro["_eclasses_"] except KeyError: return False