index-mailbox-list.c revision 73b50eecfc31750a312e2f940023f522eb07178c
/* Copyright (C) 2006-2007 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "file-lock.h"
#include "imap-match.h"
#include "mail-index.h"
#include "mail-storage.h"
#include "mailbox-tree.h"
#include "mailbox-list-subscriptions.h"
#include "mailbox-list-index.h"
#include "index-mailbox-list.h"
#include <stdlib.h>
#include <time.h>
/* min 2 seconds */
#define MAILBOX_LIST_SYNC_SECS 2
static enum mailbox_info_flags
{
enum mailbox_info_flags info_flags = 0;
if ((flags & MAILBOX_LIST_INDEX_FLAG_CHILDREN) != 0)
if ((flags & MAILBOX_LIST_INDEX_FLAG_NOCHILDREN) != 0)
if ((flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0)
if ((flags & MAILBOX_LIST_INDEX_FLAG_NOSELECT) != 0)
return info_flags;
}
static enum mailbox_list_index_flags
{
enum mailbox_list_index_flags flags = 0;
if ((info_flags & MAILBOX_CHILDREN) != 0)
else if ((info_flags & MAILBOX_NOCHILDREN) != 0)
if ((info_flags & MAILBOX_NONEXISTENT) != 0)
if ((info_flags & MAILBOX_NOSELECT) != 0)
return flags;
}
static int
{
const struct mail_index_header *hdr;
/* uid_validity changed */
return 0;
}
/* FIXME: single sync_stamp works only with maildir++ */
"stat(%s) failed: %m", path);
return -1;
}
/*
if mtime is older than 2 secs, we set the first bit on
if mtime is 0-2 secs old, we set the first bit off.
this way we'll always do a resync later when syncing a recently
changed directory. if the directory changes while we're syncing it
we'll resync it again later.
this would work with 1 second difference if we didn't store the
dirtyness flag in the stamp's first bit.
*/
else
}
const char **prefix_r, int *recurse_level_r)
{
const char *prefix_start, *prefix_end;
bool seen_wildcards = FALSE;
int recurse_level = 0;
if (*pattern == '%')
else if (*pattern == '*') {
recurse_level = -1;
break;
}
if (!seen_wildcards)
}
}
}
static int
{
struct mailbox_list_iterate_context *iter;
struct mailbox_list_index_sync_ctx *sync_ctx;
const struct mailbox_info *info;
const char *patterns[2];
int ret = 0;
/* FIXME: this works nicely with maildir++, but not others */
sync_flags, &sync_ctx) < 0)
return -1;
&seq) < 0) {
ret = -1;
break;
}
}
ret = -1;
if (ret < 0) {
return -1;
}
/* FIXME: single sync_stamp works only with maildir++ */
return mailbox_list_index_sync_commit(&sync_ctx);
}
static bool
const char *const *patterns)
{
int cur_recurse_level;
if ((flags & MAILBOX_LIST_ITER_RAW_LIST) != 0 ||
(flags & (subs_flags |
/* Ignore indexes completely */
return FALSE;
}
if ((flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) {
/* we'll need to know the subscriptions */
/* let the backend handle this failure */
return FALSE;
}
}
/* Refresh index before opening our view */
return FALSE;
/* FIXME: we could just do multiple lookups for different patterns */
prefix = "";
cur_recurse_level == -1)
}
prefix = "";
if (index_mailbox_list_is_synced(ctx) <= 0) {
if (index_mailbox_list_sync(ctx) < 0)
return FALSE;
/* updated, we'll have to reopen views */
return FALSE;
}
if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
} else {
/* list from index */
ctx->recurse_level);
}
return TRUE;
}
static struct mailbox_list_iterate_context *
const char *const *patterns,
enum mailbox_list_iter_flags flags)
{
struct index_mailbox_list_iterate_context *ctx;
/* no indexing */
}
}
static int
{
const struct mail_index_record *rec;
if (seq == 0) {
i_error("Mailbox list index desynced: "
"Record uid=%u expunged from mail index", uid);
return -1;
}
return 0;
}
const struct mailbox_info **info_r)
{
struct mailbox_list_index_info iinfo;
struct mailbox_node *subs_node;
int ret;
/* find the next matching mailbox */
for (;;) {
if (ret <= 0) {
return ret;
}
continue;
return -1;
i_error("Mailbox list index desynced: "
"Children flags for uid=%u wrong in mail index",
return -1;
}
/* skip nonexistent mailboxes when finding with "*" */
ctx->recurse_level < 0)
continue;
/* get subscription states */
}
}
return 0;
}
}
static const struct mailbox_info *
{
struct index_mailbox_list_iterate_context *ctx =
(struct index_mailbox_list_iterate_context *)_ctx;
const struct mailbox_info *info;
struct mailbox_node *subs_node;
const char *index_name;
/* listing mailboxes from index */
return NULL;
}
return info;
/* index isn't being used */
}
/* listing subscriptions, but we also want flags */
return NULL;
if (ctx->ns_prefix_len > 0 &&
return NULL;
}
}
static int
{
struct index_mailbox_list_iterate_context *ctx =
(struct index_mailbox_list_iterate_context *)_ctx;
return ret;
}
{
}
const char *dir)
{
const char *path;
int ret;
/* FIXME: a bit ugly way to get the flags, but this will do for now.. */
#ifndef MMAP_CONFLICTS_WRITE
if ((storage_flags & MAIL_STORAGE_FLAG_MMAP_DISABLE) != 0)
#endif
/* try opening once more. it should be created
directly into memory now. */
if (ret <= 0) {
/* everything failed. there's a bug in the
code, but just work around it by disabling
the index completely */
return -1;
}
}
}
ilist->mail_index);
/* skip indexing */
return -1;
}
&ilist->list_sync_view) < 0) {
return -1;
}
return 0;
}
{
const char *dir;
/* FIXME: for now we only work with maildir++ */
/* reserve the module context anyway, so syncing code knows
that the index is disabled */
return;
}
/* sync_init allocates the extensions. do it here before opening the
index files, so that our initial memory pool size guesses are a
bit more optimal */
}
}
void index_mailbox_list_init(void); /* called in mailbox-list-register.c */
void index_mailbox_list_init(void)
{
}