From 1a27cfa8e337b7e3298ba230059e766cdbc1123d Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 24 Aug 2020 19:10:43 +0300
Subject: [PATCH] imap: imap_client_hibernate() - Return reason string on
failure
This helps writing a unit test for it.
---
src/imap/cmd-idle.c | 3 ++-
src/imap/imap-client-hibernate.c | 10 +++++++++-
src/imap/imap-client.h | 5 +++--
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/src/imap/cmd-idle.c b/src/imap/cmd-idle.c
index 8a05582d03..2b31dc714e 100644
--- a/src/imap/cmd-idle.c
+++ b/src/imap/cmd-idle.c
@@ -175,11 +175,12 @@ static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx)
static void idle_hibernate_timeout(struct cmd_idle_context *ctx)
{
struct client *client = ctx->client;
+ const char *reason;
i_assert(ctx->sync_ctx == NULL);
i_assert(!ctx->sync_pending);
- if (imap_client_hibernate(&client)) {
+ if (imap_client_hibernate(&client, &reason)) {
/* client may be destroyed now */
} else {
/* failed - don't bother retrying */
diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c
index d3451b1bf6..0709e4a244 100644
--- a/src/imap/imap-client-hibernate.c
+++ b/src/imap/imap-client-hibernate.c
@@ -203,19 +203,23 @@ imap_hibernate_process_send(struct client *client, const buffer_t *state,
return 0;
}
-bool imap_client_hibernate(struct client **_client)
+bool imap_client_hibernate(struct client **_client, const char **reason_r)
{
struct client *client = *_client;
buffer_t *state;
const char *error;
int ret, fd_notify = -1, fd_hibernate = -1;
+ *reason_r = NULL;
+
if (client->fd_in != client->fd_out) {
/* we won't try to hibernate stdio clients */
+ *reason_r = "stdio clients can't be hibernated";
return FALSE;
}
if (o_stream_get_buffer_used_size(client->output) > 0) {
/* wait until we've sent the pending output to client */
+ *reason_r = "output pending to client";
return FALSE;
}
@@ -233,11 +237,13 @@ bool imap_client_hibernate(struct client **_client)
"Couldn't export state: %s (mailbox=%s)", error,
client->mailbox == NULL ? "" :
mailbox_get_vname(client->mailbox));
+ *reason_r = error;
} else if (ret == 0) {
e_debug(client->event, "Couldn't hibernate imap client: "
"Couldn't export state: %s (mailbox=%s)", error,
client->mailbox == NULL ? "" :
mailbox_get_vname(client->mailbox));
+ *reason_r = error;
}
if (ret > 0 && client->mailbox != NULL) {
fd_notify = mailbox_watch_extract_notify_fd(client->mailbox,
@@ -248,6 +254,7 @@ bool imap_client_hibernate(struct client **_client)
e_debug(client->event, "Couldn't hibernate imap client: "
"Couldn't extract notifications fd: %s",
error);
+ *reason_r = error;
ret = -1;
}
}
@@ -257,5 +264,6 @@ bool imap_client_hibernate(struct client **_client)
e_error(client->event,
"Couldn't hibernate imap client: %s", error);
+ *reason_r = error;
ret = -1;
}
}
diff --git a/src/imap/imap-client.h b/src/imap/imap-client.h
index f2ffe0d7c9..4e591d5c7c 100644
--- a/src/imap/imap-client.h
+++ b/src/imap/imap-client.h
@@ -323,8 +323,9 @@ enum mailbox_feature client_enabled_mailbox_features(struct client *client);
const char *const *client_enabled_features(struct client *client);
/* Send client processing to imap-idle process. If successful, returns TRUE
- and destroys the client. */
-bool imap_client_hibernate(struct client **client);
+ and destroys the client. If hibernation failed, the exact reason is
+ returned (mainly for unit tests). */
+bool imap_client_hibernate(struct client **client, const char **reason_r);
struct imap_search_update *
client_search_update_lookup(struct client *client, const char *tag,