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);