bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "lib.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "ioloop.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "istream.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "write-full.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "strescape.h"
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen#include "process-title.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "master-service.h"
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen#include "master-service-settings.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "mail-namespace.h"
feaa6a3d82ea61496ced1f83a726ff33047c7da2Timo Sirainen#include "mail-storage-private.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "mail-storage-service.h"
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include "mail-search-build.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "master-connection.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include <unistd.h>
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#define INDEXER_PROTOCOL_MAJOR_VERSION 1
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#define INDEXER_PROTOCOL_MINOR_VERSION 0
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
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
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstruct master_connection {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct mail_storage_service_ctx *storage_service;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen int fd;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct io *io;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct istream *input;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct ostream *output;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool version_received:1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen};
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic void ATTR_NULL(1, 2)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenindexer_worker_refresh_proctitle(const char *username, const char *mailbox,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen uint32_t seq1, uint32_t seq2)
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen{
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen if (!master_service_settings_get(master_service)->verbose_proctitle)
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen return;
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (username == NULL)
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen process_title_set("[idling]");
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen else if (seq1 == 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen process_title_set(t_strdup_printf("[%s %s]", username, mailbox));
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen else {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen process_title_set(t_strdup_printf("[%s %s - %u/%u]",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen username, mailbox, seq1, seq2));
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainenstatic int
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainenindex_mailbox_precache(struct master_connection *conn, struct mailbox *box)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
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);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mailbox_status status;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mailbox_transaction_context *trans;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mail_search_args *search_args;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mail_search_context *ctx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mail *mail;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mailbox_metadata metadata;
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen uint32_t seq, first_uid = 0, last_uid = 0;
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen char percentage_str[2+1+1];
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen unsigned int counter = 0, max, percentage, percentage_sent = 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen int ret = 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_PRECACHE_FIELDS,
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen &metadata) < 0) {
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen i_error("Mailbox %s: Precache-fields lookup failed: %s",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_vname(box),
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen }
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen if (mailbox_get_status(box, STATUS_MESSAGES | STATUS_LAST_CACHED_SEQ,
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen &status) < 0) {
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen i_error("Mailbox %s: Status lookup failed: %s",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_vname(box),
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen return -1;
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen seq = status.last_cached_seq + 1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi trans = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_NO_CACHE_DEC,
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi "indexing");
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen search_args = mail_search_build_init();
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_search_build_add_seqset(search_args, seq, status.messages);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ctx = mailbox_search_init(trans, search_args, NULL,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen metadata.precache_fields, NULL);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_search_args_unref(&search_args);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
fced91d6314b7c934650b6ee2c540abc520efd74Timo Sirainen max = status.messages + 1 - seq;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen while (mailbox_search_next(ctx, &mail)) {
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen if (first_uid == 0)
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen first_uid = mail->uid;
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen last_uid = mail->uid;
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_precache(mail);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (++counter % 100 == 0) {
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen percentage = counter*100 / max;
5dba704bc6df4db2972ebfb2581b9061a0d19a89Timo Sirainen if (percentage != percentage_sent && percentage < 100) {
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen percentage_sent = percentage;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (i_snprintf(percentage_str,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen sizeof(percentage_str), "%u\n",
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen percentage) < 0)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen i_unreached();
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen (void)write_full(conn->fd, percentage_str,
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen strlen(percentage_str));
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen indexer_worker_refresh_proctitle(username, box_vname,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen counter, max);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen if (mailbox_search_deinit(&ctx) < 0) {
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen i_error("Mailbox %s: Mail search failed: %s",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_vname(box),
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ret = -1;
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen }
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen const char *uids = first_uid == 0 ? "" :
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen t_strdup_printf(" (UIDs %u..%u)", first_uid, last_uid);
2e429f79325f6a5fd90e966e654bcb0696e467a4Timo Sirainen if (mailbox_transaction_commit(&trans) < 0) {
14eac90de704acfdbea0e685cc33646dec76267cTimo Sirainen i_error("Mailbox %s: Transaction commit failed: %s"
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen " (attempted to index %u messages%s)",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_vname(box),
14eac90de704acfdbea0e685cc33646dec76267cTimo Sirainen mailbox_get_last_internal_error(box, NULL),
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen counter, uids);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ret = -1;
e4065b371a07ab584c02803125467cb9df26690eTimo Sirainen } else {
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen i_info("Indexed %u messages in %s%s",
1c197c242a4cc72897a7cc162a555db1c0773fdfTimo Sirainen counter, mailbox_get_vname(box), uids);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return ret;
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen}
0be9d7c58e51c21eb521501e212a8e8ff7593769Timo Sirainen
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainenstatic int
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainenindex_mailbox(struct master_connection *conn, struct mail_user *user,
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen const char *mailbox, unsigned int max_recent_msgs,
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen const char *what)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct mail_namespace *ns;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct mailbox *box;
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen struct mailbox_status status;
4605fd7e1fd4ff1fecb8494696fb3604cff46cf5Timo Sirainen const char *path, *errstr;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen enum mail_error error;
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen enum mailbox_sync_flags sync_flags = MAILBOX_SYNC_FLAG_FULL_READ;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen int ret;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen ns = mail_namespace_find(user->namespaces, mailbox);
feaa6a3d82ea61496ced1f83a726ff33047c7da2Timo Sirainen box = mailbox_alloc(ns->list, mailbox, 0);
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainen mailbox_set_reason(box, "indexing");
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX, &path);
73a7078395e91baebd7f1be197e844624c62b476Timo Sirainen if (ret < 0) {
73a7078395e91baebd7f1be197e844624c62b476Timo Sirainen i_error("Getting path to mailbox %s failed: %s",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox, mailbox_get_last_internal_error(box, NULL));
feaa6a3d82ea61496ced1f83a726ff33047c7da2Timo Sirainen mailbox_free(&box);
73a7078395e91baebd7f1be197e844624c62b476Timo Sirainen return -1;
73a7078395e91baebd7f1be197e844624c62b476Timo Sirainen }
73a7078395e91baebd7f1be197e844624c62b476Timo Sirainen if (ret == 0) {
cc3baa5b92de8d492bdb757bb6165b3eddb1a92eTimo Sirainen i_info("Indexes disabled for mailbox %s, skipping", mailbox);
73a7078395e91baebd7f1be197e844624c62b476Timo Sirainen mailbox_free(&box);
4605fd7e1fd4ff1fecb8494696fb3604cff46cf5Timo Sirainen return 0;
4605fd7e1fd4ff1fecb8494696fb3604cff46cf5Timo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = 0;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen if (max_recent_msgs != 0) {
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 if (mailbox_open(box) < 0) {
ecf44c74416ffa4e7c331e49a1e283be6b1aa668Timo Sirainen i_error("Opening mailbox %s failed: %s", mailbox,
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen ret = -1;
ecf44c74416ffa4e7c331e49a1e283be6b1aa668Timo Sirainen } else {
ecf44c74416ffa4e7c331e49a1e283be6b1aa668Timo Sirainen mailbox_get_open_status(box, STATUS_RECENT, &status);
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen }
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen if (ret < 0 || status.recent > max_recent_msgs) {
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen mailbox_free(&box);
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen return ret;
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen }
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen }
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen if (strchr(what, 'o') != NULL)
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen sync_flags |= MAILBOX_SYNC_FLAG_OPTIMIZE;
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen if (mailbox_sync(box, sync_flags) < 0) {
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi errstr = mailbox_get_last_internal_error(box, &error);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (error != MAIL_ERROR_NOTFOUND) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("Syncing mailbox %s failed: %s",
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen mailbox, errstr);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen } else if (user->mail_debug) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_debug("Syncing mailbox %s failed: %s",
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen mailbox, errstr);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen ret = -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen } else if (strchr(what, 'i') != NULL) {
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (index_mailbox_precache(conn, box) < 0)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen ret = -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen mailbox_free(&box);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return ret;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstatic int
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenmaster_connection_input_line(struct master_connection *conn, const char *line)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen const char *const *args = t_strsplit_tabescaped(line);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct mail_storage_service_input input;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct mail_storage_service_user *service_user;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct mail_user *user;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen const char *str, *error;
7c0e7d96e104a59df7b5aecdc0cbe4f6e304b7c7Timo Sirainen unsigned int max_recent_msgs;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen int ret;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen /* <username> <mailbox> <session ID> <max_recent_msgs> [i][o] */
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen if (str_array_length(args) != 5 ||
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);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&input);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen input.module = "mail";
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen input.service = "indexer-worker";
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen input.username = args[0];
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.) */
3e3cc37a780546844d1a3b17e2375534f36aa5f6Timo Sirainen if (args[2][0] != '\0')
3e3cc37a780546844d1a3b17e2375534f36aa5f6Timo Sirainen input.session_id_prefix = args[2];
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (mail_storage_service_lookup_next(conn->storage_service, &input,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen &service_user, &user, &error) <= 0) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("User %s lookup failed: %s", args[0], error);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen ret = -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen } else {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen indexer_worker_refresh_proctitle(user->username, args[1], 0, 0);
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen ret = index_mailbox(conn, user, args[1],
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen max_recent_msgs, args[4]);
3c6a7ca2d3ed89dd999cc6885220097777090791Timo Sirainen /* refresh proctitle before a potentially long-running
3c6a7ca2d3ed89dd999cc6885220097777090791Timo Sirainen user unref */
3c6a7ca2d3ed89dd999cc6885220097777090791Timo Sirainen indexer_worker_refresh_proctitle(user->username, "(deinit)", 0, 0);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen mail_user_unref(&user);
eb318ea05532d2e54ed3bfc89bc15dcf1adae838Timo Sirainen mail_storage_service_user_unref(&service_user);
3c6a7ca2d3ed89dd999cc6885220097777090791Timo Sirainen indexer_worker_refresh_proctitle(NULL, NULL, 0, 0);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen str = ret < 0 ? "-1\n" : "100\n";
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return write_full(conn->fd, str, strlen(str));
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstatic void master_connection_input(struct master_connection *conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen const char *line;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen int ret;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (i_stream_read(conn->input) < 0) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen master_service_stop(master_service);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (!conn->version_received) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if ((line = i_stream_next_line(conn->input)) == NULL)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (!version_string_verify(line, INDEXER_MASTER_NAME,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen INDEXER_PROTOCOL_MAJOR_VERSION)) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("Indexer master not compatible with this master "
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen "(mixed old and new binaries?)");
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen master_service_stop(master_service);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->version_received = TRUE;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen T_BEGIN {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen ret = master_connection_input_line(conn, line);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen } T_END;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (ret < 0) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen master_service_stop(master_service);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen break;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstruct master_connection *
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenmaster_connection_create(int fd, struct mail_storage_service_ctx *storage_service)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct master_connection *conn;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen const char *handshake;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn = i_new(struct master_connection, 1);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->storage_service = storage_service;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->fd = fd;
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
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 Sirainen return conn;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenvoid master_connection_destroy(struct master_connection **_conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct master_connection *conn = *_conn;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen *_conn = NULL;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen io_remove(&conn->io);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_stream_destroy(&conn->input);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (close(conn->fd) < 0)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("close(master conn) failed: %m");
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_free(conn);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen master_service_client_connection_destroyed(master_service);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}