Hi Gato,
there seems to be one possible “deadlock” in RosterItemProvider.java in getItems() if n threads succeed to get “con2” and then want to get “con”. Generating some load I also get these ones, but they are easy to fix.
I inserted a printStacktrace() in getCon() to see where it blocks, after 150kB stacktraces it was interesting to see that a transacted db connection is used, but this seems not to be the reason for the locks:
java.lang.Exception
at org.jivesoftware.database.ConnectionPool.getCon(ConnectionPool.java:406)
at org.jivesoftware.database.ConnectionPool.getConnection(ConnectionPool.java:137)
at org.jivesoftware.database.EmbeddedConnectionProvider.getConnection(EmbeddedConn ectionProvider.java:54)
at org.jivesoftware.database.DbConnectionManager.getConnection(DbConnectionManager .java:113)
at org.jivesoftware.database.DbConnectionManager.getTransactionConnection(DbConnec tionManager.java:134)
at org.jivesoftware.wildfire.user.DefaultUserProvider.deleteUser(DefaultUserProvid er.java:149)
at org.jivesoftware.wildfire.user.UserManager.deleteUser(UserManager.java:137)
at org.jivesoftware.wildfire.handler.IQRegisterHandler.handleIQ(IQRegisterHandler. java:221)
at org.jivesoftware.wildfire.handler.IQHandler.process(IQHandler.java:48)
at org.jivesoftware.wildfire.IQRouter.handle(IQRouter.java:256)
at org.jivesoftware.wildfire.IQRouter.route(IQRouter.java:79)
at org.jivesoftware.wildfire.PacketRouter.route(PacketRouter.java:65)
at org.jivesoftware.wildfire.net.SocketReader.processIQ(SocketReader.java:395)
at org.jivesoftware.wildfire.net.ClientSocketReader.processIQ(ClientSocketReader.j ava:50)
at org.jivesoftware.wildfire.net.SocketReader.readStream(SocketReader.java:263)
at org.jivesoftware.wildfire.net.SocketReader.run(SocketReader.java:119)
at java.lang.Thread.run(Unknown Source)
LG
Fix for RosterItemProvider.java
public Iterator getItems(String username) {
…
/* comment this, and get this connection a few lines later
con2 = DbConnectionManager.getConnection();
gstmt = con2.prepareStatement(LOAD_ROSTER_ITEM_GROUPS);
*/
// Load all the contacts in the roster
con = DbConnectionManager.getConnection(); // this one may causes a deadlock
pstmt = con.prepareStatement(LOAD_ROSTER);
…
// Load the groups for the loaded contact
// close the connection and open the next one
con.close();
con = null;
con2 = DbConnectionManager.getConnection();
gstmt = con2.prepareStatement(LOAD_ROSTER_ITEM_GROUPS);
ResultSet gs = null;
…
/code
Possible problem in DefaultUserProvider.java in deleteUser():
con = DbConnectionManager.getTransactionConnection();
…
// now the 2nd connection is requested, if many users are deleted this one will block
try {
VCardManager.getInstance().deleteVCard(username);
}
/code
The only valid fix imho would be a cascaded delete using constraints. I think that all serious databases support this feature.
Anyway, an invalid fix could be to done in ConnectionPool.java: run() closes idle connections but currently it does not call freeConnection() after doing so. My error: “free” (checkinTime) does not apply here - checkoutTime should be checked … how long may a transaction take? As nearly every db connection is using autocomit such a check s**ks, because it can not rollback the timed out transactions before closing the connection.
Message was extended