Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ var targets: [Target] = [
"unittest.cpp",
"unittest.mm"
],
sources: ["CertificateUtilsTests.swift", "IMAPConnectionLeaseTests.swift", "IMAPConnectionOwnerLifetimeTests.swift", "IMAPIdleCancellationTests.swift", "IMAPInterruptCurrentCommandTests.swift", "IMAPLoginTests.swift", "LeaseTestTCPEndpoint.swift", "LibetpanHelperTests.swift", "unittest.swift"],
sources: ["CertificateUtilsTests.swift", "IMAPAutomaticDisconnectDelayTests.swift", "IMAPConnectionLeaseTests.swift", "IMAPConnectionOwnerLifetimeTests.swift", "IMAPIdleCancellationTests.swift", "IMAPInterruptCurrentCommandTests.swift", "IMAPLoginTests.swift", "LeaseTestTCPEndpoint.swift", "LibetpanHelperTests.swift", "unittest.swift"],
resources: [
.copy("data")
]
Expand Down
11 changes: 6 additions & 5 deletions src/async/imap/MCIMAPAsyncConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ IMAPAsyncConnection::IMAPAsyncConnection()
mScheduledAutomaticDisconnect = false;
mReserved = false;
mLeaseGeneration = 0;
mAutomaticDisconnectDelay = 30;
}

IMAPAsyncConnection::~IMAPAsyncConnection()
Expand Down Expand Up @@ -363,9 +362,11 @@ bool IMAPAsyncConnection::isReserved()
return reserved;
}

void IMAPAsyncConnection::setAutomaticDisconnectDelay(time_t delay)
void IMAPAsyncConnection::restartAutomaticDisconnect()
{
mAutomaticDisconnectDelay = delay;
if (mScheduledAutomaticDisconnect) {
tryAutomaticDisconnect();
}
Comment thread
dbezverkhnii marked this conversation as resolved.
}

