Software /
code /
prosody
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 |
parent | 7367:2aef5e8b69e9 |
child | 7371: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"; |