void mail_commands_free_memory(void) { unsigned int diff; while (stable_mail_commands_head != NULL) { struct mail_command *cmd = stable_mail_commands_head; if (cmd->refcount == 0) i_assert(cmd->id == 0); else if (cmd->refcount == 1 && (cmd->session->disconnected || mail_command_is_timed_out(cmd))) { /* session was probably lost */ mail_command_unref(&cmd); } else { break; } mail_command_free(stable_mail_commands_head); if (global_used_memory < stats_settings->memory_limit || stable_mail_commands_head == NULL) break; diff = ioloop_time - stable_mail_commands_head->last_update.tv_sec; if (diff < stats_settings->command_min_time) break; } }
void mail_commands_deinit(void) { while (stable_mail_commands_head != NULL) { struct mail_command *cmd = stable_mail_commands_head; if (cmd->id != 0) mail_command_unref(&cmd); mail_command_free(stable_mail_commands_head); } }
static void client_unref_iters(struct client *client) { if (client->mail_cmd_iter != NULL) mail_command_unref(&client->mail_cmd_iter); if (client->mail_session_iter != NULL) mail_session_unref(&client->mail_session_iter); if (client->mail_user_iter != NULL) mail_user_unref(&client->mail_user_iter); if (client->mail_domain_iter != NULL) mail_domain_unref(&client->mail_domain_iter); if (client->mail_ip_iter != NULL) mail_ip_unref(&client->mail_ip_iter); }
static int client_export_iter_command(struct client *client) { struct client_export_cmd *cmd = client->cmd_export; struct mail_command *command = client->mail_cmd_iter; i_assert(cmd->level == MAIL_EXPORT_LEVEL_COMMAND); mail_command_unref(&client->mail_cmd_iter); if (!cmd->header_sent) { o_stream_nsend_str(client->output, "cmd\targs\tsession\tuser\tlast_update"MAIL_STATS_HEADER); cmd->header_sent = TRUE; } for (; command != NULL; command = command->stable_next) { if (client_is_busy(client)) break; if (!mail_export_filter_match_session(&cmd->filter, command->session)) continue; str_truncate(cmd->str, 0); str_append_tabescaped(cmd->str, command->name); str_append_c(cmd->str, '\t'); str_append_tabescaped(cmd->str, command->args); str_append_c(cmd->str, '\t'); T_BEGIN { str_append(cmd->str, guid_128_to_string(command->session->guid)); str_append_c(cmd->str, '\t'); str_append_tabescaped(cmd->str, command->session->user->name); } T_END; client_export_timeval(cmd->str, &command->last_update); client_export_mail_stats(cmd->str, &command->stats); str_append_c(cmd->str, '\n'); o_stream_nsend(client->output, str_data(cmd->str), str_len(cmd->str)); } if (command != NULL) { client->mail_cmd_iter = command; mail_command_ref(command); return 0; } return 1; }
int mail_command_update_parse(const char *const *args, const char **error_r) { struct mail_session *session; struct mail_command *cmd; struct stats *new_stats, *diff_stats; buffer_t *buf; const char *error; unsigned int i, cmd_id; bool done = FALSE, continued = FALSE; /* <session guid> <cmd id> [d] <name> <args> <stats> <session guid> <cmd id> c[d] <stats> */ if (str_array_length(args) < 3) { *error_r = "UPDATE-CMD: Too few parameters"; return -1; } if (mail_session_get(args[0], &session, error_r) < 0) return -1; if (str_to_uint(args[1], &cmd_id) < 0 || cmd_id == 0) { *error_r = "UPDATE-CMD: Invalid command id"; return -1; } for (i = 0; args[2][i] != '\0'; i++) { switch (args[2][i]) { case 'd': done = TRUE; break; case 'c': continued = TRUE; break; default: *error_r = "UPDATE-CMD: Invalid flags parameter"; return -1; } } cmd = mail_command_find(session, cmd_id); if (!continued) { /* new command */ if (cmd != NULL) { *error_r = "UPDATE-CMD: Duplicate new command id"; return -1; } if (str_array_length(args) < 5) { *error_r = "UPDATE-CMD: Too few parameters"; return -1; } cmd = mail_command_add(session, args[3], args[4]); cmd->id = cmd_id; session->highest_cmd_id = I_MAX(session->highest_cmd_id, cmd_id); session->num_cmds++; session->user->num_cmds++; session->user->domain->num_cmds++; if (session->ip != NULL) session->ip->num_cmds++; mail_global_stats.num_cmds++; args += 5; } else { if (cmd == NULL) { /* already expired command, ignore */ i_warning("UPDATE-CMD: Already expired"); return 0; } args += 3; cmd->last_update = ioloop_timeval; } buf = t_buffer_create(256); if (args[0] == NULL || base64_decode(args[0], strlen(args[0]), NULL, buf) < 0) { *error_r = t_strdup_printf("UPDATE-CMD: Invalid base64 input"); return -1; } new_stats = stats_alloc(pool_datastack_create()); diff_stats = stats_alloc(pool_datastack_create()); if (!stats_import(buf->data, buf->used, cmd->stats, new_stats, &error)) { *error_r = t_strdup_printf("UPDATE-CMD: %s", error); return -1; } if (!stats_diff(cmd->stats, new_stats, diff_stats, &error)) { *error_r = t_strdup_printf("UPDATE-CMD: stats shrank: %s", error); return -1; } stats_add(cmd->stats, diff_stats); if (done) { cmd->id = 0; mail_command_unref(&cmd); } mail_session_refresh(session, NULL); return 0; }