# HG changeset patch # User Kim Alvefur # Date 1453222067 -3600 # Node ID 98b4794b72e4ca96f132062afa146d8da36d9026 # Parent 77b9c7e5fd635786c6277305d435b372d6e44043 mod_mam: Include an in-memory fallback driver diff -r 77b9c7e5fd63 -r 98b4794b72e4 mod_mam/README.markdown --- a/mod_mam/README.markdown Tue Jan 19 17:47:05 2016 +0100 +++ b/mod_mam/README.markdown Tue Jan 19 17:47:47 2016 +0100 @@ -58,6 +58,9 @@ } ``` +If no archive-capable storage backend can be opened then an in-memory +one will be used as fallback. + Query size limits ----------------- @@ -116,12 +119,10 @@ ------- --------------- trunk Works - 0.10 Works [^2] - 0.9 Unsupported + 0.10 Works + 0.9 Works 0.8 Does not work ------- --------------- [^1]: Might be changed to "mam" at some point -[^2]: requires a storage driver with archive support, eg - mod\_storage\_sql in 0.10 diff -r 77b9c7e5fd63 -r 98b4794b72e4 mod_mam/fallback_archive.lib.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_mam/fallback_archive.lib.lua Tue Jan 19 17:47:47 2016 +0100 @@ -0,0 +1,84 @@ +-- luacheck: ignore 212/self + +local uuid = require "util.uuid".generate; +local store = module:shared("archive"); +local archive_store = { _provided_by = "mam"; name = "fallback"; }; + +function archive_store:append(username, key, value, when, with) + local archive = store[username]; + if not archive then + archive = { [0] = 0 }; + store[username] = archive; + end + local index = (archive[0] or #archive)+1; + local item = { key = key, when = when, with = with, value = value }; + if not key or archive[key] then + key = uuid(); + item.key = key; + end + archive[index] = item; + archive[key] = index; + archive[0] = index; + return key; +end + +function archive_store:find(username, query) + local archive = store[username] or {}; + local start, stop, step = 1, archive[0] or #archive, 1; + local qstart, qend, qwith = -math.huge, math.huge; + local limit; + + if query then + if query.reverse then + start, stop, step = stop, start, -1; + if query.before and archive[query.before] then + start = archive[query.before] - 1; + end + elseif query.after and archive[query.after] then + start = archive[query.after] + 1; + end + qwith = query.with; + limit = query.limit; + qstart = query.start or qstart; + qend = query["end"] or qend; + end + + return function () + if limit and limit <= 0 then return end + for i = start, stop, step do + local item = archive[i]; + if (not qwith or qwith == item.with) and item.when >= qstart and item.when <= qend then + if limit then limit = limit - 1; end + start = i + step; -- Start on next item + return item.key, item.value, item.when, item.with; + end + end + end +end + +function archive_store:delete(username, query) + if not query or next(query) == nil then + -- no specifics, delete everything + store[username] = nil; + return true; + end + local archive = store[username]; + if not archive then return true; end -- no messages, nothing to delete + + local start, stop, step = 1, archive[0] or #archive, 1; + local qstart = query.start or -math.huge; + local qend = query["end"] or math.huge; + local qwith = query.with; + store[username] = nil; + for i = 1, #archive do + local item = archive[i]; + local when, with = item.when, item.when; + -- Add things that don't match the query + if not ((not qwith or qwith == item.with) and item.when >= qstart and item.when <= qend) then + self:append(username, item.key, item.value, when, with); + end + end + return true; +end + +return archive_store; diff -r 77b9c7e5fd63 -r 98b4794b72e4 mod_mam/mod_mam.lua --- a/mod_mam/mod_mam.lua Tue Jan 19 17:47:05 2016 +0100 +++ b/mod_mam/mod_mam.lua Tue Jan 19 17:47:47 2016 +0100 @@ -39,10 +39,8 @@ local archive = assert(module:open_store(archive_store, "archive")); if archive.name == "null" then - module:log("debug", "Attempt to open archive storage returned null driver"); - module:log("error", "Unable to open archive storage, no archive capable storage driver enabled?"); - module:log("info", "See https://prosody.im/doc/storage and https://prosody.im/doc/archiving for more information"); - return; + module:log("info", "Using in-memory fallback archive driver"); + archive = module:require "fallback_archive"; elseif not archive.find then module:log("debug", "Attempt to open archive storage returned a valid driver but it does not seem to implement the storage API"); module:log("error", "mod_%s does not support archiving", archive._provided_by or archive.name and "storage_"..archive.name.."(?)" or "");