1 /**************************************************************************
3 * Copyright (C) 1995 Silicon Graphics, Inc.
5 * These coded instructions, statements, and computer programs were
6 * developed by SGI for public use. If any changes are made to this code
7 * please try to get the changes back to the author. Feel free to make
8 * modifications and changes to the code and release it.
10 **************************************************************************/
12 /* FUZZ: disable check_for_math_include */
18 #include <sys/types.h>
26 #include <sys/param.h>
36 /* allocate memory and exit if out of memory */
37 void *mymalloc(size_t size
) {
42 errexit("Call to malloc() failed\n");
47 * Receive n bytes from a socket
50 recvdata(SOCKET sock
, char *ptr
, int nbytes
) {
57 D_PRINTF( "In recvdata(%d, %d)\n", sock
, nleft
);
58 nread
= NETREAD(sock
, ptr
, nleft
);
59 D_PRINTF( "NETREAD() returned %d\n", nread
);
60 if (BADSOCKET(nread
) || nread
== 0)
62 /* return error value NETWRITE */
63 D_PRINTF( "Error in recvdata(): %s\n",neterrstr() );
67 D_PRINTF( "NETREAD() data: \"%.*s\"\n", nread
, ptr
);
73 return(nbytes
- nleft
);
79 * Send n bytes to a socket
82 senddata(SOCKET sock
, char *ptr
, int nbytes
) {
85 D_PRINTF( "In senddata(%d, \"%.*s\", %d)\n", sock
, nbytes
, ptr
, nbytes
);
89 nwritten
= NETWRITE(sock
, ptr
, nleft
);
90 D_PRINTF( "senddata() returned %d\n", nwritten
);
91 if (BADSOCKET(nwritten
))
93 /* return error value from NETWRITE */
94 D_PRINTF( "Error in senddata(): %s\n", neterrstr() );
100 return(nbytes
- nleft
);
104 /* GENERAL NOTE: the conversion routines that follow pass their results
105 * back in a static arrays. A second call to the same routine overwrites
106 * the previous buffer value for that routine. If you want to save the
107 * value in the buffer copy it to another variable.
111 timeval_to_text(const struct timeval
*the_timeval
) {
113 * given a timeval (seconds and microseconds), put the text
114 * "seconds.microseconds" into timeval_as_text
116 THREAD
static char timeval_as_text
[SIZEOF_TIMEVALTEXT
+1];
117 int seconds
, microseconds
;
120 seconds
= the_timeval
->tv_sec
;
121 microseconds
= the_timeval
->tv_usec
;
122 returnval
= sprintf(timeval_as_text
,
123 "%10d.%6.6d\t", seconds
, microseconds
);
124 return timeval_as_text
;
129 double_to_text(const double the_double
) {
131 * given a double, return text
133 THREAD
static char double_as_text
[SIZEOF_DOUBLETEXT
+ 1];
136 returnval
= sprintf(double_as_text
, "%17.01f\t", the_double
);
137 return(double_as_text
);
141 text_to_timeval(char *timeval_as_text
) {
143 long int seconds
, microseconds
;
144 struct timeval the_timeval
;
146 D_PRINTF("T/%d %s\n", (int)timeval_as_text
, timeval_as_text
);
147 returnval
= sscanf(timeval_as_text
, "%ld.%ld",
148 &seconds
, µseconds
);
149 the_timeval
.tv_sec
= seconds
;
150 the_timeval
.tv_usec
= microseconds
;
155 text_to_double(char *double_as_text
) {
156 double the_double
= 0;
159 D_PRINTF("D/%d %s\n", (int)double_as_text
, double_as_text
);
160 returnval
= sscanf(double_as_text
, "%lf", &the_double
);
166 text_to_rqst_stats(char *rqst_stats_as_text
) {
167 THREAD
static rqst_stats_t rqst_stats
;
168 rqst_stats_t
*the_rqst_stats
= &rqst_stats
;
170 the_rqst_stats
->totalresponsetime
=
171 text_to_timeval(strtok(rqst_stats_as_text
, "\t"));
173 the_rqst_stats
->totalresponsetimesq
=
174 text_to_double(strtok((char *)0, "\t"));
176 the_rqst_stats
->minresponsetime
=
177 text_to_timeval(strtok((char *)0, "\t"));
179 the_rqst_stats
->maxresponsetime
=
180 text_to_timeval(strtok((char *)0, "\t"));
182 the_rqst_stats
->totalconnecttime
=
183 text_to_timeval(strtok((char *)0, "\t"));
185 the_rqst_stats
->totalconnecttimesq
=
186 text_to_double(strtok((char *)0, "\t"));
188 the_rqst_stats
->minconnecttime
=
189 text_to_timeval(strtok((char *)0, "\t"));
191 the_rqst_stats
->maxconnecttime
=
192 text_to_timeval(strtok((char *)0, "\t"));
194 the_rqst_stats
->totalconnects
= (unsigned long)
195 text_to_double(strtok((char *)0, "\t"));
197 the_rqst_stats
->totalerrs
= (unsigned long)
198 text_to_double(strtok((char *)0, "\t"));
200 the_rqst_stats
->totalerrortime
=
201 text_to_timeval(strtok((char *)0, "\t"));
203 the_rqst_stats
->totalbytes
=
204 text_to_double(strtok((char *)0, "\t"));
206 the_rqst_stats
->totalbytessq
=
207 text_to_double(strtok((char *)0, "\t"));
209 the_rqst_stats
->minbytes
=
210 text_to_double(strtok((char *)0, "\t"));
212 the_rqst_stats
->maxbytes
=
213 text_to_double(strtok((char *)0, "\t"));
215 the_rqst_stats
->totalbody
=
216 text_to_double(strtok((char *)0, "\t"));
218 the_rqst_stats
->totalbodysq
=
219 text_to_double(strtok((char *)0, "\t"));
221 the_rqst_stats
->minbody
=
222 text_to_double(strtok((char *)0, "\t"));
224 the_rqst_stats
->maxbody
=
225 text_to_double(strtok((char *)0, "\t"));
227 return(the_rqst_stats
);
228 } /* end text_to_rqst_stats */
232 rqst_stats_to_text(rqst_stats_t
*the_rqst_stats
) {
233 THREAD
static char rqst_stats_as_text
[SIZEOF_RQSTSTATSTEXT
];
236 *rqst_stats_as_text
= 0;
238 tmpbuf
= timeval_to_text(&(the_rqst_stats
->totalresponsetime
));
239 strcat(rqst_stats_as_text
, tmpbuf
);
241 tmpbuf
= double_to_text((the_rqst_stats
->totalresponsetimesq
));
242 strcat(rqst_stats_as_text
, tmpbuf
);
244 tmpbuf
= timeval_to_text(&(the_rqst_stats
->minresponsetime
));
245 strcat(rqst_stats_as_text
, tmpbuf
);
247 tmpbuf
= timeval_to_text(&(the_rqst_stats
->maxresponsetime
));
248 strcat(rqst_stats_as_text
, tmpbuf
);
250 tmpbuf
= timeval_to_text(&(the_rqst_stats
->totalconnecttime
));
251 strcat(rqst_stats_as_text
, tmpbuf
);
253 tmpbuf
= double_to_text((the_rqst_stats
->totalconnecttimesq
));
254 strcat(rqst_stats_as_text
, tmpbuf
);
256 tmpbuf
= timeval_to_text(&(the_rqst_stats
->minconnecttime
));
257 strcat(rqst_stats_as_text
, tmpbuf
);
259 tmpbuf
= timeval_to_text(&(the_rqst_stats
->maxconnecttime
));
260 strcat(rqst_stats_as_text
, tmpbuf
);
262 tmpbuf
= double_to_text((the_rqst_stats
->totalconnects
));
263 strcat(rqst_stats_as_text
, tmpbuf
);
265 tmpbuf
= double_to_text((the_rqst_stats
->totalerrs
));
266 strcat(rqst_stats_as_text
, tmpbuf
);
268 tmpbuf
= timeval_to_text(&(the_rqst_stats
->totalerrortime
));
269 strcat(rqst_stats_as_text
, tmpbuf
);
271 tmpbuf
= double_to_text((the_rqst_stats
->totalbytes
));
272 strcat(rqst_stats_as_text
, tmpbuf
);
274 tmpbuf
= double_to_text((the_rqst_stats
->totalbytessq
));
275 strcat(rqst_stats_as_text
, tmpbuf
);
277 tmpbuf
= double_to_text((the_rqst_stats
->minbytes
));
278 strcat(rqst_stats_as_text
, tmpbuf
);
280 tmpbuf
= double_to_text((the_rqst_stats
->maxbytes
));
281 strcat(rqst_stats_as_text
, tmpbuf
);
283 tmpbuf
= double_to_text((the_rqst_stats
->totalbody
));
284 strcat(rqst_stats_as_text
, tmpbuf
);
286 tmpbuf
= double_to_text((the_rqst_stats
->totalbodysq
));
287 strcat(rqst_stats_as_text
, tmpbuf
);
289 tmpbuf
= double_to_text((the_rqst_stats
->minbody
));
290 strcat(rqst_stats_as_text
, tmpbuf
);
292 tmpbuf
= double_to_text((the_rqst_stats
->maxbody
));
293 strcat(rqst_stats_as_text
, tmpbuf
);
295 D_PRINTF("rqst_stats_to_text returning %d: %s\n",
296 strlen(rqst_stats_as_text
),
297 rqst_stats_as_text
);
299 return(rqst_stats_as_text
);
304 text_to_stats(char *stats_as_text
) {
306 rqst_stats_t
*the_rqst_stats
;
307 THREAD
static stats_t stats
;
308 stats_t
*the_stats
= &stats
;
310 D_PRINTF( "Parsing stats: %s\n", stats_as_text
);
312 the_rqst_stats
= text_to_rqst_stats(stats_as_text
);
313 the_stats
->rs
= *the_rqst_stats
;
315 /* grab main structure */
316 the_stats
->starttime
= text_to_timeval(strtok((char *)0, "\t"));
317 the_stats
->endtime
= text_to_timeval(strtok((char *)0, "\t"));
318 the_stats
->datatime
= text_to_timeval(strtok((char *)0, "\t"));
319 the_stats
->totalpages
= (unsigned long) text_to_double(strtok((char *)0, "\t"));
320 the_stats
->total_num_of_files
= (unsigned int) text_to_double(strtok((char *)0, "\t"));
321 for (i
= 0; i
< number_of_pages
; i
++)
323 the_stats
->page_numbers
[i
] = (unsigned int) text_to_double(strtok((char *)0, "\t"));
325 /* return bytes read */
326 D_PRINTF( "Returning stats\n");
328 } /* end text_to_stats */
333 stats_to_text(const stats_t
*the_stats
) {
335 THREAD
static char stats_as_text
[SIZEOF_STATSTEXT
];
337 rqst_stats_t the_rqst_stats
;
342 the_rqst_stats
= the_stats
->rs
;
343 tmpbuf
= rqst_stats_to_text(&the_rqst_stats
);
344 strcat(stats_as_text
, tmpbuf
);
348 tmpbuf
= timeval_to_text(&(the_stats
->starttime
));
349 strcat(stats_as_text
, tmpbuf
);
351 tmpbuf
= timeval_to_text(&(the_stats
->endtime
));
352 strcat(stats_as_text
, tmpbuf
);
354 tmpbuf
= timeval_to_text(&(the_stats
->datatime
));
355 strcat(stats_as_text
, tmpbuf
);
357 tmpbuf
= double_to_text((the_stats
->totalpages
));
358 strcat(stats_as_text
, tmpbuf
);
360 tmpbuf
= double_to_text((the_stats
->total_num_of_files
));
361 strcat(stats_as_text
, tmpbuf
);
363 for (i
= 0; i
< number_of_pages
; i
++)
365 tmpbuf
= double_to_text((the_stats
->page_numbers
[i
]));
366 strcat(stats_as_text
, tmpbuf
);
369 strcat(stats_as_text
, "\n");
371 return(stats_as_text
);
372 } /* end stats_to_text */
377 text_to_page_stats(char *page_stats_as_text
) {
378 rqst_stats_t
*the_rqst_stats
;
379 THREAD
static page_stats_t pagestat
;
380 page_stats_t
*pagestats
= &pagestat
;
383 the_rqst_stats
= text_to_rqst_stats(page_stats_as_text
);
385 /* grab main structure */
386 pagestats
->totalpages
= (unsigned long) text_to_double(strtok((char *)0, "\t"));
388 pagestats
->page_size
= (unsigned int) text_to_double(strtok((char *)0, "\t"));
390 pagestats
->page_valid
= (int) text_to_double(strtok((char *)0, "\t"));
392 pagestats
->rs
= *the_rqst_stats
;
393 /* return bytes read */
396 } /* end text_to_page_stats */
401 page_stats_to_text(const page_stats_t
*pagestats
) {
402 THREAD
static char page_stats_as_text
[SIZEOF_PAGESTATSTEXT
];
404 rqst_stats_t the_rqst_stats
;
406 *page_stats_as_text
= 0;
409 the_rqst_stats
= pagestats
->rs
;
410 tmpbuf
= rqst_stats_to_text(&the_rqst_stats
);
411 strcat(page_stats_as_text
, tmpbuf
);
414 tmpbuf
= double_to_text(pagestats
->totalpages
);
415 strcat(page_stats_as_text
, tmpbuf
);
417 tmpbuf
= double_to_text(pagestats
->page_size
);
418 strcat(page_stats_as_text
, tmpbuf
);
420 tmpbuf
= double_to_text(pagestats
->page_valid
);
421 strcat(page_stats_as_text
, tmpbuf
);
423 strcat(page_stats_as_text
, "\n");
425 return(page_stats_as_text
);
426 } /* end page_stats_to_text */
429 rqtimer_init(rqst_timer_t
*p
) {
430 memset(p
, 0, sizeof(*p
));
434 rqstat_init(rqst_stats_t
*p
) {
435 memset(p
, 0, sizeof(*p
));
437 p
->minbytes
= DBL_MAX
;
438 p
->minbody
= DBL_MAX
;
439 p
->minconnecttime
.tv_sec
= LONG_MAX
;
440 p
->minconnecttime
.tv_usec
= LONG_MAX
;
441 p
->minresponsetime
.tv_sec
= LONG_MAX
;
442 p
->minresponsetime
.tv_usec
= LONG_MAX
;
446 stats_init(stats_t
*p
) {
448 memset(p
, 0, sizeof(*p
));
450 p
->rs
.minbytes
= DBL_MAX
;
451 p
->rs
.minbody
= DBL_MAX
;
452 p
->rs
.minconnecttime
.tv_sec
= LONG_MAX
;
453 p
->rs
.minconnecttime
.tv_usec
= LONG_MAX
;
454 p
->rs
.minresponsetime
.tv_sec
= LONG_MAX
;
455 p
->rs
.minresponsetime
.tv_usec
= LONG_MAX
;
459 page_stats_init(page_stats_t
*p
) {
461 memset(p
, 0, sizeof(*p
));
463 /* commented out so that unread pages result in
464 page_stats_as_text buffer overflow
465 p->rs.minbytes = DBL_MAX;
466 p->rs.minbody = DBL_MAX;
467 p->rs.minconnecttime.tv_sec = LONG_MAX;
468 p->rs.minconnecttime.tv_usec = LONG_MAX;
469 p->rs.minresponsetime.tv_sec = LONG_MAX;
470 p->rs.minresponsetime.tv_usec = LONG_MAX;
476 rqstat_times(rqst_stats_t
*rs
, rqst_timer_t
*rt
)
480 compdifftime(&(rt
->exittime
), &(rt
->entertime
),
481 &(rs
->totalresponsetime
));
482 t
= timevaldouble(&(rs
->totalresponsetime
));
483 rs
->totalresponsetimesq
= t
* t
;
485 rs
->minresponsetime
= rs
->totalresponsetime
;
486 rs
->maxresponsetime
= rs
->totalresponsetime
;
488 compdifftime(&(rt
->afterconnect
), &(rt
->beforeconnect
),
489 &(rs
->totalconnecttime
));
491 t
= timevaldouble(&(rs
->totalconnecttime
));
492 rs
->totalconnecttimesq
= t
* t
;
494 rs
->minconnecttime
= rs
->totalconnecttime
;
495 rs
->maxconnecttime
= rs
->totalconnecttime
;
497 rs
->totalbody
= rt
->bodybytes
;
498 rs
->totalbodysq
= ((double)(rt
->bodybytes
)) * ((double)(rt
->bodybytes
));
499 rs
->minbody
= rt
->bodybytes
;
500 rs
->maxbody
= rt
->bodybytes
;
502 rs
->totalbytes
= rt
->totalbytes
;
503 rs
->totalbytessq
= ((double)(rt
->totalbytes
)) * ((double)(rt
->totalbytes
));
504 rs
->minbytes
= rt
->totalbytes
;
505 rs
->maxbytes
= rt
->totalbytes
;
507 rs
->totalconnects
= 1;
509 rs
->totalerrortime
.tv_sec
= 0;
510 rs
->totalerrortime
.tv_usec
= 0;
514 rqstat_sum(rqst_stats_t
*sum
, rqst_stats_t
*incr
)
516 addtime( &(sum
->totalresponsetime
), &(incr
->totalresponsetime
));
517 mintime( &(sum
->minresponsetime
), &(incr
->minresponsetime
));
518 maxtime( &(sum
->maxresponsetime
), &(incr
->maxresponsetime
));
519 sum
->totalresponsetimesq
+= incr
->totalresponsetimesq
;
521 addtime( &(sum
->totalconnecttime
), &(incr
->totalconnecttime
));
522 mintime( &(sum
->minconnecttime
), &(incr
->minconnecttime
));
523 maxtime( &(sum
->maxconnecttime
), &(incr
->maxconnecttime
));
524 sum
->totalconnecttimesq
+= incr
->totalconnecttimesq
;
526 sum
->totalconnects
+= incr
->totalconnects
;
527 sum
->totalerrs
+= incr
->totalerrs
;
528 addtime( &(sum
->totalerrortime
), &(incr
->totalerrortime
));
530 sum
->totalbytes
+= incr
->totalbytes
;
532 sum
->totalbytessq
+= incr
->totalbytessq
;
533 sum
->minbytes
= min(sum
->minbytes
, incr
->minbytes
);
534 sum
->maxbytes
= max(sum
->maxbytes
, incr
->maxbytes
);
536 sum
->totalbody
+= incr
->totalbody
;
538 sum
->totalbodysq
+= incr
->totalbodysq
;
539 sum
->minbody
= min(sum
->minbody
, incr
->minbody
);
540 sum
->maxbody
= max(sum
->maxbody
, incr
->maxbody
);
546 rqstat_print(rqst_stats_t
*stats
)
548 rqstat_fprint(stdout
, stats
);
553 rqstat_fprint(FILE *f
, rqst_stats_t
*stats
)
555 struct timeval meantime
, /*vartime,*/ stdtime
;
557 fprintf(f
, "%d connection(s) to server, %d errors\n",
558 stats
->totalconnects
, stats
->totalerrs
);
560 if (stats
->totalconnects
== 0) {
561 fprintf(f
,"NO CONNECTIONS, THEREFORE NO STATISTICS\n"
562 "IS YOUR WEBSERVER RUNNING?\n"
563 "DO THE PAGES EXIST ON THE SERVER?\n");
568 fprintf(f
, "\n\t\t\t Average Std Dev Minimum Maximum\n\n");
570 /* first line (connect time) */
571 avgtime(&(stats
->totalconnecttime
),
572 stats
->totalconnects
, &meantime
);
574 /* variancetime(&(stats->totalconnecttime),
575 stats->totalconnecttimesq,
576 stats->totalconnects, &vartime); */
578 stddevtime(&(stats
->totalconnecttime
),
579 stats
->totalconnecttimesq
,
580 stats
->totalconnects
, &stdtime
);
582 fprintf(f
, "Connect time (sec) \t%3d.%6.6d %3d.%6.6d %3d.%6.6d %3d.%6.6d\n",
587 stats
->minconnecttime
.tv_sec
,
588 stats
->minconnecttime
.tv_usec
,
589 stats
->maxconnecttime
.tv_sec
,
590 stats
->maxconnecttime
.tv_usec
);
592 /* second line (response time) */
593 avgtime(&(stats
->totalresponsetime
),
594 stats
->totalconnects
, &meantime
);
596 /* variancetime(&(stats->totalresponsetime),
597 stats->totalresponsetimesq,
598 stats->totalconnects, &vartime); */
600 stddevtime(&(stats
->totalresponsetime
),
601 stats
->totalresponsetimesq
,
602 stats
->totalconnects
, &stdtime
);
604 fprintf(f
, "Response time (sec) \t%3d.%6.6d %3d.%6.6d %3d.%6.6d %3d.%6.6d\n",
609 stats
->minresponsetime
.tv_sec
,
610 stats
->minresponsetime
.tv_usec
,
611 stats
->maxresponsetime
.tv_sec
,
612 stats
->maxresponsetime
.tv_usec
);
614 /* 3rd-5th lines (response size, body size, # bytes moved */
615 fprintf(f
, "Response size (bytes) \t%10.0lf %10.0lf %10.0lf %10.0lf\n",
616 mean(stats
->totalbytes
, stats
->totalconnects
),
617 stddev(stats
->totalbytes
, stats
->totalbytessq
, stats
->totalconnects
),
621 fprintf(f
, "Body size (bytes) \t%10.0lf %10.0lf %10.0lf %10.0lf\n\n",
622 mean(stats
->totalbody
, stats
->totalconnects
),
623 stddev(stats
->totalbody
, stats
->totalbodysq
, stats
->totalconnects
),
627 fprintf(f
, "%.0lf body bytes moved + %.0lf header bytes moved = %.0lf total\n",
629 stats
->totalbytes
- stats
->totalbody
,