bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#define INDEXER_WORKER_HANDSHAKE "VERSION\tindexer-worker-master\t1\t0\n%u\n"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#define INDEXER_MASTER_NAME "indexer-master-worker"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct mail_storage_service_ctx *storage_service;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenindexer_worker_refresh_proctitle(const char *username, const char *mailbox,
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen if (!master_service_settings_get(master_service)->verbose_proctitle)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen else if (seq1 == 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen process_title_set(t_strdup_printf("[%s %s]", username, mailbox));
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen process_title_set(t_strdup_printf("[%s %s - %u/%u]",
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainenindex_mailbox_precache(struct master_connection *conn, struct mailbox *box)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mail_storage *storage = mailbox_get_storage(box);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const char *username = mail_storage_get_user(storage)->username;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const char *box_vname = mailbox_get_vname(box);
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen unsigned int counter = 0, max, percentage, percentage_sent = 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_PRECACHE_FIELDS,
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen i_error("Mailbox %s: Precache-fields lookup failed: %s",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen if (mailbox_get_status(box, STATUS_MESSAGES | STATUS_LAST_CACHED_SEQ,
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen i_error("Mailbox %s: Status lookup failed: %s",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi trans = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_NO_CACHE_DEC,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_search_build_add_seqset(search_args, seq, status.messages);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ctx = mailbox_search_init(trans, search_args, NULL,
5dba704bc6df4db2972ebfb2581b9061a0d19a89Timo Sirainen if (percentage != percentage_sent && percentage < 100) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen indexer_worker_refresh_proctitle(username, box_vname,
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen t_strdup_printf(" (UIDs %u..%u)", first_uid, last_uid);
14eac90de704acfdbea0e685cc33646dec76267cTimo Sirainen i_error("Mailbox %s: Transaction commit failed: %s"
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen " (attempted to index %u messages%s)",
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainenindex_mailbox(struct master_connection *conn, struct mail_user *user,
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen const char *mailbox, unsigned int max_recent_msgs,
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen enum mailbox_sync_flags sync_flags = MAILBOX_SYNC_FLAG_FULL_READ;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen ns = mail_namespace_find(user->namespaces, mailbox);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX, &path);
73a7078395e91baebd7f1be197e844624c62b476Timo Sirainen i_error("Getting path to mailbox %s failed: %s",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox, mailbox_get_last_internal_error(box, NULL));
cc3baa5b92de8d492bdb757bb6165b3eddb1a92eTimo Sirainen i_info("Indexes disabled for mailbox %s, skipping", mailbox);
ecf44c74416ffa4e7c331e49a1e283be6b1aa668Timo Sirainen /* index only if there aren't too many recent messages.
ecf44c74416ffa4e7c331e49a1e283be6b1aa668Timo Sirainen don't bother syncing the mailbox, that alone can take a
ecf44c74416ffa4e7c331e49a1e283be6b1aa668Timo Sirainen while with large maildirs. */
ecf44c74416ffa4e7c331e49a1e283be6b1aa668Timo Sirainen i_error("Opening mailbox %s failed: %s", mailbox,
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
ecf44c74416ffa4e7c331e49a1e283be6b1aa668Timo Sirainen mailbox_get_open_status(box, STATUS_RECENT, &status);
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen if (ret < 0 || status.recent > max_recent_msgs) {
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi errstr = mailbox_get_last_internal_error(box, &error);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenmaster_connection_input_line(struct master_connection *conn, const char *line)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen const char *const *args = t_strsplit_tabescaped(line);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct mail_storage_service_user *service_user;
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen /* <username> <mailbox> <session ID> <max_recent_msgs> [i][o] */
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen str_to_uint(args[3], &max_recent_msgs) < 0 || args[4][0] == '\0') {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("Invalid input from master: %s", line);
3e3cc37a780546844d1a3b17e2375534f36aa5f6Timo Sirainen /* if session-id is given, use it as a prefix to a unique session ID.
3e3cc37a780546844d1a3b17e2375534f36aa5f6Timo Sirainen we can't use the session-id directly or stats process will complain
3e3cc37a780546844d1a3b17e2375534f36aa5f6Timo Sirainen about duplicates. (especially LMTP would use the same session-id for
3e3cc37a780546844d1a3b17e2375534f36aa5f6Timo Sirainen multiple users' indexing at the same time.) */
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (mail_storage_service_lookup_next(conn->storage_service, &input,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("User %s lookup failed: %s", args[0], error);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen indexer_worker_refresh_proctitle(user->username, args[1], 0, 0);
3c6a7ca2d3ed89dd999cc6885220097777090791Timo Sirainen /* refresh proctitle before a potentially long-running
3c6a7ca2d3ed89dd999cc6885220097777090791Timo Sirainen user unref */
3c6a7ca2d3ed89dd999cc6885220097777090791Timo Sirainen indexer_worker_refresh_proctitle(user->username, "(deinit)", 0, 0);
eb318ea05532d2e54ed3bfc89bc15dcf1adae838Timo Sirainen mail_storage_service_user_unref(&service_user);
3c6a7ca2d3ed89dd999cc6885220097777090791Timo Sirainen indexer_worker_refresh_proctitle(NULL, NULL, 0, 0);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return write_full(conn->fd, str, strlen(str));
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstatic void master_connection_input(struct master_connection *conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if ((line = i_stream_next_line(conn->input)) == NULL)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (!version_string_verify(line, INDEXER_MASTER_NAME,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("Indexer master not compatible with this master "
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen "(mixed old and new binaries?)");
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen ret = master_connection_input_line(conn, line);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenmaster_connection_create(int fd, struct mail_storage_service_ctx *storage_service)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->io = io_add(conn->fd, IO_READ, master_connection_input, conn);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->input = i_stream_create_fd(conn->fd, (size_t)-1);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen handshake = t_strdup_printf(INDEXER_WORKER_HANDSHAKE,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen master_service_get_process_limit(master_service));
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen (void)write_full(conn->fd, handshake, strlen(handshake));
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenvoid master_connection_destroy(struct master_connection **_conn)