Comparison

plugins/mod_storage_memory.lua @ 11200:bf8f2da84007

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Thu, 05 Nov 2020 22:31:25 +0100
parent 10926:c55bd98a54f8
child 11274:ecbfde402364
comparison
equal deleted inserted replaced
11199:6c7c50a4de32 11200:bf8f2da84007
6 local new_id = require "util.id".medium; 6 local new_id = require "util.id".medium;
7 7
8 local auto_purge_enabled = module:get_option_boolean("storage_memory_temporary", false); 8 local auto_purge_enabled = module:get_option_boolean("storage_memory_temporary", false);
9 local auto_purge_stores = module:get_option_set("storage_memory_temporary_stores", {}); 9 local auto_purge_stores = module:get_option_set("storage_memory_temporary_stores", {});
10 10
11 local archive_item_limit = module:get_option_number("storage_archive_item_limit", 1000);
12
11 local memory = setmetatable({}, { 13 local memory = setmetatable({}, {
12 __index = function(t, k) 14 __index = function(t, k)
13 local store = module:shared(k) 15 local store = module:shared(k)
14 t[k] = store; 16 t[k] = store;
15 return store; 17 return store;
48 50
49 local archive_store = {}; 51 local archive_store = {};
50 archive_store.__index = archive_store; 52 archive_store.__index = archive_store;
51 53
52 archive_store.users = _users; 54 archive_store.users = _users;
55
56 archive_store.caps = {
57 total = true;
58 quota = archive_item_limit;
59 truncate = true;
60 };
53 61
54 function archive_store:append(username, key, value, when, with) 62 function archive_store:append(username, key, value, when, with)
55 if is_stanza(value) then 63 if is_stanza(value) then
56 value = st.preserialize(value); 64 value = st.preserialize(value);
57 value = envload("return xml"..serialize(value), "=(stanza)", { xml = st.deserialize }) 65 value = envload("return xml"..serialize(value), "=(stanza)", { xml = st.deserialize })
68 key = new_id(); 76 key = new_id();
69 v.key = key; 77 v.key = key;
70 end 78 end
71 if a[key] then 79 if a[key] then
72 table.remove(a, a[key]); 80 table.remove(a, a[key]);
81 elseif #a >= archive_item_limit then
82 return nil, "quota-limit";
73 end 83 end
74 local i = #a+1; 84 local i = #a+1;
75 a[i] = v; 85 a[i] = v;
76 a[key] = i; 86 a[key] = i;
77 return key; 87 return key;
78 end 88 end
79 89
80 function archive_store:find(username, query) 90 function archive_store:find(username, query)
81 local items = self.store[username or NULL]; 91 local items = self.store[username or NULL];
82 if not items then 92 if not items then
83 return function () end, 0; 93 if query then
84 end 94 if query.before or query.after then
85 local count = #items; 95 return nil, "item-not-found";
86 local i = 0; 96 end
97 if query.total then
98 return function () end, 0;
99 end
100 end
101 return function () end;
102 end
103 local count = nil;
104 local i, last_key = 0;
87 if query then 105 if query then
88 items = array():append(items); 106 items = array():append(items);
89 if query.key then 107 if query.key then
90 items:filter(function (item) 108 items:filter(function (item)
91 return item.key == query.key; 109 return item.key == query.key;
104 if query["end"] then 122 if query["end"] then
105 items:filter(function (item) 123 items:filter(function (item)
106 return item.when <= query["end"]; 124 return item.when <= query["end"];
107 end); 125 end);
108 end 126 end
109 count = #items; 127 if query.total then
128 count = #items;
129 end
110 if query.reverse then 130 if query.reverse then
111 items:reverse(); 131 items:reverse();
112 if query.before then 132 if query.before then
113 for j = 1, count do 133 local found = false;
134 for j = 1, #items do
114 if (items[j].key or tostring(j)) == query.before then 135 if (items[j].key or tostring(j)) == query.before then
136 found = true;
115 i = j; 137 i = j;
116 break; 138 break;
117 end 139 end
118 end 140 end
119 end 141 if not found then
142 return nil, "item-not-found";
143 end
144 end
145 elseif query.before then
146 last_key = query.before;
120 elseif query.after then 147 elseif query.after then
121 for j = 1, count do 148 local found = false;
149 for j = 1, #items do
122 if (items[j].key or tostring(j)) == query.after then 150 if (items[j].key or tostring(j)) == query.after then
151 found = true;
123 i = j; 152 i = j;
124 break; 153 break;
125 end 154 end
155 end
156 if not found then
157 return nil, "item-not-found";
126 end 158 end
127 end 159 end
128 if query.limit and #items - i > query.limit then 160 if query.limit and #items - i > query.limit then
129 items[i+query.limit+1] = nil; 161 items[i+query.limit+1] = nil;
130 end 162 end
131 end 163 end
132 return function () 164 return function ()
133 i = i + 1; 165 i = i + 1;
134 local item = items[i]; 166 local item = items[i];
135 if not item then return; end 167 if not item or (last_key and item.key == last_key) then return; end
136 return item.key, item.value(), item.when, item.with; 168 return item.key, item.value(), item.when, item.with;
137 end, count; 169 end, count;
170 end
171
172 function archive_store:get(username, wanted_key)
173 local items = self.store[username or NULL];
174 if not items then return nil, "item-not-found"; end
175 local i = items[wanted_key];
176 if not i then return nil, "item-not-found"; end
177 local item = items[i];
178 return item.value(), item.when, item.with;
179 end
180
181 function archive_store:set(username, wanted_key, new_value, new_when, new_with)
182 local items = self.store[username or NULL];
183 if not items then return nil, "item-not-found"; end
184 local i = items[wanted_key];
185 if not i then return nil, "item-not-found"; end
186 local item = items[i];
187
188 if is_stanza(new_value) then
189 new_value = st.preserialize(new_value);
190 item.value = envload("return xml"..serialize(new_value), "=(stanza)", { xml = st.deserialize })
191 else
192 item.value = envload("return "..serialize(new_value), "=(data)", {});
193 end
194 if new_when then
195 item.when = new_when;
196 end
197 if new_with then
198 item.with = new_when;
199 end
200 return true;
201 end
202
203 function archive_store:summary(username, query)
204 local iter, err = self:find(username, query)
205 if not iter then return iter, err; end
206 local counts = {};
207 local earliest = {};
208 local latest = {};
209 for _, _, when, with in iter do
210 counts[with] = (counts[with] or 0) + 1;
211 if earliest[with] == nil then
212 earliest[with] = when;
213 end
214 latest[with] = when;
215 end
216 return {
217 counts = counts;
218 earliest = earliest;
219 latest = latest;
220 };
138 end 221 end
139 222
140 223
141 function archive_store:delete(username, query) 224 function archive_store:delete(username, query)
142 if not query or next(query) == nil then 225 if not query or next(query) == nil then