]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
log: Forgot to add new files to recent commit.
authorTimo Sirainen <tss@iki.fi>
Mon, 6 Feb 2012 19:25:37 +0000 (21:25 +0200)
committerTimo Sirainen <tss@iki.fi>
Mon, 6 Feb 2012 19:25:37 +0000 (21:25 +0200)
src/log/doveadm-connection.c [new file with mode: 0644]
src/log/doveadm-connection.h [new file with mode: 0644]
src/log/log-error-buffer.c [new file with mode: 0644]
src/log/log-error-buffer.h [new file with mode: 0644]

diff --git a/src/log/doveadm-connection.c b/src/log/doveadm-connection.c
new file mode 100644 (file)
index 0000000..9c5f1ed
--- /dev/null
@@ -0,0 +1,88 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ostream.h"
+#include "str.h"
+#include "strescape.h"
+#include "master-service.h"
+#include "log-error-buffer.h"
+#include "doveadm-connection.h"
+
+#include <unistd.h>
+
+struct doveadm_connection {
+       struct log_error_buffer *errorbuf;
+
+       int fd;
+       struct ostream *output;
+};
+
+static void doveadm_connection_destroy(struct doveadm_connection **_conn);
+
+static int doveadm_connection_send_errors(struct doveadm_connection *conn)
+{
+       struct log_error_buffer_iter *iter;
+       const struct log_error *error;
+       string_t *str = t_str_new(256);
+       int ret = 0;
+
+       iter = log_error_buffer_iter_init(conn->errorbuf);
+       while ((error = log_error_buffer_iter_next(iter)) != NULL) {
+               str_truncate(str, 0);
+               str_printfa(str, "%s\t%ld\t",
+                           failure_log_type_names[error->type],
+                           (long)error->timestamp);
+               str_tabescape_write(str, error->prefix);
+               str_append_c(str, '\t');
+               str_tabescape_write(str, error->text);
+               str_append_c(str, '\n');
+               if (o_stream_send(conn->output,
+                                 str_data(str), str_len(str)) < 0) {
+                       ret = -1;
+                       break;
+               }
+       }
+       log_error_buffer_iter_deinit(&iter);
+       return ret;
+}
+
+static int doveadm_output(struct doveadm_connection *conn)
+{
+       int ret;
+
+       if ((ret = o_stream_flush(conn->output)) != 0) {
+               /* error / finished */
+               doveadm_connection_destroy(&conn);
+       }
+       return 1;
+}
+
+void doveadm_connection_create(struct log_error_buffer *errorbuf, int fd)
+{
+       struct doveadm_connection *conn;
+
+       conn = i_new(struct doveadm_connection, 1);
+       conn->errorbuf = errorbuf;
+       conn->fd = fd;
+       conn->output = o_stream_create_fd(conn->fd, (size_t)-1, FALSE);
+       if (doveadm_connection_send_errors(conn) < 0)
+               doveadm_connection_destroy(&conn);
+       else {
+               o_stream_set_flush_callback(conn->output, doveadm_output, conn);
+               o_stream_set_flush_pending(conn->output, TRUE);
+       }
+}
+
+static void doveadm_connection_destroy(struct doveadm_connection **_conn)
+{
+       struct doveadm_connection *conn = *_conn;
+
+       *_conn = NULL;
+
+       o_stream_destroy(&conn->output);
+       if (close(conn->fd) < 0)
+               i_error("close(doveadm connection) failed: %m");
+       i_free(conn);
+
+       master_service_client_connection_destroyed(master_service);
+}
diff --git a/src/log/doveadm-connection.h b/src/log/doveadm-connection.h
new file mode 100644 (file)
index 0000000..c37eee4
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef DOVEADM_CONNECTION_H
+#define DOVEADM_CONNECTION_H
+
+void doveadm_connection_create(struct log_error_buffer *errorbuf, int fd);
+
+#endif
diff --git a/src/log/log-error-buffer.c b/src/log/log-error-buffer.c
new file mode 100644 (file)
index 0000000..26e86e8
--- /dev/null
@@ -0,0 +1,121 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "log-error-buffer.h"
+
+#define LOG_ERROR_BUFFER_MAX_LINES 1000
+
+struct log_error_data {
+       struct log_error_data *next;
+
+       enum log_type type;
+       time_t timestamp;
+       unsigned char prefix_text[];
+};
+
+struct log_error_buffer {
+       struct log_error_data *head, *tail;
+       unsigned int count;
+};
+
+struct log_error_buffer_iter {
+       struct log_error_buffer *buf;
+       struct log_error_data *cur;
+       struct log_error error;
+};
+
+struct log_error_buffer *log_error_buffer_init(void)
+{
+       struct log_error_buffer *buf;
+
+       buf = i_new(struct log_error_buffer, 1);
+       return buf;
+}
+
+static void log_error_buffer_delete_head(struct log_error_buffer *buf)
+{
+       struct log_error_data *data;
+
+       i_assert(buf->head != NULL);
+
+       buf->count--;
+       data = buf->head;
+       buf->head = data->next;
+       if (buf->tail == data) {
+               /* last one */
+               buf->tail = NULL;
+       }
+       i_free(data);
+}
+
+void log_error_buffer_add(struct log_error_buffer *buf,
+                         const struct log_error *error)
+{
+       unsigned int prefix_size = strlen(error->prefix)+1;
+       unsigned int text_size = strlen(error->text)+1;
+       struct log_error_data *data;
+
+       if (buf->count == LOG_ERROR_BUFFER_MAX_LINES)
+               log_error_buffer_delete_head(buf);
+
+       /* @UNSAFE */
+       data = i_malloc(sizeof(*data) + prefix_size + text_size);
+       data->type = error->type;
+       data->timestamp = error->timestamp;
+       memcpy(data->prefix_text, error->prefix, prefix_size);
+       memcpy(data->prefix_text + prefix_size, error->text, text_size);
+
+       if (buf->tail != NULL)
+               buf->tail->next = data;
+       else
+               buf->head = data;
+       buf->tail = data;
+       buf->count++;
+}
+
+void log_error_buffer_deinit(struct log_error_buffer **_buf)
+{
+       struct log_error_buffer *buf = *_buf;
+
+       *_buf = NULL;
+       while (buf->count > 0)
+               log_error_buffer_delete_head(buf);
+       i_free(buf);
+}
+
+struct log_error_buffer_iter *
+log_error_buffer_iter_init(struct log_error_buffer *buf)
+{
+       struct log_error_buffer_iter *iter;
+
+       iter = i_new(struct log_error_buffer_iter, 1);
+       iter->buf = buf;
+       iter->cur = buf->head;
+       return iter;
+}
+
+struct log_error *
+log_error_buffer_iter_next(struct log_error_buffer_iter *iter)
+{
+       struct log_error_data *data = iter->cur;
+
+       if (data == NULL)
+               return NULL;
+       iter->cur = iter->cur->next;
+
+       iter->error.type = data->type;
+       iter->error.timestamp = data->timestamp;
+       iter->error.prefix = (const void *)data->prefix_text;
+       iter->error.text = (const void *)(data->prefix_text +
+                                         strlen(iter->error.prefix) + 1);
+       return &iter->error;
+}
+
+void log_error_buffer_iter_deinit(struct log_error_buffer_iter **_iter)
+{
+       struct log_error_buffer_iter *iter = *_iter;
+
+       *_iter = NULL;
+
+       i_free(iter);
+}
diff --git a/src/log/log-error-buffer.h b/src/log/log-error-buffer.h
new file mode 100644 (file)
index 0000000..e863c35
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef LOG_ERROR_BUFFER_H
+#define LOG_ERROR_BUFFER_H
+
+struct log_error_buffer;
+
+struct log_error {
+       enum log_type type;
+       time_t timestamp;
+       const char *prefix;
+       const char *text;
+};
+
+struct log_error_buffer *log_error_buffer_init(void);
+void log_error_buffer_add(struct log_error_buffer *buf,
+                         const struct log_error *error);
+void log_error_buffer_deinit(struct log_error_buffer **buf);
+
+struct log_error_buffer_iter *
+log_error_buffer_iter_init(struct log_error_buffer *buf);
+struct log_error *
+log_error_buffer_iter_next(struct log_error_buffer_iter *iter);
+void log_error_buffer_iter_deinit(struct log_error_buffer_iter **iter);
+
+#endif