summaryrefslogtreecommitdiffstats
path: root/src/lib-index/mail-index-transaction-private.h
blob: eb438b2f2ab3d1088fbe1281cc2fde1fa915bdc6 (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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#ifndef MAIL_INDEX_TRANSACTION_PRIVATE_H
#define MAIL_INDEX_TRANSACTION_PRIVATE_H

#include "seq-range-array.h"
#include "mail-transaction-log.h"

ARRAY_DEFINE_TYPE(seq_array_array, ARRAY_TYPE(seq_array));

struct mail_index_transaction_keyword_update {
	ARRAY_TYPE(seq_range) add_seq;
	ARRAY_TYPE(seq_range) remove_seq;
};

struct mail_index_transaction_ext_hdr_update {
	size_t alloc_size;
	/* mask is in bytes, not bits */
	unsigned char *mask;
	unsigned char *data;
};

struct mail_index_transaction_vfuncs {
	void (*reset)(struct mail_index_transaction *t);
	int (*commit)(struct mail_index_transaction *t,
		      struct mail_index_transaction_commit_result *result_r);
	void (*rollback)(struct mail_index_transaction *t);
};

union mail_index_transaction_module_context {
	struct mail_index_transaction_vfuncs super;
	struct mail_index_module_register *reg;
};

struct mail_index_flag_update {
	uint32_t uid1, uid2;
	uint16_t add_flags;
	uint16_t remove_flags;
};

struct mail_index_transaction {
	struct mail_index_transaction *prev, *next;
	int refcount;

	enum mail_index_transaction_flags flags;
	struct mail_index_transaction_vfuncs v, *vlast;
	struct mail_index_view *view;
	struct mail_index_view *latest_view;

	/* NOTE: If you add anything new, remember to update
	   mail_index_transaction_reset_v() to reset it. */
        ARRAY(struct mail_index_record) appends;
	uint32_t first_new_seq, last_new_seq;
	uint32_t highest_append_uid;
	/* lowest/highest sequence that updates flags/keywords */
	uint32_t min_flagupdate_seq, max_flagupdate_seq;

	ARRAY(struct mail_transaction_modseq_update) modseq_updates;
	ARRAY(struct mail_transaction_expunge_guid) expunges;
	ARRAY(struct mail_index_flag_update) updates;
	size_t last_update_idx;

	unsigned char pre_hdr_change[sizeof(struct mail_index_header)];
	unsigned char pre_hdr_mask[sizeof(struct mail_index_header)];
	unsigned char post_hdr_change[sizeof(struct mail_index_header)];
	unsigned char post_hdr_mask[sizeof(struct mail_index_header)];

	ARRAY(struct mail_index_transaction_ext_hdr_update) ext_hdr_updates;
	ARRAY_TYPE(seq_array_array) ext_rec_updates;
	ARRAY_TYPE(seq_array_array) ext_rec_atomics;
	ARRAY(struct mail_transaction_ext_intro) ext_resizes;
	ARRAY(struct mail_transaction_ext_reset) ext_resets;
	ARRAY(uint32_t) ext_reset_ids;
	ARRAY(uint32_t) ext_reset_atomic;

	ARRAY(struct mail_index_transaction_keyword_update) keyword_updates;
	buffer_t *attribute_updates; /* [+-][ps]key\0.. */
	buffer_t *attribute_updates_suffix; /* <timestamp>[<value len>].. */

	uint64_t min_highest_modseq;
	uint64_t max_modseq;
	ARRAY_TYPE(seq_range) *conflict_seqs;

	/* Module-specific contexts. */
	ARRAY(union mail_index_transaction_module_context *) module_contexts;

	bool no_appends:1;

	bool sync_transaction:1;
	bool appends_nonsorted:1;
	bool expunges_nonsorted:1;
	bool drop_unnecessary_flag_updates:1;
	bool pre_hdr_changed:1;
	bool post_hdr_changed:1;
	bool reset:1;
	bool index_deleted:1;
	bool index_undeleted:1;
	bool commit_deleted_index:1;
	bool tail_offset_changed:1;
	/* non-extension updates. flag updates don't change this because
	   they may be added and removed, so be sure to check that the updates
	   array is non-empty also. */
	bool log_updates:1;
	/* extension updates */
	bool log_ext_updates:1;
};

#define MAIL_INDEX_TRANSACTION_HAS_CHANGES(t) \
	((t)->log_updates || (t)->log_ext_updates || \
	 (array_is_created(&(t)->updates) && array_count(&(t)->updates) > 0) || \
	 (t)->index_deleted || (t)->index_undeleted)

typedef void hook_mail_index_transaction_created_t(struct mail_index_transaction *t);

void mail_index_transaction_hook_register(hook_mail_index_transaction_created_t *hook);
void mail_index_transaction_hook_unregister(hook_mail_index_transaction_created_t *hook);

struct mail_index_record *
mail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq);

void mail_index_transaction_ref(struct mail_index_transaction *t);
void mail_index_transaction_unref(struct mail_index_transaction **t);
void mail_index_transaction_reset_v(struct mail_index_transaction *t);

void mail_index_transaction_sort_appends(struct mail_index_transaction *t);
void mail_index_transaction_sort_expunges(struct mail_index_transaction *t);
uint32_t mail_index_transaction_get_next_uid(struct mail_index_transaction *t);
void mail_index_transaction_set_log_updates(struct mail_index_transaction *t);
void mail_index_update_day_headers(struct mail_index_transaction *t, time_t day_stamp);

unsigned int
mail_index_transaction_get_flag_update_pos(struct mail_index_transaction *t,
					   unsigned int left_idx,
					   unsigned int right_idx,
					   uint32_t seq);
void mail_index_transaction_lookup_latest_keywords(struct mail_index_transaction *t,
						   uint32_t seq,
						   ARRAY_TYPE(keyword_indexes) *keywords);

bool mail_index_cancel_flag_updates(struct mail_index_transaction *t,
				    uint32_t seq);
bool mail_index_cancel_keyword_updates(struct mail_index_transaction *t,
				       uint32_t seq);

/* As input the array's each element starts with struct seq_range where
   uid1..uid2 are actually sequences within the transaction view. This function
   changes the sequences into UIDs. If the transaction has any appends, they
   must have already been assigned UIDs. */
void mail_index_transaction_seq_range_to_uid(struct mail_index_transaction *t,
					     ARRAY_TYPE(seq_range) *array);
void mail_index_transaction_finish_so_far(struct mail_index_transaction *t);
void mail_index_transaction_finish(struct mail_index_transaction *t);
void mail_index_transaction_export(struct mail_index_transaction *t,
				   struct mail_transaction_log_append_ctx *append_ctx,
				   enum mail_index_transaction_change *changes_r);
int mail_transaction_expunge_guid_cmp(const struct mail_transaction_expunge_guid *e1,
				      const struct mail_transaction_expunge_guid *e2);
unsigned int
mail_index_transaction_get_flag_update_pos(struct mail_index_transaction *t,
					   unsigned int left_idx,
					   unsigned int right_idx,
					   uint32_t seq);

void mail_index_ext_using_reset_id(struct mail_index_transaction *t,
				   uint32_t ext_id, uint32_t reset_id);

#endif