/[james]/transfcount/transfcount.c
ViewVC logotype

Annotation of /transfcount/transfcount.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 88 - (hide annotations) (download) (as text)
Wed Jul 12 15:20:37 2017 UTC (7 years, 5 months ago) by james
File MIME type: text/x-csrc
File size: 4631 byte(s)
Tool to measure data transferred by a process.
1 james 88 /**
2     * Measure data transferred by a process.
3     *
4     * Used with LD_PRELOAD.
5     */
6    
7     #define _GNU_SOURCE
8     #include <dlfcn.h>
9     #include <stdbool.h>
10     #include <stdio.h>
11     #include <stdlib.h>
12     #include <time.h>
13     #include <unistd.h>
14     #include <sys/types.h>
15     #include <sys/socket.h>
16     #include <sys/stat.h>
17    
18     static unsigned long long total_sent = 0;
19     static unsigned long long total_recv = 0;
20     static time_t start_time;
21    
22     static void transfcount_init(void);
23     static void transfcount_atexit(void);
24     static void transfcount_print_bytes(unsigned long long n);
25    
26     typedef ssize_t (*send_type)(int sockfd, const void *buf, size_t len,
27     int flags);
28     typedef int (*sendmmsg_type)(int sockfd, struct mmsghdr *msgvec,
29     unsigned int vlen, int flags);
30     typedef ssize_t (*recv_type)(int sockfd, void *buf, size_t len, int flags);
31     typedef ssize_t (*read_type)(int fd, void *buf, size_t count);
32     typedef ssize_t (*write_type)(int fd, const void *buf, size_t count);
33    
34     static send_type orig_send;
35     static sendmmsg_type orig_sendmmsg;
36     static recv_type orig_recv;
37     static read_type orig_read;
38     static write_type orig_write;
39    
40    
41     /**
42     * send - send a message on a socket.
43     */
44     ssize_t send(int sockfd, const void *buf, size_t len, int flags)
45     {
46     ssize_t bytes;
47    
48     transfcount_init();
49    
50     /*printf("######## send(sockfd=%i, buf=%p, len=%zi, flags=%x) -> ",
51     sockfd, buf, len, flags);*/
52    
53     bytes = orig_send(sockfd, buf, len, flags);
54     total_sent += bytes;
55     /*printf("%lu\n", bytes);*/
56    
57     return bytes;
58     }
59    
60    
61     /**
62     * sendmmsg - send multiple messages on a socket.
63     */
64     int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
65     int flags)
66     {
67     int sent, i;
68    
69     transfcount_init();
70    
71     /*printf("######## sendmmsg(sockfd=%i, msgvec=%p, vlen=%u, flags=%x) -> ",
72     sockfd, msgvec, vlen, flags);*/
73    
74     sent = orig_sendmmsg(sockfd, msgvec, vlen, flags);
75     /*printf("%i\n", sent);*/
76     for (i = 0; i < sent; i++)
77     total_sent += msgvec[i].msg_len;
78    
79     return sent;
80     }
81    
82    
83     /**
84     * recv - receive a message from a socket.
85     */
86     ssize_t recv(int sockfd, void *buf, size_t len, int flags)
87     {
88     ssize_t bytes;
89    
90     transfcount_init();
91    
92     /*printf("######## recv(sockfd=%i, buf=%p, len=%zi, flags=%x) -> ",
93     sockfd, buf, len, flags);*/
94    
95     bytes = orig_recv(sockfd, buf, len, flags);
96     total_recv += bytes;
97     /*printf("%lu\n", bytes);*/
98    
99     return bytes;
100     }
101    
102    
103     /**
104     * read - read from a file descriptor.
105     */
106     ssize_t read(int fd, void *buf, size_t count)
107     {
108     struct stat statbuf;
109     ssize_t bytes;
110    
111     transfcount_init();
112    
113     fstat(fd, &statbuf);
114     if (!S_ISSOCK(statbuf.st_mode))
115     return orig_read(fd, buf, count);
116    
117     /*printf("######## read(fd=%i, buf=%p, count=%zi) -> ",
118     fd, buf, count);*/
119    
120     bytes = orig_read(fd, buf, count);
121     if (bytes != -1)
122     total_recv += bytes;
123     /*printf("%lu\n", bytes);*/
124    
125     return bytes;
126     }
127    
128    
129     /**
130     * write - write to a file descriptor.
131     */
132     ssize_t write(int fd, const void *buf, size_t count)
133     {
134     struct stat statbuf;
135     ssize_t bytes;
136    
137     transfcount_init();
138    
139     fstat(fd, &statbuf);
140     if (!S_ISSOCK(statbuf.st_mode))
141     return orig_write(fd, buf, count);
142    
143     /*printf("######## write(fd=%i, buf=%p, count=%zi) -> ",
144     fd, buf, count);*/
145    
146     bytes = orig_write(fd, buf, count);
147     if (bytes != -1)
148     total_sent += bytes;
149     /*printf("%lu\n", bytes);*/
150    
151     return bytes;
152     }
153    
154    
155     /**
156     * Set up library.
157     */
158     void transfcount_init(void)
159     {
160     static bool init_done = false;
161    
162     if (init_done)
163     return;
164    
165     orig_send = (send_type)dlsym(RTLD_NEXT, "send");
166     orig_sendmmsg = (sendmmsg_type)dlsym(RTLD_NEXT, "sendmmsg");
167     orig_recv = (recv_type)dlsym(RTLD_NEXT, "recv");
168     orig_read = (read_type)dlsym(RTLD_NEXT, "read");
169     orig_write = (write_type)dlsym(RTLD_NEXT, "write");
170    
171     atexit(transfcount_atexit);
172    
173     start_time = time(NULL);
174    
175     init_done = true;
176     }
177    
178    
179     /**
180     * Output transfer statistics.
181     */
182     void transfcount_atexit(void)
183     {
184     time_t end_time = time(NULL);
185     time_t duration = end_time - start_time;
186    
187     if (total_sent == 0 && total_recv == 0)
188     return;
189    
190     if (duration == 0)
191     duration = 1;
192    
193     fprintf(stderr, "[>>> Sent ");
194     transfcount_print_bytes(total_sent);
195     fprintf(stderr, "B (");
196     transfcount_print_bytes(total_sent / duration);
197     fprintf(stderr, "B/s) >>>] [<<< Received ");
198     transfcount_print_bytes(total_recv);
199     fprintf(stderr, "B (");
200     transfcount_print_bytes(total_recv / duration);
201     fprintf(stderr, "B/s) <<<]\n");
202     }
203    
204    
205     /**
206     * Print a size as human readable.
207     */
208     void transfcount_print_bytes(unsigned long long n)
209     {
210     if (1024 * 1024 * 1024 <= n) {
211     fprintf(stderr, "%.1fGi", (double) n / 1024 / 1024 / 1024);
212     } else if (1024 * 1024 <= n) {
213     fprintf(stderr, "%.1fMi", (double) n / 1024 / 1024);
214     } else if (1024 <= n) {
215     fprintf(stderr, "%.1fKi", (double) n / 1024);
216     } else {
217     fprintf(stderr, "%llu", n);
218     }
219     }
220    

  ViewVC Help
Powered by ViewVC 1.1.26