1 /* This monitors a copy to a file, and prints nice stats */
2
3 #define EX_UTILS_NO_USE_INPUT 1
4 #include "ex_utils.h"
5
6 #include <sys/time.h>
7 #include <time.h>
8
9 #define CUR_RATE_NUM_SECS 60
10
main(int argc,char * argv[])11 int main(int argc, char *argv[])
12 {
13 Vstr_base *s1 = NULL;
14 Vstr_base *s2 = ex_init(&s1);
15 int fd = -1;
16 struct stat stat_buf;
17 time_t beg_time;
18 unsigned int beg_sz = 0;
19 unsigned int last_sz = 0;
20 unsigned int count = 0;
21 struct
22 {
23 time_t timestamp;
24 unsigned int sz;
25 } cur[CUR_RATE_NUM_SECS];
26
27 if (argc != 2)
28 {
29 size_t pos = 0;
30
31 VSTR_ADD_CSTR_PTR(s1, 0, argc ? argv[0] : "mon_cp");
32
33 if ((pos = vstr_srch_chr_rev(s1, 1, s1->len, '/')))
34 vstr_del(s1, 1, pos);
35
36 VSTR_ADD_CSTR_PTR(s1, 0, " Format: ");
37 VSTR_ADD_CSTR_PTR(s1, s1->len, " <filename>\n");
38
39 io_put_all(s1, STDERR_FILENO);
40
41 exit (EXIT_FAILURE);
42 }
43
44 fd = io_open(argv[1]);
45
46 if (fstat(fd, &stat_buf) == -1)
47 err(EXIT_FAILURE, "fstat");
48
49 vstr_cntl_conf(s1->conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$');
50 vstr_cntl_conf(s2->conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$');
51 vstr_sc_fmt_add_bkmg_Byte_uint(s1->conf, "{BKMG:%u}");
52 vstr_sc_fmt_add_bkmg_Byte_uint(s2->conf, "{BKMG:%u}");
53 vstr_sc_fmt_add_bkmg_Bytes_uint(s2->conf, "{BKMG/s:%u}");
54
55 if (s1->conf->malloc_bad || s2->conf->malloc_bad)
56 errno = ENOMEM, err(EXIT_FAILURE, "conf");
57
58 beg_time = time(NULL); --beg_time;
59 beg_sz = last_sz = stat_buf.st_size;
60 while (count < CUR_RATE_NUM_SECS)
61 {
62 cur[count].timestamp = beg_time;
63 cur[count].sz = beg_sz;
64 ++count;
65 }
66
67 vstr_add_fmt(s1, 0, "Start size = ${BKMG:%u}, current period = %u seconds.\n",
68 beg_sz, CUR_RATE_NUM_SECS);
69
70 count = 0;
71 while (count < (5 * 60)) /* same for 5 minutes */
72 {
73 size_t prev_len = s2->len;
74 time_t now;
75
76 if (fstat(fd, &stat_buf) == -1)
77 err(EXIT_FAILURE, "fstat:");
78
79 ++count;
80 if (last_sz != (unsigned int)stat_buf.st_size)
81 count = 0;
82 if (last_sz > (unsigned int)stat_buf.st_size)
83 break;
84 last_sz = stat_buf.st_size;
85
86 now = time(NULL);
87 memmove(cur, cur + 1, sizeof(cur[0]) * (CUR_RATE_NUM_SECS - 1));
88 cur[CUR_RATE_NUM_SECS - 1].timestamp = now;
89 cur[CUR_RATE_NUM_SECS - 1].sz = last_sz;
90
91 vstr_del(s2, 1, s2->len);
92 vstr_add_fmt(s2, 0,
93 "CP = $8{BKMG:%u} | "
94 "Rate = $10{BKMG/s:%u} | "
95 "CP(C) = $8{BKMG:%u} | "
96 "Rate(C) = $10{BKMG/s:%u}",
97 (last_sz - beg_sz),
98 (unsigned int)((last_sz - beg_sz) /
99 (now - beg_time)),
100 (last_sz - cur[0].sz),
101 (unsigned int)((last_sz - cur[0].sz) /
102 (now - cur[0].timestamp)));
103
104 if (s2->len < prev_len)
105 {
106 vstr_add_rep_chr(s1, s1->len, '\b', prev_len - s2->len);
107 vstr_add_rep_chr(s1, s1->len, ' ', prev_len - s2->len);
108 }
109
110 vstr_add_rep_chr(s1, s1->len, '\b', prev_len);
111 vstr_add_vstr(s1, s1->len, s2, 1, s2->len, 0);
112
113 if (s1->conf->malloc_bad || s2->conf->malloc_bad)
114 errno = ENOMEM, err(EXIT_FAILURE, "data");
115
116 io_put_all(s1, STDOUT_FILENO);
117
118 sleep(1);
119 }
120
121 close(fd);
122
123 vstr_add_rep_chr(s1, s1->len, '\n', 1);
124
125 io_put_all(s1, STDOUT_FILENO);
126
127 exit (ex_exit(s1, s2));
128 }
129