1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "time-util.h"
#include "stats.h"
#include "stats-parser.h"
#include "mail-stats.h"
static struct stats_parser_field mail_stats_fields[] = {
#define E(parsename, name, type) { parsename, offsetof(struct mail_stats, name), sizeof(((struct mail_stats *)0)->name), type }
#define EN(parsename, name) E(parsename, name, STATS_PARSER_TYPE_UINT)
E("user_cpu", user_cpu, STATS_PARSER_TYPE_TIMEVAL),
E("sys_cpu", sys_cpu, STATS_PARSER_TYPE_TIMEVAL),
E("clock_time", clock_time, STATS_PARSER_TYPE_TIMEVAL),
EN("min_faults", min_faults),
EN("maj_faults", maj_faults),
EN("vol_cs", vol_cs),
EN("invol_cs", invol_cs),
EN("disk_input", disk_input),
EN("disk_output", disk_output),
EN("read_count", read_count),
EN("read_bytes", read_bytes),
EN("write_count", write_count),
EN("write_bytes", write_bytes),
/*EN("mopen", trans_stats.open_lookup_count),
EN("mstat", trans_stats.stat_lookup_count),
EN("mfstat", trans_stats.fstat_lookup_count),*/
EN("mail_lookup_path", trans_lookup_path),
EN("mail_lookup_attr", trans_lookup_attr),
EN("mail_read_count", trans_files_read_count),
EN("mail_read_bytes", trans_files_read_bytes),
EN("mail_cache_hits", trans_cache_hit_count)
};
static size_t mail_stats_alloc_size(void)
{
return sizeof(struct mail_stats);
}
static unsigned int mail_stats_field_count(void)
{
return N_ELEMENTS(mail_stats_fields);
}
static const char *mail_stats_field_name(unsigned int n)
{
i_assert(n < N_ELEMENTS(mail_stats_fields));
return mail_stats_fields[n].name;
}
static void
mail_stats_field_value(string_t *str, const struct stats *stats,
unsigned int n)
{
i_assert(n < N_ELEMENTS(mail_stats_fields));
stats_parser_value(str, &mail_stats_fields[n], stats);
}
static bool
mail_stats_diff(const struct stats *stats1, const struct stats *stats2,
struct stats *diff_stats_r, const char **error_r)
{
return stats_parser_diff(mail_stats_fields, N_ELEMENTS(mail_stats_fields),
stats1, stats2, diff_stats_r, error_r);
}
static void mail_stats_add(struct stats *dest, const struct stats *src)
{
stats_parser_add(mail_stats_fields, N_ELEMENTS(mail_stats_fields),
dest, src);
}
static bool
mail_stats_have_changed(const struct stats *_prev, const struct stats *_cur)
{
const struct mail_stats *prev = (const struct mail_stats *)_prev;
const struct mail_stats *cur = (const struct mail_stats *)_cur;
if (cur->disk_input != prev->disk_input ||
cur->disk_output != prev->disk_output ||
cur->trans_lookup_path != prev->trans_lookup_path ||
cur->trans_lookup_attr != prev->trans_lookup_attr ||
cur->trans_files_read_count != prev->trans_files_read_count ||
cur->trans_files_read_bytes != prev->trans_files_read_bytes ||
cur->trans_cache_hit_count != prev->trans_cache_hit_count)
return TRUE;
/* allow a tiny bit of changes that are caused by this
timeout handling */
if (timeval_diff_msecs(&cur->user_cpu, &prev->user_cpu) != 0)
return TRUE;
if (timeval_diff_msecs(&cur->sys_cpu, &prev->sys_cpu) != 0)
return TRUE;
if (cur->maj_faults > prev->maj_faults+10)
return TRUE;
if (cur->invol_cs > prev->invol_cs+10)
return TRUE;
/* don't check for read/write count/bytes changes, since they get
changed by stats checking itself */
return FALSE;
}
static void mail_stats_export(buffer_t *buf, const struct stats *_stats)
{
const struct mail_stats *stats = (const struct mail_stats *)_stats;
buffer_append(buf, stats, sizeof(*stats));
}
static bool
mail_stats_import(const unsigned char *data, size_t size, size_t *pos_r,
struct stats *_stats, const char **error_r)
{
struct mail_stats *stats = (struct mail_stats *)_stats;
if (size < sizeof(*stats)) {
*error_r = "mail_stats too small";
return FALSE;
}
memcpy(stats, data, sizeof(*stats));
*pos_r = sizeof(*stats);
return TRUE;
}
void mail_stats_add_transaction(struct mail_stats *stats,
const struct mailbox_transaction_stats *trans_stats)
{
stats->trans_lookup_path += trans_stats->open_lookup_count;
stats->trans_lookup_attr += trans_stats->stat_lookup_count +
trans_stats->fstat_lookup_count;
stats->trans_files_read_count += trans_stats->files_read_count;
stats->trans_files_read_bytes += trans_stats->files_read_bytes;
stats->trans_cache_hit_count += trans_stats->cache_hit_count;
}
const struct stats_vfuncs mail_stats_vfuncs = {
"mail",
mail_stats_alloc_size,
mail_stats_field_count,
mail_stats_field_name,
mail_stats_field_value,
mail_stats_diff,
mail_stats_add,
mail_stats_have_changed,
mail_stats_export,
mail_stats_import
};
/* for the stats_mail plugin: */
void old_stats_mail_init(void);
void old_stats_mail_deinit(void);
static struct stats_item *mail_stats_item;
void old_stats_mail_init(void)
{
mail_stats_item = stats_register(&mail_stats_vfuncs);
}
void old_stats_mail_deinit(void)
{
stats_unregister(&mail_stats_item);
}
|