-
Notifications
You must be signed in to change notification settings - Fork 6
/
stats.c
180 lines (162 loc) · 5.6 KB
/
stats.c
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
169
170
171
172
173
174
175
176
177
178
179
180
/* hey emacs! -*- Mode: C; c-file-style: "k&r"; indent-tabs-mode: nil -*- */
/*
* stats.c
* some functions to collect statistics
*
* $Id: stats.c,v 1.6 2002/03/27 03:02:12 jp Exp $
*
* Copyright (c) 2000 Jean-Pierre Lefebvre <helix@step.polymtl.ca>
* and Remi Lefebvre <remi@debian.org>
*
* atftp is free software; you can redistribute them and/or modify them
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include "config.h"
#include <limits.h>
#include <string.h>
#include "tftp_def.h"
#include "stats.h"
#include "logger.h"
/*
* That structure allows global statistic to be collected. See stats.h.
*/
struct server_stats s_stats;
/*
* Must be called to initilise stats structure and record the
* start time.
*/
void stats_start(void)
{
/* stats struct initialisation */
memset(&s_stats, 0, sizeof(s_stats));
s_stats.min_time.tv_sec = LONG_MAX;
pthread_mutex_init(&s_stats.mutex, NULL);
gettimeofday(&s_stats.start_time, NULL);
}
/*
* Called when execution is finnished, before calling stats_print.
*/
void stats_end(void)
{
gettimeofday(&s_stats.end_time, NULL);
}
/*
* Called by server threads each time a file is sent succesfully.
* Be aware that a mutex is locked in there.
*/
void stats_send_locked(void)
{
pthread_mutex_lock(&s_stats.mutex);
s_stats.number_of_server++;
s_stats.num_file_send++;
pthread_mutex_unlock(&s_stats.mutex);
}
/*
* Called by verver threads each time a file is received.
*/
void stats_recv_locked(void)
{
pthread_mutex_lock(&s_stats.mutex);
s_stats.number_of_server++;
s_stats.num_file_recv++;
pthread_mutex_unlock(&s_stats.mutex);
}
/*
* Called by server threads each time tftpd_send_file or tftpd_recv_file
* return with error.
*/
void stats_err_locked(void)
{
pthread_mutex_lock(&s_stats.mutex);
s_stats.number_of_err++;
pthread_mutex_unlock(&s_stats.mutex);
}
/*
* Called by server threads when the maximum number of threads is reached.
*/
void stats_abort_locked(void)
{
pthread_mutex_lock(&s_stats.mutex);
s_stats.number_of_abort++;
pthread_mutex_unlock(&s_stats.mutex);
}
/*
* Called by main thread only (in fact in tftpd_receive_request(), but
* before stdin_mutex is released) every time a new thread is created.
* We record the number of thread, the number of simultaeous thread, the
* between threads.
*/
void stats_new_thread(int number_of_thread)
{
struct timeval tmp;
if (number_of_thread > s_stats.max_simul_threads)
s_stats.max_simul_threads = number_of_thread;
/* calculate the arrival time of this thread */
if (s_stats.prev_time.tv_sec != 0)
{
gettimeofday(&s_stats.curr_time, NULL);
timeval_diff(&s_stats.diff_time, &s_stats.curr_time,
&s_stats.prev_time);
if (timeval_diff(&tmp, &s_stats.diff_time,
&s_stats.min_time) < 0)
memcpy(&s_stats.min_time, &s_stats.diff_time,
sizeof(struct timeval));
if (timeval_diff(&tmp, &s_stats.diff_time,
&s_stats.max_time) > 0)
memcpy(&s_stats.max_time, &s_stats.diff_time,
sizeof(struct timeval));
memcpy(&s_stats.prev_time, &s_stats.curr_time,
sizeof(struct timeval));
}
else
gettimeofday(&s_stats.prev_time, NULL);
}
/*
* Called by server threads when the finnished to add CPU ressources
* information.
*/
void stats_thread_usage_locked(void)
{
struct tms tms_tmp;
times(&tms_tmp);
pthread_mutex_lock(&s_stats.mutex);
s_stats.tms_thread.tms_utime += tms_tmp.tms_utime;
s_stats.tms_thread.tms_stime += tms_tmp.tms_stime;
pthread_mutex_unlock(&s_stats.mutex);
}
/*
* Called at the end of the main thread, when no other threads are
* running, to print the final statistics.
*/
void stats_print(void)
{
struct timeval tmp;
timeval_diff(&tmp, &s_stats.end_time, &s_stats.start_time);
times(&s_stats.tms);
s_stats.tms.tms_utime += s_stats.tms_thread.tms_utime;
s_stats.tms.tms_stime += s_stats.tms_thread.tms_stime;
logger(LOG_INFO, " Load measurements:");
logger(LOG_INFO, " User: %8.3fs Sys:%8.3fs",
(double)(s_stats.tms.tms_utime) / CLOCKS_PER_SEC,
(double)(s_stats.tms.tms_stime) / CLOCKS_PER_SEC);
logger(LOG_INFO, " Total:%8.3fs CPU:%8.3f%%",
(double)(tmp.tv_sec + tmp.tv_usec * 1e-6),
(double)(s_stats.tms.tms_utime + s_stats.tms.tms_stime) /
(double)(tmp.tv_sec + tmp.tv_usec * 1e-6));
logger(LOG_INFO, " Time between connections:");
if (s_stats.min_time.tv_sec == LONG_MAX)
logger(LOG_INFO, " Min: ----- Max: -----");
else
logger(LOG_INFO, " Min: %.3fs Max: %.3fs",
(double)(s_stats.min_time.tv_sec + s_stats.min_time.tv_usec * 1e-6),
(double)(s_stats.max_time.tv_sec + s_stats.max_time.tv_usec * 1e-6));
logger(LOG_INFO, " Thread stats:");
logger(LOG_INFO, " simultaneous threads: %d", s_stats.max_simul_threads);
logger(LOG_INFO, " number of servers: %d", s_stats.number_of_server);
logger(LOG_INFO, " number of aborts: %d", s_stats.number_of_abort);
logger(LOG_INFO, " number of errors: %d", s_stats.number_of_err);
logger(LOG_INFO, " number of files sent: %d", s_stats.num_file_send);
logger(LOG_INFO, " number of files received: %d", s_stats.num_file_recv);
}