summaryrefslogtreecommitdiffstats
path: root/src/lib-storage/index/dbox-multi/mdbox-map.h
blob: 9571f0e9ec494b6167152e9f2eff1e8997d7f480 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#ifndef MDBOX_MAP_H
#define MDBOX_MAP_H

#include "seq-range-array.h"

struct dbox_file_append_context;
struct mdbox_map_append_context;
struct mdbox_storage;

enum mdbox_map_append_flags {
	DBOX_MAP_APPEND_FLAG_ALT	= 0x01
};

struct mdbox_map_mail_index_header {
	uint32_t highest_file_id;
	/* increased every time storage is rebuilt */
	uint32_t rebuild_count;
};

struct mdbox_map_mail_index_record {
	uint32_t file_id;
	uint32_t offset;
	uint32_t size; /* including pre/post metadata */
};

struct mdbox_map_file_msg {
	uint32_t map_uid;
	uint32_t offset;
	uint32_t refcount;
};
ARRAY_DEFINE_TYPE(mdbox_map_file_msg, struct mdbox_map_file_msg);

struct mdbox_map *
mdbox_map_init(struct mdbox_storage *storage, struct mailbox_list *root_list);
void mdbox_map_deinit(struct mdbox_map **map);

/* Open the map. Returns 1 if ok, 0 if map doesn't exist, -1 if error. */
int mdbox_map_open(struct mdbox_map *map);
/* Open or create the map. This is done automatically for most operations.
   Returns 0 if ok, -1 if error. */
int mdbox_map_open_or_create(struct mdbox_map *map);
/* Refresh the map. Returns 0 if ok, -1 if error. */
int mdbox_map_refresh(struct mdbox_map *map);
/* Returns TRUE if map has been fsck'd. */
bool mdbox_map_is_fscked(struct mdbox_map *map);

/* Return the current rebuild counter */
uint32_t mdbox_map_get_rebuild_count(struct mdbox_map *map);

/* Look up file_id and offset for given map UID. Returns 1 if ok, 0 if UID
   is already expunged, -1 if error. */
int mdbox_map_lookup(struct mdbox_map *map, uint32_t map_uid,
		     uint32_t *file_id_r, uoff_t *offset_r);
/* Like mdbox_map_lookup(), but look up everything. */
int mdbox_map_lookup_full(struct mdbox_map *map, uint32_t map_uid,
			  struct mdbox_map_mail_index_record *rec_r,
			  uint16_t *refcount_r);
/* Like mdbox_map_lookup_full(), but look up with sequence. */
int mdbox_map_lookup_seq_full(struct mdbox_map *map, uint32_t seq,
			      struct mdbox_map_mail_index_record *rec_r,
			      uint16_t *refcount_r);
/* Return map UID for the map sequence. */
uint32_t mdbox_map_lookup_uid(struct mdbox_map *map, uint32_t seq);
/* Returns the total number of messages in the map. */
unsigned int mdbox_map_get_messages_count(struct mdbox_map *map);

/* Get all messages from file */
int mdbox_map_get_file_msgs(struct mdbox_map *map, uint32_t file_id,
			    ARRAY_TYPE(mdbox_map_file_msg) *recs);

/* Begin atomic context. There can be multiple transactions/appends within the
   same atomic context. */
struct mdbox_map_atomic_context *mdbox_map_atomic_begin(struct mdbox_map *map);
/* Lock the map immediately. */
int mdbox_map_atomic_lock(struct mdbox_map_atomic_context *atomic,
			  const char *reason);
/* Returns TRUE if map is locked */
bool mdbox_map_atomic_is_locked(struct mdbox_map_atomic_context *atomic);
/* When finish() is called, rollback the changes. If data was already written
   to map's transaction log, this desyncs the map and causes a rebuild */
void mdbox_map_atomic_set_failed(struct mdbox_map_atomic_context *atomic);
/* Mark this atomic as having succeeded. This is internally done if
   transaction or append is committed within this atomic, but not when the
   atomic is used standalone. */
void mdbox_map_atomic_set_success(struct mdbox_map_atomic_context *atomic);
/* Remove fsck'd flag. */
void mdbox_map_atomic_unset_fscked(struct mdbox_map_atomic_context *atomic);
/* Commit/rollback changes within this atomic context. */
int mdbox_map_atomic_finish(struct mdbox_map_atomic_context **atomic);

struct mdbox_map_transaction_context *
mdbox_map_transaction_begin(struct mdbox_map_atomic_context *atomic,
			    bool external);
/* Write transaction to map and leave it locked. Call _free() to update tail
   offset and unlock. */
int mdbox_map_transaction_commit(struct mdbox_map_transaction_context *ctx,
				 const char *reason);
void mdbox_map_transaction_free(struct mdbox_map_transaction_context **ctx);

int mdbox_map_update_refcount(struct mdbox_map_transaction_context *ctx,
			      uint32_t map_uid, int diff);
int mdbox_map_update_refcounts(struct mdbox_map_transaction_context *ctx,
			       const ARRAY_TYPE(uint32_t) *map_uids, int diff);
int mdbox_map_remove_file_id(struct mdbox_map *map, uint32_t file_id);

/* Return all files containing messages with zero refcount. */
int mdbox_map_get_zero_ref_files(struct mdbox_map *map,
				 ARRAY_TYPE(seq_range) *file_ids_r);

struct mdbox_map_append_context *
mdbox_map_append_begin(struct mdbox_map_atomic_context *atomic);
/* Request file for saving a new message with given size (if available). If an
   existing file can be used, the record is locked and updated in index.
   Returns 0 if ok, -1 if error. */
int mdbox_map_append_next(struct mdbox_map_append_context *ctx, uoff_t mail_size,
			  enum mdbox_map_append_flags flags,
			  struct dbox_file_append_context **file_append_ctx_r,
			  struct ostream **output_r);
/* Finished saving the last mail. Saves the message size. */
void mdbox_map_append_finish(struct mdbox_map_append_context *ctx);
/* Abort saving the last mail. */
void mdbox_map_append_abort(struct mdbox_map_append_context *ctx);
/* Assign map UIDs to all appended msgs to multi-files. */
int mdbox_map_append_assign_map_uids(struct mdbox_map_append_context *ctx,
				     uint32_t *first_map_uid_r,
				     uint32_t *last_map_uid_r);
/* The appends are existing messages that were simply moved to a new file.
   map_uids contains the moved messages' map UIDs. */
int mdbox_map_append_move(struct mdbox_map_append_context *ctx,
			  const ARRAY_TYPE(uint32_t) *map_uids,
			  const ARRAY_TYPE(seq_range) *expunge_map_uids);
/* Flush/fsync appends. */
int mdbox_map_append_flush(struct mdbox_map_append_context *ctx);
/* Returns 0 if ok, -1 if error. */
int mdbox_map_append_commit(struct mdbox_map_append_context *ctx);
void mdbox_map_append_free(struct mdbox_map_append_context **ctx);

/* Returns map's uidvalidity */
uint32_t mdbox_map_get_uid_validity(struct mdbox_map *map);

void mdbox_map_set_corrupted(struct mdbox_map *map, const char *format, ...)
	ATTR_FORMAT(2, 3);

#endif