blob: f9c613b50d0cbb937f1741dbf14d63e771f699f6 [file] [log] [blame]
# Copyright: 2005 Gentoo Foundation
# Author(s): Brian Harring (ferringb@gentoo.org)
# License: GPL2
# $Id: template.py 1911 2005-08-25 03:44:21Z ferringb $
import cache_errors
from mappings import ProtectedDict
class database(object):
# this is for metadata/cache transfer.
# basically flags the cache needs be updated when transfered cache to cache.
# leave this.
complete_eclass_entries_ = True
autocommits = False
cleanse_keys = False
serialize_eclasses = True
def __init__(self, location, label, auxdbkeys, readonly=False):
""" initialize the derived class; specifically, store label/keys"""
self._known_keys = auxdbkeys
self.location = location
self.label = label
self.readonly = readonly
self.sync_rate = 0
self.updates = 0
def __getitem__(self, cpv):
"""set a cpv to values
This shouldn't be overriden in derived classes since it handles the __eclasses__ conversion.
that said, if the class handles it, they can override it."""
if self.updates > self.sync_rate:
self.commit()
self.updates = 0
d=self._getitem(cpv)
if self.serialize_eclasses and "_eclasses_" in d:
d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"])
return d
def _getitem(self, cpv):
"""get cpv's values.
override this in derived classess"""
raise NotImplementedError
def __setitem__(self, cpv, values):
"""set a cpv to values
This shouldn't be overriden in derived classes since it handles the readonly checks"""
if self.readonly:
raise cache_errors.ReadOnlyRestriction()
if self.cleanse_keys:
d=ProtectedDict(values)
for k in d.keys():
if d[k] == '':
del d[k]
if self.serialize_eclasses and "_eclasses_" in values:
d["_eclasses_"] = serialize_eclasses(d["_eclasses_"])
elif self.serialize_eclasses and "_eclasses_" in values:
d = ProtectedDict(values)
d["_eclasses_"] = serialize_eclasses(d["_eclasses_"])
else:
d = values
self._setitem(cpv, d)
if not self.autocommits:
self.updates += 1
if self.updates > self.sync_rate:
self.commit()
self.updates = 0
def _setitem(self, name, values):
"""__setitem__ calls this after readonly checks. override it in derived classes
note _eclassees_ key *must* be handled"""
raise NotImplementedError
def __delitem__(self, cpv):
"""delete a key from the cache.
This shouldn't be overriden in derived classes since it handles the readonly checks"""
if self.readonly:
raise cache_errors.ReadOnlyRestriction()
if not self.autocommits:
self.updates += 1
self._delitem(cpv)
if self.updates > self.sync_rate:
self.commit()
self.updates = 0
def _delitem(self,cpv):
"""__delitem__ calls this after readonly checks. override it in derived classes"""
raise NotImplementedError
def has_key(self, cpv):
raise NotImplementedError
def keys(self):
return tuple(self.iterkeys())
def iterkeys(self):
raise NotImplementedError
def iteritems(self):
for x in self.iterkeys():
yield (x, self[x])
def items(self):
return list(self.iteritems())
def sync(self, rate=0):
self.sync_rate = rate
if(rate == 0):
self.commit()
def commit(self):
if not self.autocommits:
raise NotImplementedError
def __contains__(self, cpv):
return self.has_key(cpv)
def get_matches(self, match_dict):
"""generic function for walking the entire cache db, matching restrictions to
filter what cpv's are returned. Derived classes should override this if they
can implement a faster method then pulling each cpv:values, and checking it.
For example, RDBMS derived classes should push the matching logic down to the
actual RDBM."""
import re
restricts = {}
for key,match in match_dict.iteritems():
# XXX this sucks.
try:
if isinstance(match, str):
restricts[key] = re.compile(match).match
else:
restricts[key] = re.compile(match[0],match[1]).match
except re.error, e:
raise InvalidRestriction(key, match, e)
if key not in self.__known_keys:
raise InvalidRestriction(key, match, "Key isn't valid")
for cpv in self.keys():
cont = True
vals = self[cpv]
for key, match in restricts.iteritems():
if not match(vals[key]):
cont = False
break
if cont:
yield cpv
def serialize_eclasses(eclass_dict):
"""takes a dict, returns a string representing said dict"""
return "\t".join(["%s\t%s\t%s" % (k, v[0], str(v[1])) for k,v in eclass_dict.items()])
def reconstruct_eclasses(cpv, eclass_string):
"""returns a dict when handed a string generated by serialize_eclasses"""
eclasses = eclass_string.rstrip().lstrip().split("\t")
if eclasses == [""]:
# occasionally this occurs in the fs backends. they suck.
return {}
if len(eclasses) % 3 != 0:
raise cache_errors.CacheCorruption(cpv, "_eclasses_ was of invalid len %i" % len(eclasses))
d={}
for x in range(0, len(eclasses), 3):
d[eclasses[x]] = (eclasses[x + 1], long(eclasses[x + 2]))
del eclasses
return d