Pipelining disabled for "other" email services. Closes #4763

This commit is contained in:
Eric Gregory 2012-02-23 16:17:59 -08:00
parent 6e89c450dc
commit e91eafce7a
7 changed files with 52 additions and 15 deletions

View file

@ -186,6 +186,7 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
account_info.imap_server_host = login.imap_host;
account_info.imap_server_port = login.imap_port;
account_info.imap_server_tls = login.imap_tls;
account_info.imap_server_pipeline = (login.provider != Geary.ServiceProvider.OTHER);
account_info.smtp_server_host = login.smtp_host;
account_info.smtp_server_port = login.smtp_port;
account_info.smtp_server_tls = login.smtp_tls;

View file

@ -11,6 +11,7 @@ public class Geary.AccountInformation : Object {
private const string IMAP_HOST = "imap_host";
private const string IMAP_PORT = "imap_port";
private const string IMAP_TLS = "imap_tls";
private const string IMAP_PIPELINE = "imap_pipeline";
private const string SMTP_HOST = "smtp_host";
private const string SMTP_PORT = "smtp_port";
private const string SMTP_TLS = "smtp_tls";
@ -22,6 +23,7 @@ public class Geary.AccountInformation : Object {
public string imap_server_host { get; set; default = ""; }
public uint16 imap_server_port { get; set; default = Imap.ClientConnection.DEFAULT_PORT_TLS; }
public bool imap_server_tls { get; set; default = true; }
public bool imap_server_pipeline { get; set; default = true; }
public string smtp_server_host { get; set; default = ""; }
public uint16 smtp_server_port { get; set; default = Smtp.ClientConnection.SECURE_SMTP_PORT; }
@ -46,6 +48,7 @@ public class Geary.AccountInformation : Object {
imap_server_port = get_uint16_value(key_file, GROUP, IMAP_PORT,
Imap.ClientConnection.DEFAULT_PORT_TLS);
imap_server_tls = get_bool_value(key_file, GROUP, IMAP_TLS, true);
imap_server_pipeline = get_bool_value(key_file, GROUP, IMAP_PIPELINE, true);
smtp_server_host = get_string_value(key_file, GROUP, SMTP_HOST);
smtp_server_port = get_uint16_value(key_file, GROUP, SMTP_PORT,
@ -97,6 +100,7 @@ public class Geary.AccountInformation : Object {
key_file.set_value(GROUP, IMAP_HOST, imap_server_host);
key_file.set_integer(GROUP, IMAP_PORT, imap_server_port);
key_file.set_boolean(GROUP, IMAP_TLS, imap_server_tls);
key_file.set_boolean(GROUP, IMAP_PIPELINE, imap_server_pipeline);
key_file.set_value(GROUP, SMTP_HOST, smtp_server_host);
key_file.set_integer(GROUP, SMTP_PORT, smtp_server_port);

View file

@ -40,14 +40,14 @@ public class Geary.Engine {
case ServiceProvider.GMAIL:
return new GmailAccount(
"Gmail account %s".printf(cred.to_string()), cred.user, account_info, user_data_dir,
new Geary.Imap.Account(GmailAccount.IMAP_ENDPOINT, GmailAccount.SMTP_ENDPOINT, cred),
new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
new Geary.Imap.Account(GmailAccount.IMAP_ENDPOINT, GmailAccount.SMTP_ENDPOINT, cred,
account_info), new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
case ServiceProvider.YAHOO:
return new YahooAccount(
"Yahoo account %s".printf(cred.to_string()), cred.user, account_info, user_data_dir,
new Geary.Imap.Account(YahooAccount.IMAP_ENDPOINT, YahooAccount.SMTP_ENDPOINT, cred),
new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
new Geary.Imap.Account(YahooAccount.IMAP_ENDPOINT, YahooAccount.SMTP_ENDPOINT, cred,
account_info), new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
case ServiceProvider.OTHER:
Endpoint imap_endpoint = new Endpoint(account_info.imap_server_host,
@ -60,7 +60,7 @@ public class Geary.Engine {
return new OtherAccount(
"Other account %s".printf(cred.to_string()), cred.user, account_info, user_data_dir,
new Geary.Imap.Account(imap_endpoint, smtp_endpoint, cred),
new Geary.Imap.Account(imap_endpoint, smtp_endpoint, cred, account_info),
new Geary.Sqlite.Account(cred, user_data_dir, resource_dir));
default:

View file

@ -32,12 +32,13 @@ private class Geary.Imap.Account : Geary.AbstractAccount, Geary.RemoteAccount {
private Geary.Smtp.ClientSession smtp;
private Gee.HashMap<string, string?> delims = new Gee.HashMap<string, string?>();
public Account(Geary.Endpoint imap_endpoint, Geary.Endpoint smtp_endpoint, Geary.Credentials cred) {
public Account(Geary.Endpoint imap_endpoint, Geary.Endpoint smtp_endpoint, Geary.Credentials cred,
Geary.AccountInformation account_info) {
base ("IMAP Account for %s".printf(cred.to_string()));
this.cred = cred;
session_mgr = new ClientSessionManager(imap_endpoint, cred);
session_mgr = new ClientSessionManager(imap_endpoint, cred, account_info);
session_mgr.login_failed.connect(on_login_failed);
smtp = new Geary.Smtp.ClientSession(smtp_endpoint);
}

View file

@ -9,6 +9,7 @@ public class Geary.Imap.ClientSessionManager {
private Endpoint endpoint;
private Credentials credentials;
private AccountInformation account_info;
private Gee.HashSet<ClientSession> sessions = new Gee.HashSet<ClientSession>();
private Geary.NonblockingMutex sessions_mutex = new Geary.NonblockingMutex();
private Gee.HashSet<SelectedContext> examined_contexts = new Gee.HashSet<SelectedContext>();
@ -19,9 +20,11 @@ public class Geary.Imap.ClientSessionManager {
public signal void login_failed();
public ClientSessionManager(Endpoint endpoint, Credentials credentials) {
public ClientSessionManager(Endpoint endpoint, Credentials credentials,
AccountInformation account_info) {
this.endpoint = endpoint;
this.credentials = credentials;
this.account_info = account_info;
adjust_session_pool.begin();
}
@ -186,7 +189,7 @@ public class Geary.Imap.ClientSessionManager {
// This should only be called when sessions_mutex is locked.
private async ClientSession create_new_authorized_session(Cancellable? cancellable) throws Error {
ClientSession new_session = new ClientSession(endpoint);
ClientSession new_session = new ClientSession(endpoint, account_info);
add_session(new_session);

View file

@ -167,6 +167,7 @@ public class Geary.Imap.ClientSession {
state_to_string, event_to_string);
private Geary.Endpoint endpoint;
private Geary.AccountInformation account_info;
private Geary.State.Machine fsm;
private ClientConnection? cx = null;
private string? current_mailbox = null;
@ -183,6 +184,8 @@ public class Geary.Imap.ClientSession {
private int unselected_keepalive_secs = 0;
private int selected_with_idle_keepalive_secs = 0;
private bool allow_idle = true;
private NonblockingMutex serialized_cmds_mutex = new NonblockingMutex();
private int waiting_to_send = 0;
// state used only during connect and disconnect
private bool awaiting_connect_response = false;
@ -225,8 +228,9 @@ public class Geary.Imap.ClientSession {
public virtual signal void unsolicited_flags(MailboxAttributes attrs) {
}
public ClientSession(Geary.Endpoint endpoint) {
public ClientSession(Geary.Endpoint endpoint, Geary.AccountInformation account_info) {
this.endpoint = endpoint;
this.account_info = account_info;
Geary.State.Mapping[] mappings = {
new Geary.State.Mapping(State.DISCONNECTED, Event.CONNECT, on_connect),
@ -1085,10 +1089,28 @@ public class Geary.Imap.ClientSession {
new ImapError.NOT_CONNECTED("Not connected to %s", endpoint.to_string()));
}
int claim_stub = NonblockingMutex.INVALID_TOKEN;
if (!account_info.imap_server_pipeline) {
try {
debug("[%s] Waiting to send cmd %s: %d", to_string(), cmd.to_string(), ++waiting_to_send);
claim_stub = yield serialized_cmds_mutex.claim_async(cancellable);
debug("[%s] Ready, now waiting to send cmd %s: %d", to_string(), cmd.to_string(), --waiting_to_send);
} catch (Error wait_err) {
return new AsyncCommandResponse(null, user, wait_err);
}
}
try {
yield cx.send_async(cmd, cancellable);
} catch (Error err) {
return new AsyncCommandResponse(null, user, err);
} catch (Error send_err) {
try {
if (!account_info.imap_server_pipeline && claim_stub != NonblockingMutex.INVALID_TOKEN)
serialized_cmds_mutex.release(ref claim_stub);
} catch (Error abort_err) {
debug("Error attempting to abort from send operation: %s", abort_err.message);
}
return new AsyncCommandResponse(null, user, send_err);
}
// If the command didn't complete in the context of send_async(), wait for it
@ -1103,6 +1125,14 @@ public class Geary.Imap.ClientSession {
assert(cmd_response.is_sealed());
assert(cmd_response.status_response.tag.equals(cmd.tag));
if (!account_info.imap_server_pipeline && claim_stub != NonblockingMutex.INVALID_TOKEN) {
try {
serialized_cmds_mutex.release(ref claim_stub);
} catch (Error notify_err) {
return new AsyncCommandResponse(null, user, notify_err);
}
}
return new AsyncCommandResponse(cmd_response, user, null);
}
@ -1270,7 +1300,7 @@ public class Geary.Imap.ClientSession {
}
public string to_string() {
return "ClientSession:%s".printf(endpoint.to_string());
return "ClientSession:%s".printf((cx == null) ? endpoint.to_string() : cx.to_string());
}
public string to_full_string() {

View file

@ -88,8 +88,6 @@ public abstract class Geary.NonblockingAbstractSemaphore {
reset();
}
// TODO: Allow the caller to pass their own cancellable in if they want to be able to cancel
// this particular wait (and not all waiting threads of execution)
public async void wait_async(Cancellable? cancellable = null) throws Error {
for (;;) {
check_user_cancelled(cancellable);