Mercurial > prosody-hg
comparison plugins/muc/mod_muc.lua @ 7370:0ebc7ff1fff5
MUC: Switch to util.cache for storing rooms, store rooms to disk on eviction
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Mon, 18 Apr 2016 19:18:37 +0200 |
| parents | 2aef5e8b69e9 |
| children | d5ba0dec0c95 |
comparison
equal
deleted
inserted
replaced
| 7369:c5cae59831d7 | 7370:0ebc7ff1fff5 |
|---|---|
| 59 local history = module:require "muc/history"; | 59 local history = module:require "muc/history"; |
| 60 room_mt.send_history = history.send; | 60 room_mt.send_history = history.send; |
| 61 room_mt.get_historylength = history.get_length; | 61 room_mt.get_historylength = history.get_length; |
| 62 room_mt.set_historylength = history.set_length; | 62 room_mt.set_historylength = history.set_length; |
| 63 | 63 |
| 64 local iterators = require "util.iterators"; | |
| 65 local jid_split = require "util.jid".split; | 64 local jid_split = require "util.jid".split; |
| 66 local jid_bare = require "util.jid".bare; | 65 local jid_bare = require "util.jid".bare; |
| 67 local st = require "util.stanza"; | 66 local st = require "util.stanza"; |
| 67 local cache = require "util.cache"; | |
| 68 local um_is_admin = require "core.usermanager".is_admin; | 68 local um_is_admin = require "core.usermanager".is_admin; |
| 69 | |
| 70 local rooms = module:shared "rooms"; | |
| 71 | 69 |
| 72 module:depends("disco"); | 70 module:depends("disco"); |
| 73 module:add_identity("conference", "text", module:get_option_string("name", "Prosody Chatrooms")); | 71 module:add_identity("conference", "text", module:get_option_string("name", "Prosody Chatrooms")); |
| 74 module:add_feature("http://jabber.org/protocol/muc"); | 72 module:add_feature("http://jabber.org/protocol/muc"); |
| 75 module:depends "muc_unique" | 73 module:depends "muc_unique" |
| 98 local room_configs = module:open_store("config"); | 96 local room_configs = module:open_store("config"); |
| 99 | 97 |
| 100 local function room_save(room, forced) | 98 local function room_save(room, forced) |
| 101 local node = jid_split(room.jid); | 99 local node = jid_split(room.jid); |
| 102 local is_persistent = persistent.get(room); | 100 local is_persistent = persistent.get(room); |
| 103 persistent_rooms:set(nil, room.jid, is_persistent); | 101 if is_persistent or forced then |
| 104 if is_persistent then | 102 persistent_rooms:set(nil, room.jid, true); |
| 105 local data = room:freeze(); | 103 local data = room:freeze(forced); |
| 106 room_configs:set(node, data); | 104 return room_configs:set(node, data); |
| 107 elseif forced then | 105 else |
| 108 room_configs:set(node, nil); | 106 persistent_rooms:set(nil, room.jid, nil); |
| 109 if not next(room._occupants) then -- Room empty | 107 return room_configs:set(node, nil); |
| 110 rooms[room.jid] = nil; | 108 end |
| 111 end | 109 end |
| 112 end | 110 |
| 113 end | 111 local rooms = cache.new(module:get_option_number("muc_room_cache_size", 100), function (_, room) |
| 112 module:log("debug", "%s evicted", room); | |
| 113 room_save(room, true); -- Force to disk | |
| 114 end); | |
| 114 | 115 |
| 115 -- Automatically destroy empty non-persistent rooms | 116 -- Automatically destroy empty non-persistent rooms |
| 116 module:hook("muc-occupant-left",function(event) | 117 module:hook("muc-occupant-left",function(event) |
| 117 local room = event.room | 118 local room = event.room |
| 118 if not room:has_occupant() and not persistent.get(room) then -- empty, non-persistent room | 119 if not room:has_occupant() and not persistent.get(room) then -- empty, non-persistent room |
| 119 module:fire_event("muc-room-destroyed", { room = room }); | 120 module:fire_event("muc-room-destroyed", { room = room }); |
| 120 end | 121 end |
| 121 end); | 122 end); |
| 122 | 123 |
| 123 function track_room(room) | 124 function track_room(room) |
| 124 rooms[room.jid] = room; | 125 rooms:set(room.jid, room); |
| 125 -- When room is created, over-ride 'save' method | 126 -- When room is created, over-ride 'save' method |
| 126 room.save = room_save; | 127 room.save = room_save; |
| 127 end | 128 end |
| 128 | 129 |
| 129 local function restore_room(jid) | 130 local function restore_room(jid) |
| 135 return room; | 136 return room; |
| 136 end | 137 end |
| 137 end | 138 end |
| 138 | 139 |
| 139 function forget_room(room) | 140 function forget_room(room) |
| 140 local room_jid = room.jid; | 141 module:log("debug", "Forgetting %s", room); |
| 141 local node = jid_split(room.jid); | 142 rooms.save = nil; |
| 142 rooms[room_jid] = nil; | 143 rooms:set(room.jid, nil); |
| 143 room_configs:set(node, nil); | 144 end |
| 144 if persistent.get(room) then | 145 |
| 145 persistent_rooms:set(nil, room_jid, nil); | 146 function delete_room(room) |
| 147 module:log("debug", "Deleting %s", room); | |
| 148 room_configs:set(jid_split(room.jid), nil); | |
| 149 persistent_rooms:set(nil, room.jid, nil); | |
| 150 end | |
| 151 | |
| 152 function module.unload() | |
| 153 for room in rooms:values() do | |
| 154 room:save(true); | |
| 155 forget_room(room); | |
| 146 end | 156 end |
| 147 end | 157 end |
| 148 | 158 |
| 149 function get_room_from_jid(room_jid) | 159 function get_room_from_jid(room_jid) |
| 150 local room = rooms[room_jid]; | 160 local room = rooms:get(room_jid); |
| 151 if room == nil then | 161 if room then |
| 152 -- Check if in persistent storage | 162 rooms:set(room_jid, room); -- bump to top; |
| 153 if persistent_rooms:get(nil, room_jid) then | 163 return room; |
| 154 room = restore_room(room_jid); | 164 end |
| 155 if room == nil then | 165 return restore_room(room_jid); |
| 156 module:log("error", "Missing data for room '%s', removing from persistent room list", room_jid); | |
| 157 persistent_rooms:set(nil, room_jid, nil); | |
| 158 end | |
| 159 end | |
| 160 end | |
| 161 return room | |
| 162 end | 166 end |
| 163 | 167 |
| 164 function each_room(local_only) | 168 function each_room(local_only) |
| 165 if not local_only then | 169 if local_only then |
| 170 return rooms:values(); | |
| 171 end | |
| 172 return coroutine.wrap(function () | |
| 173 local seen = {}; -- Don't iterate over persistent rooms twice | |
| 174 for room in rooms:values() do | |
| 175 coroutine.yield(room); | |
| 176 seen[room.jid] = true; | |
| 177 end | |
| 166 for room_jid in pairs(persistent_rooms_storage:get(nil) or {}) do | 178 for room_jid in pairs(persistent_rooms_storage:get(nil) or {}) do |
| 167 if rooms[room_jid] == nil then -- Don't restore rooms that already exist | 179 if seen[room_jid] then |
| 168 local room = restore_room(room_jid); | 180 local room = restore_room(room_jid); |
| 169 if room == nil then | 181 if room == nil then |
| 170 module:log("error", "Missing data for room '%s', omitting from iteration", room_jid); | 182 module:log("error", "Missing data for room '%s', omitting from iteration", room_jid); |
| 183 else | |
| 184 coroutine.yield(room); | |
| 171 end | 185 end |
| 172 end | 186 end |
| 173 end | 187 end |
| 174 end | 188 end); |
| 175 return iterators.values(rooms); | |
| 176 end | 189 end |
| 177 | 190 |
| 178 module:hook("host-disco-items", function(event) | 191 module:hook("host-disco-items", function(event) |
| 179 local reply = event.reply; | 192 local reply = event.reply; |
| 180 module:log("debug", "host-disco-items called"); | 193 module:log("debug", "host-disco-items called"); |
| 188 module:hook("muc-room-pre-create", function(event) | 201 module:hook("muc-room-pre-create", function(event) |
| 189 track_room(event.room); | 202 track_room(event.room); |
| 190 end, -1000); | 203 end, -1000); |
| 191 | 204 |
| 192 module:hook("muc-room-destroyed",function(event) | 205 module:hook("muc-room-destroyed",function(event) |
| 193 return forget_room(event.room); | 206 local room = event.room; |
| 194 end) | 207 forget_room(room); |
| 208 delete_room(room); | |
| 209 end); | |
| 195 | 210 |
| 196 do | 211 do |
| 197 local restrict_room_creation = module:get_option("restrict_room_creation"); | 212 local restrict_room_creation = module:get_option("restrict_room_creation"); |
| 198 if restrict_room_creation == true then | 213 if restrict_room_creation == true then |
| 199 restrict_room_creation = "admin"; | 214 restrict_room_creation = "admin"; |
