bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "lib.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "array.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "aqueue.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "ioloop.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "istream.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "ostream.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "str.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "strescape.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "master-service.h"
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen#include "indexer-queue.h"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#include "worker-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_MASTER_HANDSHAKE "VERSION\tindexer-master-worker\t1\t0\n"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen#define INDEXER_WORKER_NAME "indexer-worker-master"
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstruct worker_connection {
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen int refcount;
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen char *socket_path;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen indexer_status_callback_t *callback;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen int fd;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct io *io;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct istream *input;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct ostream *output;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen char *request_username;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(void *) request_contexts;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct aqueue *request_queue;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen unsigned int process_limit;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool version_received:1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen};
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstruct worker_connection *
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenworker_connection_create(const char *socket_path,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen indexer_status_callback_t *callback)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct worker_connection *conn;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn = i_new(struct worker_connection, 1);
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen conn->refcount = 1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->socket_path = i_strdup(socket_path);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->callback = callback;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->fd = -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_array_init(&conn->request_contexts, 32);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->request_queue = aqueue_init(&conn->request_contexts.arr);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return conn;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainenstatic void worker_connection_unref(struct worker_connection *conn)
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen{
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen i_assert(conn->refcount > 0);
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen if (--conn->refcount > 0)
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen return;
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen aqueue_deinit(&conn->request_queue);
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen array_free(&conn->request_contexts);
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen i_free(conn->socket_path);
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen i_free(conn);
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen}
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstatic void worker_connection_disconnect(struct worker_connection *conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen unsigned int i, count = aqueue_count(conn->request_queue);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (conn->fd != -1) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen io_remove(&conn->io);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_stream_destroy(&conn->input);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen o_stream_destroy(&conn->output);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (close(conn->fd) < 0)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("close(%s) failed: %m", conn->socket_path);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->fd = -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen /* cancel any pending requests */
b24870f2d47f9f1f5f373af6287b1d48e383e74dTimo Sirainen if (count > 0) {
2ee34f0b0b15523389fe3774788acbd412176253Timo Sirainen i_error("Indexer worker disconnected, "
2ee34f0b0b15523389fe3774788acbd412176253Timo Sirainen "discarding %u requests for %s",
2ee34f0b0b15523389fe3774788acbd412176253Timo Sirainen count, conn->request_username);
b24870f2d47f9f1f5f373af6287b1d48e383e74dTimo Sirainen }
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen /* conn->callback() can try to destroy us */
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen conn->refcount++;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen for (i = 0; i < count; i++) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen void *const *contextp =
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen array_idx(&conn->request_contexts,
7fdc192eecebb462cf72d2aaeacea6a30000d0acTimo Sirainen aqueue_idx(conn->request_queue, 0));
b24870f2d47f9f1f5f373af6287b1d48e383e74dTimo Sirainen void *context = *contextp;
b24870f2d47f9f1f5f373af6287b1d48e383e74dTimo Sirainen
b24870f2d47f9f1f5f373af6287b1d48e383e74dTimo Sirainen aqueue_delete_tail(conn->request_queue);
b24870f2d47f9f1f5f373af6287b1d48e383e74dTimo Sirainen conn->callback(-1, context);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
71dc24a58788ccd92723c68bef37584ffc34b984Timo Sirainen i_free_and_null(conn->request_username);
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen worker_connection_unref(conn);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenvoid worker_connection_destroy(struct worker_connection **_conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen struct worker_connection *conn = *_conn;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen *_conn = NULL;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen worker_connection_disconnect(conn);
2a4723165754cf9a93d7d91a9fb7949176ddd38bTimo Sirainen worker_connection_unref(conn);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstatic int
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenworker_connection_input_line(struct worker_connection *conn, const char *line)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen void *const *contextp, *context;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen int percentage;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (aqueue_count(conn->request_queue) == 0) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("Input from worker without pending requests: %s", line);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (str_to_int(line, &percentage) < 0 ||
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen percentage < -1 || percentage > 100) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("Invalid input from worker: %s", line);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen contextp = array_idx(&conn->request_contexts,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen aqueue_idx(conn->request_queue, 0));
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen context = *contextp;
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen if (percentage < 0 || percentage == 100) {
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen /* the request is finished */
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen aqueue_delete_tail(conn->request_queue);
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen if (aqueue_count(conn->request_queue) == 0)
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen i_free_and_null(conn->request_username);
ff9eb4a57ff1a151182cdfbfc19f5a4bed54ecafTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->callback(percentage, context);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return 0;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenstatic void worker_connection_input(struct worker_connection *conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen const char *line;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (i_stream_read(conn->input) < 0) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen worker_connection_disconnect(conn);
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_WORKER_NAME,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen INDEXER_PROTOCOL_MAJOR_VERSION)) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("Indexer worker not compatible with this master "
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen "(mixed old and new binaries?)");
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen worker_connection_disconnect(conn);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->version_received = TRUE;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (conn->process_limit == 0) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if ((line = i_stream_next_line(conn->input)) == NULL)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (str_to_uint(line, &conn->process_limit) < 0 ||
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->process_limit == 0) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("Indexer worker sent invalid handshake: %s",
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen line);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen worker_connection_disconnect(conn);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (worker_connection_input_line(conn, line) < 0) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen worker_connection_disconnect(conn);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen break;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenint worker_connection_connect(struct worker_connection *conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_assert(conn->fd == -1);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->fd = net_connect_unix(conn->socket_path);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (conn->fd == -1) {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_error("connect(%s) failed: %m", conn->socket_path);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen conn->io = io_add(conn->fd, IO_READ, worker_connection_input, conn);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->input = i_stream_create_fd(conn->fd, (size_t)-1);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->output = o_stream_create_fd(conn->fd, (size_t)-1);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_set_no_error_handling(conn->output, TRUE);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(conn->output, INDEXER_MASTER_HANDSHAKE);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return 0;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenbool worker_connection_is_connected(struct worker_connection *conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return conn->fd != -1;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenbool worker_connection_get_process_limit(struct worker_connection *conn,
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen unsigned int *limit_r)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (conn->process_limit == 0)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return FALSE;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen *limit_r = conn->process_limit;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return TRUE;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenvoid worker_connection_request(struct worker_connection *conn,
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen const struct indexer_request *request,
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen void *context)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_assert(worker_connection_is_connected(conn));
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen i_assert(context != NULL);
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen i_assert(request->index || request->optimize);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen if (conn->request_username == NULL)
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen conn->request_username = i_strdup(request->username);
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen else {
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen i_assert(strcmp(conn->request_username,
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen request->username) == 0);
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen }
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen aqueue_append(conn->request_queue, &context);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen T_BEGIN {
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen string_t *str = t_str_new(128);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(str, request->username);
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen str_append_c(str, '\t');
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(str, request->mailbox);
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen str_append_c(str, '\t');
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen if (request->session_id != NULL)
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen str_append_tabescaped(str, request->session_id);
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen str_printfa(str, "\t%u\t", request->max_recent_msgs);
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen if (request->index)
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen str_append_c(str, 'i');
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen if (request->optimize)
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen str_append_c(str, 'o');
294f579cd3803e2d9997231fdc46523c23774a8fTimo Sirainen str_append_c(str, '\n');
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(conn->output, str_data(str), str_len(str));
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen } T_END;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenbool worker_connection_is_busy(struct worker_connection *conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return aqueue_count(conn->request_queue) > 0;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainenconst char *worker_connection_get_username(struct worker_connection *conn)
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen{
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen return conn->request_username;
d9e404180ff26dbbaea68534a5f176765022b76bTimo Sirainen}