"Fossies" - the Fresh Open Source Software Archive 
Member "bonnie++-1.04/zcav.cpp" (5 Sep 2017, 8306 Bytes) of package /linux/privat/bonnie++_1.04.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "zcav.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.03e_vs_1.04.
1
2 using namespace std;
3
4 #include <unistd.h>
5 #include <sys/time.h>
6 #include <sys/resource.h>
7 #include <time.h>
8 #include <cstdlib>
9 #include <cstring>
10 #include "bonnie.h"
11 #ifdef HAVE_VECTOR
12 #include <vector>
13 #else
14 #include <vector.h>
15 #endif
16
17 // Read the specified number of megabytes of data from the fd and return the
18 // amount of time elapsed in seconds.
19 double access_data(int fd, int size, void *buf, int chunk_size, int do_write);
20
21 // Returns the mean of the values in the array. If the array contains
22 // more than 2 items then discard the highest and lowest thirds of the
23 // results before calculating the mean.
24 double average(double *array, int count);
25 void printavg(int position, double avg, int block_size);
26
27 const int MEG = 1024*1024;
28 const int DEFAULT_CHUNK_SIZE = 1;
29 typedef double *PDOUBLE;
30
31 void usage()
32 {
33 printf("Usage: zcav [-b block-size] [-c count] [-n number of megs to read]\n"
34 " [-u uid-to-use:gid-to-use] [-g gid-to-use]\n"
35 " [-f] file-name\n"
36 "File name of \"-\" means standard input\n"
37 "Count is the number of times to read the data (default 1).\n"
38 "Version: " BON_VERSION "\n");
39 exit(1);
40 }
41
42 int main(int argc, char *argv[])
43 {
44 vector<double *> times;
45 vector<int> count;
46 int block_size = 256;
47
48 int max_loops = 1, pass_size = 0, chunk_size = DEFAULT_CHUNK_SIZE;
49 int do_write = 0;
50 char *file_name = NULL;
51
52 char *userName = NULL, *groupName = NULL;
53 int c;
54 while(-1 != (c = getopt(argc, argv, "-c:b:f:g:n:u:w")) )
55 {
56 switch(char(c))
57 {
58 case 'b':
59 {
60 int rc = sscanf(optarg, "%d:%d", &block_size, &chunk_size);
61 if(rc == 1)
62 chunk_size = DEFAULT_CHUNK_SIZE;
63 else if(rc != 2)
64 usage();
65 }
66 break;
67 case 'c':
68 max_loops = atoi(optarg);
69 break;
70 case 'g':
71 if(groupName)
72 usage();
73 groupName = optarg;
74 break;
75 case 'u':
76 {
77 if(userName)
78 usage();
79 userName = strdup(optarg);
80 int i;
81 for(i = 0; userName[i] && userName[i] != ':'; i++)
82 {}
83 if(userName[i] == ':')
84 {
85 if(groupName)
86 usage();
87 userName[i] = '\0';
88 groupName = &userName[i + 1];
89 }
90 }
91 break;
92 case 'n':
93 pass_size = atoi(optarg);
94 break;
95 case 'w':
96 do_write = 1;
97 break;
98 case 'f':
99 case char(1):
100 file_name = optarg;
101 break;
102 default:
103 usage();
104 }
105 }
106
107 pass_size = pass_size / block_size;
108
109 if(userName || groupName)
110 {
111 if(bon_setugid(userName, groupName, false))
112 return 1;
113 if(userName)
114 free(userName);
115 }
116
117 if(max_loops < 1 || block_size < 1 || chunk_size < 1
118 || chunk_size > block_size)
119 usage();
120 if(!file_name)
121 usage();
122 printf("#loops: %d, version: %s\n", max_loops, BON_VERSION);
123
124 int i;
125 void *buf = calloc(chunk_size * MEG, 1);
126 int fd;
127 if(strcmp(file_name, "-"))
128 {
129 if(do_write)
130 fd = open(file_name, O_WRONLY);
131 else
132 fd = open(file_name, O_RDONLY);
133 if(fd == -1)
134 {
135 printf("Can't open %s\n", file_name);
136 return 1;
137 }
138 }
139 else
140 {
141 fd = 0;
142 }
143 if(max_loops > 1)
144 {
145 struct stat stat_out, stat_err;
146 if(fstat(1, &stat_out) || fstat(2, &stat_err))
147 {
148 printf("Can't stat stdout/stderr.\n");
149 return 1;
150 }
151 for(int loops = 0; loops < max_loops; loops++)
152 {
153 if(lseek(fd, 0, SEEK_SET))
154 {
155 printf("Can't llseek().\n");
156 return 1;
157 }
158 double total_read_time = 0.0;
159 for(i = 0; (loops == 0 || times[0][i] != -1.0) && (!pass_size || i < pass_size); i++)
160 {
161 double read_time = access_data(fd, block_size, buf, chunk_size, do_write);
162 total_read_time += read_time;
163 if(loops == 0)
164 {
165 times.push_back(new double[max_loops]);
166 count.push_back(0);
167 }
168 times[i][loops] = read_time;
169 if(read_time < 0.0)
170 {
171 if(i == 0)
172 {
173 fprintf(stderr, "Data file/device too small.\n");
174 return 1;
175 }
176 times[i][0] = -1.0;
177 break;
178 }
179 count[i]++;
180 }
181 time_t now = time(NULL);
182 struct tm *cur_time = localtime(&now);
183 fprintf(stderr, "# Finished loop %d, %d:%02d:%02d\n", loops + 1
184 , cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);
185 printf("# Read %d gigs in %d seconds, %d megabytes per second.\n"
186 , i * block_size / 1024, int(total_read_time)
187 , int(double(i * block_size) / total_read_time));
188 if(stat_out.st_dev != stat_err.st_dev || stat_out.st_ino != stat_err.st_ino)
189 {
190 fprintf(stderr, "Read %d gigs in %d seconds, %d megabytes per second.\n"
191 , i * block_size / 1024, int(total_read_time)
192 , int(double(i * block_size) / total_read_time));
193 }
194 }
195 printf("#\n#block offset (GiB), MiB/s, time\n");
196 for(i = 0; count[i]; i++)
197 {
198 printavg(i, average(times[i], count[i]), block_size);
199 }
200 }
201 else
202 {
203 printf("#block offset (GiB), MiB/s, time\n");
204 double total_read_time = 0.0;
205 for(i = 0; !pass_size || i < pass_size; i++)
206 {
207 double read_time = access_data(fd, block_size, buf, chunk_size, do_write);
208 if(read_time < 0.0)
209 break;
210 printavg(i, read_time, block_size);
211 total_read_time += read_time;
212 }
213 if(i == 0)
214 {
215 fprintf(stderr, "File/device too small.\n");
216 return 1;
217 }
218 printf("# Read %d gigs in %d seconds, %d megabytes per second.\n"
219 , i * block_size / 1024, int(total_read_time)
220 , int(double(i * block_size) / total_read_time));
221 }
222 return 0;
223 }
224
225 void printavg(int position, double avg, int block_size)
226 {
227 if(avg < MinTime)
228 printf("#%.2f ++++ %.3f \n", float(position) * float(block_size) / 1024.0, avg);
229 else
230 printf("%.2f %.2f %.3f\n", float(position) * float(block_size) / 1024.0, float(double(block_size) / avg), avg);
231 }
232
233 int compar(const void *a, const void *b)
234 {
235 double *c = (double *)(a);
236 double *d = (double *)(b);
237 if(*c < *d) return -1;
238 if(*c > *d) return 1;
239 return 0;
240 }
241
242 // Returns the mean of the values in the array. If the array contains
243 // more than 2 items then discard the highest and lowest thirds of the
244 // results before calculating the mean.
245 double average(double *array, int count)
246 {
247 qsort(array, count, sizeof(double), compar);
248 int skip = count / 3;
249 int arr_items = count - (skip * 2);
250 double total = 0.0;
251 for(int i = skip; i < (count - skip); i++)
252 {
253 total += array[i];
254 }
255 return total / arr_items;
256 }
257
258 // just like read() or write() but will not return a partial result and the
259 // size is expressed in MEG.
260 ssize_t access_all(int fd, void *buf, size_t chunk_size, int do_write)
261 {
262 ssize_t total = 0;
263 chunk_size *= MEG;
264 while(total != static_cast<ssize_t>(chunk_size) )
265 {
266 ssize_t rc;
267 // for both read and write just pass the base address of the buffer
268 // as we don't care for the data, if we ever do checksums we have to
269 // change this
270 if(do_write)
271 rc = write(fd, buf, chunk_size - total);
272 else
273 rc = read(fd, buf, chunk_size - total);
274 if(rc == -1 || rc == 0)
275 return -1;
276 total += rc;
277 }
278 if(do_write && fsync(fd))
279 return -1;
280 return total / MEG;
281 }
282
283 // Read the specified number of megabytes of data from the fd and return the
284 // amount of time elapsed in seconds. If do_write == 1 then write data.
285 double access_data(int fd, int size, void *buf, int chunk_size, int do_write)
286 {
287 struct timeval tp;
288
289 if (gettimeofday(&tp, static_cast<struct timezone *>(NULL)) == -1)
290 {
291 printf("Can't get time.\n");
292 return -1.0;
293 }
294 double start = double(tp.tv_sec) +
295 (double(tp.tv_usec) / 1000000.0);
296
297 for(int i = 0; i < size; i += chunk_size)
298 {
299 int access_size = chunk_size;
300 if(i + chunk_size > size)
301 access_size = size - i;
302 int rc = access_all(fd, buf, access_size, do_write);
303 if(rc != access_size)
304 return -1.0;
305 }
306 if (gettimeofday(&tp, static_cast<struct timezone *>(NULL)) == -1)
307 {
308 printf("Can't get time.\n");
309 return -1.0;
310 }
311 return (double(tp.tv_sec) + (double(tp.tv_usec) / 1000000.0))
312 - start;
313 }
314