/[Apache-SVN]/httpd/flood/trunk/flood_profile.c
ViewVC logotype

Contents of /httpd/flood/trunk/flood_profile.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 653656 - (show annotations) (download)
Tue May 6 00:42:11 2008 UTC (16 years, 3 months ago) by fielding
File MIME type: text/plain
File size: 29584 byte(s)
promote flood to released products
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Originally developed by Aaron Bannert and Justin Erenkrantz, eBuilt.
17 */
18
19 #include <apr_file_io.h>
20 #include <apr_strings.h>
21 #include <apr_errno.h>
22
23 #if APR_HAVE_STRING_H
24 #include <string.h> /* strncasecmp */
25 #endif
26 #if APR_HAVE_STDLIB_H
27 #include <stdlib.h> /* strtol */
28 #endif
29
30 #include "config.h"
31 #include "flood_profile.h"
32 #include "flood_config.h"
33 #include "flood_net.h"
34
35 #if FLOOD_HAS_OPENSSL
36 #include "flood_net_ssl.h"
37 #endif /* FLOOD_HAS_OPENSSL */
38
39 #include "flood_round_robin.h"
40 #include "flood_simple_reports.h"
41 #include "flood_easy_reports.h"
42 #include "flood_socket_generic.h"
43 #include "flood_socket_keepalive.h"
44 #include "flood_report_relative_times.h"
45
46 extern apr_file_t *local_stdout;
47 extern apr_file_t *local_stderr;
48
49 struct profile_event_handler_t {
50 const char *handler_name;
51 const char *impl_name;
52 void *handler;
53 };
54 typedef struct profile_event_handler_t profile_event_handler_t;
55
56 struct profile_group_handler_t {
57 const char *class;
58 const char *group_name;
59 const char **handlers;
60 };
61 typedef struct profile_group_handler_t profile_group_handler_t;
62
63 /**
64 * Generic implementation for profile_init.
65 */
66 static apr_status_t generic_profile_init(profile_t **profile, config_t *config, const char * profile_name, apr_pool_t *pool)
67 {
68 return APR_ENOTIMPL;
69 }
70
71 /**
72 * Generic implementation for report_init.
73 */
74 static apr_status_t generic_report_init(report_t **report, config_t *config, const char *profile_name, apr_pool_t *pool)
75 {
76 /* by default, don't generate a report */
77 *report = NULL;
78 return APR_SUCCESS;
79 }
80
81 /**
82 * Generic implementation for get_next_url.
83 */
84 static apr_status_t generic_get_next_url(request_t **request, profile_t *profile)
85 {
86 return APR_ENOTIMPL;
87 }
88
89 /**
90 * Generic implementation for create_req.
91 */
92 static apr_status_t generic_create_req(profile_t *profile, request_t *request)
93 {
94 return APR_ENOTIMPL;
95 }
96
97 /**
98 * Generic implementation for postprocess.
99 */
100 static apr_status_t generic_postprocess(profile_t *p, request_t *req, response_t *resp)
101 {
102 return APR_SUCCESS;
103 }
104
105 /**
106 * Generic implementation for verify_resp.
107 */
108 static apr_status_t generic_verify_resp(int *verified, profile_t *profile, request_t *req, response_t *resp)
109 {
110 return APR_ENOTIMPL;
111 }
112
113 /**
114 * Generic implementation for process_stats.
115 */
116 static apr_status_t generic_process_stats(report_t *report, int verified, request_t *req, response_t *resp)
117 {
118 /* by default report nothing */
119 return APR_SUCCESS;
120 }
121
122 /**
123 * Generic implementation for loop_condition.
124 */
125 static int generic_loop_condition(profile_t *p)
126 {
127 return 0; /* by default, don't loop */
128 }
129
130 /**
131 * Generic implementation for request_destroy.
132 */
133 static apr_status_t generic_request_destroy(request_t *req)
134 {
135 return APR_SUCCESS;
136 }
137
138 /**
139 * Generic implementation for response_destroy.
140 */
141 static apr_status_t generic_response_destroy(response_t *resp)
142 {
143 return APR_SUCCESS;
144 }
145
146 /**
147 * Generic implementation for report_stats.
148 */
149 static apr_status_t generic_report_stats(report_t *report)
150 {
151 /* nothing to report, but not a failure */
152 return APR_SUCCESS;
153 }
154
155 /**
156 * Generic implementation for destroy_report.
157 */
158 static apr_status_t generic_destroy_report(report_t *report)
159 {
160 return APR_SUCCESS;
161 }
162
163 /**
164 * Generic implementation for profile_destroy.
165 */
166 static apr_status_t generic_profile_destroy(profile_t *p)
167 {
168 return APR_SUCCESS;
169 }
170
171 const char *profile_event_handler_names[] = {
172 "profile_init",
173 "report_init",
174 "get_next_url",
175 "socket_init",
176 "begin_conn",
177 "create_req",
178 "send_req",
179 "recv_resp",
180 "postprocess",
181 "verify_resp",
182 "process_stats",
183 "loop_condition",
184 "end_conn",
185 "request_destroy",
186 "response_destroy",
187 "socket_destroy",
188 "report_stats",
189 "destroy_report",
190 "profile_destroy",
191 NULL
192 };
193
194 profile_event_handler_t profile_event_handlers[] = {
195 {"profile_init", "generic_profile_init", &generic_profile_init},
196 {"report_init", "generic_report_init", &generic_report_init},
197 {"get_next_url", "generic_get_next_url", &generic_get_next_url},
198 {"socket_init", "generic_socket_init", &generic_socket_init},
199 {"begin_conn", "generic_begin_conn", &generic_begin_conn},
200 {"create_req", "generic_create_req", &generic_create_req},
201 {"send_req", "generic_send_req", &generic_send_req},
202 {"recv_resp", "generic_recv_resp", &generic_recv_resp},
203 {"postprocess", "generic_postprocess", &generic_postprocess},
204 {"verify_resp", "generic_verify_resp", &generic_verify_resp},
205 {"process_stats", "generic_process_stats", &generic_process_stats},
206 {"loop_condition", "generic_loop_condition", &generic_loop_condition},
207 {"end_conn", "generic_end_conn", &generic_end_conn},
208 {"request_destroy", "generic_request_destroy", &generic_request_destroy},
209 {"response_destroy", "generic_response_destroy", &generic_response_destroy},
210 {"socket_destroy", "generic_socket_destroy", &generic_socket_destroy},
211 {"report_stats", "generic_report_stats", &generic_report_stats},
212 {"destroy_report", "generic_destroy_report", &generic_destroy_report},
213 {"profile_destroy", "generic_profile_destroy", &generic_profile_destroy},
214
215 /* Alternative Implementations that are currently available: */
216
217 /* Always retrieve the full response */
218 {"recv_resp", "generic_fullresp_recv_resp", &generic_fullresp_recv_resp},
219
220 /* Keep-Alive support */
221 {"socket_init", "keepalive_socket_init", &keepalive_socket_init},
222 {"begin_conn", "keepalive_begin_conn", &keepalive_begin_conn},
223 {"send_req", "keepalive_send_req", &keepalive_send_req},
224 {"recv_resp", "keepalive_recv_resp", &keepalive_recv_resp},
225 {"end_conn", "keepalive_end_conn", &keepalive_end_conn},
226 {"socket_destroy", "keepalive_socket_destroy", &keepalive_socket_destroy},
227
228 /* Round Robin */
229 {"profile_init", "round_robin_profile_init", &round_robin_profile_init},
230 {"get_next_url", "round_robin_get_next_url", &round_robin_get_next_url},
231 {"create_req", "round_robin_create_req", &round_robin_create_req},
232 {"postprocess", "round_robin_postprocess", &round_robin_postprocess},
233 {"loop_condition", "round_robin_loop_condition", &round_robin_loop_condition},
234 {"profile_destroy", "round_robin_profile_destroy",&round_robin_profile_destroy},
235
236 /* Verification by OK/200 */
237 {"verify_resp", "verify_200", &verify_200},
238 {"verify_resp", "verify_status_code", &verify_status_code},
239
240 /* Simple Reports */
241 {"report_init", "simple_report_init", &simple_report_init},
242 {"process_stats", "simple_process_stats", &simple_process_stats},
243 {"report_stats", "simple_report_stats", &simple_report_stats},
244 {"destroy_report", "simple_destroy_report", &simple_destroy_report},
245
246 /* Easy Reports */
247 {"report_init", "easy_report_init", &easy_report_init},
248 {"process_stats", "easy_process_stats", &easy_process_stats},
249 {"report_stats", "easy_report_stats", &easy_report_stats},
250 {"destroy_report", "easy_destroy_report", &easy_destroy_report},
251
252 /* Relative Times Report */
253 {"report_init", "relative_times_report_init", &relative_times_report_init},
254 {"process_stats", "relative_times_process_stats", &relative_times_process_stats},
255 {"report_stats", "relative_times_report_stats", &relative_times_report_stats},
256 {"destroy_report", "relative_times_destroy_report",&relative_times_destroy_report},
257
258 {NULL} /* sentinel value */
259 };
260
261 const char * profile_group_handler_names[] = {
262 "report",
263 "socket",
264 "profiletype",
265 NULL
266 };
267
268 const char * report_easy_group[] = { "easy_report_init", "easy_process_stats", "easy_report_stats", "easy_destroy_report", NULL };
269 const char * report_simple_group[] = { "simple_report_init", "simple_process_stats", "simple_report_stats", "simple_destroy_report", NULL };
270 const char * socket_generic_group[] = { "generic_socket_init", "generic_begin_conn", "generic_send_req", "generic_recv_resp", "generic_end_conn", "generic_socket_destroy", NULL };
271 const char * socket_keepalive_group[] = { "keepalive_socket_init", "keepalive_begin_conn", "keepalive_send_req", "keepalive_recv_resp", "keepalive_end_conn", "keepalive_socket_destroy", NULL };
272 const char * profile_round_robin_group[] = { "round_robin_profile_init", "round_robin_get_next_url", "round_robin_create_req", "round_robin_postprocess", "round_robin_loop_condition", "round_robin_profile_destroy", NULL };
273 const char * report_relative_times_group[] = { "relative_times_report_init", "relative_times_process_stats", "relative_times_report_stats", "relative_times_destroy_report", NULL };
274
275 profile_group_handler_t profile_group_handlers[] = {
276 {"report", "easy", report_easy_group },
277 {"report", "simple", report_simple_group },
278 {"socket", "generic", socket_generic_group },
279 {"socket", "keepalive", socket_keepalive_group },
280 {"profiletype", "round_robin", profile_round_robin_group },
281 {"report", "relative_times", report_relative_times_group },
282 {NULL}
283 };
284
285 /**
286 * Assign the appropriate implementation to the profile_events_t handler
287 * for the given function name and overriden function name.
288 * Returns APR_SUCCESS if an appropriate handler was found and assigned, or
289 * returns APR_ENOTIMPL if no match was found.
290 */
291 static apr_status_t assign_profile_event_handler(profile_events_t *events,
292 const char *handler_name,
293 const char *impl_name)
294 {
295 profile_event_handler_t *p;
296
297 for (p = &profile_event_handlers[0]; p && (*p).handler_name; p++) {
298 /* these are case insensitive (both key and value) for the sake of simplicity */
299 if (strncasecmp(impl_name, (*p).impl_name, FLOOD_STRLEN_MAX) == 0) {
300 if (strncasecmp(handler_name, (*p).handler_name, FLOOD_STRLEN_MAX) == 0) {
301 /* we got a match, assign it */
302
303 /* stupid cascading if, no big deal since it only happens at startup */
304 if (strncasecmp(handler_name, "profile_init", FLOOD_STRLEN_MAX) == 0) {
305 events->profile_init = (*p).handler;
306 } else if (strncasecmp(handler_name, "report_init", FLOOD_STRLEN_MAX) == 0){
307 events->report_init = (*p).handler;
308 } else if (strncasecmp(handler_name, "socket_init", FLOOD_STRLEN_MAX) == 0){
309 events->socket_init = (*p).handler;
310 } else if (strncasecmp(handler_name, "get_next_url", FLOOD_STRLEN_MAX) == 0){
311 events->get_next_url = (*p).handler;
312 } else if (strncasecmp(handler_name, "begin_conn", FLOOD_STRLEN_MAX) == 0) {
313 events->begin_conn = (*p).handler;
314 } else if (strncasecmp(handler_name, "create_req", FLOOD_STRLEN_MAX) == 0) {
315 events->create_req = (*p).handler;
316 } else if (strncasecmp(handler_name, "send_req", FLOOD_STRLEN_MAX) == 0) {
317 events->send_req = (*p).handler;
318 } else if (strncasecmp(handler_name, "recv_resp", FLOOD_STRLEN_MAX) == 0) {
319 events->recv_resp = (*p).handler;
320 } else if (strncasecmp(handler_name, "postprocess", FLOOD_STRLEN_MAX) == 0) {
321 events->postprocess = (*p).handler;
322 } else if (strncasecmp(handler_name, "verify_resp", FLOOD_STRLEN_MAX) == 0) {
323 events->verify_resp = (*p).handler;
324 } else if (strncasecmp(handler_name, "process_stats", FLOOD_STRLEN_MAX) == 0) {
325 events->process_stats = (*p).handler;
326 } else if (strncasecmp(handler_name, "loop_condition", FLOOD_STRLEN_MAX) == 0) {
327 events->loop_condition = (*p).handler;
328 } else if (strncasecmp(handler_name, "end_conn", FLOOD_STRLEN_MAX) == 0) {
329 events->end_conn = (*p).handler;
330 } else if (strncasecmp(handler_name, "request_destroy", FLOOD_STRLEN_MAX) == 0) {
331 events->request_destroy = (*p).handler;
332 } else if (strncasecmp(handler_name, "response_destroy", FLOOD_STRLEN_MAX) == 0) {
333 events->response_destroy = (*p).handler;
334 } else if (strncasecmp(handler_name, "socket_destroy", FLOOD_STRLEN_MAX) == 0) {
335 events->socket_destroy = (*p).handler;
336 } else if (strncasecmp(handler_name, "report_stats", FLOOD_STRLEN_MAX) == 0) {
337 events->report_stats = (*p).handler;
338 } else if (strncasecmp(handler_name, "destroy_report", FLOOD_STRLEN_MAX) == 0) {
339 events->destroy_report = (*p).handler;
340 } else if (strncasecmp(handler_name, "profile_destroy", FLOOD_STRLEN_MAX) == 0) {
341 events->profile_destroy = (*p).handler;
342 } else {
343 /* some internal error, our static structs don't match up */
344 return APR_EGENERAL;
345 }
346 return APR_SUCCESS;
347 } else {
348 /* invalid implementation for this handler */
349 apr_file_printf(local_stderr, "Invalid handler (%s) "
350 "specified.\n",
351 handler_name ? handler_name : "NULL");
352 return APR_ENOTIMPL; /* XXX: There's probably a better return val than this? */
353 }
354 }
355 }
356 apr_file_printf(local_stderr, "Invalid implementation (%s) for "
357 "this handler (%s)\n",
358 impl_name ? impl_name : "NULL",
359 handler_name ? handler_name : "NULL");
360 return APR_ENOTIMPL; /* no implementation found */
361 }
362
363 /**
364 * Assign all functions listed in the group to the profile_events_t handler
365 * Returns APR_SUCCESS if an appropriate handler was found and assigned, or
366 * returns APR_NOTFOUND if no match was found.
367 */
368 static apr_status_t assign_profile_group_handler(profile_events_t *events,
369 const char *class_name,
370 const char *group_name)
371 {
372 profile_event_handler_t *p;
373 profile_group_handler_t *g;
374 const char **handlers;
375
376 /* Find our group. */
377 for (g = &profile_group_handlers[0]; g && g->class; g++)
378 {
379 if (!strncasecmp(class_name, g->class, FLOOD_STRLEN_MAX) &&
380 !strncasecmp(group_name, g->group_name, FLOOD_STRLEN_MAX))
381 break;
382 }
383
384 if (!g->class) {
385 apr_file_printf(local_stderr, "Invalid class '%s' or groupname '%s'.\n",
386 class_name, group_name);
387 return APR_EGENERAL;
388 }
389
390 /* For all of the handlers, set them. */
391 for (handlers = g->handlers; *handlers; handlers++)
392 {
393 for (p = profile_event_handlers; p && p->handler_name; p++) {
394 if (!strncasecmp(p->impl_name, *handlers, FLOOD_STRLEN_MAX))
395 assign_profile_event_handler(events, p->handler_name,
396 p->impl_name);
397 }
398 }
399 return APR_SUCCESS;
400 }
401
402 /**
403 * Construct a profile_event_handler_t struct, with the "generic"
404 * implementations in place by default.
405 */
406 static apr_status_t create_profile_events(profile_events_t **events, apr_pool_t *pool)
407 {
408 apr_status_t stat;
409 profile_events_t *new_events;
410
411 if ((new_events = apr_pcalloc(pool, sizeof(profile_events_t))) == NULL)
412 return APR_ENOMEM;
413
414 if ((stat = assign_profile_event_handler(new_events,
415 "profile_init",
416 "generic_profile_init")) != APR_SUCCESS)
417 return stat;
418 if ((stat = assign_profile_event_handler(new_events,
419 "report_init",
420 "generic_report_init")) != APR_SUCCESS)
421 return stat;
422 if ((stat = assign_profile_event_handler(new_events,
423 "socket_init",
424 "generic_socket_init")) != APR_SUCCESS)
425 return stat;
426 if ((stat = assign_profile_event_handler(new_events,
427 "get_next_url",
428 "generic_get_next_url")) != APR_SUCCESS)
429 return stat;
430 if ((stat = assign_profile_event_handler(new_events,
431 "create_req",
432 "generic_create_req")) != APR_SUCCESS)
433 return stat;
434 if ((stat = assign_profile_event_handler(new_events,
435 "begin_conn",
436 "generic_begin_conn")) != APR_SUCCESS)
437 return stat;
438 if ((stat = assign_profile_event_handler(new_events,
439 "send_req",
440 "generic_send_req")) != APR_SUCCESS)
441 return stat;
442 if ((stat = assign_profile_event_handler(new_events,
443 "recv_resp",
444 "generic_recv_resp")) != APR_SUCCESS)
445 return stat;
446 if ((stat = assign_profile_event_handler(new_events,
447 "verify_resp",
448 "generic_verify_resp")) != APR_SUCCESS)
449 return stat;
450 if ((stat = assign_profile_event_handler(new_events,
451 "postprocess",
452 "generic_postprocess")) != APR_SUCCESS)
453 return stat;
454 if ((stat = assign_profile_event_handler(new_events,
455 "process_stats",
456 "generic_process_stats")) != APR_SUCCESS)
457 return stat;
458 if ((stat = assign_profile_event_handler(new_events,
459 "loop_condition",
460 "generic_loop_condition")) != APR_SUCCESS)
461 return stat;
462 if ((stat = assign_profile_event_handler(new_events,
463 "end_conn",
464 "generic_end_conn")) != APR_SUCCESS)
465 return stat;
466 if ((stat = assign_profile_event_handler(new_events,
467 "request_destroy",
468 "generic_request_destroy")) != APR_SUCCESS)
469 return stat;
470 if ((stat = assign_profile_event_handler(new_events,
471 "response_destroy",
472 "generic_response_destroy")) != APR_SUCCESS)
473 return stat;
474 if ((stat = assign_profile_event_handler(new_events,
475 "socket_destroy",
476 "generic_socket_destroy")) != APR_SUCCESS)
477 return stat;
478 if ((stat = assign_profile_event_handler(new_events,
479 "report_stats",
480 "generic_report_stats")) != APR_SUCCESS)
481 return stat;
482 if ((stat = assign_profile_event_handler(new_events,
483 "destroy_report",
484 "generic_destroy_report")) != APR_SUCCESS)
485 return stat;
486 if ((stat = assign_profile_event_handler(new_events,
487 "profile_destroy",
488 "generic_profile_destroy")) != APR_SUCCESS)
489 return stat;
490
491 *events = new_events;
492
493 return APR_SUCCESS;
494 }
495
496 /**
497 * Initializes the profile_events_t structure according to what we
498 * find in the given configuration. Dynamically allocated memory
499 * is pulled from the given pool.
500 */
501 static apr_status_t initialize_events(profile_events_t **events, const char * profile_name, config_t *config, apr_pool_t *pool)
502 {
503 apr_status_t stat;
504 const char **p;
505 profile_events_t *new_events;
506 struct apr_xml_elem *root_elem, *profile_elem, *profile_event_elem;
507 char *xml_profile;
508
509 xml_profile = apr_pstrdup(pool, XML_PROFILE);
510
511 if ((stat = retrieve_root_xml_elem(&root_elem, config)) != APR_SUCCESS) {
512 return stat;
513 }
514
515 if ((stat = create_profile_events(&new_events, pool)) != APR_SUCCESS) {
516 return stat;
517 }
518
519 /* retrieve our profile xml element */
520 if ((stat = retrieve_xml_elem_with_childmatch(
521 &profile_elem, root_elem,
522 xml_profile, "name", profile_name)) != APR_SUCCESS)
523 return stat;
524
525 /* For each event in the profile_events_t struct, allow the config
526 * parameters to override an implementation.
527 */
528 for (p = &profile_group_handler_names[0]; *p; p++) {
529 stat = retrieve_xml_elem_child(&profile_event_elem, profile_elem, *p);
530 /* We found a match */
531 if (stat == APR_SUCCESS)
532 {
533 stat = assign_profile_group_handler(new_events, *p,
534 profile_event_elem->first_cdata.first->text);
535 if (stat != APR_SUCCESS)
536 return stat;
537 }
538 }
539
540 /* For each event in the profile_events_t struct, allow the config
541 * parameters to override an implementation.
542 */
543 for (p = &profile_event_handler_names[0]; *p; p++) {
544 if ((stat = retrieve_xml_elem_child(
545 &profile_event_elem,
546 profile_elem,
547 *p)) == APR_SUCCESS) {
548
549 /* search for the implementation in our tables and assign it */
550 if ((stat = assign_profile_event_handler(
551 new_events,
552 *p,
553 profile_event_elem->first_cdata.first->text)) != APR_SUCCESS) {
554 #ifdef PROFILE_DEBUG
555 apr_file_printf(local_stdout, "Profile '%s' failed to override '%s' with '%s'.\n",
556 profile_name, *p, profile_event_elem->first_cdata.first->text);
557 #endif /* PROFILE_DEBUG */
558 return stat;
559 } else {
560 #ifdef PROFILE_DEBUG
561 apr_file_printf(local_stdout, "Profile '%s' overrides '%s' with '%s'.\n",
562 profile_name, *p, profile_event_elem->first_cdata.first->text);
563 #endif /* PROFILE_DEBUG */
564 }
565
566 } else {
567 #ifdef PROFILE_DEBUG
568 apr_file_printf(local_stdout, "Profile '%s' uses default '%s'.\n",
569 profile_name, *p);
570 #endif /* PROFILE_DEBUG */
571 }
572 }
573
574 *events = new_events;
575
576 return APR_SUCCESS;
577 }
578
579 /**
580 * Essential guts of the main test loop -- a single run of a test profile:
581 */
582 apr_status_t run_profile(apr_pool_t *pool, config_t *config, const char * profile_name)
583 {
584 profile_events_t *events;
585 profile_t *profile;
586 report_t *report;
587 request_t *req;
588 response_t *resp;
589 socket_t *socket;
590 flood_timer_t *timer;
591 apr_status_t stat;
592 int verified;
593
594 /* init to NULL for the sake of our error checking */
595 events = NULL;
596 profile = NULL;
597 req = NULL;
598 resp = NULL;
599 socket = NULL;
600 verified = FLOOD_INVALID;
601
602 /* assign the implementations (function pointers) */
603 if ((stat = initialize_events(&events, profile_name, config, pool)) != APR_SUCCESS) {
604 return stat;
605 }
606
607 if (events == NULL) {
608 apr_file_printf(local_stderr, "Error initializing test profile.\n");
609 return APR_EGENERAL; /* FIXME: What error code to return? */
610 }
611
612 /* initialize this profile */
613 if ((stat = events->profile_init(&profile, config, profile_name, pool)) != APR_SUCCESS)
614 return stat;
615
616 /* initialize this report */
617 if ((stat = events->report_init(&report, config, profile_name, pool)) != APR_SUCCESS)
618 return stat;
619
620 /* initialize the socket */
621 if ((stat = events->socket_init(&socket, pool)) != APR_SUCCESS)
622 return stat;
623
624 timer = apr_palloc(pool, sizeof(flood_timer_t));
625
626 do {
627 if ((stat = events->get_next_url(&req, profile)) != APR_SUCCESS)
628 return stat;
629
630 /* sample timer "begin" */
631 timer->begin = apr_time_now();
632
633 if ((stat = events->begin_conn(socket, req, pool)) != APR_SUCCESS) {
634 apr_file_printf(local_stderr, "open request failed (%s).\n",
635 req->uri);
636 return stat;
637 }
638
639 /* connect()ion was just made, sample it */
640 timer->connect = apr_time_now();
641
642 /* FIXME: I don't like doing this after we've opened the socket.
643 * But, I'm not sure how to do it otherwise.
644 */
645 if ((stat = events->create_req(profile, req)) != APR_SUCCESS) {
646 apr_file_printf(local_stderr, "create request failed (%s).\n",
647 req->uri);
648 return stat;
649 }
650
651 /* If we wanted to keep track of our request generation overhead,
652 * we could take a timer sample here */
653
654 if ((stat = events->send_req(socket, req, pool)) != APR_SUCCESS) {
655 apr_file_printf(local_stderr, "send request failed (%s).\n",
656 req->uri);
657 return stat;
658 }
659
660 /* record the time at which we finished sending the entire request */
661 timer->write = apr_time_now();
662
663 if ((stat = events->recv_resp(&resp, socket, pool)) != APR_SUCCESS) {
664 apr_file_printf(local_stderr, "receive request failed (%s).\n",
665 req->uri);
666 return stat;
667 }
668
669 /* record the time at which we received the first chunk of response data */
670 timer->read = apr_time_now();
671
672 if ((stat = events->postprocess(profile, req, resp)) != APR_SUCCESS) {
673 apr_file_printf(local_stderr, "postprocessing failed (%s).\n",
674 req->uri);
675 return stat;
676 }
677
678 if ((stat = events->verify_resp(&verified, profile, req, resp)) != APR_SUCCESS) {
679 apr_file_printf(local_stderr,
680 "Error while verifying query (%s).\n", req->uri);
681 return stat;
682 }
683
684 if ((stat = events->end_conn(socket, req, resp)) != APR_SUCCESS) {
685 apr_file_printf(local_stderr,
686 "Unable to end the connection (%s).\n", req->uri);
687 return stat;
688 }
689
690 /* record the time at which we had finished reading the entire response.
691 * Note: this sample includes overhead from postprocessing and verification
692 * and is not a good representation of raw server response speed. */
693 timer->close = apr_time_now();
694
695 if ((stat = events->process_stats(report, verified, req, resp, timer)) != APR_SUCCESS) {
696 apr_file_printf(local_stderr,
697 "Unable to process statistics (%s).\n", req->uri);
698 return stat;
699 }
700
701
702 if ((stat = events->request_destroy(req)) != APR_SUCCESS) {
703 apr_file_printf(local_stderr, "Error cleaning up request.\n");
704 return stat;
705 }
706
707 if ((stat = events->response_destroy(resp)) != APR_SUCCESS) {
708 apr_file_printf(local_stderr, "Error cleaning up Response.\n");
709 return stat;
710 }
711
712 if ((stat = events->socket_destroy(socket)) != APR_SUCCESS) {
713 apr_file_printf(local_stderr, "Error cleaning up Socket.\n");
714 return stat;
715 }
716
717 } while (events->loop_condition(profile));
718
719 if ((stat = events->report_stats(report)) != APR_SUCCESS) {
720 apr_file_printf(local_stderr, "Unable to report statistics.\n");
721 return stat;
722 }
723
724 if (events->destroy_report(report) != APR_SUCCESS) {
725 apr_file_printf(local_stderr, "Error cleaning up report '%s'.\n", profile_name);
726 return APR_EGENERAL; /* FIXME: What error code to return? */
727 }
728
729 if (events->profile_destroy(profile) != APR_SUCCESS) {
730 apr_file_printf(local_stderr, "Error cleaning up profile '%s'.\n", profile_name);
731 return APR_EGENERAL; /* FIXME: What error code to return? */
732 }
733
734 return APR_SUCCESS;
735 }

Properties

Name Value
svn:eol-style native

infrastructure at apache.org
ViewVC Help
Powered by ViewVC 1.1.26