static int do_synclogfile(const char *synclogfile) { strarray_t *folders = NULL; sync_log_reader_t *slr; int nskipped = 0; int i; int r; slr = sync_log_reader_create_with_filename(synclogfile); r = sync_log_reader_begin(slr); if (r) goto out; folders = read_sync_log_items(slr); sync_log_reader_end(slr); /* sort folders for locality of reference in file processing mode */ strarray_sort(folders, cmpstringp_raw); signals_poll(); /* have some due items in the queue, try to index them */ rx = search_begin_update(verbose); for (i = 0; i < folders->count; i++) { const char *mboxname = strarray_nth(folders, i); if (verbose > 1) syslog(LOG_INFO, "do_synclogfile: indexing %s", mboxname); r = index_one(mboxname, /*blocking*/1); if (r == IMAP_MAILBOX_NONEXISTENT) r = 0; if (r == IMAP_MAILBOX_LOCKED || r == IMAP_AGAIN) { nskipped++; if (nskipped > 10000) { syslog(LOG_ERR, "IOERROR: skipped too many times at %s", mboxname); break; } r = 0; /* try again at the end */ strarray_append(folders, mboxname); } if (r) { syslog(LOG_ERR, "IOERROR: failed to index %s: %s", mboxname, error_message(r)); break; } if (sleepmicroseconds) usleep(sleepmicroseconds); } search_end_update(rx); rx = NULL; out: strarray_free(folders); sync_log_reader_free(slr); return r; }
static int do_sync_filename(const char *filename) { sync_log_reader_t *slr; int r; if ((filename == NULL) || !strcmp(filename, "-")) slr = sync_log_reader_create_with_fd(0); /* STDIN */ else slr = sync_log_reader_create_with_filename(filename); r = sync_log_reader_begin(slr); if (!r) r = do_sync(slr); sync_log_reader_end(slr); sync_log_reader_free(slr); return r; }
static int do_daemon_work(const char *channel, const char *sync_shutdown_file, unsigned long timeout, unsigned long min_delta, int *restartp) { int r = 0; time_t session_start; time_t single_start; int delta; struct stat sbuf; sync_log_reader_t *slr; *restartp = RESTART_NONE; slr = sync_log_reader_create_with_channel(channel); session_start = time(NULL); while (1) { single_start = time(NULL); signals_poll(); /* Check for shutdown file */ if (sync_shutdown_file && !stat(sync_shutdown_file, &sbuf)) { unlink(sync_shutdown_file); break; } /* See if its time to RESTART */ if ((timeout > 0) && ((single_start - session_start) > (time_t) timeout)) { *restartp = RESTART_NORMAL; break; } r = sync_log_reader_begin(slr); if (r) { /* including specifically r == IMAP_AGAIN */ if (min_delta > 0) { sleep(min_delta); } else { usleep(100000); /* 1/10th second */ } continue; } /* Process the work log */ if ((r=do_sync(slr))) { syslog(LOG_ERR, "Processing sync log file %s failed: %s", sync_log_reader_get_file_name(slr), error_message(r)); break; } r = sync_log_reader_end(slr); if (r) break; delta = time(NULL) - single_start; if (((unsigned) delta < min_delta) && ((min_delta-delta) > 0)) sleep(min_delta-delta); } sync_log_reader_free(slr); if (*restartp == RESTART_NORMAL) { r = do_restart(); if (r) { syslog(LOG_ERR, "sync_client RESTART failed: %s", error_message(r)); } else { syslog(LOG_INFO, "sync_client RESTART succeeded"); } r = 0; } return(r); }
/* * Begin reading a sync log file. If the reader is reading from a * channel, rename the current log file so it will not be appended to by * the write side code, and open the file. Otherwise, just open the file * (note this is still necessary even when the reader is reading from a * file descriptor). * * When sync_log_reader_begin() returns success, you should loop calling * sync_log_reader_getitem() and handling the items, until it returns * EOF, and then call sync_log_reader_end(). * * Returns zero on success, IMAP_AGAIN if reading from a channel and * there is no current log file, or an IMAP error code on failure. */ EXPORTED int sync_log_reader_begin(sync_log_reader_t *slr) { struct stat sbuf; int r; if (slr->input) { r = sync_log_reader_end(slr); if (r) return r; } if (stat(slr->work_file, &sbuf) == 0) { /* Existing work log file - process this first */ syslog(LOG_NOTICE, "Reprocessing sync log file %s", slr->work_file); } else if (!slr->log_file) { syslog(LOG_ERR, "Failed to stat %s: %m", slr->log_file); return IMAP_IOERROR; } else { /* Check for sync_log file */ if (stat(slr->log_file, &sbuf) < 0) { if (errno == ENOENT) return IMAP_AGAIN; /* no problem, try again later */ syslog(LOG_ERR, "Failed to stat %s: %m", slr->log_file); return IMAP_IOERROR; } /* Move sync_log to our work file */ if (rename(slr->log_file, slr->work_file) < 0) { syslog(LOG_ERR, "Rename %s -> %s failed: %m", slr->log_file, slr->work_file); return IMAP_IOERROR; } } if (slr->fd < 0) { int fd = open(slr->work_file, O_RDWR, 0); if (fd < 0) { syslog(LOG_ERR, "Failed to open %s: %m", slr->work_file); return IMAP_IOERROR; } if (lock_blocking(fd, slr->work_file) < 0) { syslog(LOG_ERR, "Failed to lock %s: %m", slr->work_file); close(fd); return IMAP_IOERROR; } slr->fd = fd; slr->fd_is_ours = 1; /* we can unlock immediately, since we have serialised * any process which held the lock over the rename. All * future attempts to lock this inode will stat and notice * the rename, so they won't write any more */ lock_unlock(slr->fd, slr->work_file); } slr->input = prot_new(slr->fd, /*write*/0); return 0; }