apr_status_t round_robin_profile_init()

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;
}