--- /dev/null
+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)