Commit a9ec7c81 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Optimization work (avoid loading a user when possible). JM-599

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3579 b35dd754-fafc-0310-a699-88a17e54d16e
parent 3076f778
...@@ -7,6 +7,7 @@ import org.jivesoftware.wildfire.XMPPServer; ...@@ -7,6 +7,7 @@ import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.auth.UnauthorizedException; import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.disco.ServerFeaturesProvider; import org.jivesoftware.wildfire.disco.ServerFeaturesProvider;
import org.jivesoftware.wildfire.roster.RosterItem; import org.jivesoftware.wildfire.roster.RosterItem;
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;
...@@ -28,6 +29,7 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr ...@@ -28,6 +29,7 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr
private IQHandlerInfo info; private IQHandlerInfo info;
private PresenceManager presenceManager; private PresenceManager presenceManager;
private RosterManager rosterManager;
public IQLastActivityHandler() { public IQLastActivityHandler() {
super("XMPP Last Activity Handler"); super("XMPP Last Activity Handler");
...@@ -47,12 +49,12 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr ...@@ -47,12 +49,12 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr
} }
try { try {
User user = UserManager.getInstance().getUser(username); RosterItem item = rosterManager.getRoster(username).getRosterItem(packet.getFrom());
RosterItem item = user.getRoster().getRosterItem(packet.getFrom());
// Check that the user requesting this information is subscribed to the user's presence // Check that the user requesting this information is subscribed to the user's presence
if (item.getSubStatus() == RosterItem.SUB_FROM || if (item.getSubStatus() == RosterItem.SUB_FROM ||
item.getSubStatus() == RosterItem.SUB_BOTH) { item.getSubStatus() == RosterItem.SUB_BOTH) {
if (sessionManager.getSessions(username).isEmpty()) { if (sessionManager.getSessions(username).isEmpty()) {
User user = UserManager.getInstance().getUser(username);
// The user is offline so answer the user's "last available time and the // The user is offline so answer the user's "last available time and the
// status message of the last unavailable presence received from the user" // status message of the last unavailable presence received from the user"
long lastActivityTime = presenceManager.getLastActivity(user); long lastActivityTime = presenceManager.getLastActivity(user);
...@@ -81,8 +83,8 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr ...@@ -81,8 +83,8 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr
return info; return info;
} }
public Iterator getFeatures() { public Iterator<String> getFeatures() {
ArrayList features = new ArrayList(); ArrayList<String> features = new ArrayList<String>();
features.add("jabber:iq:last"); features.add("jabber:iq:last");
return features.iterator(); return features.iterator();
} }
...@@ -90,5 +92,6 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr ...@@ -90,5 +92,6 @@ public class IQLastActivityHandler extends IQHandler implements ServerFeaturesPr
public void initialize(XMPPServer server) { public void initialize(XMPPServer server) {
super.initialize(server); super.initialize(server);
presenceManager = server.getPresenceManager(); presenceManager = server.getPresenceManager();
rosterManager = server.getRosterManager();
} }
} }
\ No newline at end of file
...@@ -11,9 +11,7 @@ ...@@ -11,9 +11,7 @@
package org.jivesoftware.wildfire.handler; package org.jivesoftware.wildfire.handler;
import org.dom4j.DocumentHelper;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.IQHandlerInfo; import org.jivesoftware.wildfire.IQHandlerInfo;
import org.jivesoftware.wildfire.PacketException; import org.jivesoftware.wildfire.PacketException;
...@@ -62,6 +60,7 @@ import org.xmpp.packet.PacketError; ...@@ -62,6 +60,7 @@ import org.xmpp.packet.PacketError;
public class IQvCardHandler extends IQHandler { public class IQvCardHandler extends IQHandler {
private IQHandlerInfo info; private IQHandlerInfo info;
private XMPPServer server;
private UserManager userManager; private UserManager userManager;
public IQvCardHandler() { public IQvCardHandler() {
...@@ -70,61 +69,60 @@ public class IQvCardHandler extends IQHandler { ...@@ -70,61 +69,60 @@ public class IQvCardHandler extends IQHandler {
} }
public IQ handleIQ(IQ packet) throws UnauthorizedException, PacketException { public IQ handleIQ(IQ packet) throws UnauthorizedException, PacketException {
IQ result = null; IQ result = IQ.createResultIQ(packet);
try { IQ.Type type = packet.getType();
IQ.Type type = packet.getType(); if (type.equals(IQ.Type.set)) {
if (type.equals(IQ.Type.set)) { try {
result = IQ.createResultIQ(packet);
User user = userManager.getUser(packet.getFrom().getNode()); User user = userManager.getUser(packet.getFrom().getNode());
// Proper format
Element vcard = packet.getChildElement(); Element vcard = packet.getChildElement();
if (vcard != null) { if (vcard != null) {
try { VCardManager.getInstance().setVCard(user.getUsername(), vcard);
VCardManager.getInstance().setVCard(user.getUsername(), vcard);
}
catch (Exception e) {
Log.error(e);
result.setError(PacketError.Condition.internal_server_error);
}
} }
} }
else if (type.equals(IQ.Type.get)) { catch (UserNotFoundException e) {
JID recipient = packet.getTo();
// If no TO was specified then get the vCard of the sender of the packet
if (recipient == null) {
recipient = packet.getFrom();
}
result = IQ.createResultIQ(packet); result = IQ.createResultIQ(packet);
result.setChildElement(packet.getChildElement().createCopy());
Element vcard = DocumentHelper.createElement(QName.get("vCard", "vcard-temp")); result.setError(PacketError.Condition.item_not_found);
result.setChildElement(vcard); }
// Only try to get the vCard values of non-anonymous users catch (Exception e) {
if (recipient != null && userManager.isRegisteredUser(recipient.getNode())) { Log.error(e);
User user = userManager.getUser(recipient.getNode()); result.setError(PacketError.Condition.internal_server_error);
}
}
else if (type.equals(IQ.Type.get)) {
JID recipient = packet.getTo();
// If no TO was specified then get the vCard of the sender of the packet
if (recipient == null) {
recipient = packet.getFrom();
}
// By default return an empty vCard
result.setChildElement("vCard", "vcard-temp");
// Only try to get the vCard values of non-anonymous users
if (recipient != null) {
if (recipient.getNode() != null && server.isLocal(recipient)) {
VCardManager vManager = VCardManager.getInstance(); VCardManager vManager = VCardManager.getInstance();
Element userVCard = vManager.getVCard(user.getUsername()); Element userVCard = vManager.getVCard(recipient.getNode());
if (userVCard != null) { if (userVCard != null) {
result.setChildElement(userVCard); result.setChildElement(userVCard);
} }
} }
} else {
else { result = IQ.createResultIQ(packet);
result = IQ.createResultIQ(packet); result.setChildElement(packet.getChildElement().createCopy());
result.setChildElement(packet.getChildElement().createCopy()); result.setError(PacketError.Condition.item_not_found);
result.setError(PacketError.Condition.not_acceptable); }
} }
} }
catch (UserNotFoundException e) { else {
result = IQ.createResultIQ(packet);
result.setChildElement(packet.getChildElement().createCopy()); result.setChildElement(packet.getChildElement().createCopy());
result.setError(PacketError.Condition.item_not_found); result.setError(PacketError.Condition.not_acceptable);
} }
return result; return result;
} }
public void initialize(XMPPServer server) { public void initialize(XMPPServer server) {
super.initialize(server); super.initialize(server);
this.server = server;
userManager = server.getUserManager(); userManager = server.getUserManager();
} }
......
...@@ -391,7 +391,10 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -391,7 +391,10 @@ public class LdapGroupProvider implements GroupProvider {
// In order to lookup a username from the manager, the username // In order to lookup a username from the manager, the username
// must be a properly escaped JID node. // must be a properly escaped JID node.
String escapedUsername = JID.escapeNode(username); String escapedUsername = JID.escapeNode(username);
userManager.getUser(escapedUsername); if (!escapedUsername.equals(username)) {
// Check if escaped username is valid
userManager.getUser(escapedUsername);
}
// No exception, so the user must exist. Add the user as a group // No exception, so the user must exist. Add the user as a group
// member using the escaped username. // member using the escaped username.
userJID = server.createJID(escapedUsername, null); userJID = server.createJID(escapedUsername, null);
......
...@@ -295,9 +295,18 @@ public class Roster implements Cacheable { ...@@ -295,9 +295,18 @@ public class Roster implements Cacheable {
// If the item only had shared groups before this update then make it persistent // If the item only had shared groups before this update then make it persistent
if (item.isShared() && item.getID() == 0) { if (item.isShared() && item.getID() == 0) {
// Do nothing if item is only shared and it is using the default user name // Do nothing if item is only shared and it is using the default user name
String defaultContactName = UserNameManager.getUserName(item.getJid()); if (item.isOnlyShared()) {
if (item.isOnlyShared() && defaultContactName.equals(item.getNickname())) { String defaultContactName = null;
return; try {
defaultContactName = UserNameManager.getUserName(item.getJid());
}
catch (UserNotFoundException e) {
// Cannot update a roster item for a local user that does not exist
defaultContactName = item.getNickname();
}
if (defaultContactName.equals(item.getNickname())) {
return;
}
} }
try { try {
rosterItemProvider.createItem(username, item); rosterItemProvider.createItem(username, item);
......
...@@ -11,20 +11,20 @@ ...@@ -11,20 +11,20 @@
package org.jivesoftware.wildfire.user; package org.jivesoftware.wildfire.user;
import org.jivesoftware.wildfire.roster.Roster; import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.util.Cacheable;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.XMPPServer; import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.event.UserEventDispatcher; import org.jivesoftware.wildfire.event.UserEventDispatcher;
import org.jivesoftware.util.Log; import org.jivesoftware.wildfire.roster.Roster;
import org.jivesoftware.util.Cacheable;
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.database.DbConnectionManager;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* Encapsulates information about a user. New users are created using * Encapsulates information about a user. New users are created using
...@@ -40,6 +40,8 @@ public class User implements Cacheable { ...@@ -40,6 +40,8 @@ public class User implements Cacheable {
private static final String LOAD_PROPERTIES = private static final String LOAD_PROPERTIES =
"SELECT name, propValue FROM jiveUserProp WHERE username=?"; "SELECT name, propValue FROM jiveUserProp WHERE username=?";
private static final String LOAD_PROPERTY =
"SELECT propValue FROM jiveUserProp WHERE username=? AND name=?";
private static final String DELETE_PROPERTY = private static final String DELETE_PROPERTY =
"DELETE FROM jiveUserProp WHERE username=? AND name=?"; "DELETE FROM jiveUserProp WHERE username=? AND name=?";
private static final String UPDATE_PROPERTY = private static final String UPDATE_PROPERTY =
...@@ -55,6 +57,41 @@ public class User implements Cacheable { ...@@ -55,6 +57,41 @@ public class User implements Cacheable {
private Map<String,String> properties = null; private Map<String,String> properties = null;
/**
* Returns the value of the specified property for the given username. This method is
* an optimization to avoid loading a user to get a specific property.
*
* @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 static String getPropertyValue(String username, String propertyName) {
String propertyValue = null;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_PROPERTY);
pstmt.setString(1, username);
pstmt.setString(2, propertyName);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
propertyValue = rs.getString(1);
}
rs.close();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { Log.error(e); }
try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); }
}
return propertyValue;
}
/** /**
* Constructs a new user. All arguments can be <tt>null</tt> except the username. * Constructs a new user. All arguments can be <tt>null</tt> except the username.
* Typically, User objects should not be constructed by end-users of the API. * Typically, User objects should not be constructed by end-users of the API.
......
...@@ -244,6 +244,28 @@ public class UserManager implements IQResultListener { ...@@ -244,6 +244,28 @@ 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 = (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