return 1;
i_stream_skip(file->input, size);
- return dbox_file_seek_next_at_metadata(file, offset);
+ if ((ret = dbox_file_seek_next_at_metadata(file, offset)) <= 0)
+ return ret;
+
+ ret = dbox_file_get_mail_stream(file, *offset, &size, NULL, &expunged);
+ if (ret <= 0)
+ return ret;
+ if (expunged) {
+ *last_r = TRUE;
+ return 0;
+ }
+ return 1;
}
static int
return ret;
}
-int dbox_file_metadata_read(struct dbox_file *file, uoff_t offset,
- bool *expunged_r)
+int dbox_file_metadata_read(struct dbox_file *file)
{
- uoff_t physical_size, metadata_offset;
+ uoff_t metadata_offset;
int ret;
- if (file->metadata_read_offset == offset || file->maildir_file)
- return 1;
- i_assert(offset != 0);
+ i_assert(file->cur_offset != 0 || file->maildir_file);
- ret = dbox_file_get_mail_stream(file, offset, &physical_size,
- NULL, expunged_r);
- if (ret <= 0 || *expunged_r)
- return ret;
+ if (file->metadata_read_offset == file->cur_offset ||
+ file->maildir_file)
+ return 1;
- metadata_offset = offset + file->msg_header_size + physical_size;
+ metadata_offset = file->cur_offset + file->msg_header_size +
+ file->cur_physical_size;
ret = dbox_file_metadata_read_at(file, metadata_offset);
if (ret <= 0)
return ret;
- file->metadata_read_offset = offset;
+ file->metadata_read_offset = file->cur_offset;
return 1;
}
void dbox_file_unlock(struct dbox_file *file);
/* Seek to given offset in file and return the message's input stream
- and physical size. Returns 1 if ok, 0 if file/offset is corrupted,
+ and physical size. Returns 1 if ok/expunged, 0 if file/offset is corrupted,
-1 if I/O error. */
int dbox_file_get_mail_stream(struct dbox_file *file, uoff_t offset,
uoff_t *physical_size_r,
struct istream **stream_r, bool *expunged_r);
-/* Seek to next message after given offset, or to first message if offset=0.
- If there are no more messages, last_r is set to TRUE. Returns 1 if ok,
- 0 if file/offset is corrupted, -1 if I/O error. */
-int dbox_file_seek_next(struct dbox_file *file, uoff_t *offset, bool *last_r);
+/* Seek to next message after current one. If there are no more messages,
+ returns 0 and last_r is set to TRUE. Returns 1 if ok, 0 if file/offset is
+ corrupted, -1 if I/O error. */
+int dbox_file_seek_next(struct dbox_file *file, uoff_t *offset_r, bool *last_r);
/* Returns TRUE if mail_size bytes can be appended to the file. */
bool dbox_file_can_append(struct dbox_file *file, uoff_t mail_size);
/* Flush writes to dbox file. */
int dbox_file_flush_append(struct dbox_file *file);
-/* Read to given message's metadata. Returns 1 if ok, 0 if file/offset is
- corrupted, -1 if I/O error. If message has already been expunged,
- expunged_r=TRUE and 1 is returned. */
-int dbox_file_metadata_read(struct dbox_file *file, uoff_t offset,
- bool *expunged_r);
-
+/* Read current message's metadata. Returns 1 if ok, 0 if metadata is
+ corrupted, -1 if I/O error. */
+int dbox_file_metadata_read(struct dbox_file *file);
/* Return wanted metadata value, or NULL if not found. */
const char *dbox_file_metadata_get(struct dbox_file *file,
enum dbox_metadata_key key);
dbox_mail_metadata_read(struct dbox_mail *mail, struct dbox_file **file_r)
{
struct mail *_mail = &mail->imail.mail.mail;
- uoff_t offset;
+ uoff_t offset, size;
bool expunged;
if (dbox_mail_open(mail, &offset, file_r) < 0)
return -1;
- if (dbox_file_metadata_read(*file_r, offset, &expunged) <= 0)
+ if (dbox_file_get_mail_stream(*file_r, offset, &size,
+ NULL, &expunged) <= 0)
return -1;
if (expunged) {
mail_set_expunged(_mail);
return -1;
}
+ if (dbox_file_metadata_read(*file_r) <= 0)
+ return -1;
return 0;
}
--- /dev/null
+#ifndef DBOX_MAP_PRIVATE_H
+#define DBOX_MAP_PRIVATE_H
+
+#include "dbox-map.h"
+
+struct dbox_mail_lookup_rec {
+ uint32_t map_uid;
+ uint16_t refcount;
+ struct dbox_mail_index_map_record rec;
+};
+
+struct dbox_map {
+ struct dbox_storage *storage;
+ struct mail_index *index;
+ struct mail_index_view *view;
+
+ uint32_t map_ext_id, ref_ext_id;
+ ARRAY_TYPE(seq_range) ref0_file_ids;
+};
+
+struct dbox_map_append {
+ struct dbox_file *file;
+ uoff_t offset, size;
+};
+
+struct dbox_map_append_context {
+ struct dbox_mailbox *mbox;
+ struct dbox_map *map;
+
+ struct mail_index_sync_ctx *sync_ctx;
+ struct mail_index_view *sync_view;
+ struct mail_index_transaction *trans;
+
+ ARRAY_DEFINE(files, struct dbox_file *);
+ ARRAY_DEFINE(appends, struct dbox_map_append);
+
+ uint32_t first_new_file_id;
+ uint32_t orig_next_uid;
+
+ unsigned int files_nonappendable_count;
+
+ unsigned int failed:1;
+};
+
+int dbox_map_refresh(struct dbox_map *map);
+int dbox_map_view_lookup_rec(struct dbox_map *map, struct mail_index_view *view,
+ uint32_t seq, struct dbox_mail_lookup_rec *rec_r);
+
+#endif
#include "ostream.h"
#include "dbox-storage.h"
#include "dbox-file.h"
-#include "dbox-map.h"
+#include "dbox-map-private.h"
#define MAX_BACKWARDS_LOOKUPS 10
-struct dbox_mail_index_map_header {
- uint32_t highest_file_id;
-};
-
-struct dbox_mail_index_map_record {
- uint32_t file_id;
- uint32_t offset;
- uint32_t size;
-};
-
-struct dbox_map {
- struct dbox_storage *storage;
- struct mail_index *index;
- struct mail_index_view *view;
-
- uint32_t map_ext_id, ref_ext_id;
- ARRAY_TYPE(seq_range) ref0_file_ids;
-};
-
-struct dbox_map_append {
- struct dbox_file *file;
- uoff_t offset, size;
-};
-
-struct dbox_map_append_context {
- struct dbox_mailbox *mbox;
- struct dbox_map *map;
-
- struct mail_index_sync_ctx *sync_ctx;
- struct mail_index_view *sync_view;
- struct mail_index_transaction *trans;
-
- ARRAY_DEFINE(files, struct dbox_file *);
- ARRAY_DEFINE(appends, struct dbox_map_append);
-
- uint32_t first_new_file_id;
- uint32_t orig_next_uid;
-
- unsigned int files_nonappendable_count;
-
- unsigned int failed:1;
-};
-
void dbox_map_set_corrupted(struct dbox_map *map, const char *format, ...)
{
va_list args;
return 0;
}
-static int dbox_map_refresh(struct dbox_map *map)
+int dbox_map_refresh(struct dbox_map *map)
{
struct mail_index_view_sync_ctx *ctx;
bool delayed_expunges;
return 1;
}
+int dbox_map_view_lookup_rec(struct dbox_map *map, struct mail_index_view *view,
+ uint32_t seq, struct dbox_mail_lookup_rec *rec_r)
+{
+ const uint16_t *ref16_p;
+ const void *data;
+ bool expunged;
+
+ memset(rec_r, 0, sizeof(*rec_r));
+ mail_index_lookup_uid(view, seq, &rec_r->map_uid);
+
+ mail_index_lookup_ext(view, seq, map->map_ext_id, &data, &expunged);
+ if (data == NULL) {
+ dbox_map_set_corrupted(map, "missing map extension");
+ return -1;
+ }
+ memcpy(&rec_r->rec, data, sizeof(rec_r->rec));
+
+ mail_index_lookup_ext(view, seq, map->ref_ext_id, &data, &expunged);
+ if (data == NULL) {
+ dbox_map_set_corrupted(map, "missing ref extension");
+ return -1;
+ }
+ ref16_p = data;
+ rec_r->refcount = *ref16_p;
+ return 0;
+}
+
int dbox_map_get_file_msgs(struct dbox_map *map, uint32_t file_id,
ARRAY_TYPE(dbox_map_file_msg) *recs)
{
const struct mail_index_header *hdr;
+ struct dbox_mail_lookup_rec rec;
struct dbox_map_file_msg msg;
- const struct dbox_mail_index_map_record *rec;
- const uint16_t *ref16_p;
- unsigned int seq;
- const void *data;
- bool expunged;
+ uint32_t seq;
if (dbox_map_refresh(map) < 0)
return -1;
memset(&msg, 0, sizeof(msg));
for (seq = 1; seq <= hdr->messages_count; seq++) {
- mail_index_lookup_uid(map->view, seq, &msg.map_uid);
-
- mail_index_lookup_ext(map->view, seq, map->map_ext_id,
- &data, &expunged);
- if (data == NULL) {
- dbox_map_set_corrupted(map, "missing map extension");
+ if (dbox_map_view_lookup_rec(map, map->view, seq, &rec) < 0)
return -1;
- }
- rec = data;
- if (rec->file_id != file_id)
- continue;
- msg.offset = rec->offset;
- mail_index_lookup_ext(map->view, seq, map->ref_ext_id,
- &data, &expunged);
- if (data == NULL) {
- dbox_map_set_corrupted(map, "missing ref extension");
- return -1;
+ if (rec.rec.file_id == file_id) {
+ msg.map_uid = rec.map_uid;
+ msg.offset = rec.rec.offset;
+ msg.refcount = rec.refcount;
+ array_append(recs, &msg, 1);
}
- ref16_p = data;
- msg.refcount = *ref16_p;
-
- array_append(recs, &msg, 1);
}
return 0;
}
#ifndef DBOX_MAP_H
#define DBOX_MAP_H
+#include "seq-range-array.h"
+
struct dbox_storage;
struct dbox_mailbox;
struct dbox_file;
struct dbox_map_append_context;
+struct dbox_mail_lookup_rec;
+
+struct dbox_mail_index_map_header {
+ uint32_t highest_file_id;
+};
+
+struct dbox_mail_index_map_record {
+ uint32_t file_id;
+ uint32_t offset;
+ uint32_t size;
+};
struct dbox_map_file_msg {
uint32_t map_uid;
int dbox_map_update_refcounts(struct dbox_map *map,
const ARRAY_TYPE(seq_range) *map_uids, int diff);
-/* */
int dbox_map_remove_file_id(struct dbox_map *map, uint32_t file_id);
/* Return all files containing messages with zero refcount. */
mail_index_ext_register(index, "dbox-hdr",
sizeof(struct dbox_index_header), 0, 0);
mbox->guid_ext_id =
- mail_index_ext_register(index, "guid", 0, 16, 1);
+ mail_index_ext_register(index, "guid", 0, DBOX_GUID_BIN_LEN, 1);
index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
mbox->maildir_uidlist = maildir_uidlist_init_readonly(&mbox->ibox);
return TRUE;
}
-static struct mailbox *
+struct mailbox *
dbox_mailbox_open(struct mail_storage *_storage, const char *name,
struct istream *input, enum mailbox_open_flags flags)
{
#define DBOX_MAIL_FILE_UID_PREFIX "u."
#define DBOX_MAIL_FILE_MULTI_FORMAT DBOX_MAIL_FILE_MULTI_PREFIX"%u"
#define DBOX_MAIL_FILE_UID_FORMAT DBOX_MAIL_FILE_UID_PREFIX"%u"
+#define DBOX_GUID_BIN_LEN (128/8)
/* How often to scan for stale temp files (based on dir's atime) */
#define DBOX_TMP_SCAN_SECS (8*60*60)
void dbox_transaction_class_init(void);
void dbox_transaction_class_deinit(void);
+struct mailbox *
+dbox_mailbox_open(struct mail_storage *storage, const char *name,
+ struct istream *input, enum mailbox_open_flags flags);
+
struct mail *
dbox_mail_alloc(struct mailbox_transaction_context *t,
enum mail_fetch_field wanted_fields,
struct dbox_file *file, uoff_t *offset)
{
uint32_t seq;
- bool expunged, last;
+ bool last;
int ret;
ret = dbox_file_seek_next(file, offset, &last);
return 0;
}
- ret = dbox_file_metadata_read(file, *offset, &expunged);
+ ret = dbox_file_metadata_read(file);
if (ret <= 0) {
if (ret < 0)
return -1;
file->current_path);
return 0;
}
- if (!expunged) {
- /* FIXME: file->uid doesn't work for multi files */
- mail_index_append(ctx->trans, file->uid, &seq);
- dbox_sync_index_metadata(ctx, file, seq, file->uid);
- }
+
+ /* FIXME: file->uid doesn't work for multi files */
+ mail_index_append(ctx->trans, file->uid, &seq);
+ dbox_sync_index_metadata(ctx, file, seq, file->uid);
return 1;
}
}
static int
-dbox_sync_index_multi_file(struct dbox_sync_rebuild_context *ctx ATTR_UNUSED,
- const char *dir ATTR_UNUSED,
- const char *fname ATTR_UNUSED)
+dbox_sync_index_multi_file(struct dbox_sync_rebuild_context *ctx,
+ const char *dir, const char *fname)
{
/* FIXME */
return 0;