Commit 5a2e745b authored by Matt Tucker's avatar Matt Tucker Committed by matt

Work on offline presence optimization.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@6355 b35dd754-fafc-0310-a699-88a17e54d16e
parent c7d972d6
-- $Revision: $
-- $Date: $
CREATE TABLE jivePresence (
username VARCHAR(64) NOT NULL,
offlinePresence VARCHAR(2000),
offlineDate CHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
UPDATE jiveVersion set version=11 where name = 'wildfire';
\ No newline at end of file
CREATE TABLE jivePresence (
username VARCHAR(64) NOT NULL,
offlinePresence LONGVARCHAR,
offlineDate VARCHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
UPDATE jiveVersion set version=11 where name = 'wildfire';
\ No newline at end of file
# $Revision: $
# $Date: $
CREATE TABLE jivePresence (
username VARCHAR(64) NOT NULL,
offlinePresence TEXT,
offlineDate CHAR(15) NOT NULL,
PRIMARY KEY (username)
);
UPDATE jiveVersion set version=11 where name = 'wildfire';
\ No newline at end of file
-- $Revision: $
-- $Date: $
CREATE TABLE jivePresence (
username VARCHAR2(64) NOT NULL,
offlinePresence LONG,
offlineDate CHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
UPDATE jiveVersion set version=11 where name = 'wildfire';
-- $Revision: $
-- $Date: $
CREATE TABLE jivePresence (
username VARCHAR(64) NOT NULL,
offlinePresence TEXT,
offlineDate VARCHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
UPDATE jiveVersion set version=11 where name = 'wildfire';
/* $Revision: $ */
/* $Date: $ */
CREATE TABLE jivePresence (
username NVARCHAR(64) NOT NULL,
offlinePresence NTEXT,
offlineDate CHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
UPDATE jiveVersion set version=11 where name = 'wildfire';
/* $Revision: $ */
/* $Date: $ */
CREATE TABLE jivePresence (
username NVARCHAR(64) NOT NULL,
offlinePresence TEXT,
offlineDate CHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
UPDATE jiveVersion set version=11 where name = 'wildfire';
...@@ -40,6 +40,12 @@ CREATE TABLE jiveOffline ( ...@@ -40,6 +40,12 @@ CREATE TABLE jiveOffline (
CONSTRAINT jiveOffline_pk PRIMARY KEY (username, messageID) CONSTRAINT jiveOffline_pk PRIMARY KEY (username, messageID)
); );
CREATE TABLE jivePresence (
username VARCHAR(64) NOT NULL,
offlinePresence VARCHAR(2000),
offlineDate CHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
CREATE TABLE jiveRoster ( CREATE TABLE jiveRoster (
rosterID INTEGER NOT NULL, rosterID INTEGER NOT NULL,
...@@ -336,7 +342,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1); ...@@ -336,7 +342,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 10); INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 11;
-- Entry for admin user -- Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate) INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
...@@ -43,7 +43,7 @@ CREATE TABLE jiveOffline ( ...@@ -43,7 +43,7 @@ CREATE TABLE jiveOffline (
CREATE TABLE jivePresence ( CREATE TABLE jivePresence (
username VARCHAR(64) NOT NULL, username VARCHAR(64) NOT NULL,
offlinePresence LONGVARCHAR, offlinePresence LONGVARCHAR,
lastActivity VARCHAR(15), offlineDate VARCHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username) CONSTRAINT jivePresence_pk PRIMARY KEY (username)
); );
...@@ -329,7 +329,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1); ...@@ -329,7 +329,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 10); INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 11);
// Entry for admin user // Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate) INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
...@@ -57,6 +57,13 @@ CREATE TABLE jiveOffline ( ...@@ -57,6 +57,13 @@ CREATE TABLE jiveOffline (
PRIMARY KEY (username, messageID) PRIMARY KEY (username, messageID)
); );
CREATE TABLE jivePresence (
username VARCHAR(64) NOT NULL,
offlinePresence TEXT,
offlineDate CHAR(15) NOT NULL,
PRIMARY KEY (username)
);
CREATE TABLE jiveRoster ( CREATE TABLE jiveRoster (
rosterID BIGINT NOT NULL, rosterID BIGINT NOT NULL,
username VARCHAR(64) NOT NULL, username VARCHAR(64) NOT NULL,
...@@ -311,7 +318,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1); ...@@ -311,7 +318,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 10); INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 11);
# Entry for admin user # Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate) INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
...@@ -41,6 +41,14 @@ CREATE TABLE jiveOffline ( ...@@ -41,6 +41,14 @@ CREATE TABLE jiveOffline (
); );
CREATE TABLE jivePresence (
username VARCHAR2(64) NOT NULL,
offlinePresence LONG,
offlineDate CHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
CREATE TABLE jiveRoster ( CREATE TABLE jiveRoster (
rosterID INTEGER NOT NULL, rosterID INTEGER NOT NULL,
username VARCHAR2(64) NOT NULL, username VARCHAR2(64) NOT NULL,
...@@ -317,7 +325,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1); ...@@ -317,7 +325,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 10); INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 11);
-- Entry for admin user -- Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate) INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
...@@ -43,6 +43,14 @@ CREATE TABLE jiveOffline ( ...@@ -43,6 +43,14 @@ CREATE TABLE jiveOffline (
); );
CREATE TABLE jivePresence (
username VARCHAR(64) NOT NULL,
offlinePresence TEXT,
offlineDate VARCHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
CREATE TABLE jiveRoster ( CREATE TABLE jiveRoster (
rosterID INTEGER NOT NULL, rosterID INTEGER NOT NULL,
username VARCHAR(64) NOT NULL, username VARCHAR(64) NOT NULL,
...@@ -326,7 +334,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1); ...@@ -326,7 +334,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 10); INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 11);
-- Entry for admin user -- Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate) INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
...@@ -41,6 +41,14 @@ CREATE TABLE jiveOffline ( ...@@ -41,6 +41,14 @@ CREATE TABLE jiveOffline (
); );
CREATE TABLE jivePresence (
username NVARCHAR(64) NOT NULL,
offlinePresence NTEXT,
offlineDate CHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
CREATE TABLE jiveRoster ( CREATE TABLE jiveRoster (
rosterID INTEGER NOT NULL, rosterID INTEGER NOT NULL,
username NVARCHAR(64) NOT NULL, username NVARCHAR(64) NOT NULL,
...@@ -324,7 +332,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1); ...@@ -324,7 +332,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 10); INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 11);
/* Entry for admin user */ /* Entry for admin user */
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate) INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
...@@ -41,6 +41,14 @@ CREATE TABLE jiveOffline ( ...@@ -41,6 +41,14 @@ CREATE TABLE jiveOffline (
); );
CREATE TABLE jivePresence (
username NVARCHAR(64) NOT NULL,
offlinePresence TEXT,
offlineDate CHAR(15) NOT NULL,
CONSTRAINT jivePresence_pk PRIMARY KEY (username)
);
CREATE TABLE jiveRoster ( CREATE TABLE jiveRoster (
rosterID INTEGER NOT NULL, rosterID INTEGER NOT NULL,
username NVARCHAR(64) NOT NULL, username NVARCHAR(64) NOT NULL,
...@@ -324,7 +332,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1); ...@@ -324,7 +332,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1); INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1); INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 10); INSERT INTO jiveVersion (name, version) VALUES ('wildfire', 11);
/* Entry for admin user */ /* Entry for admin user */
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate) INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
...@@ -44,7 +44,7 @@ public class SchemaManager { ...@@ -44,7 +44,7 @@ public class SchemaManager {
/** /**
* Current Wildfire database schema version. * Current Wildfire database schema version.
*/ */
private static final int DATABASE_VERSION = 10; private static final int DATABASE_VERSION = 11;
/** /**
* Creates a new Schema manager. * Creates a new Schema manager.
......
...@@ -682,8 +682,8 @@ public class ClientSession extends Session { ...@@ -682,8 +682,8 @@ public class ClientSession extends Session {
wasAvailable = true; wasAvailable = true;
// Notify listeners that the session is now available // Notify listeners that the session is now available
PresenceEventDispatcher.availableSession(this, presence); PresenceEventDispatcher.availableSession(this, presence);
} else }
if (this.presence.isAvailable() && oldPresence.getPriority() != this.presence.getPriority()) else if (this.presence.isAvailable() && oldPresence.getPriority() != this.presence.getPriority())
{ {
// The client has changed the priority of his presence // The client has changed the priority of his presence
sessionManager.changePriority(getAddress(), this.presence.getPriority()); sessionManager.changePriority(getAddress(), this.presence.getPriority());
......
...@@ -1269,6 +1269,27 @@ public class SessionManager extends BasicModule { ...@@ -1269,6 +1269,27 @@ public class SessionManager extends BasicModule {
return anonymousSessions.size(); return anonymousSessions.size();
} }
/**
* Returns the number of sessions for a user that are available. For the count
* of all sessions for the user, including sessions that are just starting
* or closed, see {@see #getSessionCount(String)}.
*
* @param username the user.
* @return number of available sessions for a user.
*/
public int getActiveSessionCount(String username) {
if (username == null || !userManager.isRegisteredUser(username)) {
return 0;
}
int sessionCount = 0;
for (Session session: sessions.get(username).getSessions()) {
if (session.getStatus() != Session.STATUS_CLOSED) {
sessionCount++;
}
}
return sessionCount;
}
public int getSessionCount(String username) { public int getSessionCount(String username) {
if (username == null || !userManager.isRegisteredUser(username)) { if (username == null || !userManager.isRegisteredUser(username)) {
return 0; return 0;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* $Revision: 3128 $ * $Revision: 3128 $
* $Date: 2005-11-30 15:31:54 -0300 (Wed, 30 Nov 2005) $ * $Date: 2005-11-30 15:31:54 -0300 (Wed, 30 Nov 2005) $
* *
* Copyright (C) 2004 Jive Software. All rights reserved. * Copyright (C) 2004-2006 Jive Software. All rights reserved.
* *
* This software is published under the terms of the GNU Public License (GPL), * This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution. * a copy of which is included in this distribution.
...@@ -14,10 +14,7 @@ package org.jivesoftware.wildfire.spi; ...@@ -14,10 +14,7 @@ package org.jivesoftware.wildfire.spi;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.DocumentException; import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper; import org.dom4j.DocumentHelper;
import org.jivesoftware.util.LocaleUtils; import org.jivesoftware.util.*;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.Cache;
import org.jivesoftware.util.CacheManager;
import org.jivesoftware.wildfire.*; import org.jivesoftware.wildfire.*;
import org.jivesoftware.wildfire.auth.UnauthorizedException; import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.component.InternalComponentManager; import org.jivesoftware.wildfire.component.InternalComponentManager;
...@@ -31,6 +28,7 @@ import org.jivesoftware.wildfire.roster.RosterManager; ...@@ -31,6 +28,7 @@ import org.jivesoftware.wildfire.roster.RosterManager;
import org.jivesoftware.wildfire.user.User; import org.jivesoftware.wildfire.user.User;
import org.jivesoftware.wildfire.user.UserManager; import org.jivesoftware.wildfire.user.UserManager;
import org.jivesoftware.wildfire.user.UserNotFoundException; import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.database.DbConnectionManager;
import org.xmpp.component.Component; import org.xmpp.component.Component;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError; import org.xmpp.packet.PacketError;
...@@ -40,6 +38,8 @@ import java.util.ArrayList; ...@@ -40,6 +38,8 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.sql.*;
import java.sql.Connection;
/** /**
* Simple in memory implementation of the PresenceManager interface. * Simple in memory implementation of the PresenceManager interface.
...@@ -48,8 +48,15 @@ import java.util.List; ...@@ -48,8 +48,15 @@ import java.util.List;
*/ */
public class PresenceManagerImpl extends BasicModule implements PresenceManager { public class PresenceManagerImpl extends BasicModule implements PresenceManager {
private static final String LAST_PRESENCE_PROP = "lastUnavailablePresence"; private static final String LOAD_OFFLINE_PRESENCE =
private static final String LAST_ACTIVITY_PROP = "lastActivity"; "SELECT offlinePresence, offlineDate FROM jivePresence WHERE username=?";
private static final String INSERT_OFFLINE_PRESENCE =
"INSERT INTO jivePresence(username, offlinePresence, offlineDate) VALUES(?,?,?)";
private static final String DELETE_OFFLINE_PRESENCE =
"DELETE FROM jivePresence WHERE username=?";
private static final String NULL_STRING = "NULL";
private static final long NULL_LONG = -1L;
private SessionManager sessionManager; private SessionManager sessionManager;
private UserManager userManager; private UserManager userManager;
...@@ -60,8 +67,8 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -60,8 +67,8 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
private InternalComponentManager componentManager; private InternalComponentManager componentManager;
private Cache lastActivityCache; private Cache<String, Long> lastActivityCache;
private Cache offlinePresenceCache; private Cache<String, String> offlinePresenceCache;
public PresenceManagerImpl() { public PresenceManagerImpl() {
super("Presence manager"); super("Presence manager");
...@@ -71,7 +78,7 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -71,7 +78,7 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
} }
public boolean isAvailable(User user) { public boolean isAvailable(User user) {
return sessionManager.getSessionCount(user.getUsername()) > 0; return sessionManager.getActiveSessionCount(user.getUsername()) > 0;
} }
public Presence getPresence(User user) { public Presence getPresence(User user) {
...@@ -112,33 +119,54 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -112,33 +119,54 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
} }
public String getLastPresenceStatus(User user) { public String getLastPresenceStatus(User user) {
String answer = null; String username = user.getUsername();
String presenceXML = user.getProperties().get(LAST_PRESENCE_PROP); String presenceStatus = null;
String presenceXML = offlinePresenceCache.get(username);
if (presenceXML == null) {
loadOfflinePresence(username);
}
presenceXML = offlinePresenceCache.get(username);
if (presenceXML != null) { if (presenceXML != null) {
// If the cached answer is no data, return null.
if (presenceXML.equals(NULL_STRING)) {
return null;
}
// Otherwise, parse out the status from the XML.
try { try {
// Parse the element // Parse the element
Document element = DocumentHelper.parseText(presenceXML); Document element = DocumentHelper.parseText(presenceXML);
answer = element.getRootElement().elementTextTrim("status"); presenceStatus = element.getRootElement().elementTextTrim("status");
} }
catch (DocumentException e) { catch (DocumentException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e); Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} }
} }
return answer; return presenceStatus;
} }
public long getLastActivity(User user) { public long getLastActivity(User user) {
long answer = -1; String username = user.getUsername();
String offline = user.getProperties().get(LAST_ACTIVITY_PROP); long lastActivity = NULL_LONG;
if (offline != null) { Long offlineDate = lastActivityCache.get(username);
if (offlineDate == null) {
loadOfflinePresence(username);
}
offlineDate = lastActivityCache.get(username);
if (offlineDate != null) {
// If the cached answer is no data, return -1.
if (offlineDate == NULL_LONG) {
return NULL_LONG;
}
else {
try { try {
answer = (System.currentTimeMillis() - Long.parseLong(offline)); lastActivity = (System.currentTimeMillis() - offlineDate);
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e); Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} }
} }
return answer; }
return lastActivity;
} }
public void userAvailable(Presence presence) { public void userAvailable(Presence presence) {
...@@ -151,16 +179,33 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -151,16 +179,33 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
// Ignore anonymous users // Ignore anonymous users
return; return;
} }
// Optimization: only delete the unavailable presence information if this
// is the first session created on the server.
if (sessionManager.getSessionCount(username) > 1) {
return;
}
Connection con = null;
PreparedStatement pstmt = null;
try { try {
User probeeUser = userManager.getUser(username); con = DbConnectionManager.getConnection();
probeeUser.getProperties().remove(LAST_PRESENCE_PROP); pstmt = con.prepareStatement(DELETE_OFFLINE_PRESENCE);
pstmt.setString(1, username);
pstmt.execute();
} }
catch (UserNotFoundException e) { catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
} }
} }
} }
public void userUnavailable(Presence presence) { public void userUnavailable(Presence presence) {
// TODO: test to see if presence data preserved when system is shut down.
// Only save the last presence status and keep track of the time when the user went // Only save the last presence status and keep track of the time when the user went
// offline if this is an unavailable presence sent to THE SERVER and the presence belongs // offline if this is an unavailable presence sent to THE SERVER and the presence belongs
// to a local user. // to a local user.
...@@ -170,18 +215,43 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -170,18 +215,43 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
// Ignore anonymous users // Ignore anonymous users
return; return;
} }
try {
User probeeUser = userManager.getUser(username); // TODO: this check won't current work: getActiveSessionCount returns 1 when it shouldn't.
if (!presence.getElement().elements().isEmpty()) { // If the user has any remaining sessions, don't record the offline info.
// if (sessionManager.getActiveSessionCount(username) > 0) {
// return;
// }
String offlinePresence = null;
// Save the last unavailable presence of this user if the presence contains any // Save the last unavailable presence of this user if the presence contains any
// child element such as <status> // child element such as <status>.
probeeUser.getProperties().put(LAST_PRESENCE_PROP, presence.toXML()); if (!presence.getElement().elements().isEmpty()) {
offlinePresence = presence.toXML();
} }
// Keep track of the time when the user went offline // Keep track of the time when the user went offline
probeeUser.getProperties().put(LAST_ACTIVITY_PROP, java.util.Date offlinePresenceDate = new java.util.Date();
String.valueOf(System.currentTimeMillis()));
// Insert data into the database.
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_OFFLINE_PRESENCE);
pstmt.setString(1, username);
if (offlinePresence != null) {
DbConnectionManager.setLargeTextField(pstmt, 2, offlinePresence);
} }
catch (UserNotFoundException e) { else {
pstmt.setNull(2, Types.VARCHAR);
}
pstmt.setString(3, StringUtils.dateToMillis(offlinePresenceDate));
pstmt.execute();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
} }
} }
} }
...@@ -221,11 +291,8 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -221,11 +291,8 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
public boolean canProbePresence(JID prober, String probee) throws UserNotFoundException { public boolean canProbePresence(JID prober, String probee) throws UserNotFoundException {
RosterItem item = rosterManager.getRoster(probee).getRosterItem(prober); RosterItem item = rosterManager.getRoster(probee).getRosterItem(prober);
if (item.getSubStatus() == RosterItem.SUB_FROM return item.getSubStatus() == RosterItem.SUB_FROM
|| item.getSubStatus() == RosterItem.SUB_BOTH) { || item.getSubStatus() == RosterItem.SUB_BOTH;
return true;
}
return false;
} }
public void probePresence(JID prober, JID probee) { public void probePresence(JID prober, JID probee) {
...@@ -248,8 +315,11 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -248,8 +315,11 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
// If the probee is not online then try to retrieve his last unavailable // If the probee is not online then try to retrieve his last unavailable
// presence which may contain particular information and send it to the // presence which may contain particular information and send it to the
// prober // prober
String presenceXML = String presenceXML = offlinePresenceCache.get(probee.getNode());
userManager.getUserProperty(probee.getNode(), LAST_PRESENCE_PROP); if (presenceXML == null) {
loadOfflinePresence(probee.getNode());
}
presenceXML = offlinePresenceCache.get(probee.getNode());
if (presenceXML != null) { if (presenceXML != null) {
try { try {
// Parse the element // Parse the element
...@@ -408,4 +478,40 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -408,4 +478,40 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
} }
return null; return null;
} }
/**
* Loads offline presence data for the user into cache.
*
* @param username the username.
*/
private void loadOfflinePresence(String username) {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_OFFLINE_PRESENCE);
pstmt.setString(1, username);
rs = pstmt.executeQuery();
if (rs.next()) {
String offlinePresence = DbConnectionManager.getLargeTextField(rs, 1);
if (rs.wasNull()) {
offlinePresence = NULL_STRING;
}
long offlineDate = Long.parseLong(rs.getString(2).trim());
offlinePresenceCache.put(username, offlinePresence);
lastActivityCache.put(username, offlineDate);
}
else {
offlinePresenceCache.put(username, NULL_STRING);
lastActivityCache.put(username, NULL_LONG);
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
}
} }
\ No newline at end of file
...@@ -273,28 +273,6 @@ public class UserManager implements IQResultListener { ...@@ -273,28 +273,6 @@ public class UserManager implements IQResultListener {
return provider.findUsers(fields, query); return provider.findUsers(fields, query);
} }
/**
* Returns the value of the specified property for the given username. If the user
* has been loaded into memory then the ask the user to return the value of the
* property. However, if the user is not present in memory then try to get the property
* value directly from the database as a way to optimize the performance.
*
* @param username the username of the user to get a specific property value.
* @param propertyName the name of the property to return its value.
* @return the value of the specified property for the given username.
*/
public String getUserProperty(String username, String propertyName) {
username = username.trim().toLowerCase();
User user = userCache.get(username);
if (user == null) {
return User.getPropertyValue(username, propertyName);
}
else {
// User is in memory so ask the user for the specified property value
return user.getProperties().get(propertyName);
}
}
/** /**
* Returns true if the specified local username belongs to a registered local user. * Returns true if the specified local username belongs to a registered local user.
* *
......
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