Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 152424b2 authored by cketti's avatar cketti
Browse files

Add a way to close all open IMAP connections

Use a "connection generation" value to mark all connections that have been created since the last closeAllConnections() call. Using that value we can recognize "old" connections that have not been in the connection pool at the time closeAllConnections() was called. We close them as soon as they are passed to releaseConnection().
parent f5c9c32a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ import java.net.SocketException

internal interface ImapConnection {
    val logId: String
    val connectionGeneration: Int
    val isConnected: Boolean
    val outputStream: OutputStream
    val isUidPlusCapable: Boolean
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@ interface ImapStore {
    @Throws(MessagingException::class)
    fun getFolders(): List<FolderListItem>

    fun closeAllConnections()

    companion object {
        fun create(
            serverSettings: ServerSettings,
+12 −3
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ class RealImapConnection implements ImapConnection {
    private final TrustedSocketFactory socketFactory;
    private final int socketConnectTimeout;
    private final int socketReadTimeout;
    private final int connectionGeneration;

    private Socket socket;
    private PeekableInputStream inputStream;
@@ -96,24 +97,27 @@ class RealImapConnection implements ImapConnection {


    public RealImapConnection(ImapSettings settings, TrustedSocketFactory socketFactory,
            ConnectivityManager connectivityManager, OAuth2TokenProvider oauthTokenProvider) {
            ConnectivityManager connectivityManager, OAuth2TokenProvider oauthTokenProvider, int connectionGeneration) {
        this.settings = settings;
        this.socketFactory = socketFactory;
        this.connectivityManager = connectivityManager;
        this.oauthTokenProvider = oauthTokenProvider;
        this.socketConnectTimeout = SOCKET_CONNECT_TIMEOUT;
        this.socketReadTimeout = SOCKET_READ_TIMEOUT;
        this.connectionGeneration = connectionGeneration;
    }

    RealImapConnection(ImapSettings settings, TrustedSocketFactory socketFactory,
    public RealImapConnection(ImapSettings settings, TrustedSocketFactory socketFactory,
            ConnectivityManager connectivityManager, OAuth2TokenProvider oauthTokenProvider,
            int socketConnectTimeout, int socketReadTimeout) {
            int socketConnectTimeout, int socketReadTimeout,
            int connectionGeneration) {
        this.settings = settings;
        this.socketFactory = socketFactory;
        this.connectivityManager = connectivityManager;
        this.oauthTokenProvider = oauthTokenProvider;
        this.socketConnectTimeout = socketConnectTimeout;
        this.socketReadTimeout = socketReadTimeout;
        this.connectionGeneration = connectionGeneration;
    }

    @Override
@@ -910,4 +914,9 @@ class RealImapConnection implements ImapConnection {
    public boolean isDataAvailable() throws IOException {
        return inputStream.available() > 0;
    }

    @Override
    public int getConnectionGeneration() {
        return connectionGeneration;
    }
}
+25 −3
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ class RealImapStore implements ImapStore, ImapConnectionManager, InternalImapSto
    private String pathDelimiter = null;
    private final Deque<ImapConnection> connections = new LinkedList<>();
    private FolderNameCodec folderNameCodec;
    private volatile int connectionGeneration = 1;


    public RealImapStore(ServerSettings serverSettings, ImapStoreConfig config,
@@ -296,9 +297,29 @@ class RealImapStore implements ImapStore, ImapConnectionManager, InternalImapSto
    @Override
    public void releaseConnection(ImapConnection connection) {
        if (connection != null && connection.isConnected()) {
            if (connection.getConnectionGeneration() == connectionGeneration) {
                synchronized (connections) {
                    connections.offer(connection);
                }
            } else {
                connection.close();
            }
        }
    }

    @Override
    public void closeAllConnections() {
        Timber.v("ImapStore.closeAllConnections()");

        List<ImapConnection> connectionsToClose;
        synchronized (connections) {
            connectionGeneration++;
            connectionsToClose = new ArrayList<>(connections);
            connections.clear();
        }

        for (ImapConnection connection : connectionsToClose) {
            connection.close();
        }
    }

@@ -307,7 +328,8 @@ class RealImapStore implements ImapStore, ImapConnectionManager, InternalImapSto
                new StoreImapSettings(),
                trustedSocketFactory,
                connectivityManager,
                oauthTokenProvider);
                oauthTokenProvider,
                connectionGeneration);
    }

    @Override
+1 −1
Original line number Diff line number Diff line
@@ -975,7 +975,7 @@ public class RealImapConnectionTest {
    private ImapConnection createImapConnection(ImapSettings settings, TrustedSocketFactory socketFactory,
            ConnectivityManager connectivityManager, OAuth2TokenProvider oAuth2TokenProvider) {
        return new RealImapConnection(settings, socketFactory, connectivityManager, oAuth2TokenProvider,
                SOCKET_CONNECT_TIMEOUT, SOCKET_READ_TIMEOUT);
                SOCKET_CONNECT_TIMEOUT, SOCKET_READ_TIMEOUT, 1);
    }

    private ImapConnection startServerAndCreateImapConnection(MockImapServer server) throws IOException {
Loading