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