xmppcomponent_listener: Switch to util.xmppstream from xmlhandlers
[prosody.git] / core / storagemanager.lua
1
2 local error, type = error, type;
3 local setmetatable = setmetatable;
4
5 local config = require "core.configmanager";
6 local datamanager = require "util.datamanager";
7 local modulemanager = require "core.modulemanager";
8 local multitable = require "util.multitable";
9 local hosts = hosts;
10 local log = require "util.logger".init("storagemanager");
11
12 local olddm = {}; -- maintain old datamanager, for backwards compatibility
13 for k,v in pairs(datamanager) do olddm[k] = v; end
14
15 module("storagemanager")
16
17 local default_driver_mt = { name = "internal" };
18 default_driver_mt.__index = default_driver_mt;
19 function default_driver_mt:open(store)
20         return setmetatable({ host = self.host, store = store }, default_driver_mt);
21 end
22 function default_driver_mt:get(user) return olddm.load(user, self.host, self.store); end
23 function default_driver_mt:set(user, data) return olddm.store(user, self.host, self.store, data); end
24
25 local stores_available = multitable.new();
26
27 function initialize_host(host)
28         host_session.events.add_handler("item-added/data-driver", function (event)
29                 local item = event.item;
30                 stores_available:set(host, item.name, item);
31         end);
32         
33         host_session.events.add_handler("item-removed/data-driver", function (event)
34                 local item = event.item;
35                 stores_available:set(host, item.name, nil);
36         end);
37 end
38
39 local function load_driver(host, driver_name)
40         if not driver_name then
41                 return;
42         end
43         local driver = stores_available:get(host, driver_name);
44         if not driver then
45                 if driver_name ~= "internal" then
46                         modulemanager.load(host, "storage_"..driver_name);
47                         return stores_available:get(host, driver_name);
48                 else
49                         return setmetatable({host = host}, default_driver_mt);
50                 end
51         end
52 end
53
54 function open(host, store, typ)
55         local storage = config.get(host, "core", "storage");
56         local driver_name;
57         local option_type = type(storage);
58         if option_type == "string" then
59                 driver_name = storage;
60         elseif option_type == "table" then
61                 driver_name = storage[store];
62         end
63         
64         local driver = load_driver(host, driver_name);
65         if not driver then
66                 driver_name = config.get(host, "core", "default_storage");
67                 driver = load_driver(host, driver_name);
68                 if not driver then
69                         if storage or driver_name then
70                                 log("warn", "Falling back to default driver for %s storage on %s", store, host);
71                         end
72                         driver_name = "internal";
73                         driver = load_driver(host, driver_name);
74                 end
75         end
76         
77         local ret, err = driver:open(store, typ);
78         if not ret then
79                 if err == "unsupported-store" then
80                         log("debug", "Storage driver %s does not support store %s (%s), falling back to internal driver",
81                                 driver_name, store, typ);
82                         ret = setmetatable({ host = host, store = store }, default_driver_mt); -- default to default driver
83                         err = nil;
84                 end
85         end
86         return ret, err;
87 end
88
89 function datamanager.load(username, host, datastore)
90         return open(host, datastore):get(username);
91 end
92 function datamanager.store(username, host, datastore, data)
93         return open(host, datastore):set(username, data);
94 end
95
96 return _M;