Added live-object store and simple indexing.
[didex.git] / didex / values.py
CommitLineData
b080a59c
FT
1import threading
2from . import store, lib
3from .store import storedesc
4
5class cursor(lib.closable):
6 def __init__(self, bk, st):
7 self.bk = bk
8 self.st = st
9
10 def close(self):
11 self.bk.close()
12
13 def __iter__(self):
14 return self
15
16 def __next__(self):
17 k, id = next(self.bk)
18 return k, self.st.get(id)
19
20 def skip(self, n=1):
21 self.bk.skip(n)
22
23class base(storedesc):
24 def __init__(self, store, indextype, name, datatype, default):
25 self.store = store
26 self.indextype = indextype
27 self.name = name
28 self.typ = datatype
29 self.default = default
30 self.idx = None
31 self.lk = threading.Lock()
32 self.mattr = "__idx_%s_new" % name
33 self.iattr = "__idx_%s_cur" % name
34
35 def index(self):
36 with self.lk:
37 if self.idx is None:
38 self.idx = self.indextype(self.store.db(), self.name, self.typ)
39 return self.idx
40
41 def __get__(self, obj, cls):
42 if obj is None: return self
43 return getattr(obj, self.mattr, self.default)
44
45 def __set__(self, obj, val):
46 setattr(obj, self.mattr, val)
47
48 def __delete__(self, obj):
49 delattr(obj, self.mattr)
50
51 def get(self, **kwargs):
52 return cursor(self.index().get(**kwargs), self.store)
53
54class simple(base):
55 def __init__(self, store, indextype, name, datatype, default=None):
56 super().__init__(store, indextype, name, datatype, default)
57
58 def register(self, id, obj, tx):
59 val = self.__get__(obj, None)
60 self.index().put(val, id, tx=tx)
61 tx.postcommit(lambda: setattr(obj, self.iattr, val))
62
63 def unregister(self, id, obj, tx):
64 self.index().remove(getattr(obj, self.iattr), id, tx=tx)
65 tx.postcommit(lambda: delattr(obj, self.iattr))
66
67 def update(self, id, obj, tx):
68 val = self.__get__(obj, None)
69 ival = getattr(obj, self.iattr)
70 if val != ival:
71 idx = self.index()
72 idx.remove(ival, id, tx=tx)
73 idx.put(val, id, tx=tx)
74 tx.postcommit(lambda: setattr(obj, self.iattr, val))
75
76class multi(base):
77 def __init__(self, store, indextype, name, datatype):
78 super().__init__(store, indextype, name, datatype, ())
79
80 def register(self, id, obj, tx):
81 vals = frozenset(self.__get__(obj, None))
82 idx = self.index()
83 for val in vals:
84 idx.put(val, id, tx=tx)
85 tx.postcommit(lambda: setattr(obj, self.iattr, vals))
86
87 def unregister(self, id, obj, tx):
88 idx = self.index()
89 for val in getattr(obj, self.iattr):
90 idx.remove(val, id, tx=tx)
91 tx.postcommit(lambda: delattr(obj, self.iattr))
92
93 def update(self, id, obj, tx):
94 vals = frozenset(self.__get__(obj, None))
95 ivals = getattr(obj, self.iattr)
96 if vals != ivals:
97 idx = self.index()
98 for val in ivals - vals:
99 idx.remove(val, id, tx=tx)
100 for val in vals - ivals:
101 idx.put(val, id, tx=tx)
102 tx.postcommit(lambda: setattr(obj, self.iattr, vals))