static void get_metadata_cache_fields(struct mailbox *box, struct mailbox_metadata *metadata_r) { const struct mail_cache_field *fields; enum mail_cache_decision_type dec; ARRAY_TYPE(mailbox_cache_field) *cache_fields; struct mailbox_cache_field *cf; unsigned int i, count; if (box->metadata_pool == NULL) { box->metadata_pool = pool_alloconly_create("mailbox metadata", 1024*3); } fields = mail_cache_register_get_list(box->cache, box->metadata_pool, &count); cache_fields = p_new(box->metadata_pool, ARRAY_TYPE(mailbox_cache_field), 1); p_array_init(cache_fields, box->metadata_pool, count); for (i = 0; i < count; i++) { dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED; if (dec != MAIL_CACHE_DECISION_NO) { cf = array_append_space(cache_fields); cf->name = fields[i].name; cf->decision = fields[i].decision; cf->last_used = fields[i].last_used; } } metadata_r->cache_fields = cache_fields; }
static void index_storage_mailbox_update_cache(struct mailbox *box, const struct mailbox_update *update) { const struct mailbox_cache_field *updates = update->cache_updates; ARRAY(struct mail_cache_field) new_fields; const struct mail_cache_field *old_fields; struct mail_cache_field field; unsigned int i, j, old_count; old_fields = mail_cache_register_get_list(box->cache, pool_datastack_create(), &old_count); /* There shouldn't be many fields, so don't worry about O(n^2). */ t_array_init(&new_fields, 32); for (i = 0; updates[i].name != NULL; i++) { /* see if it's an existing field */ for (j = 0; j < old_count; j++) { if (strcmp(updates[i].name, old_fields[j].name) == 0) break; } if (j != old_count) { field = old_fields[j]; } else if (strncmp(updates[i].name, "hdr.", 4) == 0) { /* new header */ memset(&field, 0, sizeof(field)); field.name = updates[i].name; field.type = MAIL_CACHE_FIELD_HEADER; } else { /* new unknown field. we can't do anything about this since we don't know its type */ continue; } field.decision = updates[i].decision; if (updates[i].last_used != (time_t)-1) field.last_used = updates[i].last_used; array_append(&new_fields, &field, 1); } if (array_count(&new_fields) > 0) { mail_cache_register_fields(box->cache, array_idx_modifiable(&new_fields, 0), array_count(&new_fields)); } }
static void get_metadata_precache_fields(struct mailbox *box, struct mailbox_metadata *metadata_r) { const struct mail_cache_field *fields; unsigned int i, count; enum mail_fetch_field cache = 0; fields = mail_cache_register_get_list(box->cache, pool_datastack_create(), &count); for (i = 0; i < count; i++) { const char *name = fields[i].name; if (strncmp(name, "hdr.", 4) == 0 || strcmp(name, "date.sent") == 0 || strcmp(name, "imap.envelope") == 0) cache |= MAIL_FETCH_STREAM_HEADER; else if (strcmp(name, "mime.parts") == 0 || strcmp(name, "binary.parts") == 0 || strcmp(name, "imap.body") == 0 || strcmp(name, "imap.bodystructure") == 0 || strcmp(name, "body.snippet") == 0) cache |= MAIL_FETCH_STREAM_BODY; else if (strcmp(name, "date.received") == 0) cache |= MAIL_FETCH_RECEIVED_DATE; else if (strcmp(name, "date.save") == 0) cache |= MAIL_FETCH_SAVE_DATE; else if (strcmp(name, "size.virtual") == 0) cache |= MAIL_FETCH_VIRTUAL_SIZE; else if (strcmp(name, "size.physical") == 0) cache |= MAIL_FETCH_PHYSICAL_SIZE; else if (strcmp(name, "pop3.uidl") == 0) cache |= MAIL_FETCH_UIDL_BACKEND; else if (strcmp(name, "pop3.order") == 0) cache |= MAIL_FETCH_POP3_ORDER; else if (strcmp(name, "guid") == 0) cache |= MAIL_FETCH_GUID; else if (strcmp(name, "flags") == 0) { /* just ignore for now at least.. */ } else if (box->storage->set->mail_debug) i_debug("Ignoring unknown cache field: %s", name); } metadata_r->precache_fields = cache; }
static void index_mail_parse_header_register_all_wanted(struct index_mail *mail) { struct mail *_mail = &mail->mail.mail; const struct mail_cache_field *all_cache_fields; unsigned int i, count; all_cache_fields = mail_cache_register_get_list(_mail->box->cache, pool_datastack_create(), &count); for (i = 0; i < count; i++) { if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) != 0) continue; if (!mail_cache_field_want_add(_mail->transaction->cache_trans, _mail->seq, i)) continue; array_idx_set(&mail->header_match, all_cache_fields[i].idx, &mail->header_match_value); } }
static void index_storage_get_status_cache_fields(struct mailbox *box, struct mailbox_status *status_r) { const struct mail_cache_field *fields; enum mail_cache_decision_type dec; ARRAY_TYPE(const_string) *cache_fields; unsigned int i, count; fields = mail_cache_register_get_list(box->cache, pool_datastack_create(), &count); cache_fields = t_new(ARRAY_TYPE(const_string), 1); t_array_init(cache_fields, count); for (i = 0; i < count; i++) { dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED; if (dec != MAIL_CACHE_DECISION_NO) array_append(cache_fields, &fields[i].name, 1); } status_r->cache_fields = cache_fields; }
static int maildir_get_pop3_state(struct index_mail *mail) { struct mailbox *box = mail->mail.mail.box; struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box); const struct mail_cache_field *fields; unsigned int i, count, psize_idx, vsize_idx; enum mail_cache_decision_type dec, vsize_dec; enum mail_fetch_field allowed_pop3_fields; bool not_pop3_only = FALSE; if (mail->pop3_state_set) return mail->pop3_state; /* if this mail itself has non-pop3 fields we know we're not pop3-only */ allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY | MAIL_FETCH_STORAGE_ID | MAIL_FETCH_VIRTUAL_SIZE; if (mail->data.wanted_headers != NULL || (mail->data.wanted_fields & ~allowed_pop3_fields) != 0) not_pop3_only = TRUE; /* get vsize decisions */ psize_idx = ibox->cache_fields[MAIL_CACHE_PHYSICAL_FULL_SIZE].idx; vsize_idx = ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx; if (not_pop3_only) { vsize_dec = mail_cache_field_get_decision(box->cache, vsize_idx); vsize_dec &= ~MAIL_CACHE_DECISION_FORCED; } else { /* also check if there are any non-[pv]size cached fields */ vsize_dec = MAIL_CACHE_DECISION_NO; fields = mail_cache_register_get_list(box->cache, pool_datastack_create(), &count); for (i = 0; i < count; i++) { dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED; if (fields[i].idx == vsize_idx) vsize_dec = dec; else if (dec != MAIL_CACHE_DECISION_NO && fields[i].idx != psize_idx) not_pop3_only = TRUE; } } if (!not_pop3_only) { /* either nothing is cached, or only vsize is cached. */ mail->pop3_state = 1; } else if (vsize_dec != MAIL_CACHE_DECISION_YES && (box->flags & MAILBOX_FLAG_POP3_SESSION) == 0) { /* if virtual size isn't cached permanently, POP3 isn't being used */ mail->pop3_state = -1; } else { /* possibly a mixed pop3/imap */ mail->pop3_state = 0; } mail->pop3_state_set = TRUE; return mail->pop3_state; }