X-Git-Url: http://dolda2000.com/gitweb/?p=didex.git;a=blobdiff_plain;f=didex%2Fstore.py;fp=didex%2Fstore.py;h=15d2eca11beab793506299b83fbe93eabff9adc9;hp=0000000000000000000000000000000000000000;hb=b080a59cbbe6b293d754bfa97c386eeede6b51ee;hpb=da5de0141d1328b254425b6a70d7a2c1f3c41c2b diff --git a/didex/store.py b/didex/store.py new file mode 100644 index 0000000..15d2eca --- /dev/null +++ b/didex/store.py @@ -0,0 +1,90 @@ +import threading, pickle +from . import db, index, cache +from .db import txnfun + +class environment(object): + def __init__(self, path): + self.path = path + self.lk = threading.Lock() + self.bk = None + + def __call__(self): + with self.lk: + if self.bk is None: + self.bk = db.environment(self.path) + return self.bk + + def close(self): + with self.lk: + if self.bk is not None: + self.bk.close() + self.bk = None + +class storedesc(object): + pass + +def storedescs(obj): + t = type(obj) + ret = getattr(t, "__didex_attr", None) + if ret is None: + ret = [] + for nm, val in t.__dict__.items(): + if isinstance(val, storedesc): + ret.append((nm, val)) + t.__didex_attr = ret + return ret + +class store(object): + def __init__(self, name, *, env=None, path=".", ncache=None): + self.name = name + self.lk = threading.Lock() + if env: + self.env = env + else: + self.env = environment(path) + self._db = None + if ncache is None: + ncache = cache.cache() + self.cache = ncache + self.cache.load = self._load + + def db(self): + with self.lk: + if self._db is None: + self._db = self.env().db(self.name) + return self._db + + def _load(self, id): + try: + return pickle.loads(self.db().get(id)) + except: + raise KeyError(id, "could not unpickle data") + + def _encode(self, obj): + return pickle.dumps(obj) + + def get(self, id, *, load=True): + return self.cache.get(id, load=load) + + @txnfun(lambda self: self.db().env.env) + def register(self, obj, *, tx): + id = self.db().add(self._encode(obj), tx=tx) + for nm, attr in storedescs(obj): + attr.register(id, obj, tx) + self.cache.put(id, obj) + return id + + @txnfun(lambda self: self.db().env.env) + def unregister(self, id, *, tx): + obj = self.get(id) + for nm, attr in storedescs(obj): + attr.unregister(id, obj, tx) + self.db().remove(id, tx=tx) + self.cache.remove(id) + + @txnfun(lambda self: self.db().env.env) + def update(self, id, *, tx): + obj = self.get(id, load=False) + for nm, attr, in storedescs(obj): + attr.update(id, obj, tx) + self.db().replace(id, self._encode(obj), tx=tx)