summaryrefslogtreecommitdiffstats
path: root/src/old-stats/mail-user.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/old-stats/mail-user.c')
-rw-r--r--src/old-stats/mail-user.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/old-stats/mail-user.c b/src/old-stats/mail-user.c
new file mode 100644
index 0000000..7b3bc7a
--- /dev/null
+++ b/src/old-stats/mail-user.c
@@ -0,0 +1,177 @@
+/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "buffer.h"
+#include "ioloop.h"
+#include "hash.h"
+#include "llist.h"
+#include "base64.h"
+#include "global-memory.h"
+#include "stats-settings.h"
+#include "mail-stats.h"
+#include "mail-domain.h"
+#include "mail-user.h"
+
+static HASH_TABLE(char *, struct mail_user *) mail_users_hash;
+/* users are sorted by their last_update timestamp, oldest first */
+static struct mail_user *mail_users_head, *mail_users_tail;
+struct mail_user *stable_mail_users;
+
+static size_t mail_user_memsize(const struct mail_user *user)
+{
+ return sizeof(*user) + strlen(user->name) + 1;
+}
+
+struct mail_user *mail_user_login(const char *username)
+{
+ struct mail_user *user;
+ const char *domain;
+
+ user = hash_table_lookup(mail_users_hash, username);
+ if (user != NULL) {
+ mail_user_refresh(user, NULL);
+ return user;
+ }
+
+ domain = i_strchr_to_next(username, '@');
+ if (domain == NULL)
+ domain = "";
+
+ user = i_malloc(MALLOC_ADD(sizeof(struct mail_user), stats_alloc_size()));
+ user->stats = (void *)(user + 1);
+ user->name = i_strdup(username);
+ user->reset_timestamp = ioloop_time;
+ user->domain = mail_domain_login_create(domain);
+
+ hash_table_insert(mail_users_hash, user->name, user);
+ DLLIST_PREPEND_FULL(&stable_mail_users, user,
+ stable_prev, stable_next);
+ DLLIST2_APPEND_FULL(&mail_users_head, &mail_users_tail, user,
+ sorted_prev, sorted_next);
+ DLLIST_PREPEND_FULL(&user->domain->users, user,
+ domain_prev, domain_next);
+ mail_domain_ref(user->domain);
+
+ user->last_update = ioloop_timeval;
+ global_memory_alloc(mail_user_memsize(user));
+ return user;
+}
+
+void mail_user_disconnected(struct mail_user *user)
+{
+ mail_domain_disconnected(user->domain);
+}
+
+struct mail_user *mail_user_lookup(const char *username)
+{
+ return hash_table_lookup(mail_users_hash, username);
+}
+
+void mail_user_ref(struct mail_user *user)
+{
+ user->refcount++;
+}
+
+void mail_user_unref(struct mail_user **_user)
+{
+ struct mail_user *user = *_user;
+
+ i_assert(user->refcount > 0);
+ user->refcount--;
+
+ *_user = NULL;
+}
+
+static void mail_user_free(struct mail_user *user)
+{
+ i_assert(user->refcount == 0);
+ i_assert(user->sessions == NULL);
+
+ global_memory_free(mail_user_memsize(user));
+ hash_table_remove(mail_users_hash, user->name);
+ DLLIST_REMOVE_FULL(&stable_mail_users, user,
+ stable_prev, stable_next);
+ DLLIST2_REMOVE_FULL(&mail_users_head, &mail_users_tail, user,
+ sorted_prev, sorted_next);
+ DLLIST_REMOVE_FULL(&user->domain->users, user,
+ domain_prev, domain_next);
+ mail_domain_unref(&user->domain);
+
+ i_free(user->name);
+ i_free(user);
+}
+
+void mail_user_refresh(struct mail_user *user,
+ const struct stats *diff_stats)
+{
+ if (diff_stats != NULL)
+ stats_add(user->stats, diff_stats);
+ user->last_update = ioloop_timeval;
+ DLLIST2_REMOVE_FULL(&mail_users_head, &mail_users_tail, user,
+ sorted_prev, sorted_next);
+ DLLIST2_APPEND_FULL(&mail_users_head, &mail_users_tail, user,
+ sorted_prev, sorted_next);
+ mail_domain_refresh(user->domain, diff_stats);
+}
+
+int mail_user_add_parse(const char *const *args, const char **error_r)
+{
+ struct mail_user *user;
+ struct stats *empty_stats, *diff_stats;
+ buffer_t *buf;
+ const char *service, *error;
+
+ /* <user> <service> <diff stats> */
+ if (str_array_length(args) < 3) {
+ *error_r = "ADD-USER: Too few parameters";
+ return -1;
+ }
+
+ user = mail_user_login(args[0]);
+ service = args[1];
+
+ buf = t_buffer_create(256);
+ if (base64_decode(args[2], strlen(args[2]), NULL, buf) < 0) {
+ *error_r = t_strdup_printf("ADD-USER %s %s: Invalid base64 input",
+ user->name, service);
+ return -1;
+ }
+ empty_stats = stats_alloc(pool_datastack_create());
+ diff_stats = stats_alloc(pool_datastack_create());
+ if (!stats_import(buf->data, buf->used, empty_stats, diff_stats, &error)) {
+ *error_r = t_strdup_printf("ADD-USER %s %s: %s",
+ user->name, service, error);
+ return -1;
+ }
+ mail_user_refresh(user, diff_stats);
+ return 0;
+}
+
+void mail_users_free_memory(void)
+{
+ unsigned int diff;
+
+ while (mail_users_head != NULL && mail_users_head->refcount == 0) {
+ mail_user_free(mail_users_head);
+
+ if (global_used_memory < stats_settings->memory_limit ||
+ mail_users_head == NULL)
+ break;
+
+ diff = ioloop_time - mail_users_head->last_update.tv_sec;
+ if (diff < stats_settings->user_min_time)
+ break;
+ }
+}
+
+void mail_users_init(void)
+{
+ hash_table_create(&mail_users_hash, default_pool, 0, str_hash, strcmp);
+}
+
+void mail_users_deinit(void)
+{
+ while (mail_users_head != NULL)
+ mail_user_free(mail_users_head);
+ hash_table_destroy(&mail_users_hash);
+}