From f77a0996242de1cfc74597621a1e7d12f304eafb Mon Sep 17 00:00:00 2001 From: M66B Date: Tue, 27 Jul 2021 16:17:15 +0200 Subject: [PATCH] Added connection pool debugging --- .../java/com/sun/mail/imap/IMAPStore.java | 76 ++++++++++++++++--- app/src/main/java/eu/faircode/email/Log.java | 15 +++- 2 files changed, 76 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/sun/mail/imap/IMAPStore.java b/app/src/main/java/com/sun/mail/imap/IMAPStore.java index c22838cdf9..f31636c5b8 100644 --- a/app/src/main/java/com/sun/mail/imap/IMAPStore.java +++ b/app/src/main/java/com/sun/mail/imap/IMAPStore.java @@ -662,6 +662,14 @@ public class IMAPStore extends Store } try { + synchronized (pool) { + Map crumb = new HashMap<>(); + crumb.put("host", host); + crumb.put("connections", Integer.toString(pool.authenticatedConnections.size())); + crumb.put("inuse", Boolean.toString(pool.storeConnectionInUse)); + eu.faircode.email.Log.breadcrumb("protocolConnect", crumb); + } + boolean poolEmpty; synchronized (pool) { poolEmpty = pool.authenticatedConnections.isEmpty(); @@ -1144,9 +1152,18 @@ public class IMAPStore extends Store * releaseStoreProtocol(p); * } */ - private IMAPProtocol getStoreProtocol() throws ProtocolException { + private IMAPProtocol getStoreProtocol(String reason) throws ProtocolException { IMAPProtocol p = null; + synchronized (pool) { + Map crumb = new HashMap<>(); + crumb.put("host", host); + crumb.put("reason", reason); + crumb.put("connections", Integer.toString(pool.authenticatedConnections.size())); + crumb.put("inuse", Boolean.toString(pool.storeConnectionInUse)); + eu.faircode.email.Log.breadcrumb("getStoreProtocol", crumb); + } + while (p == null) { synchronized (pool) { waitIfIdle(); @@ -1230,7 +1247,7 @@ public class IMAPStore extends Store * Get a store protocol object for use by a folder. */ IMAPProtocol getFolderStoreProtocol() throws ProtocolException { - IMAPProtocol p = getStoreProtocol(); + IMAPProtocol p = getStoreProtocol("getFolderStoreProtocol"); p.removeResponseHandler(this); p.addResponseHandler(nonStoreResponseHandler); return p; @@ -1317,6 +1334,14 @@ public class IMAPStore extends Store * Release the protocol object back to the connection pool. */ void releaseProtocol(IMAPFolder folder, IMAPProtocol protocol) { + synchronized (pool) { + Map crumb = new HashMap<>(); + crumb.put("host", host); + crumb.put("folder", folder.fullName); + crumb.put("connections", Integer.toString(pool.authenticatedConnections.size())); + crumb.put("inuse", Boolean.toString(pool.storeConnectionInUse)); + eu.faircode.email.Log.breadcrumb("releaseProtocol", crumb); + } synchronized (pool) { if (protocol != null) { @@ -1350,6 +1375,13 @@ public class IMAPStore extends Store * Release the store connection. */ private void releaseStoreProtocol(IMAPProtocol protocol) { + synchronized (pool) { + Map crumb = new HashMap<>(); + crumb.put("host", host); + crumb.put("connections", Integer.toString(pool.authenticatedConnections.size())); + crumb.put("inuse", Boolean.toString(pool.storeConnectionInUse)); + eu.faircode.email.Log.breadcrumb("releaseStoreProtocol", crumb); + } // will be called from idle() without the Store lock held, // but cleanup is synchronized and will acquire the Store lock @@ -1393,6 +1425,14 @@ public class IMAPStore extends Store * Release a store protocol object that was being used by a folder. */ void releaseFolderStoreProtocol(IMAPProtocol protocol) { + synchronized (pool) { + Map crumb = new HashMap<>(); + crumb.put("host", host); + crumb.put("connections", Integer.toString(pool.authenticatedConnections.size())); + crumb.put("inuse", Boolean.toString(pool.storeConnectionInUse)); + eu.faircode.email.Log.breadcrumb("releaseFolderStoreProtocol", crumb); + } + if (protocol == null) return; // should never happen protocol.removeResponseHandler(nonStoreResponseHandler); @@ -1411,6 +1451,13 @@ public class IMAPStore extends Store * Empty the connection pool. */ public void emptyConnectionPool(boolean force) { + synchronized (pool) { + Map crumb = new HashMap<>(); + crumb.put("host", host); + crumb.put("connections", Integer.toString(pool.authenticatedConnections.size())); + crumb.put("inuse", Boolean.toString(pool.storeConnectionInUse)); + eu.faircode.email.Log.breadcrumb("emptyConnectionPool", crumb); + } synchronized (pool) { for (int index = pool.authenticatedConnections.size() - 1; @@ -1553,7 +1600,7 @@ public class IMAPStore extends Store throws MessagingException { IMAPProtocol p = null; try { - p = getStoreProtocol(); + p = getStoreProtocol("hasCapability"); return p.hasCapability(capability); } catch (ProtocolException pex) { throw new MessagingException(pex.getMessage(), pex); @@ -1566,7 +1613,7 @@ public class IMAPStore extends Store throws MessagingException { IMAPProtocol p = null; try { - p = getStoreProtocol(); + p = getStoreProtocol("getCapability"); Map caps = p.getCapabilities(); if (caps != null) for (String cap : caps.values()) { @@ -1590,7 +1637,7 @@ public class IMAPStore extends Store throws MessagingException { IMAPProtocol p = null; try { - p = getStoreProtocol(); + p = getStoreProtocol("getCapabilities"); return p.getCapabilities(); } catch (ProtocolException pex) { throw new MessagingException(pex.getMessage(), pex); @@ -1652,7 +1699,7 @@ public class IMAPStore extends Store IMAPProtocol p = null; try { - p = getStoreProtocol(); + p = getStoreProtocol("isConnected"); p.noop(); } catch (ProtocolException pex) { // will return false below @@ -1741,6 +1788,13 @@ public class IMAPStore extends Store List foldersCopy = null; boolean done = true; + synchronized (pool) { + Map crumb = new HashMap<>(); + crumb.put("host", host); + crumb.put("connections", Integer.toString(pool.authenticatedConnections.size())); + crumb.put("inuse", Boolean.toString(pool.storeConnectionInUse)); + eu.faircode.email.Log.breadcrumb("closeAllFolders", crumb); + } // To avoid violating the locking hierarchy, there's no lock we // can hold that prevents another thread from trying to open a // folder at the same time we're trying to close all the folders. @@ -1924,7 +1978,7 @@ public class IMAPStore extends Store if (namespaces == null) { try { - p = getStoreProtocol(); + p = getStoreProtocol("getNameSpaces"); namespaces = p.namespace(); } catch (BadCommandException bex) { // NAMESPACE not supported, ignore it @@ -1983,7 +2037,7 @@ public class IMAPStore extends Store IMAPProtocol p = null; try { - p = getStoreProtocol(); + p = getStoreProtocol("getQuota"); qa = p.getQuotaRoot(root); } catch (BadCommandException bex) { throw new MessagingException("QUOTA not supported", bex); @@ -2011,7 +2065,7 @@ public class IMAPStore extends Store checkConnected(); IMAPProtocol p = null; try { - p = getStoreProtocol(); + p = getStoreProtocol("setQuota"); p.setQuota(quota); } catch (BadCommandException bex) { throw new MessagingException("QUOTA not supported", bex); @@ -2098,7 +2152,7 @@ public class IMAPStore extends Store boolean needNotification = false; try { synchronized (pool) { - p = getStoreProtocol(); + p = getStoreProtocol("idle"); if (pool.idleState != ConnectionPool.RUNNING) { // some other thread must be running the IDLE // command, we'll just wait for it to finish @@ -2238,7 +2292,7 @@ public class IMAPStore extends Store IMAPProtocol p = null; try { - p = getStoreProtocol(); + p = getStoreProtocol("id"); serverParams = p.id(clientParams); } catch (BadCommandException bex) { throw new MessagingException("ID not supported", bex); diff --git a/app/src/main/java/eu/faircode/email/Log.java b/app/src/main/java/eu/faircode/email/Log.java index 8f6cac7849..ebf4bedff5 100644 --- a/app/src/main/java/eu/faircode/email/Log.java +++ b/app/src/main/java/eu/faircode/email/Log.java @@ -280,17 +280,24 @@ public class Log { } } - static void breadcrumb(String name, String key, String value) { + public static void breadcrumb(String name, String key, String value) { Map crumb = new HashMap<>(); crumb.put(key, value); breadcrumb(name, crumb); } - static void breadcrumb(String name, Map crumb) { + public static void breadcrumb(String name, Map crumb) { try { + StringBuilder sb = new StringBuilder(); + sb.append("Breadcrumb ").append(name); Map ocrumb = new HashMap<>(); - for (String key : crumb.keySet()) - ocrumb.put(key, crumb.get(key)); + for (String key : crumb.keySet()) { + String val = crumb.get(key); + sb.append(' ').append(key).append('=').append(val); + ocrumb.put(key, val); + } + if (BuildConfig.DEBUG) + Log.i(sb.toString()); Bugsnag.leaveBreadcrumb(name, ocrumb, BreadcrumbType.LOG); } catch (Throwable ex) { ex.printStackTrace();