1local datamanager = require "core.storagemanager".olddm; 2local array = require "util.array"; 3local datetime = require "util.datetime"; 4local st = require "util.stanza"; 5local now = require "util.time".now; 6local id = require "util.id".medium; 7 8local host = module.host; 9 10local driver = {}; 11 12function driver:open(store, typ) 13 local mt = self[typ or "keyval"] 14 if not mt then 15 return nil, "unsupported-store"; 16 end 17 return setmetatable({ store = store, type = typ }, mt); 18end 19 20function driver:stores(username) -- luacheck: ignore 212/self 21 return datamanager.stores(username, host); 22end 23 24function driver:purge(user) -- luacheck: ignore 212/self 25 return datamanager.purge(user, host); 26end 27 28local keyval = { }; 29driver.keyval = { __index = keyval }; 30 31function keyval:get(user) 32 return datamanager.load(user, host, self.store); 33end 34 35function keyval:set(user, data) 36 return datamanager.store(user, host, self.store, data); 37end 38 39function keyval:users() 40 return datamanager.users(host, self.store, self.type); 41end 42 43local archive = {}; 44driver.archive = { __index = archive }; 45 46function archive:append(username, key, value, when, with) 47 when = when or now(); 48 if not st.is_stanza(value) then 49 return nil, "unsupported-datatype"; 50 end 51 value = st.preserialize(st.clone(value)); 52 value.when = when; 53 value.with = with; 54 value.attr.stamp = datetime.datetime(when); 55 value.attr.stamp_legacy = datetime.legacy(when); 56 57 if key then 58 local items, err = datamanager.list_load(username, host, self.store); 59 if not items and err then return items, err; end 60 if items then 61 items = array(items); 62 items:filter(function (item) 63 return item.key ~= key; 64 end); 65 value.key = key; 66 items:push(value); 67 local ok, err = datamanager.list_store(username, host, self.store, items); 68 if not ok then return ok, err; end 69 return key; 70 end 71 else 72 key = id(); 73 end 74 75 value.key = key; 76 77 local ok, err = datamanager.list_append(username, host, self.store, value); 78 if not ok then return ok, err; end 79 return key; 80end 81 82function archive:find(username, query) 83 local items, err = datamanager.list_load(username, host, self.store); 84 if not items then 85 if err then 86 return items, err; 87 else 88 return function () end, 0; 89 end 90 end 91 local count = #items; 92 local i = 0; 93 if query then 94 items = array(items); 95 if query.key then 96 items:filter(function (item) 97 return item.key == query.key; 98 end); 99 end 100 if query.with then 101 items:filter(function (item) 102 return item.with == query.with; 103 end); 104 end 105 if query.start then 106 items:filter(function (item) 107 local when = item.when or datetime.parse(item.attr.stamp); 108 return when >= query.start; 109 end); 110 end 111 if query["end"] then 112 items:filter(function (item) 113 local when = item.when or datetime.parse(item.attr.stamp); 114 return when <= query["end"]; 115 end); 116 end 117 count = #items; 118 if query.reverse then 119 items:reverse(); 120 if query.before then 121 for j = 1, count do 122 if (items[j].key or tostring(j)) == query.before then 123 i = j; 124 break; 125 end 126 end 127 end 128 elseif query.after then 129 for j = 1, count do 130 if (items[j].key or tostring(j)) == query.after then 131 i = j; 132 break; 133 end 134 end 135 end 136 if query.limit and #items - i > query.limit then 137 items[i+query.limit+1] = nil; 138 end 139 end 140 return function () 141 i = i + 1; 142 local item = items[i]; 143 if not item then return; end 144 local key = item.key or tostring(i); 145 local when = item.when or datetime.parse(item.attr.stamp); 146 local with = item.with; 147 item.key, item.when, item.with = nil, nil, nil; 148 item.attr.stamp = nil; 149 item.attr.stamp_legacy = nil; 150 item = st.deserialize(item); 151 return key, item, when, with; 152 end, count; 153end 154 155function archive:dates(username) 156 local items, err = datamanager.list_load(username, host, self.store); 157 if not items then return items, err; end 158 return array(items):pluck("when"):map(datetime.date):unique(); 159end 160 161function archive:delete(username, query) 162 if not query or next(query) == nil then 163 return datamanager.list_store(username, host, self.store, nil); 164 end 165 local items, err = datamanager.list_load(username, host, self.store); 166 if not items then 167 if err then 168 return items, err; 169 end 170 -- Store is empty 171 return 0; 172 end 173 items = array(items); 174 local count_before = #items; 175 if query then 176 if query.key then 177 items:filter(function (item) 178 return item.key ~= query.key; 179 end); 180 end 181 if query.with then 182 items:filter(function (item) 183 return item.with ~= query.with; 184 end); 185 end 186 if query.start then 187 items:filter(function (item) 188 return item.when < query.start; 189 end); 190 end 191 if query["end"] then 192 items:filter(function (item) 193 return item.when > query["end"]; 194 end); 195 end 196 if query.truncate and #items > query.truncate then 197 if query.reverse then 198 -- Before: { 1, 2, 3, 4, 5, } 199 -- After: { 1, 2, 3 } 200 for i = #items, query.truncate + 1, -1 do 201 items[i] = nil; 202 end 203 else 204 -- Before: { 1, 2, 3, 4, 5, } 205 -- After: { 3, 4, 5 } 206 local offset = #items - query.truncate; 207 for i = 1, #items do 208 items[i] = items[i+offset]; 209 end 210 end 211 end 212 end 213 local count = count_before - #items; 214 if count == 0 then 215 return 0; -- No changes, skip write 216 end 217 local ok, err = datamanager.list_store(username, host, self.store, items); 218 if not ok then return ok, err; end 219 return count; 220end 221 222module:provides("storage", driver); 223