Commit | Line | Data |
---|---|---|
b080a59c FT |
1 | import threading |
2 | from . import store, lib | |
3 | from .store import storedesc | |
4 | ||
5 | class 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 | ||
23 | class 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 | ||
54 | class 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 | ||
76 | class 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)) |