in flood_round_robin.c [746:954]
apr_status_t round_robin_profile_init(profile_t **profile,
config_t *config,
const char *profile_name,
apr_pool_t *pool)
{
apr_status_t rv;
int i;
struct apr_xml_elem *root_elem, *profile_elem,
*urllist_elem, *count_elem, *useurllist_elem, *baseurl_elem,
*subst_list_elem, *subst_entry_elem, *subst_entry_child,
*proxyurl_elem, *e;
round_robin_profile_t *p;
char *xml_profile, *xml_urllist, *urllist_name;
char *xml_subst_list, *subst_list_name;
subst_rec_t* subst_rec_p;
int valid_substs = 0;
p = apr_pcalloc(pool, sizeof(round_robin_profile_t));
p->pool = pool;
/* yeah, yeah; calloc(), whatever...this is readability baby! */
p->current_url = 0; /* start on the first URL */
p->current_round = 0; /* start counting rounds at 0 */
p->state = apr_hash_make(pool);
/* get the XML pathes to the profile and the urllist */
xml_profile = apr_pstrdup(pool, XML_PROFILE);
xml_urllist = apr_pstrdup(pool, XML_URLLIST);
if ((rv = retrieve_root_xml_elem(&root_elem, config)) != APR_SUCCESS) {
return rv;
}
/* retrieve our profile xml element */
if ((rv = retrieve_xml_elem_with_childmatch(
&profile_elem, root_elem,
xml_profile, "name", profile_name)) != APR_SUCCESS)
return rv;
/* find the count */
if ((rv = retrieve_xml_elem_child(
&count_elem, profile_elem, XML_PROFILE_COUNT)) != APR_SUCCESS) {
/* if it's missing, just default to 1 */
p->execute_rounds = 1;
} else {
if (count_elem->first_cdata.first && count_elem->first_cdata.first->text) {
p->execute_rounds = strtol(count_elem->first_cdata.first->text, NULL, 10);
if (p->execute_rounds == LONG_MAX || p->execute_rounds == LONG_MIN)
/* error, over/under-flow */
return errno;
} else {
apr_file_printf(local_stderr,
"Profile '%s' has element <%s> with no value, assuming 1.\n",
profile_name, XML_PROFILE_COUNT);
p->execute_rounds = 1;
}
}
#ifdef PROFILE_DEBUG
apr_file_printf(local_stdout,
"Profile '%s' will be run %d times.\n", profile_name, p->execute_rounds);
#endif /* PROFILE_DEBUG */
/* find out what the name of our urllist is */
if ((rv = retrieve_xml_elem_child(
&useurllist_elem, profile_elem, XML_PROFILE_USEURLLIST)) != APR_SUCCESS) {
/* useurllist is a required parameter, error */
apr_file_printf(local_stderr,
"Profile '%s' has no <%s> parameter.\n",
profile_name, XML_PROFILE_USEURLLIST);
return APR_EGENERAL;
} else {
urllist_name = apr_pstrdup(pool, useurllist_elem->first_cdata.first->text);
}
/* retrieve our urllist xml element */
if ((rv = retrieve_xml_elem_with_childmatch(
&urllist_elem, root_elem,
xml_urllist, XML_URLLIST_NAME, urllist_name)) != APR_SUCCESS)
return rv;
/* do we have base url? */
if ((rv = retrieve_xml_elem_child(
&baseurl_elem, urllist_elem, XML_URLLIST_BASE_URL)) == APR_SUCCESS) {
/* yes we do */
p->baseurl = apr_pstrdup(pool, baseurl_elem->first_cdata.first->text);
} else {
p->baseurl = NULL;
}
/* do we have proxy url? */
if ((rv = retrieve_xml_elem_child(
&proxyurl_elem, urllist_elem, XML_URLLIST_PROXY_URL)) == APR_SUCCESS) {
/* yes we do */
p->proxy_url = apr_pcalloc(p->pool, sizeof(apr_uri_t));
apr_uri_parse(p->pool, proxyurl_elem->first_cdata.first->text,
p->proxy_url);
} else {
p->proxy_url = NULL;
}
p->urls = 0;
/* Include sequences. We'll expand them later. */
p->urls = count_xml_seq_child(urllist_elem);
/* find the urls for this profile, put 'em in this list */
p->urls += count_xml_elem_child(urllist_elem, XML_URLLIST_URL);
if (p->urls <= 0) {
apr_file_printf(local_stderr, "Urllist '%s' doesn't have any urls!\n", urllist_name);
return APR_EGENERAL;
}
p->url = apr_pcalloc(p->pool, sizeof(url_t) * (p->urls + 1));
i = 0;
for (e = urllist_elem->first_child; e; e = e->next) {
if (strncasecmp(e->name, XML_URLLIST_SEQUENCE, FLOOD_STRLEN_MAX) == 0) {
rv = parse_xml_seq_info(e, p, pool);
if (rv != APR_SUCCESS) {
return rv;
}
}
if (strncasecmp(e->name, XML_URLLIST_URL, FLOOD_STRLEN_MAX) == 0) {
rv = parse_xml_url_info(e, &p->url[p->current_url++], pool);
if (rv != APR_SUCCESS) {
return rv;
}
}
}
/* Reset this back to 0. */
p->current_url = 0;
/* now initialize the subst_list for random text substitution */
/* get the subst_list from the config file */
/* the subst_list has pairs or substitution variables and files */
/* later on, in handle_param_string(), when a substitution variable */
/* is found, it will be substituted with a randomly chosen line from */
/* the subsitution file */
/* there can be an arbitrary number of such pairs */
/* the pairs scope is the entire configuration file */
/* they are not specific to a profile, url or urllist */
xml_subst_list = apr_pstrdup(pool, XML_SUBST_LIST);
if ((rv = retrieve_xml_elem_child(
&subst_list_elem, root_elem, XML_SUBST_LIST)) == APR_SUCCESS) {
/* count the subst_entries for this config file and allocate space */
p->subst_count = 0;
p->subst_count += count_xml_elem_child(subst_list_elem, XML_SUBST_ENTRY);
p->subst_list = apr_pcalloc(p->pool, sizeof(subst_rec_t) * (p->subst_count + 1));
/* get the subst_list info and populate the data structures */
subst_rec_p = p->subst_list;
for (e = subst_list_elem->first_child; e; e = e->next) {
if (strncasecmp(e->name, XML_SUBST_ENTRY, FLOOD_STRLEN_MAX) == 0) {
subst_entry_elem = e;
for (subst_entry_child = subst_entry_elem->first_child;
subst_entry_child;
subst_entry_child = subst_entry_child->next) {
if (strncasecmp(subst_entry_child->name,
XML_SUBST_VAR, FLOOD_STRLEN_MAX) == 0) {
if (subst_entry_child->first_cdata.first
&& subst_entry_child->first_cdata.first->text) {
((subst_rec_t*)subst_rec_p)->subst_var =
apr_pstrdup(pool,
subst_entry_child->first_cdata.first->text);
}
}
if (strncasecmp(subst_entry_child->name,
XML_SUBST_FILE, FLOOD_STRLEN_MAX) == 0) {
if (subst_entry_child->first_cdata.first
&& subst_entry_child->first_cdata.first->text) {
((subst_rec_t*)subst_rec_p)->subst_file_name =
apr_pstrdup(pool,
subst_entry_child->first_cdata.first->text);
}
}
}
}
/* this is the end of each subst_entry fetch */
/* at this point we should have the subst_var and subst_file_name */
if (subst_rec_p->subst_var && subst_rec_p->subst_file_name) {
subst_rec_p->valid = 1;
}
/* we should have the same number of valid substs as */
/* the subst_count above */
valid_substs++;
subst_rec_p++;
}
if (valid_substs != p->subst_count) {
apr_file_printf(local_stderr,
"Profile '%s' valid substs: %d inconsistent with subst count %d.\n",
profile_name, valid_substs, p->subst_count);
return APR_EGENERAL;
}
/* now open all the substitution files */
subst_rec_p = p->subst_list;
while(subst_rec_p->valid) {
subst_file_open(&(subst_rec_p->subst_file),
subst_rec_p->subst_file_name,
&(subst_rec_p->fsize), pool);
subst_rec_p++;
}
}
*profile = p;
return APR_SUCCESS;
}