Commit 0dfb2b24 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gaston

Persistent rooms will always remain in memory. RoomSurrogates are no longer necessary.


git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@459 b35dd754-fafc-0310-a699-88a17e54d16e
parent 4b45689b
...@@ -493,6 +493,17 @@ public class IQOwnerHandler { ...@@ -493,6 +493,17 @@ public class IQOwnerHandler {
presences.addAll(room.addMember(jid, null, senderRole)); presences.addAll(room.addMember(jid, null, senderRole));
} }
// Destroy the room if the room is no longer persistent and there are no occupants in
// the room
if (!room.isPersistent() && room.getOccupantsCount() == 0) {
try {
room.destroyRoom(null, null);
}
catch (UnauthorizedException e) {
// Do nothing.
}
}
} }
finally { finally {
room.lock.writeLock().unlock(); room.lock.writeLock().unlock();
......
...@@ -172,8 +172,8 @@ public class MUCRoomImpl implements MUCRoom { ...@@ -172,8 +172,8 @@ public class MUCRoomImpl implements MUCRoom {
private boolean publicRoom = true; private boolean publicRoom = true;
/** /**
* Persistent rooms are saved to the database so that when the last occupant leaves the room, * Persistent rooms are saved to the database to make sure that rooms configurations can be
* the room is removed from memory but it's configuration is saved in the database. * restored in case the server goes down.
*/ */
private boolean persistent = false; private boolean persistent = false;
...@@ -279,17 +279,6 @@ public class MUCRoomImpl implements MUCRoom { ...@@ -279,17 +279,6 @@ public class MUCRoomImpl implements MUCRoom {
rolesToBroadcastPresence.add("moderator"); rolesToBroadcastPresence.add("moderator");
rolesToBroadcastPresence.add("participant"); rolesToBroadcastPresence.add("participant");
rolesToBroadcastPresence.add("visitor"); rolesToBroadcastPresence.add("visitor");
// If the room is persistent load the configuration values from the DB
try {
MUCPersistenceManager.loadFromDB(this);
if (this.isPersistent()) {
this.savedToDB = true;
this.roomLocked = false;
}
}
catch (IllegalArgumentException e) {
// Do nothing. The room does not exist.
}
} }
public String getName() { public String getName() {
...@@ -578,7 +567,9 @@ public class MUCRoomImpl implements MUCRoom { ...@@ -578,7 +567,9 @@ public class MUCRoomImpl implements MUCRoom {
// "unavailable" from the room to the owner including a <destroy/> element and reason // "unavailable" from the room to the owner including a <destroy/> element and reason
// (if provided) as defined under the "Destroying a Room" use case. // (if provided) as defined under the "Destroying a Room" use case.
if (occupants.isEmpty()) { // Remove the room from the server only if there are no more occupants and the room is
// not persistent
if (occupants.isEmpty() && !isPersistent()) {
endTime = System.currentTimeMillis(); endTime = System.currentTimeMillis();
server.removeChatRoom(name); server.removeChatRoom(name);
...@@ -1631,6 +1622,11 @@ public class MUCRoomImpl implements MUCRoom { ...@@ -1631,6 +1622,11 @@ public class MUCRoomImpl implements MUCRoom {
public void setSavedToDB(boolean saved) { public void setSavedToDB(boolean saved) {
this.savedToDB = saved; this.savedToDB = saved;
if (saved) {
// Unlock the room now. This is necessary only when a persistent room has been
// retrieved from the database.
this.roomLocked = false;
}
} }
public void setPersistent(boolean persistent) { public void setPersistent(boolean persistent) {
......
...@@ -91,13 +91,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -91,13 +91,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
*/ */
private Map<String,MUCRoom> rooms = new ConcurrentHashMap<String,MUCRoom>(); private Map<String,MUCRoom> rooms = new ConcurrentHashMap<String,MUCRoom>();
/**
* Cache for the persistent room surrogates. There will be a persistent room surrogate for each
* persistent room that has not been loaded into memory. Whenever a persistent room is loaded or
* unloaded from memory the cache is updated.
*/
private Cache persistentRoomSurrogateCache;
/** /**
* chat users managed by this manager, table: key user jid (XMPPAddress); value ChatUser * chat users managed by this manager, table: key user jid (XMPPAddress); value ChatUser
*/ */
...@@ -164,13 +157,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -164,13 +157,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
historyStrategy = new HistoryStrategy(null); historyStrategy = new HistoryStrategy(null);
} }
private void initializeCaches() {
// create cache - no size limit and expires after one hour of being idle
persistentRoomSurrogateCache = new Cache("Room Surrogates", -1, JiveConstants.HOUR);
// warm-up cache now to avoid a delay responding the first disco request
populateRoomSurrogateCache();
}
/** /**
* Probes the presence of any user who's last packet was sent more than 5 minute ago. * Probes the presence of any user who's last packet was sent more than 5 minute ago.
*/ */
...@@ -269,8 +255,14 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -269,8 +255,14 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
room = rooms.get(roomName.toLowerCase()); room = rooms.get(roomName.toLowerCase());
if (room == null) { if (room == null) {
room = new MUCRoomImpl(this, roomName, router); room = new MUCRoomImpl(this, roomName, router);
// Check whether the room was just created or loaded from the database // If the room is persistent load the configuration values from the DB
if (!room.isPersistent()) { try {
// Try to load the room's configuration from the database (if the room is
// persistent but was added to the DB after the server was started up)
MUCPersistenceManager.loadFromDB(room);
}
catch (IllegalArgumentException e) {
// The room does not exist so check for creation permissions
// Room creation is always allowed for sysadmin // Room creation is always allowed for sysadmin
if (isRoomCreationRestricted() && if (isRoomCreationRestricted() &&
!sysadmins.contains(userjid.toBareStringPrep())) { !sysadmins.contains(userjid.toBareStringPrep())) {
...@@ -283,13 +275,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -283,13 +275,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
} }
room.addFirstOwner(userjid.toBareStringPrep()); room.addFirstOwner(userjid.toBareStringPrep());
} }
else {
// The room was loaded from the database and is now available in memory.
// Update in the database that the room is now available in memory
MUCPersistenceManager.updateRoomInMemory(room, true);
// Remove the surrogate of the room (if any) from the surrogates cache
persistentRoomSurrogateCache.remove(room.getName());
}
rooms.put(roomName.toLowerCase(), room); rooms.put(roomName.toLowerCase(), room);
} }
} }
...@@ -297,39 +282,11 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -297,39 +282,11 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
} }
public MUCRoom getChatRoom(String roomName) { public MUCRoom getChatRoom(String roomName) {
MUCRoom answer = rooms.get(roomName.toLowerCase()); return rooms.get(roomName.toLowerCase());
// If the room is not in memory check if there exists a surrogate of the room. There
// will be a surrogate if and only if exists an room in the database for the requested
// room name
if (answer == null) {
synchronized (persistentRoomSurrogateCache) {
if (persistentRoomSurrogateCache.size() == 0) {
populateRoomSurrogateCache();
}
}
answer = (MUCRoom) persistentRoomSurrogateCache.get(roomName);
}
return answer;
} }
public List<MUCRoom> getChatRooms() { public List<MUCRoom> getChatRooms() {
List<MUCRoom> answer = new ArrayList<MUCRoom>(rooms.size() * 2); return new ArrayList<MUCRoom>(rooms.values());
synchronized (rooms) {
answer.addAll(rooms.values());
synchronized (persistentRoomSurrogateCache) {
if (persistentRoomSurrogateCache.size() == 0) {
populateRoomSurrogateCache();
}
}
answer.addAll(persistentRoomSurrogateCache.values());
}
return answer;
}
private void populateRoomSurrogateCache() {
for (MUCRoom room : MUCPersistenceManager.getRoomSurrogates(this, router)) {
persistentRoomSurrogateCache.put(room.getName(), room);
}
} }
public boolean hasChatRoom(String roomName) { public boolean hasChatRoom(String roomName) {
...@@ -341,18 +298,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -341,18 +298,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
if (room != null) { if (room != null) {
final long chatLength = room.getChatLength(); final long chatLength = room.getChatLength();
totalChatTime += chatLength; totalChatTime += chatLength;
// Update the database to indicate that the room is no longer in memory (only if the
// room is persistent
MUCPersistenceManager.updateRoomInMemory(room, false);
// Clear the surrogates cache if the room thas is being removed from memory is
// persistent
if (room.isPersistent()) {
persistentRoomSurrogateCache.clear();
}
else {
// Just force to expire old entries since the cache doesn't have a clean-up thread
persistentRoomSurrogateCache.size();
}
} }
} }
...@@ -577,10 +522,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -577,10 +522,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
// Log the room conversations every 5 minutes after a 5 minutes server startup delay // Log the room conversations every 5 minutes after a 5 minutes server startup delay
// (default values) // (default values)
timer.schedule(new LogConversationTask(), LOG_TIMEOUT, LOG_TIMEOUT); timer.schedule(new LogConversationTask(), LOG_TIMEOUT, LOG_TIMEOUT);
// Update the DB to indicate that no room is in-memory. This may be necessary when the
// server went down unexpectedly
MUCPersistenceManager.resetRoomInMemory();
initializeCaches();
} }
public void start() { public void start() {
...@@ -591,6 +532,10 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -591,6 +532,10 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
params.clear(); params.clear();
params.add(chatServiceName); params.add(chatServiceName);
Log.info(LocaleUtils.getLocalizedString("startup.starting.muc", params)); Log.info(LocaleUtils.getLocalizedString("startup.starting.muc", params));
// Load all the persistent rooms to memory
for (MUCRoom room : MUCPersistenceManager.loadRoomsFromDB(this, router)) {
rooms.put(room.getName().toLowerCase(), room);
}
} }
public void stop() { public void stop() {
...@@ -823,24 +768,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha ...@@ -823,24 +768,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
answer.add(item); answer.add(item);
} }
} }
// Load the room surrogates for persistent rooms that aren't in memory (if the cache
// is still empty)
synchronized(persistentRoomSurrogateCache) {
if (persistentRoomSurrogateCache.size() == 0) {
populateRoomSurrogateCache();
}
}
// Add items for each room surrogate (persistent room that is not in memory at
// the moment)
MUCRoom room;
for (Iterator it=persistentRoomSurrogateCache.values().iterator(); it.hasNext();) {
room = (MUCRoom)it.next();
item = DocumentHelper.createElement("item");
item.addAttribute("jid", room.getRole().getRoleAddress().toStringPrep());
item.addAttribute("name", room.getNaturalLanguageName());
answer.add(item);
}
} }
else if (name != null && node == null) { else if (name != null && node == null) {
// Answer the room occupants as items if that info is publicly available // Answer the room occupants as items if that info is publicly available
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment