Fixed cache bug.
[didex.git] / didex / store.py
CommitLineData
b080a59c
FT
1import threading, pickle
2from . import db, index, cache
3from .db import txnfun
4
5class environment(object):
6 def __init__(self, path):
7 self.path = path
8 self.lk = threading.Lock()
9 self.bk = None
10
11 def __call__(self):
12 with self.lk:
13 if self.bk is None:
14 self.bk = db.environment(self.path)
15 return self.bk
16
17 def close(self):
18 with self.lk:
19 if self.bk is not None:
20 self.bk.close()
21 self.bk = None
22
23class storedesc(object):
24 pass
25
26def storedescs(obj):
27 t = type(obj)
28 ret = getattr(t, "__didex_attr", None)
29 if ret is None:
30 ret = []
31 for nm, val in t.__dict__.items():
32 if isinstance(val, storedesc):
33 ret.append((nm, val))
34 t.__didex_attr = ret
35 return ret
36
37class store(object):
38 def __init__(self, name, *, env=None, path=".", ncache=None):
39 self.name = name
40 self.lk = threading.Lock()
41 if env:
42 self.env = env
43 else:
44 self.env = environment(path)
45 self._db = None
46 if ncache is None:
47 ncache = cache.cache()
48 self.cache = ncache
49 self.cache.load = self._load
50
51 def db(self):
52 with self.lk:
53 if self._db is None:
54 self._db = self.env().db(self.name)
55 return self._db
56
57 def _load(self, id):
58 try:
59 return pickle.loads(self.db().get(id))
60 except:
61 raise KeyError(id, "could not unpickle data")
62
63 def _encode(self, obj):
64 return pickle.dumps(obj)
65
66 def get(self, id, *, load=True):
67 return self.cache.get(id, load=load)
68
69 @txnfun(lambda self: self.db().env.env)
70 def register(self, obj, *, tx):
71 id = self.db().add(self._encode(obj), tx=tx)
72 for nm, attr in storedescs(obj):
73 attr.register(id, obj, tx)
74 self.cache.put(id, obj)
75 return id
76
77 @txnfun(lambda self: self.db().env.env)
78 def unregister(self, id, *, tx):
79 obj = self.get(id)
80 for nm, attr in storedescs(obj):
81 attr.unregister(id, obj, tx)
82 self.db().remove(id, tx=tx)
83 self.cache.remove(id)
84
85 @txnfun(lambda self: self.db().env.env)
86 def update(self, id, *, tx):
87 obj = self.get(id, load=False)
88 for nm, attr, in storedescs(obj):
89 attr.update(id, obj, tx)
90 self.db().replace(id, self._encode(obj), tx=tx)