Software / code / prosody
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 |