Commit b6a16292 b6a162923d3fdfc0c8642dd0169bf870a5ae2868 by Sergey Poznyakoff

amd: bugfixes; speed up expunging.

* libmailutils/base/amd.c (_amd_message_delete): Remove.
(amd_array_expand): Fix element size.
(amd_array_shrink): Rewrite.
(amd_expunge): Shrink the array once, after everything has been
expunged.
Generate MU_EVT_MAILBOX_MESSAGE_EXPUNGE for each expunged message.
1 parent 0cf36c45
...@@ -100,8 +100,6 @@ static int amd_get_attr_flags (mu_attribute_t attr, int *pflags); ...@@ -100,8 +100,6 @@ static int amd_get_attr_flags (mu_attribute_t attr, int *pflags);
100 static int amd_set_attr_flags (mu_attribute_t attr, int flags); 100 static int amd_set_attr_flags (mu_attribute_t attr, int flags);
101 static int amd_unset_attr_flags (mu_attribute_t attr, int flags); 101 static int amd_unset_attr_flags (mu_attribute_t attr, int flags);
102 102
103 static void _amd_message_delete (struct _amd_data *amd,
104 struct _amd_message *msg);
105 static int amd_pool_open (struct _amd_message *mhm); 103 static int amd_pool_open (struct _amd_message *mhm);
106 static int amd_pool_open_count (struct _amd_data *amd); 104 static int amd_pool_open_count (struct _amd_data *amd);
107 static void amd_pool_flush (struct _amd_data *amd); 105 static void amd_pool_flush (struct _amd_data *amd);
...@@ -233,7 +231,7 @@ amd_array_expand (struct _amd_data *amd, size_t index) ...@@ -233,7 +231,7 @@ amd_array_expand (struct _amd_data *amd, size_t index)
233 struct _amd_message **p; 231 struct _amd_message **p;
234 232
235 amd->msg_max += AMD_MSG_INC; /* FIXME: configurable? */ 233 amd->msg_max += AMD_MSG_INC; /* FIXME: configurable? */
236 p = realloc (amd->msg_array, amd->msg_max * amd->msg_size); 234 p = realloc (amd->msg_array, amd->msg_max * sizeof (amd->msg_array[0]));
237 if (!p) 235 if (!p)
238 { 236 {
239 amd->msg_max -= AMD_MSG_INC; 237 amd->msg_max -= AMD_MSG_INC;
...@@ -243,20 +241,21 @@ amd_array_expand (struct _amd_data *amd, size_t index) ...@@ -243,20 +241,21 @@ amd_array_expand (struct _amd_data *amd, size_t index)
243 } 241 }
244 if (amd->msg_count > index) 242 if (amd->msg_count > index)
245 memmove (&amd->msg_array[index+1], &amd->msg_array[index], 243 memmove (&amd->msg_array[index+1], &amd->msg_array[index],
246 (amd->msg_count-index) * amd->msg_size); 244 (amd->msg_count-index) * sizeof (amd->msg_array[0]));
247 amd->msg_count++; 245 amd->msg_count++;
248 return 0; 246 return 0;
249 } 247 }
250 248
251 /* Shrink the message array by removing element at INDEX-1 and 249 /* Shrink the message array by removing element at INDEX-COUNT and
252 shifting left by one position all the elements on the right of 250 shifting left by COUNT positions all the elements on the right of
253 it. */ 251 it. */
254 int 252 int
255 amd_array_shrink (struct _amd_data *amd, size_t index) 253 amd_array_shrink (struct _amd_data *amd, size_t index, size_t count)
256 { 254 {
257 memmove (&amd->msg_array[index-1], &amd->msg_array[index], 255 if (amd->msg_count-index-1 && index < amd->msg_count)
258 (amd->msg_count-index) * amd->msg_size); 256 memmove (&amd->msg_array[index-count+1], &amd->msg_array[index + 1],
259 amd->msg_count--; 257 (amd->msg_count-index-1) * sizeof (amd->msg_array[0]));
258 amd->msg_count -= count;
260 return 0; 259 return 0;
261 } 260 }
262 261
...@@ -1150,6 +1149,7 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -1150,6 +1149,7 @@ amd_expunge (mu_mailbox_t mailbox)
1150 size_t i; 1149 size_t i;
1151 int updated = amd->has_new_msg; 1150 int updated = amd->has_new_msg;
1152 size_t expcount = 0; 1151 size_t expcount = 0;
1152 size_t last_expunged = 0;
1153 1153
1154 if (amd == NULL) 1154 if (amd == NULL)
1155 return EINVAL; 1155 return EINVAL;
...@@ -1157,35 +1157,20 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -1157,35 +1157,20 @@ amd_expunge (mu_mailbox_t mailbox)
1157 if (amd->msg_count == 0) 1157 if (amd->msg_count == 0)
1158 return 0; 1158 return 0;
1159 1159
1160 /* Find the first dirty(modified) message. */
1161 for (i = 0; i < amd->msg_count; i++) 1160 for (i = 0; i < amd->msg_count; i++)
1162 { 1161 {
1163 mhm = amd->msg_array[i]; 1162 mhm = amd->msg_array[i];
1164 if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) ||
1165 (mhm->attr_flags & MU_ATTRIBUTE_DELETED) ||
1166 (mhm->message && mu_message_is_modified (mhm->message)))
1167 break;
1168 }
1169
1170 while (i < amd->msg_count)
1171 {
1172 mhm = amd->msg_array[i];
1173 1163
1174 if (mhm->attr_flags & MU_ATTRIBUTE_DELETED) 1164 if (mhm->attr_flags & MU_ATTRIBUTE_DELETED)
1175 { 1165 {
1176 int rc; 1166 int rc;
1167 struct _amd_message **pp;
1177 1168
1178 if (amd->delete_msg) 1169 if (amd->delete_msg)
1179 { 1170 {
1180 size_t expevt[2] = { i + 1, expcount };
1181 rc = amd->delete_msg (amd, mhm); 1171 rc = amd->delete_msg (amd, mhm);
1182 if (rc) 1172 if (rc)
1183 return rc; 1173 return rc;
1184
1185 mu_observable_notify (mailbox->observable,
1186 MU_EVT_MAILBOX_MESSAGE_EXPUNGE,
1187 expevt);
1188 ++expcount;
1189 } 1174 }
1190 else 1175 else
1191 { 1176 {
...@@ -1220,9 +1205,25 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -1220,9 +1205,25 @@ amd_expunge (mu_mailbox_t mailbox)
1220 free (old_name); 1205 free (old_name);
1221 free (new_name); 1206 free (new_name);
1222 } 1207 }
1223 _amd_message_delete (amd, mhm); 1208
1209 pp = amd_pool_lookup (mhm);
1210 if (pp)
1211 *pp = NULL;
1212 mu_message_destroy (&mhm->message, mhm);
1213 if (amd->msg_free)
1214 amd->msg_free (mhm);
1215 free (mhm);
1216 amd->msg_array[i] = NULL;
1217 last_expunged = i;
1224 updated = 1; 1218 updated = 1;
1225 /* Do not increase i! */ 1219
1220 {
1221 size_t expevt[2] = { i + 1, expcount };
1222 mu_observable_notify (mailbox->observable,
1223 MU_EVT_MAILBOX_MESSAGE_EXPUNGE,
1224 expevt);
1225 ++expcount;
1226 }
1226 } 1227 }
1227 else 1228 else
1228 { 1229 {
...@@ -1233,10 +1234,28 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -1233,10 +1234,28 @@ amd_expunge (mu_mailbox_t mailbox)
1233 _amd_message_save (amd, mhm, 1); 1234 _amd_message_save (amd, mhm, 1);
1234 updated = 1; 1235 updated = 1;
1235 } 1236 }
1236 i++; /* Move to the next message */
1237 } 1237 }
1238 } 1238 }
1239 1239
1240 if (expcount)
1241 {
1242 last_expunged++;
1243 do
1244 {
1245 size_t j;
1246
1247 for (j = 1; j < last_expunged && !amd->msg_array[last_expunged-j-1];
1248 j++)
1249 ;
1250 amd_array_shrink (amd, last_expunged - 1, j);
1251 for (last_expunged -= j;
1252 last_expunged > 0 && amd->msg_array[last_expunged - 1];
1253 last_expunged--)
1254 ;
1255 }
1256 while (last_expunged);
1257 }
1258
1240 if (updated && !amd->mailbox_size) 1259 if (updated && !amd->mailbox_size)
1241 { 1260 {
1242 mu_off_t size = 0; 1261 mu_off_t size = 0;
...@@ -1419,31 +1438,6 @@ amd_sort (struct _amd_data *amd) ...@@ -1419,31 +1438,6 @@ amd_sort (struct _amd_data *amd)
1419 msg_array_comp); 1438 msg_array_comp);
1420 } 1439 }
1421 1440
1422 static void
1423 _amd_message_delete (struct _amd_data *amd, struct _amd_message *msg)
1424 {
1425 size_t index;
1426 struct _amd_message **pp;
1427
1428 if (amd_msg_lookup (amd, msg, &index))
1429 {
1430 /* FIXME: Not found? */
1431 return;
1432 }
1433
1434 msg = _amd_get_message (amd, index);
1435
1436 pp = amd_pool_lookup (msg);
1437 if (pp)
1438 *pp = NULL;
1439
1440 mu_message_destroy (&msg->message, msg);
1441 if (amd->msg_free)
1442 amd->msg_free (msg);
1443 free (msg);
1444 amd_array_shrink (amd, index);
1445 }
1446
1447 /* Scan given message and fill amd_message_t fields. 1441 /* Scan given message and fill amd_message_t fields.
1448 NOTE: the function assumes mhm->stream != NULL. */ 1442 NOTE: the function assumes mhm->stream != NULL. */
1449 static int 1443 static int
......