Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/lib-storage/index/maildir/maildir-sync.c @ 3279:b698ae839a18 HEAD
Moved mbox/maildir-specific variables from struct index_mailbox to
mbox_mailbox and maildir_mailbox.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 08 Apr 2005 16:13:45 +0300 |
parents | 391a1064872e |
children | 2c72492dfd91 |
comparison
equal
deleted
inserted
replaced
3278:df372eecc5d0 | 3279:b698ae839a18 |
---|---|
187 #define MAILDIR_SYNC_SECS 1 | 187 #define MAILDIR_SYNC_SECS 1 |
188 | 188 |
189 #define MAILDIR_FILENAME_FLAG_FOUND 128 | 189 #define MAILDIR_FILENAME_FLAG_FOUND 128 |
190 | 190 |
191 struct maildir_sync_context { | 191 struct maildir_sync_context { |
192 struct index_mailbox *ibox; | 192 struct maildir_mailbox *mbox; |
193 const char *new_dir, *cur_dir; | 193 const char *new_dir, *cur_dir; |
194 int partial; | 194 int partial; |
195 | 195 |
196 struct maildir_uidlist_sync_ctx *uidlist_sync_ctx; | 196 struct maildir_uidlist_sync_ctx *uidlist_sync_ctx; |
197 struct maildir_index_sync_context *index_sync_ctx; | 197 struct maildir_index_sync_context *index_sync_ctx; |
198 }; | 198 }; |
199 | 199 |
200 struct maildir_index_sync_context { | 200 struct maildir_index_sync_context { |
201 struct index_mailbox *ibox; | 201 struct maildir_mailbox *mbox; |
202 struct mail_index_view *view; | 202 struct mail_index_view *view; |
203 struct mail_index_sync_ctx *sync_ctx; | 203 struct mail_index_sync_ctx *sync_ctx; |
204 struct mail_index_transaction *trans; | 204 struct mail_index_transaction *trans; |
205 | 205 |
206 struct mail_index_sync_rec sync_rec; | 206 struct mail_index_sync_rec sync_rec; |
207 uint32_t seq; | 207 uint32_t seq; |
208 int dirty_state; | 208 int dirty_state; |
209 }; | 209 }; |
210 | 210 |
211 static int maildir_expunge(struct index_mailbox *ibox, const char *path, | 211 static int maildir_expunge(struct maildir_mailbox *mbox, const char *path, |
212 void *context __attr_unused__) | 212 void *context __attr_unused__) |
213 { | 213 { |
214 if (unlink(path) == 0) { | 214 if (unlink(path) == 0) { |
215 ibox->dirty_cur_time = ioloop_time; | 215 mbox->dirty_cur_time = ioloop_time; |
216 return 1; | 216 return 1; |
217 } | 217 } |
218 if (errno == ENOENT) | 218 if (errno == ENOENT) |
219 return 0; | 219 return 0; |
220 | 220 |
221 mail_storage_set_critical(ibox->box.storage, | 221 mail_storage_set_critical(&mbox->storage->storage, |
222 "unlink(%s) failed: %m", path); | 222 "unlink(%s) failed: %m", path); |
223 return -1; | 223 return -1; |
224 } | 224 } |
225 | 225 |
226 static int maildir_sync_flags(struct index_mailbox *ibox, const char *path, | 226 static int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path, |
227 void *context) | 227 void *context) |
228 { | 228 { |
229 struct maildir_index_sync_context *ctx = context; | 229 struct maildir_index_sync_context *ctx = context; |
230 const char *newpath; | 230 const char *newpath; |
231 enum mail_flags flags; | 231 enum mail_flags flags; |
242 | 242 |
243 newpath = maildir_filename_set_flags(path, flags8, keywords); | 243 newpath = maildir_filename_set_flags(path, flags8, keywords); |
244 if (rename(path, newpath) == 0) { | 244 if (rename(path, newpath) == 0) { |
245 if ((flags8 & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) | 245 if ((flags8 & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) |
246 ctx->dirty_state = -1; | 246 ctx->dirty_state = -1; |
247 ibox->dirty_cur_time = ioloop_time; | 247 mbox->dirty_cur_time = ioloop_time; |
248 return 1; | 248 return 1; |
249 } | 249 } |
250 if (errno == ENOENT) | 250 if (errno == ENOENT) |
251 return 0; | 251 return 0; |
252 | 252 |
255 MAIL_INDEX_MAIL_FLAG_DIRTY); | 255 MAIL_INDEX_MAIL_FLAG_DIRTY); |
256 ctx->dirty_state = 1; | 256 ctx->dirty_state = 1; |
257 return 1; | 257 return 1; |
258 } | 258 } |
259 | 259 |
260 mail_storage_set_critical(ibox->box.storage, | 260 mail_storage_set_critical(&mbox->storage->storage, |
261 "rename(%s, %s) failed: %m", path, newpath); | 261 "rename(%s, %s) failed: %m", path, newpath); |
262 return -1; | 262 return -1; |
263 } | 263 } |
264 | 264 |
265 static int maildir_sync_record(struct index_mailbox *ibox, | 265 static int maildir_sync_record(struct maildir_mailbox *mbox, |
266 struct maildir_index_sync_context *ctx) | 266 struct maildir_index_sync_context *ctx) |
267 { | 267 { |
268 struct mail_index_sync_rec *sync_rec = &ctx->sync_rec; | 268 struct mail_index_sync_rec *sync_rec = &ctx->sync_rec; |
269 struct mail_index_view *view = ctx->view; | 269 struct mail_index_view *view = ctx->view; |
270 uint32_t seq, seq1, seq2, uid; | 270 uint32_t seq, seq1, seq2, uid; |
284 break; | 284 break; |
285 | 285 |
286 for (seq = seq1; seq <= seq2; seq++) { | 286 for (seq = seq1; seq <= seq2; seq++) { |
287 if (mail_index_lookup_uid(view, seq, &uid) < 0) | 287 if (mail_index_lookup_uid(view, seq, &uid) < 0) |
288 return -1; | 288 return -1; |
289 if (maildir_file_do(ibox, uid, maildir_expunge, | 289 if (maildir_file_do(mbox, uid, maildir_expunge, |
290 NULL) < 0) | 290 NULL) < 0) |
291 return -1; | 291 return -1; |
292 } | 292 } |
293 break; | 293 break; |
294 case MAIL_INDEX_SYNC_TYPE_FLAGS: | 294 case MAIL_INDEX_SYNC_TYPE_FLAGS: |
301 break; | 301 break; |
302 | 302 |
303 for (ctx->seq = seq1; ctx->seq <= seq2; ctx->seq++) { | 303 for (ctx->seq = seq1; ctx->seq <= seq2; ctx->seq++) { |
304 if (mail_index_lookup_uid(view, ctx->seq, &uid) < 0) | 304 if (mail_index_lookup_uid(view, ctx->seq, &uid) < 0) |
305 return -1; | 305 return -1; |
306 if (maildir_file_do(ibox, uid, | 306 if (maildir_file_do(mbox, uid, |
307 maildir_sync_flags, ctx) < 0) | 307 maildir_sync_flags, ctx) < 0) |
308 return -1; | 308 return -1; |
309 if (ctx->dirty_state < 0) { | 309 if (ctx->dirty_state < 0) { |
310 /* flag isn't dirty anymore */ | 310 /* flag isn't dirty anymore */ |
311 mail_index_update_flags(ctx->trans, ctx->seq, | 311 mail_index_update_flags(ctx->trans, ctx->seq, |
322 } | 322 } |
323 | 323 |
324 return 0; | 324 return 0; |
325 } | 325 } |
326 | 326 |
327 int maildir_sync_last_commit(struct index_mailbox *ibox) | 327 int maildir_sync_last_commit(struct maildir_mailbox *mbox) |
328 { | 328 { |
329 struct maildir_index_sync_context ctx; | 329 struct maildir_index_sync_context ctx; |
330 uint32_t seq; | 330 uint32_t seq; |
331 uoff_t offset; | 331 uoff_t offset; |
332 int ret; | 332 int ret; |
333 | 333 |
334 if (ibox->commit_log_file_seq == 0) | 334 if (mbox->ibox.commit_log_file_seq == 0) |
335 return 0; | 335 return 0; |
336 | 336 |
337 memset(&ctx, 0, sizeof(ctx)); | 337 memset(&ctx, 0, sizeof(ctx)); |
338 ctx.ibox = ibox; | 338 ctx.mbox = mbox; |
339 | 339 |
340 ibox->syncing_commit = TRUE; | 340 mbox->syncing_commit = TRUE; |
341 ret = mail_index_sync_begin(ibox->index, &ctx.sync_ctx, &ctx.view, | 341 ret = mail_index_sync_begin(mbox->ibox.index, &ctx.sync_ctx, &ctx.view, |
342 ibox->commit_log_file_seq, | 342 mbox->ibox.commit_log_file_seq, |
343 ibox->commit_log_file_offset, FALSE, FALSE); | 343 mbox->ibox.commit_log_file_offset, |
344 FALSE, FALSE); | |
344 if (ret > 0) { | 345 if (ret > 0) { |
345 ctx.trans = mail_index_transaction_begin(ctx.view, FALSE, TRUE); | 346 ctx.trans = mail_index_transaction_begin(ctx.view, FALSE, TRUE); |
346 | 347 |
347 while ((ret = mail_index_sync_next(ctx.sync_ctx, | 348 while ((ret = mail_index_sync_next(ctx.sync_ctx, |
348 &ctx.sync_rec)) > 0) { | 349 &ctx.sync_rec)) > 0) { |
349 if (maildir_sync_record(ibox, &ctx) < 0) { | 350 if (maildir_sync_record(mbox, &ctx) < 0) { |
350 ret = -1; | 351 ret = -1; |
351 break; | 352 break; |
352 } | 353 } |
353 } | 354 } |
354 if (mail_index_transaction_commit(ctx.trans, &seq, &offset) < 0) | 355 if (mail_index_transaction_commit(ctx.trans, &seq, &offset) < 0) |
355 ret = -1; | 356 ret = -1; |
356 if (mail_index_sync_commit(ctx.sync_ctx) < 0) | 357 if (mail_index_sync_commit(ctx.sync_ctx) < 0) |
357 ret = -1; | 358 ret = -1; |
358 } | 359 } |
359 ibox->syncing_commit = FALSE; | 360 mbox->syncing_commit = FALSE; |
360 | 361 |
361 if (ret == 0) { | 362 if (ret == 0) { |
362 ibox->commit_log_file_seq = 0; | 363 mbox->ibox.commit_log_file_seq = 0; |
363 ibox->commit_log_file_offset = 0; | 364 mbox->ibox.commit_log_file_offset = 0; |
364 } else { | 365 } else { |
365 mail_storage_set_index_error(ibox); | 366 mail_storage_set_index_error(&mbox->ibox); |
366 } | 367 } |
367 return ret; | 368 return ret; |
368 } | 369 } |
369 | 370 |
370 static struct maildir_sync_context * | 371 static struct maildir_sync_context * |
371 maildir_sync_context_new(struct index_mailbox *ibox) | 372 maildir_sync_context_new(struct maildir_mailbox *mbox) |
372 { | 373 { |
373 struct maildir_sync_context *ctx; | 374 struct maildir_sync_context *ctx; |
374 | 375 |
375 ctx = t_new(struct maildir_sync_context, 1); | 376 ctx = t_new(struct maildir_sync_context, 1); |
376 ctx->ibox = ibox; | 377 ctx->mbox = mbox; |
377 ctx->new_dir = t_strconcat(ibox->path, "/new", NULL); | 378 ctx->new_dir = t_strconcat(mbox->path, "/new", NULL); |
378 ctx->cur_dir = t_strconcat(ibox->path, "/cur", NULL); | 379 ctx->cur_dir = t_strconcat(mbox->path, "/cur", NULL); |
379 return ctx; | 380 return ctx; |
380 } | 381 } |
381 | 382 |
382 static void maildir_sync_deinit(struct maildir_sync_context *ctx) | 383 static void maildir_sync_deinit(struct maildir_sync_context *ctx) |
383 { | 384 { |
385 (void)maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx); | 386 (void)maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx); |
386 if (ctx->index_sync_ctx != NULL) | 387 if (ctx->index_sync_ctx != NULL) |
387 maildir_sync_index_abort(ctx->index_sync_ctx); | 388 maildir_sync_index_abort(ctx->index_sync_ctx); |
388 } | 389 } |
389 | 390 |
390 static int maildir_fix_duplicate(struct index_mailbox *ibox, const char *dir, | 391 static int maildir_fix_duplicate(struct maildir_mailbox *mbox, const char *dir, |
391 const char *old_fname) | 392 const char *old_fname) |
392 { | 393 { |
393 const char *new_fname, *old_path, *new_path; | 394 const char *new_fname, *old_path, *new_path; |
394 int ret = 0; | 395 int ret = 0; |
395 | 396 |
396 t_push(); | 397 t_push(); |
397 | 398 |
398 old_path = t_strconcat(dir, "/", old_fname, NULL); | 399 old_path = t_strconcat(dir, "/", old_fname, NULL); |
399 new_fname = maildir_generate_tmp_filename(&ioloop_timeval); | 400 new_fname = maildir_generate_tmp_filename(&ioloop_timeval); |
400 new_path = t_strconcat(ibox->path, "/new/", new_fname, NULL); | 401 new_path = t_strconcat(mbox->path, "/new/", new_fname, NULL); |
401 | 402 |
402 if (rename(old_path, new_path) == 0) { | 403 if (rename(old_path, new_path) == 0) { |
403 i_warning("Fixed duplicate in %s: %s -> %s", | 404 i_warning("Fixed duplicate in %s: %s -> %s", |
404 ibox->path, old_fname, new_fname); | 405 mbox->path, old_fname, new_fname); |
405 } else if (errno != ENOENT) { | 406 } else if (errno != ENOENT) { |
406 mail_storage_set_critical(ibox->box.storage, | 407 mail_storage_set_critical(&mbox->storage->storage, |
407 "rename(%s, %s) failed: %m", old_path, new_path); | 408 "rename(%s, %s) failed: %m", old_path, new_path); |
408 ret = -1; | 409 ret = -1; |
409 } | 410 } |
410 t_pop(); | 411 t_pop(); |
411 | 412 |
412 return ret; | 413 return ret; |
413 } | 414 } |
414 | 415 |
415 static int maildir_scan_dir(struct maildir_sync_context *ctx, int new_dir) | 416 static int maildir_scan_dir(struct maildir_sync_context *ctx, int new_dir) |
416 { | 417 { |
417 struct mail_storage *storage = ctx->ibox->box.storage; | 418 struct mail_storage *storage = &ctx->mbox->storage->storage; |
418 const char *dir; | 419 const char *dir; |
419 DIR *dirp; | 420 DIR *dirp; |
420 string_t *src, *dest; | 421 string_t *src, *dest; |
421 struct dirent *dp; | 422 struct dirent *dp; |
422 enum maildir_uidlist_rec_flag flags; | 423 enum maildir_uidlist_rec_flag flags; |
432 | 433 |
433 t_push(); | 434 t_push(); |
434 src = t_str_new(1024); | 435 src = t_str_new(1024); |
435 dest = t_str_new(1024); | 436 dest = t_str_new(1024); |
436 | 437 |
437 move_new = new_dir && !mailbox_is_readonly(&ctx->ibox->box) && | 438 move_new = new_dir && !mailbox_is_readonly(&ctx->mbox->ibox.box) && |
438 !ctx->ibox->keep_recent; | 439 !ctx->mbox->ibox.keep_recent; |
439 while ((dp = readdir(dirp)) != NULL) { | 440 while ((dp = readdir(dirp)) != NULL) { |
440 if (dp->d_name[0] == '.') | 441 if (dp->d_name[0] == '.') |
441 continue; | 442 continue; |
442 | 443 |
443 ret = maildir_uidlist_sync_next_pre(ctx->uidlist_sync_ctx, | 444 ret = maildir_uidlist_sync_next_pre(ctx->uidlist_sync_ctx, |
444 dp->d_name); | 445 dp->d_name); |
445 if (ret == 0) { | 446 if (ret == 0) { |
446 /* new file and we couldn't lock uidlist, check this | 447 /* new file and we couldn't lock uidlist, check this |
447 later in next sync. */ | 448 later in next sync. */ |
448 if (new_dir) | 449 if (new_dir) |
449 ctx->ibox->last_new_mtime = 0; | 450 ctx->mbox->last_new_mtime = 0; |
450 else | 451 else |
451 ctx->ibox->dirty_cur_time = ioloop_time; | 452 ctx->mbox->dirty_cur_time = ioloop_time; |
452 continue; | 453 continue; |
453 } | 454 } |
454 if (ret < 0) | 455 if (ret < 0) |
455 break; | 456 break; |
456 | 457 |
462 str_printfa(dest, "%s/%s", ctx->cur_dir, dp->d_name); | 463 str_printfa(dest, "%s/%s", ctx->cur_dir, dp->d_name); |
463 if (strchr(dp->d_name, ':') == NULL) | 464 if (strchr(dp->d_name, ':') == NULL) |
464 str_append(dest, ":2,"); | 465 str_append(dest, ":2,"); |
465 if (rename(str_c(src), str_c(dest)) == 0) { | 466 if (rename(str_c(src), str_c(dest)) == 0) { |
466 /* we moved it - it's \Recent for us */ | 467 /* we moved it - it's \Recent for us */ |
467 ctx->ibox->dirty_cur_time = ioloop_time; | 468 ctx->mbox->dirty_cur_time = ioloop_time; |
468 flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED | | 469 flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED | |
469 MAILDIR_UIDLIST_REC_FLAG_RECENT; | 470 MAILDIR_UIDLIST_REC_FLAG_RECENT; |
470 } else if (ENOTFOUND(errno)) { | 471 } else if (ENOTFOUND(errno)) { |
471 /* someone else moved it already */ | 472 /* someone else moved it already */ |
472 flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED; | 473 flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED; |
492 if (ret <= 0) { | 493 if (ret <= 0) { |
493 if (ret < 0) | 494 if (ret < 0) |
494 break; | 495 break; |
495 | 496 |
496 /* possibly duplicate - try fixing it */ | 497 /* possibly duplicate - try fixing it */ |
497 if (maildir_fix_duplicate(ctx->ibox, | 498 if (maildir_fix_duplicate(ctx->mbox, |
498 dir, dp->d_name) < 0) { | 499 dir, dp->d_name) < 0) { |
499 ret = -1; | 500 ret = -1; |
500 break; | 501 break; |
501 } | 502 } |
502 } | 503 } |
512 } | 513 } |
513 | 514 |
514 static int maildir_sync_quick_check(struct maildir_sync_context *ctx, | 515 static int maildir_sync_quick_check(struct maildir_sync_context *ctx, |
515 int *new_changed_r, int *cur_changed_r) | 516 int *new_changed_r, int *cur_changed_r) |
516 { | 517 { |
517 struct index_mailbox *ibox = ctx->ibox; | 518 struct maildir_mailbox *mbox = ctx->mbox; |
518 struct stat st; | 519 struct stat st; |
519 time_t new_mtime, cur_mtime; | 520 time_t new_mtime, cur_mtime; |
520 | 521 |
521 *new_changed_r = *cur_changed_r = FALSE; | 522 *new_changed_r = *cur_changed_r = FALSE; |
522 | 523 |
523 if (stat(ctx->new_dir, &st) < 0) { | 524 if (stat(ctx->new_dir, &st) < 0) { |
524 mail_storage_set_critical(ibox->box.storage, | 525 mail_storage_set_critical(&mbox->storage->storage, |
525 "stat(%s) failed: %m", ctx->new_dir); | 526 "stat(%s) failed: %m", ctx->new_dir); |
526 return -1; | 527 return -1; |
527 } | 528 } |
528 new_mtime = st.st_mtime; | 529 new_mtime = st.st_mtime; |
529 | 530 |
530 if (stat(ctx->cur_dir, &st) < 0) { | 531 if (stat(ctx->cur_dir, &st) < 0) { |
531 mail_storage_set_critical(ibox->box.storage, | 532 mail_storage_set_critical(&mbox->storage->storage, |
532 "stat(%s) failed: %m", ctx->cur_dir); | 533 "stat(%s) failed: %m", ctx->cur_dir); |
533 return -1; | 534 return -1; |
534 } | 535 } |
535 cur_mtime = st.st_mtime; | 536 cur_mtime = st.st_mtime; |
536 | 537 |
537 /* cur stamp is kept in index, we don't have to sync if | 538 /* cur stamp is kept in index, we don't have to sync if |
538 someone else has done it and updated the index. */ | 539 someone else has done it and updated the index. */ |
539 ibox->last_cur_mtime = mail_index_get_header(ibox->view)->sync_stamp; | 540 mbox->last_cur_mtime = |
540 if (ibox->dirty_cur_time == 0 && cur_mtime != ibox->last_cur_mtime) { | 541 mail_index_get_header(mbox->ibox.view)->sync_stamp; |
542 if (mbox->dirty_cur_time == 0 && cur_mtime != mbox->last_cur_mtime) { | |
541 /* check if the index has been updated.. */ | 543 /* check if the index has been updated.. */ |
542 if (mail_index_refresh(ibox->index) < 0) { | 544 if (mail_index_refresh(mbox->ibox.index) < 0) { |
543 mail_storage_set_index_error(ibox); | 545 mail_storage_set_index_error(&mbox->ibox); |
544 return -1; | 546 return -1; |
545 } | 547 } |
546 | 548 |
547 ibox->last_cur_mtime = | 549 mbox->last_cur_mtime = |
548 mail_index_get_header(ibox->view)->sync_stamp; | 550 mail_index_get_header(mbox->ibox.view)->sync_stamp; |
549 } | 551 } |
550 | 552 |
551 if (new_mtime != ibox->last_new_mtime || | 553 if (new_mtime != mbox->last_new_mtime || |
552 new_mtime >= ibox->last_new_sync_time - MAILDIR_SYNC_SECS) { | 554 new_mtime >= mbox->last_new_sync_time - MAILDIR_SYNC_SECS) { |
553 *new_changed_r = TRUE; | 555 *new_changed_r = TRUE; |
554 ibox->last_new_mtime = new_mtime; | 556 mbox->last_new_mtime = new_mtime; |
555 ibox->last_new_sync_time = ioloop_time; | 557 mbox->last_new_sync_time = ioloop_time; |
556 } | 558 } |
557 | 559 |
558 if (cur_mtime != ibox->last_cur_mtime || | 560 if (cur_mtime != mbox->last_cur_mtime || |
559 (ibox->dirty_cur_time != 0 && | 561 (mbox->dirty_cur_time != 0 && |
560 ioloop_time - ibox->dirty_cur_time > MAILDIR_SYNC_SECS)) { | 562 ioloop_time - mbox->dirty_cur_time > MAILDIR_SYNC_SECS)) { |
561 /* cur/ changed, or delayed cur/ check */ | 563 /* cur/ changed, or delayed cur/ check */ |
562 *cur_changed_r = TRUE; | 564 *cur_changed_r = TRUE; |
563 ibox->last_cur_mtime = cur_mtime; | 565 mbox->last_cur_mtime = cur_mtime; |
564 | 566 |
565 ibox->dirty_cur_time = | 567 mbox->dirty_cur_time = |
566 cur_mtime >= ioloop_time - MAILDIR_SYNC_SECS ? | 568 cur_mtime >= ioloop_time - MAILDIR_SYNC_SECS ? |
567 cur_mtime : 0; | 569 cur_mtime : 0; |
568 } | 570 } |
569 | 571 |
570 return 0; | 572 return 0; |
571 } | 573 } |
572 | 574 |
573 struct maildir_index_sync_context * | 575 struct maildir_index_sync_context * |
574 maildir_sync_index_begin(struct index_mailbox *ibox) | 576 maildir_sync_index_begin(struct maildir_mailbox *mbox) |
575 { | 577 { |
576 struct maildir_index_sync_context *sync_ctx; | 578 struct maildir_index_sync_context *sync_ctx; |
577 | 579 |
578 sync_ctx = i_new(struct maildir_index_sync_context, 1); | 580 sync_ctx = i_new(struct maildir_index_sync_context, 1); |
579 sync_ctx->ibox = ibox; | 581 sync_ctx->mbox = mbox; |
580 | 582 |
581 if (mail_index_sync_begin(ibox->index, &sync_ctx->sync_ctx, | 583 if (mail_index_sync_begin(mbox->ibox.index, &sync_ctx->sync_ctx, |
582 &sync_ctx->view, (uint32_t)-1, (uoff_t)-1, | 584 &sync_ctx->view, (uint32_t)-1, (uoff_t)-1, |
583 FALSE, FALSE) <= 0) { | 585 FALSE, FALSE) <= 0) { |
584 mail_storage_set_index_error(ibox); | 586 mail_storage_set_index_error(&mbox->ibox); |
585 return NULL; | 587 return NULL; |
586 } | 588 } |
587 return sync_ctx; | 589 return sync_ctx; |
588 } | 590 } |
589 | 591 |
594 } | 596 } |
595 | 597 |
596 int maildir_sync_index_finish(struct maildir_index_sync_context *sync_ctx, | 598 int maildir_sync_index_finish(struct maildir_index_sync_context *sync_ctx, |
597 int partial) | 599 int partial) |
598 { | 600 { |
599 struct index_mailbox *ibox = sync_ctx->ibox; | 601 struct maildir_mailbox *mbox = sync_ctx->mbox; |
600 struct mail_index_view *view = sync_ctx->view; | 602 struct mail_index_view *view = sync_ctx->view; |
601 struct maildir_uidlist_iter_ctx *iter; | 603 struct maildir_uidlist_iter_ctx *iter; |
602 struct mail_index_transaction *trans; | 604 struct mail_index_transaction *trans; |
603 const struct mail_index_header *hdr; | 605 const struct mail_index_header *hdr; |
604 const struct mail_index_record *rec; | 606 const struct mail_index_record *rec; |
610 const char *const *keywords; | 612 const char *const *keywords; |
611 uint32_t uid_validity, next_uid; | 613 uint32_t uid_validity, next_uid; |
612 int ret; | 614 int ret; |
613 | 615 |
614 hdr = mail_index_get_header(view); | 616 hdr = mail_index_get_header(view); |
615 uid_validity = maildir_uidlist_get_uid_validity(ibox->uidlist); | 617 uid_validity = maildir_uidlist_get_uid_validity(mbox->uidlist); |
616 if (uid_validity != hdr->uid_validity && | 618 if (uid_validity != hdr->uid_validity && |
617 uid_validity != 0 && hdr->uid_validity != 0) { | 619 uid_validity != 0 && hdr->uid_validity != 0) { |
618 /* uidvalidity changed and mailbox isn't being initialized, | 620 /* uidvalidity changed and mailbox isn't being initialized, |
619 index must be rebuilt */ | 621 index must be rebuilt */ |
620 mail_storage_set_critical(ibox->box.storage, | 622 mail_storage_set_critical(&mbox->storage->storage, |
621 "Maildir %s sync: UIDVALIDITY changed (%u -> %u)", | 623 "Maildir %s sync: UIDVALIDITY changed (%u -> %u)", |
622 ibox->path, hdr->uid_validity, uid_validity); | 624 mbox->path, hdr->uid_validity, uid_validity); |
623 mail_index_mark_corrupted(ibox->index); | 625 mail_index_mark_corrupted(mbox->ibox.index); |
624 maildir_sync_index_abort(sync_ctx); | 626 maildir_sync_index_abort(sync_ctx); |
625 return -1; | 627 return -1; |
626 } | 628 } |
627 | 629 |
628 trans = mail_index_transaction_begin(view, FALSE, TRUE); | 630 trans = mail_index_transaction_begin(view, FALSE, TRUE); |
629 sync_ctx->trans = trans; | 631 sync_ctx->trans = trans; |
630 | 632 |
631 keyword_pool = pool_alloconly_create("maildir keywords", 128); | 633 keyword_pool = pool_alloconly_create("maildir keywords", 128); |
632 | 634 |
633 seq = 0; | 635 seq = 0; |
634 iter = maildir_uidlist_iter_init(ibox->uidlist); | 636 iter = maildir_uidlist_iter_init(mbox->uidlist); |
635 while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) { | 637 while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) { |
636 p_clear(keyword_pool); | 638 p_clear(keyword_pool); |
637 maildir_filename_get_flags(filename, keyword_pool, | 639 maildir_filename_get_flags(filename, keyword_pool, |
638 &flags, &keywords); | 640 &flags, &keywords); |
639 | 641 |
664 continue; | 666 continue; |
665 } | 667 } |
666 if ((uflags & | 668 if ((uflags & |
667 MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) { | 669 MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) { |
668 mail_storage_set_critical( | 670 mail_storage_set_critical( |
669 ibox->box.storage, | 671 &mbox->storage->storage, |
670 "Maildir %s sync: " | 672 "Maildir %s sync: " |
671 "UID < next_uid " | 673 "UID < next_uid " |
672 "(%u < %u, file = %s)", | 674 "(%u < %u, file = %s)", |
673 ibox->path, uid, hdr->next_uid, | 675 mbox->path, uid, hdr->next_uid, |
674 filename); | 676 filename); |
675 mail_index_mark_corrupted(ibox->index); | 677 mail_index_mark_corrupted( |
678 mbox->ibox.index); | |
676 ret = -1; | 679 ret = -1; |
677 break; | 680 break; |
678 } | 681 } |
679 ibox->dirty_cur_time = ioloop_time; | 682 mbox->dirty_cur_time = ioloop_time; |
680 maildir_uidlist_add_flags(ibox->uidlist, | 683 maildir_uidlist_add_flags(mbox->uidlist, |
681 filename, | 684 filename, |
682 MAILDIR_UIDLIST_REC_FLAG_RACING); | 685 MAILDIR_UIDLIST_REC_FLAG_RACING); |
683 | 686 |
684 seq--; | 687 seq--; |
685 continue; | 688 continue; |
714 /* partial syncing */ | 717 /* partial syncing */ |
715 seq--; | 718 seq--; |
716 continue; | 719 continue; |
717 } | 720 } |
718 if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) { | 721 if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) { |
719 mail_storage_set_critical(ibox->box.storage, | 722 mail_storage_set_critical( |
723 &mbox->storage->storage, | |
720 "Maildir %s sync: " | 724 "Maildir %s sync: " |
721 "UID inserted in the middle of mailbox " | 725 "UID inserted in the middle of mailbox " |
722 "(%u > %u, file = %s)", | 726 "(%u > %u, file = %s)", |
723 ibox->path, rec->uid, uid, filename); | 727 mbox->path, rec->uid, uid, filename); |
724 mail_index_mark_corrupted(ibox->index); | 728 mail_index_mark_corrupted(mbox->ibox.index); |
725 ret = -1; | 729 ret = -1; |
726 break; | 730 break; |
727 } | 731 } |
728 | 732 |
729 ibox->dirty_cur_time = ioloop_time; | 733 mbox->dirty_cur_time = ioloop_time; |
730 maildir_uidlist_add_flags(ibox->uidlist, filename, | 734 maildir_uidlist_add_flags(mbox->uidlist, filename, |
731 MAILDIR_UIDLIST_REC_FLAG_RACING); | 735 MAILDIR_UIDLIST_REC_FLAG_RACING); |
732 | 736 |
733 seq--; | 737 seq--; |
734 continue; | 738 continue; |
735 } | 739 } |
736 | 740 |
737 if ((rec->flags & MAIL_RECENT) != 0) { | 741 if ((rec->flags & MAIL_RECENT) != 0) { |
738 index_mailbox_set_recent(ibox, seq); | 742 index_mailbox_set_recent(&mbox->ibox, seq); |
739 if (ibox->keep_recent) { | 743 if (mbox->ibox.keep_recent) { |
740 flags |= MAIL_RECENT; | 744 flags |= MAIL_RECENT; |
741 } else { | 745 } else { |
742 mail_index_update_flags(trans, seq, | 746 mail_index_update_flags(trans, seq, |
743 MODIFY_REMOVE, | 747 MODIFY_REMOVE, |
744 MAIL_RECENT); | 748 MAIL_RECENT); |
779 for (seq++; seq <= hdr->messages_count; seq++) | 783 for (seq++; seq <= hdr->messages_count; seq++) |
780 mail_index_expunge(trans, seq); | 784 mail_index_expunge(trans, seq); |
781 } | 785 } |
782 | 786 |
783 /* now, sync the index */ | 787 /* now, sync the index */ |
784 ibox->syncing_commit = TRUE; | 788 mbox->syncing_commit = TRUE; |
785 while ((ret = mail_index_sync_next(sync_ctx->sync_ctx, | 789 while ((ret = mail_index_sync_next(sync_ctx->sync_ctx, |
786 &sync_ctx->sync_rec)) > 0) { | 790 &sync_ctx->sync_rec)) > 0) { |
787 if (maildir_sync_record(ibox, sync_ctx) < 0) { | 791 if (maildir_sync_record(mbox, sync_ctx) < 0) { |
788 ret = -1; | 792 ret = -1; |
789 break; | 793 break; |
790 } | 794 } |
791 } | 795 } |
792 ibox->syncing_commit = FALSE; | 796 mbox->syncing_commit = FALSE; |
793 | 797 |
794 if (ibox->dirty_cur_time == 0 && | 798 if (mbox->dirty_cur_time == 0 && |
795 ibox->last_cur_mtime != (time_t)hdr->sync_stamp) { | 799 mbox->last_cur_mtime != (time_t)hdr->sync_stamp) { |
796 uint32_t sync_stamp = ibox->last_cur_mtime; | 800 uint32_t sync_stamp = mbox->last_cur_mtime; |
797 | 801 |
798 mail_index_update_header(trans, | 802 mail_index_update_header(trans, |
799 offsetof(struct mail_index_header, sync_stamp), | 803 offsetof(struct mail_index_header, sync_stamp), |
800 &sync_stamp, sizeof(sync_stamp)); | 804 &sync_stamp, sizeof(sync_stamp)); |
801 } | 805 } |
802 | 806 |
803 if (hdr->uid_validity == 0) { | 807 if (hdr->uid_validity == 0) { |
804 /* get the initial uidvalidity */ | 808 /* get the initial uidvalidity */ |
805 if (maildir_uidlist_update(ibox->uidlist) < 0) | 809 if (maildir_uidlist_update(mbox->uidlist) < 0) |
806 ret = -1; | 810 ret = -1; |
807 uid_validity = maildir_uidlist_get_uid_validity(ibox->uidlist); | 811 uid_validity = maildir_uidlist_get_uid_validity(mbox->uidlist); |
808 if (uid_validity == 0) { | 812 if (uid_validity == 0) { |
809 uid_validity = ioloop_time; | 813 uid_validity = ioloop_time; |
810 maildir_uidlist_set_uid_validity(ibox->uidlist, | 814 maildir_uidlist_set_uid_validity(mbox->uidlist, |
811 uid_validity); | 815 uid_validity); |
812 } | 816 } |
813 } else if (uid_validity == 0) { | 817 } else if (uid_validity == 0) { |
814 maildir_uidlist_set_uid_validity(ibox->uidlist, | 818 maildir_uidlist_set_uid_validity(mbox->uidlist, |
815 hdr->uid_validity); | 819 hdr->uid_validity); |
816 } | 820 } |
817 | 821 |
818 if (uid_validity != hdr->uid_validity && uid_validity != 0) { | 822 if (uid_validity != hdr->uid_validity && uid_validity != 0) { |
819 mail_index_update_header(trans, | 823 mail_index_update_header(trans, |
820 offsetof(struct mail_index_header, uid_validity), | 824 offsetof(struct mail_index_header, uid_validity), |
821 &uid_validity, sizeof(uid_validity)); | 825 &uid_validity, sizeof(uid_validity)); |
822 } | 826 } |
823 | 827 |
824 next_uid = maildir_uidlist_get_next_uid(ibox->uidlist); | 828 next_uid = maildir_uidlist_get_next_uid(mbox->uidlist); |
825 if (next_uid != 0 && hdr->next_uid != next_uid) { | 829 if (next_uid != 0 && hdr->next_uid != next_uid) { |
826 mail_index_update_header(trans, | 830 mail_index_update_header(trans, |
827 offsetof(struct mail_index_header, next_uid), | 831 offsetof(struct mail_index_header, next_uid), |
828 &next_uid, sizeof(next_uid)); | 832 &next_uid, sizeof(next_uid)); |
829 } | 833 } |
836 uoff_t offset; | 840 uoff_t offset; |
837 | 841 |
838 if (mail_index_transaction_commit(trans, &seq, &offset) < 0) | 842 if (mail_index_transaction_commit(trans, &seq, &offset) < 0) |
839 ret = -1; | 843 ret = -1; |
840 else if (seq != 0) { | 844 else if (seq != 0) { |
841 ibox->commit_log_file_seq = seq; | 845 mbox->ibox.commit_log_file_seq = seq; |
842 ibox->commit_log_file_offset = offset; | 846 mbox->ibox.commit_log_file_offset = offset; |
843 } | 847 } |
844 if (mail_index_sync_commit(sync_ctx->sync_ctx) < 0) | 848 if (mail_index_sync_commit(sync_ctx->sync_ctx) < 0) |
845 ret = -1; | 849 ret = -1; |
846 } | 850 } |
847 | 851 |
848 if (ret == 0) { | 852 if (ret == 0) { |
849 ibox->commit_log_file_seq = 0; | 853 mbox->ibox.commit_log_file_seq = 0; |
850 ibox->commit_log_file_offset = 0; | 854 mbox->ibox.commit_log_file_offset = 0; |
851 } else { | 855 } else { |
852 mail_storage_set_index_error(ibox); | 856 mail_storage_set_index_error(&mbox->ibox); |
853 } | 857 } |
854 | 858 |
855 i_free(sync_ctx); | 859 i_free(sync_ctx); |
856 return ret; | 860 return ret; |
857 } | 861 } |
913 The second case is still a problem with external changes though, | 917 The second case is still a problem with external changes though, |
914 because maildir doesn't require any kind of locking. Luckily this | 918 because maildir doesn't require any kind of locking. Luckily this |
915 problem rarely happens except under high amount of modifications. | 919 problem rarely happens except under high amount of modifications. |
916 */ | 920 */ |
917 | 921 |
918 if (!ctx->ibox->syncing_commit) { | 922 if (!ctx->mbox->syncing_commit) { |
919 ctx->index_sync_ctx = maildir_sync_index_begin(ctx->ibox); | 923 ctx->index_sync_ctx = maildir_sync_index_begin(ctx->mbox); |
920 if (ctx->index_sync_ctx == NULL) | 924 if (ctx->index_sync_ctx == NULL) |
921 return -1; | 925 return -1; |
922 } | 926 } |
923 | 927 |
924 if ((ret = maildir_uidlist_lock(ctx->ibox->uidlist)) <= 0) { | 928 if ((ret = maildir_uidlist_lock(ctx->mbox->uidlist)) <= 0) { |
925 /* failure / timeout. if forced is TRUE, we could still go | 929 /* failure / timeout. if forced is TRUE, we could still go |
926 forward and check only for renamed files, but is it worth | 930 forward and check only for renamed files, but is it worth |
927 the trouble? .. */ | 931 the trouble? .. */ |
928 return ret; | 932 return ret; |
929 } | 933 } |
930 | 934 |
931 ctx->partial = !cur_changed; | 935 ctx->partial = !cur_changed; |
932 ctx->uidlist_sync_ctx = | 936 ctx->uidlist_sync_ctx = |
933 maildir_uidlist_sync_init(ctx->ibox->uidlist, ctx->partial); | 937 maildir_uidlist_sync_init(ctx->mbox->uidlist, ctx->partial); |
934 | 938 |
935 if (maildir_scan_dir(ctx, TRUE) < 0) | 939 if (maildir_scan_dir(ctx, TRUE) < 0) |
936 return -1; | 940 return -1; |
937 if (cur_changed) { | 941 if (cur_changed) { |
938 if (maildir_scan_dir(ctx, FALSE) < 0) | 942 if (maildir_scan_dir(ctx, FALSE) < 0) |
939 return -1; | 943 return -1; |
940 } | 944 } |
941 | 945 |
942 /* finish uidlist syncing, but keep it still locked */ | 946 /* finish uidlist syncing, but keep it still locked */ |
943 maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx); | 947 maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx); |
944 if (!ctx->ibox->syncing_commit) { | 948 if (!ctx->mbox->syncing_commit) { |
945 if (maildir_sync_index_finish(ctx->index_sync_ctx, | 949 if (maildir_sync_index_finish(ctx->index_sync_ctx, |
946 ctx->partial) < 0) { | 950 ctx->partial) < 0) { |
947 ctx->index_sync_ctx = NULL; | 951 ctx->index_sync_ctx = NULL; |
948 return -1; | 952 return -1; |
949 } | 953 } |
954 ctx->uidlist_sync_ctx = NULL; | 958 ctx->uidlist_sync_ctx = NULL; |
955 | 959 |
956 return ret; | 960 return ret; |
957 } | 961 } |
958 | 962 |
959 int maildir_storage_sync_force(struct index_mailbox *ibox) | 963 int maildir_storage_sync_force(struct maildir_mailbox *mbox) |
960 { | 964 { |
961 struct maildir_sync_context *ctx; | 965 struct maildir_sync_context *ctx; |
962 int ret; | 966 int ret; |
963 | 967 |
964 ctx = maildir_sync_context_new(ibox); | 968 ctx = maildir_sync_context_new(mbox); |
965 ret = maildir_sync_context(ctx, TRUE); | 969 ret = maildir_sync_context(ctx, TRUE); |
966 maildir_sync_deinit(ctx); | 970 maildir_sync_deinit(ctx); |
967 return ret; | 971 return ret; |
968 } | 972 } |
969 | 973 |
970 struct mailbox_sync_context * | 974 struct mailbox_sync_context * |
971 maildir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags) | 975 maildir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags) |
972 { | 976 { |
973 struct index_mailbox *ibox = (struct index_mailbox *)box; | 977 struct maildir_mailbox *mbox = (struct maildir_mailbox *)box; |
974 struct maildir_sync_context *ctx; | 978 struct maildir_sync_context *ctx; |
975 int ret = 0; | 979 int ret = 0; |
976 | 980 |
977 if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 || | 981 if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 || |
978 ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) { | 982 mbox->ibox.sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= |
979 ibox->sync_last_check = ioloop_time; | 983 ioloop_time) { |
980 | 984 mbox->ibox.sync_last_check = ioloop_time; |
981 ctx = maildir_sync_context_new(ibox); | 985 |
986 ctx = maildir_sync_context_new(mbox); | |
982 ret = maildir_sync_context(ctx, FALSE); | 987 ret = maildir_sync_context(ctx, FALSE); |
983 maildir_sync_deinit(ctx); | 988 maildir_sync_deinit(ctx); |
984 } | 989 } |
985 | 990 |
986 return index_mailbox_sync_init(box, flags, ret < 0); | 991 return index_mailbox_sync_init(box, flags, ret < 0); |