Commit 29a5598a 29a5598ab4ccdb0c9a6646f26932cc37889a781d by Sergey Poznyakoff

imap4d: speed up asynchronous mailbox notifications.

* imap4d/imap4d.h (util_format_attribute_flags): New prototype.
* imap4d/sync.c: Rewrite using flag table to keep attribute flags,
mu_mailbox_translate to convert uids to message numbers and
MU_EVT_MAILBOX_MESSAGE_EXPUNGE event to report expunged messages.
* imap4d/util.c  (_imap4d_attrlist): Remove \Recent
(util_attribute_to_type): Handle \Recent separately.
(util_format_attribute_flags): New function.
(util_print_flags): Rewrite as an extra entry point to the above.

mailboxes: New event MU_EVT_MAILBOX_MESSAGE_EXPUNGE.

* include/mailutils/observer.h: Rearrange and partially rename
event constants (all uses updated):
MU_EVT_MESSAGE_APPEND   =>   MU_EVT_MAILBOX_MESSAGE_APPEND
MU_EVT_AUTHORITY_FAILED =>   MU_EVT_FOLDER_AUTHORITY_FAILED
(MU_EVT_MAILBOX_MESSAGE_EXPUNGE): New event.
* libproto/mbox/mbox.c: Generate MU_EVT_MAILBOX_MESSAGE_EXPUNGE.
* libproto/pop/mbox.c: Likewise.
* libmailutils/base/amd.c: Likewise.
1 parent d8554009
...@@ -370,6 +370,7 @@ extern char *util_localname (void); ...@@ -370,6 +370,7 @@ extern char *util_localname (void);
370 370
371 extern int util_wcard_match (const char *string, const char *pattern, 371 extern int util_wcard_match (const char *string, const char *pattern,
372 const char *delim); 372 const char *delim);
373 int util_format_attribute_flags (mu_stream_t str, int flags);
373 void util_print_flags (mu_attribute_t attr); 374 void util_print_flags (mu_attribute_t attr);
374 int util_attribute_to_type (const char *item, int *type); 375 int util_attribute_to_type (const char *item, int *type);
375 int util_type_to_attribute (int type, char **attr_str); 376 int util_type_to_attribute (int type, char **attr_str);
......
...@@ -21,163 +21,24 @@ ...@@ -21,163 +21,24 @@
21 /* 21 /*
22 22
23 */ 23 */
24 struct _uid_table 24 static int *attr_table;
25 { 25 static size_t attr_table_count;
26 size_t uid; 26 static int attr_table_loaded;
27 size_t msgno;
28 int notify;
29 mu_attribute_t attr;
30 };
31
32 static struct _uid_table *uid_table;
33 static size_t uid_table_count;
34 static int uid_table_loaded;
35
36 static void
37 add_flag (char **pbuf, const char *f)
38 {
39 char *abuf = *pbuf;
40 abuf = realloc (abuf, strlen (abuf) + strlen (f) + 2);
41 if (abuf == NULL)
42 imap4d_bye (ERR_NO_MEM);
43 if (*abuf)
44 strcat (abuf, " ");
45 strcat (abuf, "\\Seen");
46 *pbuf = abuf;
47 }
48
49 static void
50 notify_flag (size_t msgno, mu_attribute_t oattr)
51 {
52 mu_message_t msg = NULL;
53 mu_attribute_t nattr = NULL;
54 int status ;
55 mu_mailbox_get_message (mbox, msgno, &msg);
56 mu_message_get_attribute (msg, &nattr);
57 status = mu_attribute_is_equal (oattr, nattr);
58
59 if (status == 0)
60 {
61 char *abuf = malloc (1);;
62 if (!abuf)
63 imap4d_bye (ERR_NO_MEM);
64 *abuf = '\0';
65 if (mu_attribute_is_seen (nattr) && mu_attribute_is_read (nattr))
66 if (!mu_attribute_is_seen (oattr) && !mu_attribute_is_read (oattr))
67 {
68 mu_attribute_set_seen (oattr);
69 mu_attribute_set_read (oattr);
70 add_flag (&abuf, "\\Seen");
71 }
72 if (mu_attribute_is_answered (nattr))
73 if (!mu_attribute_is_answered (oattr))
74 {
75 mu_attribute_set_answered (oattr);
76 add_flag (&abuf, "\\Answered");
77 }
78 if (mu_attribute_is_flagged (nattr))
79 if (!mu_attribute_is_flagged (oattr))
80 {
81 mu_attribute_set_flagged (oattr);
82 add_flag (&abuf, "\\Flagged");
83 }
84 if (mu_attribute_is_deleted (nattr))
85 if (!mu_attribute_is_deleted (oattr))
86 {
87 mu_attribute_set_deleted (oattr);
88 add_flag (&abuf, "\\Deleted");
89 }
90 if (mu_attribute_is_draft (nattr))
91 if (!mu_attribute_is_draft (oattr))
92 {
93 mu_attribute_set_draft (oattr);
94 add_flag (&abuf, "\\Draft");
95 }
96 if (mu_attribute_is_recent (nattr))
97 if (!mu_attribute_is_recent (oattr))
98 {
99 mu_attribute_set_recent (oattr);
100 add_flag (&abuf, "\\Recent");
101 }
102 if (*abuf)
103 io_untagged_response (RESP_NONE, "%lu FETCH FLAGS (%s)",
104 (unsigned long) msgno, abuf);
105 free (abuf);
106 }
107 }
108
109 /* The EXPUNGE response reports that the specified message sequence
110 number has been permanently removed from the mailbox. The message
111 sequence number for each successive message in the mailbox is
112 immediately decremented by 1, and this decrement is reflected in
113 message sequence numbers in subsequent responses (including other
114 untagged EXPUNGE responses). */
115 static void
116 notify_deleted (void)
117 {
118 if (uid_table)
119 {
120 size_t i;
121 size_t decr = 0;
122 for (i = 0; i < uid_table_count; i++)
123 {
124 if (!(uid_table[i].notify))
125 {
126 io_untagged_response (RESP_NONE, "%lu EXPUNGED",
127 (unsigned long) uid_table[i].msgno-decr);
128 uid_table[i].notify = 1;
129 decr++;
130 }
131 }
132 }
133 }
134
135
136 static int
137 notify_uid (size_t uid)
138 {
139 if (uid_table)
140 {
141 size_t i;
142 for (i = 0; i < uid_table_count; i++)
143 {
144 if (uid_table[i].uid == uid)
145 {
146 notify_flag (uid_table[i].msgno, uid_table[i].attr);
147 uid_table[i].notify = 1;
148 return 1;
149 }
150 }
151 }
152 return 0;
153 }
154 27
155 static void 28 static void
156 free_uids (void) 29 free_uids (void)
157 { 30 {
158 if (uid_table) 31 if (attr_table)
159 { 32 {
160 size_t i; 33 free (attr_table);
161 for (i = 0; i < uid_table_count; i++) 34 attr_table = NULL;
162 mu_attribute_destroy (&(uid_table[i].attr), NULL);
163 free (uid_table);
164 uid_table = NULL;
165 } 35 }
166 uid_table_count = 0; 36 attr_table_count = 0;
167 uid_table_loaded = 0; 37 attr_table_loaded = 0;
168 }
169
170 static void
171 reset_notify (void)
172 {
173 size_t i;
174
175 for (i = 0; i < uid_table_count; i++)
176 uid_table[i].notify = 0;
177 } 38 }
178 39
179 static void 40 static void
180 reset_uids (void) 41 reread_attributes (void)
181 { 42 {
182 size_t total = 0; 43 size_t total = 0;
183 size_t i; 44 size_t i;
...@@ -185,26 +46,24 @@ reset_uids (void) ...@@ -185,26 +46,24 @@ reset_uids (void)
185 free_uids (); 46 free_uids ();
186 47
187 mu_mailbox_messages_count (mbox, &total); 48 mu_mailbox_messages_count (mbox, &total);
49 if (total > attr_table_count)
50 {
51 attr_table = realloc (attr_table, sizeof (*attr_table) * total);
52 if (!attr_table)
53 imap4d_bye (ERR_NO_MEM);
54 attr_table_count = total;
55 }
56
188 for (i = 1; i <= total; i++) 57 for (i = 1; i <= total; i++)
189 { 58 {
190 mu_message_t msg = NULL; 59 mu_message_t msg = NULL;
191 mu_attribute_t attr = NULL; 60 mu_attribute_t attr = NULL;
192 size_t uid = 0; 61
193 uid_table = realloc (uid_table, sizeof (*uid_table) *
194 (uid_table_count + 1));
195 if (!uid_table)
196 imap4d_bye (ERR_NO_MEM);
197 mu_mailbox_get_message (mbox, i, &msg); 62 mu_mailbox_get_message (mbox, i, &msg);
198 mu_message_get_attribute (msg, &attr); 63 mu_message_get_attribute (msg, &attr);
199 mu_message_get_uid (msg, &uid); 64 mu_attribute_get_flags (attr, &attr_table[i-1]);
200 uid_table[uid_table_count].uid = uid;
201 uid_table[uid_table_count].msgno = i;
202 uid_table[uid_table_count].notify = 0;
203 mu_attribute_create (&(uid_table[uid_table_count].attr), NULL);
204 mu_attribute_copy (uid_table[uid_table_count].attr, attr);
205 uid_table_count++;
206 } 65 }
207 uid_table_loaded = 1; 66 attr_table_loaded = 1;
208 } 67 }
209 68
210 static void 69 static void
...@@ -216,25 +75,34 @@ notify (void) ...@@ -216,25 +75,34 @@ notify (void)
216 75
217 mu_mailbox_messages_count (mbox, &total); 76 mu_mailbox_messages_count (mbox, &total);
218 77
219 if (!uid_table) 78 if (!attr_table)
220 { 79 {
221 reset = 1; 80 reset = 1;
222 reset_uids (); 81 reread_attributes ();
82 mu_mailbox_messages_recent (mbox, &recent);
223 } 83 }
224 84 else if (attr_table)
225 if (uid_table)
226 { 85 {
227 size_t i; 86 size_t i;
228 87
229 for (i = 1; i <= total; i++) 88 for (i = 1; i <= total; i++)
230 { 89 {
231 mu_message_t msg = NULL; 90 mu_message_t msg = NULL;
232 size_t uid = 0; 91 mu_attribute_t nattr = NULL;
92 int nflags;
93
233 mu_mailbox_get_message (mbox, i, &msg); 94 mu_mailbox_get_message (mbox, i, &msg);
234 mu_message_get_uid (msg, &uid); 95 mu_message_get_attribute (msg, &nattr);
235 notify_uid (uid); 96 mu_attribute_get_flags (nattr, &nflags);
97
98 if (nflags != attr_table[i-1])
99 {
100 io_sendf ("* %lu FETCH FLAGS (", (unsigned long) i);
101 util_format_attribute_flags (iostream, nflags);
102 io_sendf (")\n");
103 attr_table[i-1] = nflags;
104 }
236 } 105 }
237 notify_deleted ();
238 mu_mailbox_messages_recent (mbox, &recent); 106 mu_mailbox_messages_recent (mbox, &recent);
239 } 107 }
240 108
...@@ -242,35 +110,28 @@ notify (void) ...@@ -242,35 +110,28 @@ notify (void)
242 io_untagged_response (RESP_NONE, "%lu RECENT", (unsigned long) recent); 110 io_untagged_response (RESP_NONE, "%lu RECENT", (unsigned long) recent);
243 111
244 if (!reset) 112 if (!reset)
245 reset_uids (); 113 reread_attributes ();
246 else
247 reset_notify ();
248 } 114 }
249 115
250 size_t 116 size_t
251 uid_to_msgno (size_t uid) 117 uid_to_msgno (size_t uid)
252 { 118 {
253 size_t i; 119 size_t msgno;
254 for (i = 0; i < uid_table_count; i++) 120 mu_mailbox_translate (mbox, MU_MAILBOX_UID_TO_MSGNO, uid, &msgno);
255 if (uid_table[i].uid == uid) 121 return msgno;
256 return uid_table[i].msgno;
257 return 0;
258 } 122 }
259 123
260 int 124 int
261 imap4d_sync_flags (size_t msgno) 125 imap4d_sync_flags (size_t msgno)
262 { 126 {
263 size_t i; 127 if (attr_table)
264 for (i = 0; i < uid_table_count; i++) 128 {
265 if (uid_table[i].msgno == msgno) 129 mu_message_t msg = NULL;
266 { 130 mu_attribute_t attr = NULL;
267 mu_message_t msg = NULL; 131 mu_mailbox_get_message (mbox, msgno, &msg);
268 mu_attribute_t attr = NULL; 132 mu_message_get_attribute (msg, &attr);
269 mu_mailbox_get_message (mbox, msgno, &msg); 133 mu_attribute_get_flags (attr, &attr_table[msgno-1]);
270 mu_message_get_attribute (msg, &attr); 134 }
271 mu_attribute_copy (uid_table[i].attr, attr);
272 break;
273 }
274 return 0; 135 return 0;
275 } 136 }
276 137
...@@ -288,6 +149,19 @@ action (mu_observer_t observer, size_t type, void *data, void *action_data) ...@@ -288,6 +149,19 @@ action (mu_observer_t observer, size_t type, void *data, void *action_data)
288 case MU_EVT_MAILBOX_DESTROY: 149 case MU_EVT_MAILBOX_DESTROY:
289 mailbox_corrupt = 0; 150 mailbox_corrupt = 0;
290 break; 151 break;
152
153 case MU_EVT_MAILBOX_MESSAGE_EXPUNGE:
154 /* The EXPUNGE response reports that the specified message sequence
155 number has been permanently removed from the mailbox. The message
156 sequence number for each successive message in the mailbox is
157 immediately decremented by 1, and this decrement is reflected in
158 message sequence numbers in subsequent responses (including other
159 untagged EXPUNGE responses). */
160 {
161 size_t *exp = data;
162 io_untagged_response (RESP_NONE, "%lu EXPUNGED",
163 (unsigned long) (exp[0] - exp[1]));
164 }
291 } 165 }
292 return 0; 166 return 0;
293 } 167 }
...@@ -301,8 +175,11 @@ imap4d_set_observer (mu_mailbox_t mbox) ...@@ -301,8 +175,11 @@ imap4d_set_observer (mu_mailbox_t mbox)
301 mu_observer_create (&observer, mbox); 175 mu_observer_create (&observer, mbox);
302 mu_observer_set_action (observer, action, mbox); 176 mu_observer_set_action (observer, action, mbox);
303 mu_mailbox_get_observable (mbox, &observable); 177 mu_mailbox_get_observable (mbox, &observable);
304 mu_observable_attach (observable, MU_EVT_MAILBOX_CORRUPT|MU_EVT_MAILBOX_DESTROY, 178 mu_observable_attach (observable,
305 observer); 179 MU_EVT_MAILBOX_CORRUPT|
180 MU_EVT_MAILBOX_DESTROY|
181 MU_EVT_MAILBOX_MESSAGE_EXPUNGE,
182 observer);
306 mailbox_corrupt = 0; 183 mailbox_corrupt = 0;
307 } 184 }
308 185
...@@ -314,7 +191,7 @@ imap4d_sync (void) ...@@ -314,7 +191,7 @@ imap4d_sync (void)
314 If it was a close we do not send any notification. */ 191 If it was a close we do not send any notification. */
315 if (mbox == NULL) 192 if (mbox == NULL)
316 free_uids (); 193 free_uids ();
317 else if (!uid_table_loaded || !mu_mailbox_is_updated (mbox)) 194 else if (!attr_table_loaded || !mu_mailbox_is_updated (mbox))
318 { 195 {
319 if (mailbox_corrupt) 196 if (mailbox_corrupt)
320 { 197 {
...@@ -338,7 +215,7 @@ imap4d_sync (void) ...@@ -338,7 +215,7 @@ imap4d_sync (void)
338 { 215 {
339 size_t count = 0; 216 size_t count = 0;
340 mu_mailbox_messages_count (mbox, &count); 217 mu_mailbox_messages_count (mbox, &count);
341 if (count != uid_table_count) 218 if (count != attr_table_count)
342 notify (); 219 notify ();
343 } 220 }
344 return 0; 221 return 0;
......
...@@ -402,8 +402,7 @@ _imap4d_attrlist[] = ...@@ -402,8 +402,7 @@ _imap4d_attrlist[] =
402 { "\\Flagged", MU_ATTRIBUTE_FLAGGED }, 402 { "\\Flagged", MU_ATTRIBUTE_FLAGGED },
403 { "\\Deleted", MU_ATTRIBUTE_DELETED }, 403 { "\\Deleted", MU_ATTRIBUTE_DELETED },
404 { "\\Draft", MU_ATTRIBUTE_DRAFT }, 404 { "\\Draft", MU_ATTRIBUTE_DRAFT },
405 { "\\Seen", MU_ATTRIBUTE_READ }, 405 { "\\Seen", MU_ATTRIBUTE_SEEN|MU_ATTRIBUTE_READ },
406 { "\\Recent", MU_ATTRIBUTE_RECENT },
407 }; 406 };
408 407
409 #define NATTR sizeof(_imap4d_attrlist)/sizeof(_imap4d_attrlist[0]) 408 #define NATTR sizeof(_imap4d_attrlist)/sizeof(_imap4d_attrlist[0])
...@@ -414,6 +413,13 @@ int ...@@ -414,6 +413,13 @@ int
414 util_attribute_to_type (const char *item, int *type) 413 util_attribute_to_type (const char *item, int *type)
415 { 414 {
416 int i; 415 int i;
416
417 if (mu_c_strcasecmp (item, "\\Recent") == 0)
418 {
419 *type = MU_ATTRIBUTE_RECENT;
420 return 0;
421 }
422
417 for (i = 0; i < _imap4d_nattr; i++) 423 for (i = 0; i < _imap4d_nattr; i++)
418 if (mu_c_strcasecmp (item, _imap4d_attrlist[i].name) == 0) 424 if (mu_c_strcasecmp (item, _imap4d_attrlist[i].name) == 0)
419 { 425 {
...@@ -423,68 +429,38 @@ util_attribute_to_type (const char *item, int *type) ...@@ -423,68 +429,38 @@ util_attribute_to_type (const char *item, int *type)
423 return 1; 429 return 1;
424 } 430 }
425 431
426 /* Note: currently unused. Not needed, possibly? */
427 int 432 int
428 util_type_to_attribute (int type, char **attr_str) 433 util_format_attribute_flags (mu_stream_t str, int flags)
429 { 434 {
430 char *attr_list[NATTR];
431 int nattr = 0;
432 int i; 435 int i;
433 size_t len = 0; 436 int delim = 0;
434 437
435 if (MU_ATTRIBUTE_IS_UNSEEN (type))
436 *attr_str = strdup ("\\Recent");
437 else
438 *attr_str = NULL;
439
440 for (i = 0; i < _imap4d_nattr; i++) 438 for (i = 0; i < _imap4d_nattr; i++)
441 if (type & _imap4d_attrlist[i].flag) 439 if (flags & _imap4d_attrlist[i].flag)
442 { 440 {
443 attr_list[nattr++] = _imap4d_attrlist[i].name; 441 if (delim)
444 len += 1 + strlen (_imap4d_attrlist[i].name); 442 mu_stream_printf (str, " ");
443 mu_stream_printf (str, "%s", _imap4d_attrlist[i].name);
444 delim = 1;
445 } 445 }
446 446
447 *attr_str = malloc (len + 1); 447 if (MU_ATTRIBUTE_IS_UNSEEN (flags))
448 (*attr_str)[0] = 0;
449 if (*attr_str)
450 { 448 {
451 for (i = 0; i < nattr; i++) 449 if (delim)
452 { 450 mu_stream_printf (str, " ");
453 strcat (*attr_str, attr_list[i]); 451 mu_stream_printf (str, "\\Recent");
454 if (i != nattr - 1)
455 strcat (*attr_str, " ");
456 }
457 } 452 }
458 453
459 if (!*attr_str)
460 imap4d_bye (ERR_NO_MEM);
461 return 0; 454 return 0;
462 } 455 }
463 456
464 void 457 void
465 util_print_flags (mu_attribute_t attr) 458 util_print_flags (mu_attribute_t attr)
466 { 459 {
467 int i;
468 int flags = 0; 460 int flags = 0;
469 int space = 0;
470 461
471 mu_attribute_get_flags (attr, &flags); 462 mu_attribute_get_flags (attr, &flags);
472 for (i = 0; i < _imap4d_nattr; i++) 463 util_format_attribute_flags (iostream, flags);
473 if (flags & _imap4d_attrlist[i].flag)
474 {
475 if (space)
476 io_sendf (" ");
477 else
478 space = 1;
479 io_sendf (_imap4d_attrlist[i].name);
480 }
481
482 if (MU_ATTRIBUTE_IS_UNSEEN (flags))
483 {
484 if (space)
485 io_sendf (" ");
486 io_sendf ("\\Recent");
487 }
488 } 464 }
489 465
490 int 466 int
......
...@@ -24,17 +24,26 @@ ...@@ -24,17 +24,26 @@
24 #ifdef __cplusplus 24 #ifdef __cplusplus
25 extern "C" { 25 extern "C" {
26 #endif 26 #endif
27 /* Call data type: */ 27 /* Mailbox events */
28 #define MU_EVT_MAILBOX_DESTROY 0x001 /* mu_mailbox_t */ 28 /* Call data type: */
29 #define MU_EVT_FOLDER_DESTROY 0x002 /* mu_folder_t */ 29 #define MU_EVT_MAILBOX_DESTROY 0x001 /* mu_mailbox_t */
30 #define MU_EVT_MAILER_DESTROY 0x004 /* mu_mailer_t */ 30 #define MU_EVT_MAILBOX_PROGRESS 0x002 /* NULL: FIXME? */
31 #define MU_EVT_MESSAGE_DESTROY 0x008 /* mu_message_t */ 31 #define MU_EVT_MAILBOX_CORRUPT 0x004 /* mu_mailbox_t */
32 #define MU_EVT_MESSAGE_ADD 0x010 /* size_t *: FIXME */ 32 #define MU_EVT_MAILBOX_MESSAGE_APPEND 0x008 /* mu_message_qid_t: FIXME */
33 #define MU_EVT_MAILBOX_PROGRESS 0x020 /* NULL: FIXME? */ 33 #define MU_EVT_MAILBOX_MESSAGE_EXPUNGE 0x010 /* size_t [2]
34 #define MU_EVT_AUTHORITY_FAILED 0x030 /* NULL */ 34 (message number/number of
35 #define MU_EVT_MAILBOX_CORRUPT 0x040 /* mu_mailbox_t */ 35 messages removed so far) */
36 #define MU_EVT_MAILER_MESSAGE_SENT 0x080 /* mu_message_t */ 36 /* Folder events */
37 #define MU_EVT_MESSAGE_APPEND 0x100 /* mu_message_qid_t: FIXME */ 37 #define MU_EVT_FOLDER_DESTROY 0x020 /* mu_folder_t */
38 #define MU_EVT_FOLDER_AUTHORITY_FAILED 0x040 /* NULL */
39
40 /* Message events */
41 #define MU_EVT_MESSAGE_DESTROY 0x080 /* mu_message_t */
42 #define MU_EVT_MESSAGE_ADD 0x100 /* size_t *: FIXME */
43
44 /* Mailer events */
45 #define MU_EVT_MAILER_DESTROY 0x200 /* mu_mailer_t */
46 #define MU_EVT_MAILER_MESSAGE_SENT 0x400 /* mu_message_t */
38 47
39 #define MU_OBSERVER_NO_CHECK 1 48 #define MU_OBSERVER_NO_CHECK 1
40 49
......
...@@ -900,7 +900,8 @@ amd_append_message (mu_mailbox_t mailbox, mu_message_t msg) ...@@ -900,7 +900,8 @@ amd_append_message (mu_mailbox_t mailbox, mu_message_t msg)
900 char *qid; 900 char *qid;
901 if (amd->cur_msg_file_name (mhm, &qid) == 0) 901 if (amd->cur_msg_file_name (mhm, &qid) == 0)
902 { 902 {
903 mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_APPEND, 903 mu_observable_notify (mailbox->observable,
904 MU_EVT_MAILBOX_MESSAGE_APPEND,
904 qid); 905 qid);
905 free (qid); 906 free (qid);
906 } 907 }
...@@ -1148,6 +1149,7 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -1148,6 +1149,7 @@ amd_expunge (mu_mailbox_t mailbox)
1148 struct _amd_message *mhm; 1149 struct _amd_message *mhm;
1149 size_t i; 1150 size_t i;
1150 int updated = amd->has_new_msg; 1151 int updated = amd->has_new_msg;
1152 size_t expcount = 0;
1151 1153
1152 if (amd == NULL) 1154 if (amd == NULL)
1153 return EINVAL; 1155 return EINVAL;
...@@ -1175,9 +1177,15 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -1175,9 +1177,15 @@ amd_expunge (mu_mailbox_t mailbox)
1175 1177
1176 if (amd->delete_msg) 1178 if (amd->delete_msg)
1177 { 1179 {
1180 size_t expevt[2] = { i + 1, expcount };
1178 rc = amd->delete_msg (amd, mhm); 1181 rc = amd->delete_msg (amd, mhm);
1179 if (rc) 1182 if (rc)
1180 return rc; 1183 return rc;
1184
1185 mu_observable_notify (mailbox->observable,
1186 MU_EVT_MAILBOX_MESSAGE_EXPUNGE,
1187 expevt);
1188 ++expcount;
1181 } 1189 }
1182 else 1190 else
1183 { 1191 {
......
...@@ -534,9 +534,7 @@ mu_message_destroy (mu_message_t *pmsg, void *owner) ...@@ -534,9 +534,7 @@ mu_message_destroy (mu_message_t *pmsg, void *owner)
534 is very unfortunate. 534 is very unfortunate.
535 535
536 The `owner' stuff is a leftover from older mailutils versions. 536 The `owner' stuff is a leftover from older mailutils versions.
537 There is an ongoing attempt to remove it in the stream-cleanup 537 We are heading to removing it altogether. */
538 branch. When it is ready, it will be merged to the HEAD and this
539 will finally resolve this issue. */
540 if (msg->ref > 0) 538 if (msg->ref > 0)
541 msg->ref--; 539 msg->ref--;
542 if ((msg->owner && msg->owner == owner) 540 if ((msg->owner && msg->owner == owner)
......
...@@ -2589,7 +2589,7 @@ imap_parse (f_imap_t f_imap) ...@@ -2589,7 +2589,7 @@ imap_parse (f_imap_t f_imap)
2589 { 2589 {
2590 mu_observable_t observable = NULL; 2590 mu_observable_t observable = NULL;
2591 mu_folder_get_observable (f_imap->folder, &observable); 2591 mu_folder_get_observable (f_imap->folder, &observable);
2592 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED, 2592 mu_observable_notify (observable, MU_EVT_FOLDER_AUTHORITY_FAILED,
2593 NULL); 2593 NULL);
2594 status = MU_ERR_AUTH_FAILURE; 2594 status = MU_ERR_AUTH_FAILURE;
2595 } 2595 }
......
...@@ -1143,7 +1143,8 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg) ...@@ -1143,7 +1143,8 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg)
1143 { 1143 {
1144 char *buf = NULL; 1144 char *buf = NULL;
1145 mu_asprintf (&buf, "%lu", (unsigned long) size); 1145 mu_asprintf (&buf, "%lu", (unsigned long) size);
1146 mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_APPEND, buf); 1146 mu_observable_notify (mailbox->observable,
1147 MU_EVT_MAILBOX_MESSAGE_APPEND, buf);
1147 free (buf); 1148 free (buf);
1148 } 1149 }
1149 1150
...@@ -1184,7 +1185,8 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, ...@@ -1184,7 +1185,8 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted,
1184 size_t save_imapbase = 0; /* uidvalidity is save in the first message. */ 1185 size_t save_imapbase = 0; /* uidvalidity is save in the first message. */
1185 mu_off_t start_off; 1186 mu_off_t start_off;
1186 mu_off_t size; 1187 mu_off_t size;
1187 1188 size_t expcount = 0;
1189
1188 /* Set the marker position. */ 1190 /* Set the marker position. */
1189 start_off = mud->umessages[dirty]->envel_from; 1191 start_off = mud->umessages[dirty]->envel_from;
1190 1192
...@@ -1194,6 +1196,11 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, ...@@ -1194,6 +1196,11 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted,
1194 1196
1195 if (remove_deleted && ATTRIBUTE_IS_DELETED (mum->attr_flags)) 1197 if (remove_deleted && ATTRIBUTE_IS_DELETED (mum->attr_flags))
1196 { 1198 {
1199 size_t expevt[2] = { i + 1, expcount };
1200 mu_observable_notify (mailbox->observable,
1201 MU_EVT_MAILBOX_MESSAGE_EXPUNGE,
1202 expevt);
1203 expcount++;
1197 mu_message_destroy (&mum->message, mum); 1204 mu_message_destroy (&mum->message, mum);
1198 /* We save the uidvalidity in the first message, if it is being 1205 /* We save the uidvalidity in the first message, if it is being
1199 deleted we need to move the uidvalidity to the first available 1206 deleted we need to move the uidvalidity to the first available
......
...@@ -864,6 +864,7 @@ pop_expunge (mu_mailbox_t mbox) ...@@ -864,6 +864,7 @@ pop_expunge (mu_mailbox_t mbox)
864 struct _pop3_mailbox *mpd = mbox->data; 864 struct _pop3_mailbox *mpd = mbox->data;
865 int status = 0; 865 int status = 0;
866 size_t i; 866 size_t i;
867 size_t expcount = 0;
867 868
868 if (mpd == NULL) 869 if (mpd == NULL)
869 return EINVAL; 870 return EINVAL;
...@@ -879,9 +880,14 @@ pop_expunge (mu_mailbox_t mbox) ...@@ -879,9 +880,14 @@ pop_expunge (mu_mailbox_t mbox)
879 (mpm->flags & _POP3_MSG_ATTRSET) && 880 (mpm->flags & _POP3_MSG_ATTRSET) &&
880 (mpm->attr_flags & MU_ATTRIBUTE_DELETED)) 881 (mpm->attr_flags & MU_ATTRIBUTE_DELETED))
881 { 882 {
883 size_t expevt[2] = { i + 1, expcount };
882 status = mu_pop3_dele (mpd->pop3, mpm->num); 884 status = mu_pop3_dele (mpd->pop3, mpm->num);
883 if (status) 885 if (status)
884 break; 886 break;
887 mu_observable_notify (mbox->observable,
888 MU_EVT_MAILBOX_MESSAGE_EXPUNGE,
889 &expevt);
890 ++expcount;
885 } 891 }
886 } 892 }
887 return 0; 893 return 0;
......
...@@ -132,7 +132,7 @@ static const char *biff_user_name; ...@@ -132,7 +132,7 @@ static const char *biff_user_name;
132 static int 132 static int
133 notify_action (mu_observer_t obs, size_t type, void *data, void *action_data) 133 notify_action (mu_observer_t obs, size_t type, void *data, void *action_data)
134 { 134 {
135 if (type == MU_EVT_MESSAGE_APPEND && biff_user_name) 135 if (type == MU_EVT_MAILBOX_MESSAGE_APPEND && biff_user_name)
136 { 136 {
137 mu_message_qid_t qid = data; 137 mu_message_qid_t qid = data;
138 mu_mailbox_t mbox = mu_observer_get_owner (obs); 138 mu_mailbox_t mbox = mu_observer_get_owner (obs);
...@@ -183,7 +183,8 @@ attach_notify (mu_mailbox_t mbox) ...@@ -183,7 +183,8 @@ attach_notify (mu_mailbox_t mbox)
183 mu_observer_create (&observer, mbox); 183 mu_observer_create (&observer, mbox);
184 mu_observer_set_action (observer, notify_action, mbox); 184 mu_observer_set_action (observer, notify_action, mbox);
185 mu_mailbox_get_observable (mbox, &observable); 185 mu_mailbox_get_observable (mbox, &observable);
186 mu_observable_attach (observable, MU_EVT_MESSAGE_APPEND, observer); 186 mu_observable_attach (observable, MU_EVT_MAILBOX_MESSAGE_APPEND,
187 observer);
187 } 188 }
188 } 189 }
189 190
......