bool IMAPAsyncConnection::interruptCurrentCommand(IMAPOperation * operation)
Expand Down Expand Up @@ -413,9 +414,9 @@ void IMAPAsyncConnection::tryAutomaticDisconnect()
mOwner->retain();
mScheduledAutomaticDisconnect = true;
#if MC_HAS_GCD
performMethodOnDispatchQueueAfterDelay((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue(), (double) mAutomaticDisconnectDelay);
performMethodOnDispatchQueueAfterDelay((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue(), mOwner->automaticDisconnectDelay());
#else
performMethodAfterDelay((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, (double) mAutomaticDisconnectDelay);
performMethodAfterDelay((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, mOwner->automaticDisconnectDelay());
#endif

if (scheduledAutomaticDisconnect) {
Expand Down
6 changes: 3 additions & 3 deletions src/async/imap/MCIMAPAsyncConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ namespace mailcore {

virtual IMAPOperation * disconnectOperation();

// How long an idle connection stays open once its queue drains.
virtual void setAutomaticDisconnectDelay(time_t delay);
// Dispatch queue only. An idle timer already running starts over with the owner's current
// automaticDisconnectDelay.
virtual void restartAutomaticDisconnect();

private:
IMAPSession * mSession;
Expand All @@ -115,7 +116,6 @@ namespace mailcore {
MCB_LOCK_TYPE mReservationLock;
bool mReserved;
unsigned int mLeaseGeneration;
time_t mAutomaticDisconnectDelay;

virtual void tryAutomaticDisconnectAfterDelay(void * context);
virtual void scheduleAutomaticDisconnectOnQueue(void * context);
Expand Down
32 changes: 28 additions & 4 deletions src/async/imap/MCIMAPAsyncSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ IMAPAsyncSession::IMAPAsyncSession()
mMaximumConnections = DEFAULT_MAX_CONNECTIONS;
mAllowsFolderConcurrentAccessEnabled = true;
mAutomaticDisconnectDelay = 30;
MCB_LOCK_INIT(&mAutomaticDisconnectDelayLock);

mHostname = NULL;
mPort = 0;
Expand Down Expand Up @@ -84,6 +85,7 @@ IMAPAsyncSession::IMAPAsyncSession()

IMAPAsyncSession::~IMAPAsyncSession()
{
MCB_LOCK_DESTROY(&mAutomaticDisconnectDelayLock);
#if MC_HAS_GCD
if (mDispatchQueue != NULL) {
dispatch_release(mDispatchQueue);
Expand Down Expand Up @@ -240,14 +242,37 @@ unsigned int IMAPAsyncSession::maximumConnections()
return mMaximumConnections;
}

void IMAPAsyncSession::setAutomaticDisconnectDelay(time_t delay)
void IMAPAsyncSession::setAutomaticDisconnectDelay(double delay)
{
MCB_LOCK(&mAutomaticDisconnectDelayLock);
mAutomaticDisconnectDelay = delay;
MCB_UNLOCK(&mAutomaticDisconnectDelayLock);

// The pool and the idle timers belong to the dispatch queue. Kept alive until the hop lands,
// like the connection's own hop in scheduleAutomaticDisconnect.
retain();
#if MC_HAS_GCD
performMethodOnDispatchQueue((Object::Method) &IMAPAsyncSession::applyAutomaticDisconnectDelay, NULL, dispatchQueue());
#else
performMethodOnMainThread((Object::Method) &IMAPAsyncSession::applyAutomaticDisconnectDelay, NULL);
#endif
}

double IMAPAsyncSession::automaticDisconnectDelay()
{
MCB_LOCK(&mAutomaticDisconnectDelayLock);
double delay = mAutomaticDisconnectDelay;
MCB_UNLOCK(&mAutomaticDisconnectDelayLock);
return delay;
}

time_t IMAPAsyncSession::automaticDisconnectDelay()
void IMAPAsyncSession::applyAutomaticDisconnectDelay(void * context)
{
return mAutomaticDisconnectDelay;
for (unsigned int i = 0 ; i < mSessions->count() ; i ++) {
IMAPAsyncConnection * connection = (IMAPAsyncConnection *) mSessions->objectAtIndex(i);
connection->restartAutomaticDisconnect();
}
release();
}

IMAPIdentity * IMAPAsyncSession::serverIdentity()
Expand Down Expand Up @@ -290,7 +315,6 @@ IMAPAsyncConnection * IMAPAsyncSession::session()
session->setAuthType(mAuthType);
session->setConnectionType(mConnectionType);
session->setTimeout(mTimeout);
session->setAutomaticDisconnectDelay(mAutomaticDisconnectDelay);
session->setCheckCertificateEnabled(mCheckCertificateEnabled);
session->setVoIPEnabled(mVoIPEnabled);
session->setDefaultNamespace(mDefaultNamespace);
Expand Down
19 changes: 12 additions & 7 deletions src/async/imap/MCIMAPAsyncSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ namespace mailcore {
virtual void setMaximumConnections(unsigned int maxConnections);
virtual unsigned int maximumConnections();

// How long an idle connection stays open once its queue drains, in seconds.
// Applied to connections created after the change.
virtual void setAutomaticDisconnectDelay(time_t delay);
virtual time_t automaticDisconnectDelay();
// How long an idle connection stays open once its queue drains, in seconds. Callable from
// any thread: an idle timer already running starts over with the new delay, on the
// session's dispatch queue.
virtual void setAutomaticDisconnectDelay(double delay);
virtual double automaticDisconnectDelay();

/*! Reserves a connection for exclusive use: the regular per-operation selection stops
seeing it, so only operations explicitly pointed at it (IMAPOperation::setSession) run
Expand All @@ -123,8 +124,9 @@ namespace mailcore {
connection to both: the start sees it free, the acquire reserves it, and the operation
is already queued. Serialize acquireConnection and releaseConnection with every
start() on this session, and do it on the session's own dispatch queue: the pool's
bookkeeping is touched from that queue as well - operationRunningStateChanged() walks
the connection list that a new connection is appended to - so any other queue
bookkeeping is touched from that queue as well - operationRunningStateChanged() and a
change of automaticDisconnectDelay walk the connection list that a new connection is
appended to - so any other queue
serializes the callers against each other and against nothing else. */
virtual IMAPAsyncConnection * acquireConnection(String * folder);
/*! Returns a reserved connection to the shared pool and re-arms its idle
Expand Down Expand Up @@ -234,11 +236,14 @@ namespace mailcore {

public: // private
virtual void automaticConfigurationDone(IMAPSession * session);
virtual void applyAutomaticDisconnectDelay(void * context);
virtual void operationRunningStateChanged();
virtual IMAPAsyncConnection * sessionForFolder(String * folder, bool urgent = false);

private:
Array * mSessions;
// Written on the caller's thread, read by the connections when they arm their idle timer.
MCB_LOCK_TYPE mAutomaticDisconnectDelayLock;

String * mHostname;
unsigned int mPort;
Expand All @@ -254,7 +259,7 @@ namespace mailcore {
time_t mTimeout;
bool mAllowsFolderConcurrentAccessEnabled;
unsigned int mMaximumConnections;
time_t mAutomaticDisconnectDelay;
double mAutomaticDisconnectDelay;
ConnectionLogger * mConnectionLogger;
bool mAutomaticConfigurationDone;
IMAPIdentity * mServerIdentity;
Expand Down
2 changes: 1 addition & 1 deletion src/c/imap/CIMAPAsyncSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ C_SYNTHESIZE_STRING(setUsername, username)
C_SYNTHESIZE_STRING(setPassword, password)
C_SYNTHESIZE_ENUM(ConnectionType, mailcore::ConnectionType, setConnectionType, connectionType)
C_SYNTHESIZE_SCALAR(time_t, time_t, setTimeout, timeout)
C_SYNTHESIZE_SCALAR(time_t, time_t, setAutomaticDisconnectDelay, automaticDisconnectDelay)
C_SYNTHESIZE_SCALAR(double, double, setAutomaticDisconnectDelay, automaticDisconnectDelay)
C_SYNTHESIZE_BOOL(setCheckCertificateEnabled, isCheckCertificateEnabled)
C_SYNTHESIZE_STRING(setOAuth2Token, OAuth2Token)
C_SYNTHESIZE_ENUM(CAuthType, mailcore::AuthType, setAuthType, authType)
Expand Down
2 changes: 1 addition & 1 deletion src/c/imap/CIMAPAsyncSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ extern "C" {
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, MailCoreString, OAuth2Token, setOAuth2Token)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, CAuthType, authType, setAuthType)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, unsigned int, maximumConnections, setMaximumConnections)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, time_t, automaticDisconnectDelay, setAutomaticDisconnectDelay)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, double, automaticDisconnectDelay, setAutomaticDisconnectDelay)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, bool, allowsFolderConcurrentAccessEnabled, setAllowsFolderConcurrentAccessEnabled)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, CIMAPNamespace, defaultNamespace, setDefaultNamespace)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, CIMAPIdentity, clientIdentity, setClientIdentity)
Expand Down
2 changes: 1 addition & 1 deletion src/include/MailCore/CIMAPAsyncSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ extern "C" {
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, MailCoreString, OAuth2Token, setOAuth2Token)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, CAuthType, authType, setAuthType)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, unsigned int, maximumConnections, setMaximumConnections)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, time_t, automaticDisconnectDelay, setAutomaticDisconnectDelay)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, double, automaticDisconnectDelay, setAutomaticDisconnectDelay)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, bool, allowsFolderConcurrentAccessEnabled, setAllowsFolderConcurrentAccessEnabled)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, CIMAPNamespace, defaultNamespace, setDefaultNamespace)
C_SYNTHESIZE_PROPERTY_DEFINITION(CIMAPAsyncSession, CIMAPIdentity, clientIdentity, setClientIdentity)
Expand Down
6 changes: 3 additions & 3 deletions src/include/MailCore/MCIMAPAsyncConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ namespace mailcore {

virtual IMAPOperation * disconnectOperation();

// How long an idle connection stays open once its queue drains.
virtual void setAutomaticDisconnectDelay(time_t delay);
// Dispatch queue only. An idle timer already running starts over with the owner's current
// automaticDisconnectDelay.
virtual void restartAutomaticDisconnect();

private:
IMAPSession * mSession;
Expand All @@ -115,7 +116,6 @@ namespace mailcore {
MCB_LOCK_TYPE mReservationLock;
bool mReserved;
unsigned int mLeaseGeneration;
time_t mAutomaticDisconnectDelay;

virtual void tryAutomaticDisconnectAfterDelay(void * context);
virtual void scheduleAutomaticDisconnectOnQueue(void * context);
Expand Down
19 changes: 12 additions & 7 deletions src/include/MailCore/MCIMAPAsyncSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ namespace mailcore {
virtual void setMaximumConnections(unsigned int maxConnections);
virtual unsigned int maximumConnections();

// How long an idle connection stays open once its queue drains, in seconds.
// Applied to connections created after the change.
virtual void setAutomaticDisconnectDelay(time_t delay);
virtual time_t automaticDisconnectDelay();
// How long an idle connection stays open once its queue drains, in seconds. Callable from
// any thread: an idle timer already running starts over with the new delay, on the
// session's dispatch queue.
virtual void setAutomaticDisconnectDelay(double delay);
virtual double automaticDisconnectDelay();

/*! Reserves a connection for exclusive use: the regular per-operation selection stops
seeing it, so only operations explicitly pointed at it (IMAPOperation::setSession) run
Expand All @@ -123,8 +124,9 @@ namespace mailcore {
connection to both: the start sees it free, the acquire reserves it, and the operation
is already queued. Serialize acquireConnection and releaseConnection with every
start() on this session, and do it on the session's own dispatch queue: the pool's
bookkeeping is touched from that queue as well - operationRunningStateChanged() walks
the connection list that a new connection is appended to - so any other queue
bookkeeping is touched from that queue as well - operationRunningStateChanged() and a
change of automaticDisconnectDelay walk the connection list that a new connection is
appended to - so any other queue
serializes the callers against each other and against nothing else. */
virtual IMAPAsyncConnection * acquireConnection(String * folder);
/*! Returns a reserved connection to the shared pool and re-arms its idle
Expand Down Expand Up @@ -234,11 +236,14 @@ namespace mailcore {

public: // private
virtual void automaticConfigurationDone(IMAPSession * session);
virtual void applyAutomaticDisconnectDelay(void * context);
virtual void operationRunningStateChanged();
virtual IMAPAsyncConnection * sessionForFolder(String * folder, bool urgent = false);

private:
Array * mSessions;
// Written on the caller's thread, read by the connections when they arm their idle timer.
MCB_LOCK_TYPE mAutomaticDisconnectDelayLock;

String * mHostname;
unsigned int mPort;
Expand All @@ -254,7 +259,7 @@ namespace mailcore {
time_t mTimeout;
bool mAllowsFolderConcurrentAccessEnabled;
unsigned int mMaximumConnections;
time_t mAutomaticDisconnectDelay;
double mAutomaticDisconnectDelay;
ConnectionLogger * mConnectionLogger;
bool mAutomaticConfigurationDone;
IMAPIdentity * mServerIdentity;
Expand Down
9 changes: 9 additions & 0 deletions src/swift/imap/IMAPSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ public class MCOIMAPSession: NSObjectCompat {
set { session.maximumConnections = newValue }
}

/**
How long an idle connection stays open once its work is done, in seconds. Settable from any
thread at any time: an idle timer already running starts over with the new delay.
*/
public var automaticDisconnectDelay: TimeInterval {
get { return session.automaticDisconnectDelay }
set { session.automaticDisconnectDelay = newValue }
}

/**
Reserves one connection of the pool for exclusive use: the regular per-operation selection
stops seeing it, so new commands run on it only when explicitly pointed at it with
Expand Down
Loading
Loading