static bool imapc_mail_get_cached_guid(struct mail *_mail) { struct index_mail *imail = (struct index_mail *)_mail; const enum index_cache_field cache_idx = imail->ibox->cache_fields[MAIL_CACHE_GUID].idx; string_t *str; if (imail->data.guid != NULL) { if (mail_cache_field_can_add(_mail->transaction->cache_trans, _mail->seq, cache_idx)) { /* GUID was prefetched - add to cache */ index_mail_cache_add_idx(imail, cache_idx, imail->data.guid, strlen(imail->data.guid)+1); } return TRUE; } str = str_new(imail->mail.data_pool, 64); if (mail_cache_lookup_field(_mail->transaction->cache_view, str, imail->mail.mail.seq, cache_idx) > 0) { imail->data.guid = str_c(str); return TRUE; } return FALSE; }
static void index_mail_parse_finish_imap_envelope(struct index_mail *mail) { struct mail *_mail = &mail->mail.mail; const unsigned int cache_field_envelope = mail->ibox->cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx; string_t *str; str = str_new(mail->mail.data_pool, 256); imap_envelope_write_part_data(mail->data.envelope_data, str); mail->data.envelope = str_c(str); if (mail_cache_field_can_add(_mail->transaction->cache_trans, _mail->seq, cache_field_envelope)) { index_mail_cache_add_idx(mail, cache_field_envelope, str_data(str), str_len(str)); } }
static bool index_mail_want_cache(struct index_mail *mail, enum index_cache_field field) { enum mail_fetch_field fetch_field; unsigned int cache_field; switch (field) { case MAIL_CACHE_SENT_DATE: fetch_field = MAIL_FETCH_DATE; break; case MAIL_CACHE_RECEIVED_DATE: fetch_field = MAIL_FETCH_RECEIVED_DATE; break; case MAIL_CACHE_SAVE_DATE: fetch_field = MAIL_FETCH_SAVE_DATE; break; case MAIL_CACHE_VIRTUAL_FULL_SIZE: fetch_field = MAIL_FETCH_VIRTUAL_SIZE; break; case MAIL_CACHE_PHYSICAL_FULL_SIZE: fetch_field = MAIL_FETCH_PHYSICAL_SIZE; break; default: i_unreached(); } if ((mail->data.dont_cache_fetch_fields & fetch_field) != 0) return FALSE; cache_field = mail->ibox->cache_fields[field].idx; if ((mail->data.cache_fetch_fields & fetch_field) != 0) { return mail_cache_field_can_add(mail->trans->cache_trans, mail->data.seq, cache_field); } else { return mail_cache_field_want_add(mail->trans->cache_trans, mail->data.seq, cache_field); } }
static void index_mail_parse_header_finish(struct index_mail *mail) { struct mail *_mail = &mail->mail.mail; const struct index_mail_line *lines; const unsigned char *header, *data; const uint8_t *match; buffer_t *buf; size_t data_size; unsigned int i, j, count, match_idx, match_count; bool noncontiguous; /* sort it first so fields are grouped together and ordered by line number */ array_sort(&mail->header_lines, header_line_cmp); lines = array_get(&mail->header_lines, &count); match = array_get(&mail->header_match, &match_count); header = buffer_get_data(mail->header_data, NULL); buf = buffer_create_dynamic(pool_datastack_create(), 256); /* go through all the header lines we found */ for (i = match_idx = 0; i < count; i = j) { /* matches and header lines are both sorted, all matches until lines[i] weren't found */ while (match_idx < lines[i].field_idx && match_idx < match_count) { if (HEADER_MATCH_USABLE(mail, match[match_idx]) && mail_cache_field_can_add(_mail->transaction->cache_trans, _mail->seq, match_idx)) { /* this header doesn't exist. remember that. */ i_assert((match[match_idx] & HEADER_MATCH_FLAG_FOUND) == 0); index_mail_cache_add_idx(mail, match_idx, "", 0); } match_idx++; } if (match_idx < match_count) { /* save index to first header line */ j = i + 1; array_idx_set(&mail->header_match_lines, match_idx, &j); match_idx++; } if (!mail_cache_field_can_add(_mail->transaction->cache_trans, _mail->seq, lines[i].field_idx)) { /* header is already cached */ j = i + 1; continue; } /* buffer contains: { uint32_t line_num[], 0, header texts } noncontiguous is just a small optimization.. */ buffer_set_used_size(buf, 0); buffer_append(buf, &lines[i].line_num, sizeof(lines[i].line_num)); noncontiguous = FALSE; for (j = i+1; j < count; j++) { if (lines[j].field_idx != lines[i].field_idx) break; if (lines[j].start_pos != lines[j-1].end_pos) noncontiguous = TRUE; buffer_append(buf, &lines[j].line_num, sizeof(lines[j].line_num)); } buffer_append_zero(buf, sizeof(uint32_t)); if (noncontiguous) { for (; i < j; i++) { buffer_append(buf, header + lines[i].start_pos, lines[i].end_pos - lines[i].start_pos); } i--; } else { buffer_append(buf, header + lines[i].start_pos, lines[j-1].end_pos - lines[i].start_pos); } data = buffer_get_data(buf, &data_size); index_mail_cache_add_idx(mail, lines[i].field_idx, data, data_size); } for (; match_idx < match_count; match_idx++) { if (HEADER_MATCH_USABLE(mail, match[match_idx]) && mail_cache_field_can_add(_mail->transaction->cache_trans, _mail->seq, match_idx)) { /* this header doesn't exist. remember that. */ i_assert((match[match_idx] & HEADER_MATCH_FLAG_FOUND) == 0); index_mail_cache_add_idx(mail, match_idx, "", 0); } } mail->data.dont_cache_field_idx = UINT_MAX; }
static void index_mail_body_parsed_cache_bodystructure(struct index_mail *mail, enum index_cache_field field) { struct index_mail_data *data = &mail->data; unsigned int cache_field_parts = mail->ibox->cache_fields[MAIL_CACHE_MESSAGE_PARTS].idx; unsigned int cache_field_body = mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODY].idx; unsigned int cache_field_bodystructure = mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx; enum mail_cache_decision_type dec; string_t *str; bool bodystructure_cached = FALSE; bool plain_bodystructure = FALSE; bool cache_bodystructure, cache_body; if ((data->cache_flags & MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0) { if (data->messageparts_saved_to_cache || mail_cache_field_exists(mail->trans->cache_view, data->seq, cache_field_parts) > 0) { /* cached it as flag + message_parts */ plain_bodystructure = TRUE; } } if (!data->parsed_bodystructure) return; /* If BODY is fetched first but BODYSTRUCTURE is also wanted, we don't normally want to first cache BODY and then BODYSTRUCTURE. So check the wanted_fields also in here. */ if (plain_bodystructure) cache_bodystructure = FALSE; else if (field == MAIL_CACHE_IMAP_BODYSTRUCTURE || (mail->wanted_fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) != 0) { cache_bodystructure = mail_cache_field_can_add(mail->trans->cache_trans, data->seq, cache_field_bodystructure); } else { cache_bodystructure = mail_cache_field_want_add(mail->trans->cache_trans, data->seq, cache_field_bodystructure); } if (cache_bodystructure) { str = str_new(mail->data_pool, 128); imap_bodystructure_write(data->parts, str, TRUE); data->bodystructure = str_c(str); index_mail_cache_add(mail, MAIL_CACHE_IMAP_BODYSTRUCTURE, str_c(str), str_len(str)+1); bodystructure_cached = TRUE; } else { bodystructure_cached = mail_cache_field_exists(mail->trans->cache_view, data->seq, cache_field_bodystructure) > 0; } /* normally don't cache both BODY and BODYSTRUCTURE, but do it if BODY is forced to be cached */ dec = mail_cache_field_get_decision(mail->mail.mail.box->cache, cache_field_body); if (plain_bodystructure || (bodystructure_cached && (dec != (MAIL_CACHE_DECISION_FORCED | MAIL_CACHE_DECISION_YES)))) cache_body = FALSE; else if (field == MAIL_CACHE_IMAP_BODY) { cache_body = mail_cache_field_can_add(mail->trans->cache_trans, data->seq, cache_field_body); } else { cache_body = mail_cache_field_want_add(mail->trans->cache_trans, data->seq, cache_field_body); } if (cache_body) { str = str_new(mail->data_pool, 128); imap_bodystructure_write(data->parts, str, FALSE); data->body = str_c(str); index_mail_cache_add(mail, MAIL_CACHE_IMAP_BODY, str_c(str), str_len(str)+1); } }