Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}
Beispiel #4
0
/*
 * 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;
}