X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=core%2Fstoragemanager.lua;h=43409960347fe2baef73023092208de416052724;hb=0b0a013d85bf1a2d4b5a6a339b8cf946ba77aa5d;hp=94cea3b3742a023f66ef7a6818376c5fbebf59b3;hpb=b0630afdef99ee2dd1dcb2398b14c5777514c6d7;p=prosody.git diff --git a/core/storagemanager.lua b/core/storagemanager.lua index 94cea3b3..43409960 100644 --- a/core/storagemanager.lua +++ b/core/storagemanager.lua @@ -1,23 +1,21 @@ -local error = error; +local error, type = error, type; local setmetatable = setmetatable; local config = require "core.configmanager"; local datamanager = require "util.datamanager"; -local multitable = require "util.multitable"; local modulemanager = require "core.modulemanager"; +local multitable = require "util.multitable"; local hosts = hosts; local log = require "util.logger".init("storagemanager"); local olddm = {}; -- maintain old datamanager, for backwards compatibility for k,v in pairs(datamanager) do olddm[k] = v; end - -local driver_cache = multitable.new(); -local store_cache = multitable.new(); +local prosody = prosody; module("storagemanager") -local default_driver_mt = {}; +local default_driver_mt = { name = "internal" }; default_driver_mt.__index = default_driver_mt; function default_driver_mt:open(store) return setmetatable({ host = self.host, store = store }, default_driver_mt); @@ -25,37 +23,73 @@ end function default_driver_mt:get(user) return olddm.load(user, self.host, self.store); end function default_driver_mt:set(user, data) return olddm.store(user, self.host, self.store, data); end -local function load_driver_for_host(host) - if driver_cache:get(host) then return driver_cache:get(host); end - +local stores_available = multitable.new(); + +function initialize_host(host) local host_session = hosts[host]; - if not host_session then error("No such host"); end - - local driver_plugin = config.get(host, "core", "datastore"); - if not driver_plugin then return setmetatable({ host = host }, default_driver_mt); end + host_session.events.add_handler("item-added/data-driver", function (event) + local item = event.item; + stores_available:set(host, item.name, item); + end); - local provider; - local function handler(event) provider = event.item; end - host_session.events.add_handler("item-added/data-driver", handler); - local success, err = modulemanager.load(host, driver_plugin); - host_session.events.remove_handler("item-added/data-driver", handler); - if not success then error(err); end - if not provider then error("Module didn't add a provider"); end - - driver_cache:set(host, provider); - log("debug", "Data driver '%s' loaded for host '%s'", driver_plugin, host); - return provider; + host_session.events.add_handler("item-removed/data-driver", function (event) + local item = event.item; + stores_available:set(host, item.name, nil); + end); +end +prosody.events.add_handler("host-activated", initialize_host, 101); + +local function load_driver(host, driver_name) + if not driver_name then + return; + end + local driver = stores_available:get(host, driver_name); + if driver then return driver; end + if driver_name ~= "internal" then + local ok, err = modulemanager.load(host, "storage_"..driver_name); + if not ok then + log("error", "Failed to load storage driver plugin %s: %s", driver_name, err); + end + return stores_available:get(host, driver_name); + else + return setmetatable({host = host}, default_driver_mt); + end end function open(host, store, typ) - local ret = store_cache:get(host, store); + local storage = config.get(host, "core", "storage"); + local driver_name; + local option_type = type(storage); + if option_type == "string" then + driver_name = storage; + elseif option_type == "table" then + driver_name = storage[store]; + end + + local driver = load_driver(host, driver_name); + if not driver then + driver_name = config.get(host, "core", "default_storage"); + driver = load_driver(host, driver_name); + if not driver then + if driver_name or (type(storage) == "string" + or type(storage) == "table" and storage[store]) then + log("warn", "Falling back to default driver for %s storage on %s", store, host); + end + driver_name = "internal"; + driver = load_driver(host, driver_name); + end + end + + local ret, err = driver:open(store, typ); if not ret then - local driver = load_driver_for_host(host); - ret = driver:open(store, typ); - if not ret then ret = setmetatable({ host = host, store = store }, default_driver_mt); end -- default to default driver - store_cache:set(host, store, ret); + if err == "unsupported-store" then + log("debug", "Storage driver %s does not support store %s (%s), falling back to internal driver", + driver_name, store, typ); + ret = setmetatable({ host = host, store = store }, default_driver_mt); -- default to default driver + err = nil; + end end - return ret; + return ret, err; end function datamanager.load(username, host, datastore)