Skip to content

Commit

Permalink
pop3c: Added support for TOP/RETR prefetching when PIPIELINING capabi…
Browse files Browse the repository at this point in the history
…lity exists.
  • Loading branch information
sirainen committed Jan 26, 2016
1 parent 60d1fdf commit afc77c5
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 4 deletions.
88 changes: 85 additions & 3 deletions src/lib-storage/index/pop3c/pop3c-mail.c
Expand Up @@ -9,6 +9,33 @@
#include "pop3c-sync.h"
#include "pop3c-storage.h"

struct mail *
pop3c_mail_alloc(struct mailbox_transaction_context *t,
enum mail_fetch_field wanted_fields,
struct mailbox_header_lookup_ctx *wanted_headers)
{
struct pop3c_mail *mail;
pool_t pool;

pool = pool_alloconly_create("mail", 2048);
mail = p_new(pool, struct pop3c_mail, 1);
mail->imail.mail.pool = pool;

index_mail_init(&mail->imail, t, wanted_fields, wanted_headers);
return &mail->imail.mail.mail;
}

static void pop3c_mail_close(struct mail *_mail)
{
struct pop3c_mail *pmail = (struct pop3c_mail *)_mail;
struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;

/* wait for any prefetch to finish before closing the mail */
while (pmail->prefetching)
pop3c_client_wait_one(mbox->client);
index_mail_close(_mail);
}

static int pop3c_mail_get_received_date(struct mail *_mail, time_t *date_r)
{
struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
Expand Down Expand Up @@ -100,17 +127,72 @@ static void pop3c_mail_cache_size(struct index_mail *mail)
}
}

static void pop3c_mail_prefetch_done(enum pop3c_command_state state,
const char *reply, void *context)
{
struct pop3c_mail *pmail = context;

switch (state) {
case POP3C_COMMAND_STATE_OK:
break;
case POP3C_COMMAND_STATE_ERR:
case POP3C_COMMAND_STATE_DISCONNECTED:
i_stream_unref(&pmail->imail.data.stream);
pmail->imail.data.stream =
i_stream_create_error_str(EIO, "%s failed: %s",
pmail->prefetching_body ? "RETR" : "TOP", reply);
break;
}
pmail->prefetching = FALSE;
}

static bool pop3c_mail_prefetch(struct mail *_mail)
{
struct pop3c_mail *pmail = (struct pop3c_mail *)_mail;
struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
enum pop3c_capability capa;
const char *cmd;

if (pmail->imail.data.access_part != 0 &&
pmail->imail.data.stream == NULL) {
capa = pop3c_client_get_capabilities(mbox->client);
pmail->prefetching_body = (capa & POP3C_CAPABILITY_TOP) == 0 ||
(pmail->imail.data.access_part & (READ_BODY | PARSE_BODY)) != 0;
if (pmail->prefetching_body)
cmd = t_strdup_printf("RETR %u\r\n", _mail->seq);
else
cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq);

pmail->prefetching = TRUE;
pmail->imail.data.stream =
pop3c_client_cmd_stream_async(mbox->client, cmd,
pop3c_mail_prefetch_done, pmail);
i_stream_set_name(pmail->imail.data.stream, t_strcut(cmd, '\r'));
return !pmail->prefetching;
}
return index_mail_prefetch(_mail);
}

static int
pop3c_mail_get_stream(struct mail *_mail, bool get_body,
struct message_size *hdr_size,
struct message_size *body_size, struct istream **stream_r)
{
struct index_mail *mail = (struct index_mail *)_mail;
struct pop3c_mail *pmail = (struct pop3c_mail *)_mail;
struct index_mail *mail = &pmail->imail;
struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
enum pop3c_capability capa;
const char *name, *cmd, *error;
struct istream *input;

if ((mail->data.access_part & (READ_BODY | PARSE_BODY)) != 0)
get_body = TRUE;

while (pmail->prefetching) {
/* wait for prefetch to finish */
pop3c_client_wait_one(mbox->client);
}

if (get_body && mail->data.stream != NULL) {
name = i_stream_get_name(mail->data.stream);
if (strncmp(name, "RETR", 4) == 0) {
Expand Down Expand Up @@ -179,12 +261,12 @@ pop3c_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
}

struct mail_vfuncs pop3c_mail_vfuncs = {
index_mail_close,
pop3c_mail_close,
index_mail_free,
index_mail_set_seq,
index_mail_set_uid,
index_mail_set_uid_cache_updates,
index_mail_prefetch,
pop3c_mail_prefetch,
index_mail_precache,
index_mail_add_temp_wanted_fields,

Expand Down
2 changes: 1 addition & 1 deletion src/lib-storage/index/pop3c/pop3c-storage.c
Expand Up @@ -344,7 +344,7 @@ struct mailbox pop3c_mailbox = {
index_transaction_commit,
index_transaction_rollback,
NULL,
index_mail_alloc,
pop3c_mail_alloc,
index_storage_search_init,
index_storage_search_deinit,
index_storage_search_next_nonblock,
Expand Down
12 changes: 12 additions & 0 deletions src/lib-storage/index/pop3c/pop3c-storage.h
Expand Up @@ -29,6 +29,18 @@ struct pop3c_mailbox {
unsigned int logged_in:1;
};

struct pop3c_mail {
struct index_mail imail;

unsigned int prefetching:1;
unsigned int prefetching_body:1;
};

struct mail *
pop3c_mail_alloc(struct mailbox_transaction_context *t,
enum mail_fetch_field wanted_fields,
struct mailbox_header_lookup_ctx *wanted_headers);

extern struct mail_vfuncs pop3c_mail_vfuncs;

#endif

0 comments on commit afc77c5

Please sign in to comment.