Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib-index/mail-modifylog.c @ 259:cdf38b5cc2b7 HEAD
still wrong..
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 16 Sep 2002 12:52:58 +0300 |
parents | 0a45c4744f51 |
children | 51eea5cbb075 |
rev | line source |
---|---|
0 | 1 /* Copyright (C) 2002 Timo Sirainen */ |
2 | |
3 #include "lib.h" | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
221
diff
changeset
|
4 #include "file-lock.h" |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
5 #include "file-set-size.h" |
0 | 6 #include "mmap-util.h" |
29
e9375147c0cb
Added write_full() which is a simple wrapper around write() meant for
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
7 #include "write-full.h" |
0 | 8 #include "mail-index.h" |
9 #include "mail-index-util.h" | |
10 #include "mail-modifylog.h" | |
11 | |
12 #include <stdlib.h> | |
13 #include <fcntl.h> | |
14 | |
15 /* Maximum size for modify log (isn't exact) */ | |
16 #define MAX_MODIFYLOG_SIZE 10240 | |
17 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
18 #define MODIFYLOG_GROW_SIZE (sizeof(ModifyLogRecord) * 128) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
19 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
20 #define MODIFY_LOG_INITIAL_SIZE (sizeof(ModifyLogHeader) + MODIFYLOG_GROW_SIZE) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
21 |
0 | 22 #define MODIFYLOG_FILE_POSITION(log, ptr) \ |
23 ((int) ((char *) (ptr) - (char *) (log)->mmap_base)) | |
24 | |
25 struct _MailModifyLog { | |
26 MailIndex *index; | |
27 | |
28 int fd; | |
29 char *filepath; | |
30 | |
31 void *mmap_base; | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
32 size_t mmap_used_length; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
33 size_t mmap_full_length; |
0 | 34 |
35 ModifyLogHeader *header; | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
36 uoff_t synced_position; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
37 unsigned int synced_id; |
0 | 38 |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
39 unsigned int anon_mmap:1; |
0 | 40 unsigned int modified:1; |
41 unsigned int second_log:1; | |
42 }; | |
43 | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
221
diff
changeset
|
44 static const unsigned int no_expunges[] = { 0 }; |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
221
diff
changeset
|
45 |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
46 static int modifylog_set_syscall_error(MailModifyLog *log, |
231
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
47 const char *function) |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
48 { |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
49 i_assert(function != NULL); |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
50 |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
51 index_set_error(log->index, "%s failed with modify log file %s: %m", |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
52 function, log->filepath); |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
53 return FALSE; |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
54 } |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
55 |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
56 static int modifylog_set_corrupted(MailModifyLog *log, const char *fmt, ...) |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
57 { |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
58 va_list va; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
59 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
60 va_start(va, fmt); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
61 t_push(); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
62 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
63 index_set_error(log->index, "Corrupted modify log file %s: %s", |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
64 log->filepath, t_strdup_vprintf(fmt, va)); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
65 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
66 t_pop(); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
67 va_end(va); |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
68 |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
69 /* make sure we don't get back here */ |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
70 log->index->inconsistent = TRUE; |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
71 (void)unlink(log->filepath); |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
199
diff
changeset
|
72 |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
73 return FALSE; |
0 | 74 } |
75 | |
76 /* returns 1 = yes, 0 = no, -1 = error */ | |
77 static int mail_modifylog_have_other_users(MailModifyLog *log) | |
78 { | |
79 int ret; | |
80 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
81 if (log->anon_mmap) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
82 return 0; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
83 |
0 | 84 /* try grabbing exclusive lock */ |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
85 ret = file_try_lock(log->fd, F_WRLCK); |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
86 if (ret <= 0) { |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
87 if (ret < 0) |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
88 modifylog_set_syscall_error(log, "file_try_lock()"); |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
89 return ret < 0 ? -1 : 1; |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
90 } |
0 | 91 |
92 /* revert back to shared lock */ | |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
93 ret = file_try_lock(log->fd, F_RDLCK); |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
94 if (ret < 0) { |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
95 modifylog_set_syscall_error(log, "file_try_lock()"); |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
96 return -1; |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
97 } |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
98 |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
99 if (ret == 0) { |
0 | 100 /* shouldn't happen */ |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
221
diff
changeset
|
101 index_set_error(log->index, "file_lock(F_WRLCK -> F_RDLCK) " |
0 | 102 "failed with file %s", log->filepath); |
103 return -1; | |
104 } | |
105 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
106 return 0; |
0 | 107 } |
108 | |
240 | 109 static int mmap_update(MailModifyLog *log, int forced) |
0 | 110 { |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
111 ModifyLogHeader *hdr; |
0 | 112 unsigned int extra; |
113 | |
240 | 114 if (!forced && log->header != NULL && |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
115 log->mmap_full_length >= log->header->used_file_size) |
0 | 116 return TRUE; |
117 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
118 i_assert(!log->anon_mmap); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
119 |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
120 if (log->mmap_base != NULL) { |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
121 /* make sure we're synced before munmap() */ |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
122 if (log->modified && |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
123 msync(log->mmap_base, log->mmap_used_length, MS_SYNC) < 0) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
124 return modifylog_set_syscall_error(log, "msync()"); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
125 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
126 if (munmap(log->mmap_base, log->mmap_full_length) < 0) |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
127 modifylog_set_syscall_error(log, "munmap()"); |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
128 } |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
129 |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
130 log->mmap_used_length = 0; |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
131 log->header = NULL; |
0 | 132 |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
133 log->mmap_base = mmap_rw_file(log->fd, &log->mmap_full_length); |
0 | 134 if (log->mmap_base == MAP_FAILED) { |
135 log->mmap_base = NULL; | |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
136 return modifylog_set_syscall_error(log, "mmap()"); |
0 | 137 } |
138 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
139 if (log->mmap_full_length < sizeof(ModifyLogHeader)) { |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
140 index_set_error(log->index, "Too small modify log %s", |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
141 log->filepath); |
0 | 142 (void)unlink(log->filepath); |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
143 return FALSE; |
0 | 144 } |
145 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
146 extra = (log->mmap_full_length - sizeof(ModifyLogHeader)) % |
0 | 147 sizeof(ModifyLogRecord); |
148 | |
149 if (extra != 0) { | |
150 /* partial write or corrupted - | |
151 truncate the file to valid length */ | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
152 log->mmap_full_length -= extra; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
153 if (ftruncate(log->fd, (off_t)log->mmap_full_length) < 0) |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
154 modifylog_set_syscall_error(log, "ftruncate()"); |
0 | 155 } |
156 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
157 hdr = log->mmap_base; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
158 if (hdr->used_file_size > log->mmap_full_length) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
159 modifylog_set_corrupted(log, |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
160 "used_file_size larger than real file size " |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
161 "(%"PRIuUOFF_T" vs %"PRIuSIZE_T")", |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
162 hdr->used_file_size, log->mmap_full_length); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
163 return FALSE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
164 } |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
165 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
166 if ((hdr->used_file_size - sizeof(ModifyLogHeader)) % |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
167 sizeof(ModifyLogRecord) != 0) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
168 modifylog_set_corrupted(log, |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
169 "Invalid used_file_size in header (%"PRIuUOFF_T")", |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
170 hdr->used_file_size); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
171 return FALSE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
172 } |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
173 |
0 | 174 log->header = log->mmap_base; |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
175 log->mmap_used_length = log->header->used_file_size; |
0 | 176 return TRUE; |
177 } | |
178 | |
179 static MailModifyLog *mail_modifylog_new(MailIndex *index) | |
180 { | |
181 MailModifyLog *log; | |
182 | |
183 log = i_new(MailModifyLog, 1); | |
184 log->fd = -1; | |
185 log->index = index; | |
186 | |
187 index->modifylog = log; | |
188 return log; | |
189 } | |
190 | |
191 static void mail_modifylog_close(MailModifyLog *log) | |
192 { | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
193 if (log->anon_mmap) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
194 if (munmap_anon(log->mmap_base, log->mmap_full_length) < 0) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
195 modifylog_set_syscall_error(log, "munmap_anon()"); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
196 } else if (log->mmap_base != NULL) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
197 if (munmap(log->mmap_base, log->mmap_full_length) < 0) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
198 modifylog_set_syscall_error(log, "munmap()"); |
0 | 199 } |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
200 log->mmap_base = NULL; |
0 | 201 |
202 if (log->fd != -1) { | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
203 if (close(log->fd) < 0) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
204 modifylog_set_syscall_error(log, "close()"); |
0 | 205 log->fd = -1; |
206 } | |
207 | |
208 i_free(log->filepath); | |
209 } | |
210 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
211 static void mail_modifylog_init_header(MailModifyLog *log, ModifyLogHeader *hdr) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
212 { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
213 memset(hdr, 0, sizeof(ModifyLogHeader)); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
214 hdr->indexid = log->index->indexid; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
215 hdr->used_file_size = sizeof(ModifyLogHeader); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
216 } |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
217 |
0 | 218 static int mail_modifylog_init_fd(MailModifyLog *log, int fd, |
219 const char *path) | |
220 { | |
221 ModifyLogHeader hdr; | |
222 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
223 mail_modifylog_init_header(log, &hdr); |
29
e9375147c0cb
Added write_full() which is a simple wrapper around write() meant for
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
224 if (write_full(fd, &hdr, sizeof(hdr)) < 0) { |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
225 if (errno == ENOSPC) |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
226 log->index->nodiskspace = TRUE; |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
227 |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
228 index_file_set_syscall_error(log->index, path, "write_full()"); |
0 | 229 return FALSE; |
230 } | |
231 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
232 if (file_set_size(fd, MODIFY_LOG_INITIAL_SIZE) < 0) { |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
233 if (errno == ENOSPC) |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
234 log->index->nodiskspace = TRUE; |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
235 |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
236 index_file_set_syscall_error(log->index, path, |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
237 "file_set_size()"); |
0 | 238 return FALSE; |
239 } | |
240 | |
241 return TRUE; | |
242 } | |
243 | |
231
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
244 static int modifylog_mark_full(MailModifyLog *log) |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
245 { |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
246 log->header->sync_id = SYNC_ID_FULL; |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
247 |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
248 if (msync(log->mmap_base, sizeof(ModifyLogHeader), MS_SYNC) < 0) |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
249 return modifylog_set_syscall_error(log, "msync()"); |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
250 |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
251 return TRUE; |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
252 } |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
253 |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
254 static int modifylog_open_and_init_file(MailModifyLog *log, const char *path) |
0 | 255 { |
256 int fd, ret; | |
257 | |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
258 if (log->index->nodiskspace) |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
259 return FALSE; |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
260 |
0 | 261 fd = open(path, O_RDWR | O_CREAT, 0660); |
262 if (fd == -1) { | |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
263 if (errno == ENOSPC) |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
264 log->index->nodiskspace = TRUE; |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
265 |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
266 return index_file_set_syscall_error(log->index, path, "open()"); |
0 | 267 } |
268 | |
257 | 269 /* if we can't get the lock, we fail. it shouldn't happen. */ |
270 ret = file_try_lock(fd, F_WRLCK); | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
271 if (ret < 0) { |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
272 index_file_set_syscall_error(log->index, path, |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
273 "file_wait_lock()"); |
257 | 274 } else if (ret == 0) { |
275 index_set_error(log->index, "Couldn't get exclusive lock for " | |
276 "created modify log %s", path); | |
0 | 277 } |
278 | |
257 | 279 if (ret > 0 && mail_modifylog_init_fd(log, fd, path)) { |
280 /* drop back to read lock */ | |
281 if (file_wait_lock(fd, F_RDLCK) < 0) { | |
282 modifylog_set_syscall_error(log, "file_wait_lock()"); | |
283 ret = -1; | |
284 } | |
285 | |
259 | 286 if (ret > 0 && (log->header == NULL || |
287 modifylog_mark_full(log))) { | |
231
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
288 mail_modifylog_close(log); |
0 | 289 |
231
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
290 log->fd = fd; |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
291 log->filepath = i_strdup(path); |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
292 return TRUE; |
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
293 } |
0 | 294 } |
295 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
296 if (close(fd) < 0) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
297 index_file_set_syscall_error(log->index, path, "close()"); |
0 | 298 return FALSE; |
299 } | |
300 | |
301 int mail_modifylog_create(MailIndex *index) | |
302 { | |
303 MailModifyLog *log; | |
304 const char *path; | |
305 | |
306 i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE); | |
307 | |
308 log = mail_modifylog_new(index); | |
309 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
310 if (index->nodiskspace) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
311 log->mmap_full_length = MODIFY_LOG_INITIAL_SIZE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
312 log->mmap_base = mmap_anon(log->mmap_full_length); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
313 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
314 mail_modifylog_init_header(log, log->mmap_base); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
315 log->header = log->mmap_base; |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
316 log->mmap_used_length = log->header->used_file_size; |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
317 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
318 log->anon_mmap = TRUE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
319 log->filepath = i_strdup("(in-memory modify log)"); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
320 } else { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
321 path = t_strconcat(log->index->filepath, ".log", NULL); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
322 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
323 if (!modifylog_open_and_init_file(log, path) || |
240 | 324 !mmap_update(log, TRUE)) { |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
325 /* fatal failure */ |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
326 mail_modifylog_free(log); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
327 return FALSE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
328 } |
0 | 329 } |
330 | |
331 log->synced_id = log->header->sync_id; | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
332 log->synced_position = log->mmap_used_length; |
0 | 333 return TRUE; |
334 } | |
335 | |
336 /* Returns 1 = ok, 0 = full, -1 = error */ | |
337 static int mail_modifylog_open_and_verify(MailModifyLog *log, const char *path) | |
338 { | |
339 ModifyLogHeader hdr; | |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
340 ssize_t ret; |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
341 int fd; |
0 | 342 |
343 fd = open(path, O_RDWR); | |
344 if (fd == -1) { | |
345 if (errno != ENOENT) { | |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
346 index_file_set_syscall_error(log->index, path, |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
347 "open()"); |
0 | 348 } |
349 return -1; | |
350 } | |
351 | |
257 | 352 if (file_wait_lock(fd, F_RDLCK) < 0) { |
353 modifylog_set_syscall_error(log, "file_wait_lock()"); | |
354 (void)close(fd); | |
355 return -1; | |
356 } | |
357 | |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
358 ret = read(fd, &hdr, sizeof(hdr)); |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
359 if (ret < 0) |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
360 index_file_set_syscall_error(log->index, path, "read()"); |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
361 else if (ret != sizeof(hdr)) { |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
362 index_set_error(log->index, "Corrupted modify log %s ", path); |
0 | 363 ret = -1; |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
364 |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
365 (void)unlink(path); |
0 | 366 } |
367 | |
258 | 368 if (ret > 0 && hdr.indexid != log->index->indexid) { |
0 | 369 index_set_error(log->index, "IndexID mismatch for modify log " |
370 "file %s", path); | |
371 ret = -1; | |
115 | 372 |
373 /* we have to rebuild it, make sure it's deleted. */ | |
374 (void)unlink(path); | |
0 | 375 } |
376 | |
258 | 377 if (ret > 0 && hdr.sync_id == SYNC_ID_FULL) { |
0 | 378 /* full */ |
379 ret = 0; | |
380 } | |
381 | |
258 | 382 if (ret > 0) { |
0 | 383 log->fd = fd; |
384 log->filepath = i_strdup(path); | |
385 } else { | |
386 (void)close(fd); | |
387 } | |
388 | |
259 | 389 return ret > 0; |
0 | 390 } |
391 | |
392 static int mail_modifylog_find_or_create(MailModifyLog *log) | |
393 { | |
394 const char *path1, *path2; | |
115 | 395 int i, ret; |
0 | 396 |
397 for (i = 0; i < 2; i++) { | |
398 /* first try <index>.log */ | |
399 path1 = t_strconcat(log->index->filepath, ".log", NULL); | |
115 | 400 path2 = t_strconcat(log->index->filepath, ".log.2", NULL); |
401 | |
402 ret = mail_modifylog_open_and_verify(log, path1); | |
403 if (ret == 1) | |
0 | 404 return TRUE; |
405 | |
115 | 406 if (ret == 0) { |
407 /* then <index>.log.2 */ | |
408 if (mail_modifylog_open_and_verify(log, path2) == 1) | |
409 return TRUE; | |
410 } | |
0 | 411 |
412 /* try creating/reusing them */ | |
231
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
413 if (modifylog_open_and_init_file(log, path1)) |
0 | 414 return TRUE; |
415 | |
231
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
416 if (modifylog_open_and_init_file(log, path2)) |
0 | 417 return TRUE; |
418 | |
419 /* maybe the file was just switched, check the logs again */ | |
420 } | |
421 | |
237
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
422 if (!log->index->nodiskspace) { |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
423 index_set_error(log->index, "We could neither use nor create " |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
424 "the modify log for index %s", |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
425 log->index->filepath); |
06d6eca0a45f
Fixes for no diskspace handling. seems to work now.
Timo Sirainen <tss@iki.fi>
parents:
234
diff
changeset
|
426 } |
0 | 427 return FALSE; |
428 } | |
429 | |
430 int mail_modifylog_open_or_create(MailIndex *index) | |
431 { | |
432 MailModifyLog *log; | |
433 | |
434 log = mail_modifylog_new(index); | |
435 | |
436 if (!mail_modifylog_find_or_create(log) || | |
240 | 437 !mmap_update(log, TRUE)) { |
0 | 438 /* fatal failure */ |
439 mail_modifylog_free(log); | |
440 return FALSE; | |
441 } | |
442 | |
443 log->synced_id = log->header->sync_id; | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
444 log->synced_position = log->mmap_used_length; |
0 | 445 return TRUE; |
446 } | |
447 | |
448 void mail_modifylog_free(MailModifyLog *log) | |
449 { | |
450 log->index->modifylog = NULL; | |
451 | |
452 mail_modifylog_close(log); | |
453 i_free(log); | |
454 } | |
455 | |
456 int mail_modifylog_sync_file(MailModifyLog *log) | |
457 { | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
458 if (!log->modified || log->anon_mmap) |
0 | 459 return TRUE; |
460 | |
461 if (log->mmap_base != NULL) { | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
462 if (msync(log->mmap_base, log->mmap_used_length, MS_SYNC) < 0) |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
463 return modifylog_set_syscall_error(log, "msync()"); |
0 | 464 } |
465 | |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
466 if (fsync(log->fd) < 0) |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
467 return modifylog_set_syscall_error(log, "fsync()"); |
0 | 468 |
469 log->modified = FALSE; | |
470 return TRUE; | |
471 } | |
472 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
473 static int mail_modifylog_grow(MailModifyLog *log) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
474 { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
475 uoff_t new_fsize; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
476 void *base; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
477 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
478 new_fsize = (uoff_t)log->mmap_full_length + MODIFYLOG_GROW_SIZE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
479 i_assert(new_fsize < OFF_T_MAX); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
480 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
481 if (log->anon_mmap) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
482 i_assert(new_fsize < SSIZE_T_MAX); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
483 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
484 base = mremap_anon(log->mmap_base, log->mmap_full_length, |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
485 (size_t)new_fsize, MREMAP_MAYMOVE); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
486 if (base == MAP_FAILED) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
487 modifylog_set_syscall_error(log, "mremap_anon()"); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
488 return FALSE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
489 } |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
490 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
491 log->mmap_base = base; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
492 log->mmap_full_length = (size_t)new_fsize; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
493 return TRUE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
494 } |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
495 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
496 if (file_set_size(log->fd, (off_t)new_fsize) < 0) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
497 if (errno == ENOSPC) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
498 log->index->nodiskspace = TRUE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
499 return modifylog_set_syscall_error(log, "file_set_size()"); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
500 } |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
501 |
240 | 502 if (!mmap_update(log, TRUE)) |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
503 return FALSE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
504 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
505 return TRUE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
506 } |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
507 |
0 | 508 static int mail_modifylog_append(MailModifyLog *log, ModifyLogRecord *rec, |
509 int external_change) | |
510 { | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
511 ModifyLogRecord *destrec; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
512 |
0 | 513 i_assert(log->index->lock_type == MAIL_LOCK_EXCLUSIVE); |
514 i_assert(rec->seq != 0); | |
515 i_assert(rec->uid != 0); | |
516 | |
517 if (!external_change) { | |
518 switch (mail_modifylog_have_other_users(log)) { | |
519 case 0: | |
520 /* we're the only one having this log open, | |
521 no need for modify log. */ | |
522 return TRUE; | |
523 case -1: | |
524 return FALSE; | |
525 } | |
526 } | |
527 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
528 if (log->mmap_used_length == log->mmap_full_length) { |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
529 if (!mail_modifylog_grow(log)) |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
530 return FALSE; |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
531 } |
0 | 532 |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
533 i_assert(log->header->used_file_size == log->mmap_used_length); |
240 | 534 i_assert(log->mmap_used_length + sizeof(ModifyLogRecord) <= |
535 log->mmap_full_length); | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
536 |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
537 destrec = (ModifyLogRecord *) ((char *) log->mmap_base + |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
538 log->mmap_used_length); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
539 memcpy(destrec, rec, sizeof(ModifyLogRecord)); |
223
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
540 |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
541 if (!external_change && log->header->sync_id == log->synced_id) { |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
542 log->synced_position += sizeof(ModifyLogRecord); |
ca6967899c05
More cleanups. lib-storage should handle "out of disk space" conditions
Timo Sirainen <tss@iki.fi>
parents:
222
diff
changeset
|
543 log->synced_id++; |
0 | 544 } |
545 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
546 log->header->used_file_size += sizeof(ModifyLogRecord); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
547 log->mmap_used_length += sizeof(ModifyLogRecord); |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
548 |
0 | 549 log->header->sync_id++; |
550 log->modified = TRUE; | |
551 | |
552 return TRUE; | |
553 } | |
554 | |
555 int mail_modifylog_add_expunge(MailModifyLog *log, unsigned int seq, | |
556 unsigned int uid, int external_change) | |
557 { | |
558 ModifyLogRecord rec; | |
559 | |
560 /* expunges must not be added when log isn't synced */ | |
561 i_assert(external_change || log->synced_id == log->header->sync_id); | |
562 | |
563 rec.type = RECORD_TYPE_EXPUNGE; | |
564 rec.seq = seq; | |
565 rec.uid = uid; | |
566 return mail_modifylog_append(log, &rec, external_change); | |
567 } | |
568 | |
569 int mail_modifylog_add_flags(MailModifyLog *log, unsigned int seq, | |
570 unsigned int uid, int external_change) | |
571 { | |
572 ModifyLogRecord rec; | |
573 | |
574 rec.type = RECORD_TYPE_FLAGS_CHANGED; | |
575 rec.seq = seq; | |
576 rec.uid = uid; | |
577 return mail_modifylog_append(log, &rec, external_change); | |
578 } | |
579 | |
580 ModifyLogRecord *mail_modifylog_get_nonsynced(MailModifyLog *log, | |
581 unsigned int *count) | |
582 { | |
583 ModifyLogRecord *rec, *end_rec; | |
584 | |
585 i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK); | |
586 | |
587 *count = 0; | |
240 | 588 if (!mmap_update(log, FALSE)) |
0 | 589 return NULL; |
590 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
591 i_assert(log->synced_position <= log->mmap_used_length); |
0 | 592 i_assert(log->synced_position >= sizeof(ModifyLogHeader)); |
593 | |
594 rec = (ModifyLogRecord *) ((char *) log->mmap_base + | |
595 log->synced_position); | |
596 end_rec = (ModifyLogRecord *) ((char *) log->mmap_base + | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
597 log->mmap_used_length); |
0 | 598 *count = (unsigned int) (end_rec - rec); |
599 return rec; | |
600 } | |
601 | |
602 static int mail_modifylog_switch_file(MailModifyLog *log) | |
603 { | |
604 MailIndex *index = log->index; | |
605 | |
606 mail_modifylog_free(log); | |
607 return mail_modifylog_open_or_create(index); | |
608 } | |
609 | |
610 static void mail_modifylog_try_switch_file(MailModifyLog *log) | |
611 { | |
612 const char *path; | |
613 | |
614 path = t_strconcat(log->index->filepath, | |
615 log->second_log ? ".log" : ".log.2", NULL); | |
616 | |
231
bbd248788571
we shouldn't crash anymore when modify log gets full
Timo Sirainen <tss@iki.fi>
parents:
223
diff
changeset
|
617 (void)modifylog_open_and_init_file(log, path); |
0 | 618 } |
619 | |
620 int mail_modifylog_mark_synced(MailModifyLog *log) | |
621 { | |
622 i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK); | |
623 | |
240 | 624 if (!mmap_update(log, FALSE)) |
90
ccb155c2c93f
mail_modifylog_mark_synced() didn't update mmap
Timo Sirainen <tss@iki.fi>
parents:
50
diff
changeset
|
625 return FALSE; |
ccb155c2c93f
mail_modifylog_mark_synced() didn't update mmap
Timo Sirainen <tss@iki.fi>
parents:
50
diff
changeset
|
626 |
0 | 627 if (log->header->sync_id == SYNC_ID_FULL) { |
628 /* log file is full, switch to next one */ | |
629 return mail_modifylog_switch_file(log); | |
630 } | |
631 | |
632 if (log->synced_id == log->header->sync_id) { | |
633 /* we are already synced */ | |
634 return TRUE; | |
635 } | |
636 | |
637 log->synced_id = log->header->sync_id; | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
638 log->synced_position = log->mmap_used_length; |
0 | 639 |
640 log->modified = TRUE; | |
641 | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
642 if (log->mmap_used_length > MAX_MODIFYLOG_SIZE) { |
0 | 643 /* if the other file isn't locked, switch to it */ |
644 mail_modifylog_try_switch_file(log); | |
645 return TRUE; | |
646 } | |
647 | |
648 return TRUE; | |
649 } | |
650 | |
651 static int compare_uint(const void *p1, const void *p2) | |
652 { | |
653 const unsigned int *u1 = p1; | |
654 const unsigned int *u2 = p2; | |
655 | |
656 return *u1 < *u2 ? -1 : *u1 > *u2 ? 1 : 0; | |
657 } | |
658 | |
659 const unsigned int * | |
660 mail_modifylog_seq_get_expunges(MailModifyLog *log, | |
661 unsigned int first_seq, | |
662 unsigned int last_seq, | |
663 unsigned int *expunges_before) | |
664 { | |
665 ModifyLogRecord *rec, *end_rec; | |
666 unsigned int last_pos_seq, before, max_records, *arr, *expunges; | |
667 | |
668 i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK); | |
669 | |
670 *expunges_before = 0; | |
671 | |
240 | 672 if (!mmap_update(log, FALSE)) |
0 | 673 return NULL; |
674 | |
675 /* find the first expunged message that affects our range */ | |
676 rec = (ModifyLogRecord *) ((char *) log->mmap_base + | |
677 log->synced_position); | |
678 end_rec = (ModifyLogRecord *) ((char *) log->mmap_base + | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
679 log->mmap_used_length); |
0 | 680 |
681 while (rec < end_rec) { | |
682 if (rec->type == RECORD_TYPE_EXPUNGE && rec->seq <= last_seq) | |
683 break; | |
684 rec++; | |
685 } | |
686 | |
687 if (rec >= end_rec) { | |
688 /* none found */ | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
221
diff
changeset
|
689 return no_expunges; |
0 | 690 } |
691 | |
692 /* allocate memory for the returned array. the file size - synced | |
693 position should be quite near the amount of memory we need, unless | |
694 there's lots of FLAGS_CHANGED records which is why there's the | |
695 second check to make sure it's not unneededly large. */ | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
696 max_records = (log->mmap_used_length - |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
697 MODIFYLOG_FILE_POSITION(log, rec)) / |
0 | 698 sizeof(ModifyLogRecord); |
699 if (max_records > last_seq - first_seq + 1) | |
700 max_records = last_seq - first_seq + 1; | |
701 | |
702 expunges = arr = t_malloc((max_records+1) * sizeof(unsigned int)); | |
703 | |
704 /* last_pos_seq is updated all the time to contain the last_seq | |
705 comparable to current record's seq. number */ | |
706 last_pos_seq = last_seq; | |
707 | |
708 before = 0; | |
709 for (; rec < end_rec; rec++) { | |
710 if (rec->type != RECORD_TYPE_EXPUNGE) | |
711 continue; | |
712 | |
713 if (rec->seq + before < first_seq) { | |
714 /* before our range */ | |
715 before++; | |
716 last_pos_seq--; | |
717 } else if (rec->seq <= last_pos_seq) { | |
718 /* within our range */ | |
719 last_pos_seq--; | |
720 | |
721 if (max_records-- == 0) { | |
722 /* log contains more data than it should | |
723 have - must be corrupted. */ | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
724 modifylog_set_corrupted(log, |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
725 "Contains more data than expected"); |
0 | 726 return NULL; |
727 } | |
728 | |
729 *arr++ = rec->uid; | |
730 } | |
731 } | |
732 *arr = 0; | |
733 | |
734 /* sort the UID array, not including the terminating 0 */ | |
735 qsort(expunges, (unsigned int) (arr - expunges), sizeof(unsigned int), | |
736 compare_uint); | |
737 | |
738 *expunges_before = before; | |
739 return expunges; | |
740 } | |
741 | |
742 const unsigned int * | |
743 mail_modifylog_uid_get_expunges(MailModifyLog *log, | |
744 unsigned int first_uid, | |
745 unsigned int last_uid) | |
746 { | |
747 /* pretty much copy&pasted from sequence code above .. | |
748 kind of annoying */ | |
749 ModifyLogRecord *rec, *end_rec; | |
750 unsigned int before, max_records, *arr, *expunges; | |
751 | |
752 i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK); | |
753 | |
240 | 754 if (!mmap_update(log, FALSE)) |
0 | 755 return NULL; |
756 | |
757 /* find the first expunged message that affects our range */ | |
758 rec = (ModifyLogRecord *) ((char *) log->mmap_base + | |
759 log->synced_position); | |
760 end_rec = (ModifyLogRecord *) ((char *) log->mmap_base + | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
761 log->mmap_used_length); |
0 | 762 |
763 while (rec < end_rec) { | |
764 if (rec->type == RECORD_TYPE_EXPUNGE && rec->uid <= last_uid) | |
765 break; | |
766 rec++; | |
767 } | |
768 | |
769 if (rec >= end_rec) { | |
770 /* none found */ | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
221
diff
changeset
|
771 return no_expunges; |
0 | 772 } |
773 | |
774 /* allocate memory for the returned array. the file size - synced | |
775 position should be quite near the amount of memory we need, unless | |
776 there's lots of FLAGS_CHANGED records which is why there's the | |
777 second check to make sure it's not unneededly large. */ | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
778 max_records = (log->mmap_used_length - |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
779 MODIFYLOG_FILE_POSITION(log, rec)) / |
0 | 780 sizeof(ModifyLogRecord); |
781 if (max_records > last_uid - first_uid + 1) | |
782 max_records = last_uid - first_uid + 1; | |
783 | |
784 expunges = arr = t_malloc((max_records+1) * sizeof(unsigned int)); | |
785 | |
786 before = 0; | |
787 while (rec < end_rec) { | |
788 if (rec->type == RECORD_TYPE_EXPUNGE && | |
789 rec->uid >= first_uid && rec->uid <= last_uid) { | |
790 /* within our range */ | |
791 if (max_records-- == 0) { | |
792 /* log contains more data than it should | |
793 have - must be corrupted. */ | |
234
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
794 modifylog_set_corrupted(log, |
aef7c7a8f691
Modify log is now able to stay in memory. Some other fixes/cleanups.
Timo Sirainen <tss@iki.fi>
parents:
231
diff
changeset
|
795 "Contains more data than expected"); |
0 | 796 return NULL; |
797 } | |
798 *arr++ = rec->uid; | |
799 } | |
800 rec++; | |
801 } | |
802 *arr = 0; | |
803 | |
804 /* sort the UID array, not including the terminating 0 */ | |
805 qsort(expunges, (unsigned int) (arr - expunges), sizeof(unsigned int), | |
806 compare_uint); | |
807 | |
808 return expunges; | |
809 } |