diff --git a/src/libgendersllnl/hostlist.c b/src/libgendersllnl/hostlist.c index b5e4f8c..3f0a9a2 100644 --- a/src/libgendersllnl/hostlist.c +++ b/src/libgendersllnl/hostlist.c @@ -1,5 +1,5 @@ /*****************************************************************************\ - * $Id: hostlist.c,v 1.8 2008-01-29 19:09:11 chu11 Exp $ + * $LSDId: hostlist.c 11882 2012-10-03 17:31:41Z grondo $ ***************************************************************************** * Copyright (C) 2002 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). @@ -350,21 +350,6 @@ static void _error(char *file, int line, char *msg, ...) return; } -static int _advance_past_brackets (char *tok, char **str) -{ - /* if _single_ opening bracket exists b/w tok and str, push str - * past first closing bracket to next seperator */ - if ( memchr(tok, '[', *str - tok) != NULL - && memchr(tok, ']', *str - tok) == NULL ) { - char *q = strchr(*str, ']'); - if (q && memchr(*str, '[', q - *str) == NULL) { - *str = q + 1; - return (1); - } - } - - return 0; -} /* * Helper function for host list string parsing routines @@ -375,13 +360,16 @@ static int _advance_past_brackets (char *tok, char **str) * (with modifications to support bracketed hostlists, i.e.: * xxx[xx,xx,xx] is a single token) * + * _next_tok now handles multiple brackets within the same token, + * e.g. node[01-30]-[1-2,6]. */ static char * _next_tok(char *sep, char **str) { char *tok; + int level = 0; /* push str past any leading separators */ - while (**str != '\0' && strchr(sep, **str) != '\0') + while (**str != '\0' && strchr(sep, **str)) (*str)++; if (**str == '\0') @@ -390,19 +378,15 @@ static char * _next_tok(char *sep, char **str) /* assign token ptr */ tok = *str; - /* - * Advance str past any separators, but if a separator occurs between - * brackets, e.g. foo[0-3,5], then advance str past closing brackets and - * try again. - */ - do { - /* push str past token and leave pointing to first separator */ - while (**str != '\0' && strchr(sep, **str) == '\0') - (*str)++; - } while (_advance_past_brackets (tok, str)); - + while ( **str != '\0' && + (level != 0 || strchr(sep, **str) == NULL) ) { + if ( **str == '[' ) level++; + else if ( **str == ']' ) level--; + (*str)++; + } + /* nullify consecutive separators and push str beyond them */ - while (**str != '\0' && strchr(sep, **str) != '\0') + while (**str != '\0' && strchr(sep, **str) != NULL) *(*str)++ = '\0'; return tok; @@ -479,22 +463,16 @@ static int host_prefix_end(const char *hostname) return idx; } -/* - * create a hostname_t object from a string hostname - */ -static hostname_t hostname_create(const char *hostname) +static hostname_t hostname_create_with_suffix (const char *hostname, int idx) { hostname_t hn = NULL; - char *p = '\0'; - int idx = 0; + char *p = "\0"; assert(hostname != NULL); if (!(hn = (hostname_t) malloc(sizeof(*hn)))) out_of_memory("hostname create"); - idx = host_prefix_end(hostname); - if (!(hn->hostname = strdup(hostname))) { free(hn); out_of_memory("hostname create"); @@ -531,6 +509,17 @@ static hostname_t hostname_create(const char *hostname) } return hn; + +} + + +/* + * create a hostname_t object from a string hostname + */ +static hostname_t hostname_create(const char *hostname) +{ + int idx = host_prefix_end (hostname); + return hostname_create_with_suffix (hostname, idx); } /* free a hostname object @@ -901,27 +890,98 @@ static hostrange_t hostrange_intersect(hostrange_t h1, hostrange_t h2) return new; } -/* return 1 if hostname hn is within the hostrange hr - * 0 if not. +/* return offset of hn if it is in the hostlist or + * -1 if not. */ static int hostrange_hn_within(hostrange_t hr, hostname_t hn) { - int retval = 0; + int len_hr; + int len_hn; + int width; - if (hr->singlehost && (strcmp(hn->hostname, hr->prefix) == 0)) - return 1; + if (hr->singlehost) { + /* + * If the current hostrange [hr] is a `singlehost' (no valid + * numeric suffix (lo and hi)), then the hostrange [hr] + * stores just one host with name == hr->prefix. + * + * Thus the full hostname in [hn] must match hr->prefix, in + * which case we return true. Otherwise, there is no + * possibility that [hn] matches [hr]. + */ + if (strcmp (hn->hostname, hr->prefix) == 0) + return 0; + else + return -1; + } - if (strcmp(hr->prefix, hn->prefix) == 0) { - if (!hostname_suffix_is_valid(hn)) { - if (hr->singlehost) - retval = 1; - } else if (hn->num <= hr->hi && hn->num >= hr->lo) { - int width = hostname_suffix_width(hn); - int num = hn->num; - retval = _width_equiv(hr->lo, &hr->width, num, &width); - } + /* + * Now we know [hr] is not a "singlehost", so hostname + * better have a valid numeric suffix, or there is no + * way we can match + */ + if (!hostname_suffix_is_valid (hn)) + return -1; + + len_hn = strlen (hn->prefix); + + /* + * If hostrange and hostname prefixes don't match to at least + * the length of the hostname object (which will have the min + * possible prefix length), then there is no way the hostname + * falls within the range [hr]. + */ + if (strncmp (hr->prefix, hn->prefix, len_hn) != 0) + return -1; + + /* + * Now we know hostrange and hostname prefixes match up to the + * length of the hostname prefix. If the hostrange and hostname + * prefix lengths do not match (specifically if the hostname prefix + * length is less than the hostrange prefix length) and the + * hostrange prefix contains trailing digits, then it might be + * the case that the hostrange was created by forcing the prefix + * to contain digits a la f00[1-2]. So we try adjusting the + * hostname with the longer prefix and calling this function + * again with the new hostname. (Yes, this is ugly, sorry) + */ + len_hr = strlen (hr->prefix); + width = hostname_suffix_width (hn); + + if ((len_hn < len_hr) + && (width > 1) + && (isdigit (hr->prefix [len_hr - 1])) + && (hr->prefix [len_hn] == hn->suffix[0]) ) { + int rc; + /* + * Create new hostname object with its prefix offset by one + */ + hostname_t h = hostname_create_with_suffix (hn->hostname, len_hn); + /* + * Recursive call :-o + */ + rc = hostrange_hn_within (hr, h); + hostname_destroy (h); + return rc; } - return retval; + + + /* + * Finally, check whether [hn], with a valid numeric suffix, + * falls within the range of [hr] if [hn] and [hr] prefix are + * identical. + */ + if ((len_hr == len_hn) + && (strcmp (hn->prefix, hr->prefix) == 0) + && (hn->num <= hr->hi) + && (hn->num >= hr->lo)) { + int width = hostname_suffix_width (hn); + if (!_width_equiv(hr->lo, &hr->width, hn->num, &width)) + return -1; + return (hn->num - hr->lo); + } + + return -1; } @@ -1836,8 +1896,8 @@ int hostlist_delete_nth(hostlist_t hl, int n) } done: - UNLOCK_HOSTLIST(hl); hl->nhosts--; + UNLOCK_HOSTLIST(hl); return 1; } @@ -1863,17 +1923,15 @@ int hostlist_find(hostlist_t hl, const char *hostname) LOCK_HOSTLIST(hl); for (i = 0, count = 0; i < hl->nranges; i++) { - if (hostrange_hn_within(hl->hr[i], hn)) { - if (hostname_suffix_is_valid(hn) && !hl->hr[i]->singlehost) - ret = count + hn->num - hl->hr[i]->lo; - else - ret = count; - goto done; - } else + int offset = hostrange_hn_within(hl->hr[i], hn); + if (offset >= 0) { + ret = count + offset; + break; + } + else count += hostrange_count(hl->hr[i]); } - done: UNLOCK_HOSTLIST(hl); hostname_destroy(hn); return ret; @@ -2087,7 +2145,7 @@ _get_bracketed_list(hostlist_t hl, int *start, const size_t n, char *buf) if ((len < 0) || (len > n)) return n; /* truncated, buffer filled */ - if (bracket_needed && len < n && len >= 0) + if (bracket_needed && len < n) buf[len++] = '['; do { @@ -2453,7 +2511,7 @@ static int hostset_find_host(hostset_t set, const char *host) LOCK_HOSTLIST(set->hl); hn = hostname_create(host); for (i = 0; i < set->hl->nranges; i++) { - if (hostrange_hn_within(set->hl->hr[i], hn)) { + if (hostrange_hn_within(set->hl->hr[i], hn) >= 0) { retval = 1; goto done; } diff --git a/src/libgendersllnl/hostlist.h b/src/libgendersllnl/hostlist.h index c20292e..f66cb5c 100644 --- a/src/libgendersllnl/hostlist.h +++ b/src/libgendersllnl/hostlist.h @@ -1,5 +1,7 @@ /*****************************************************************************\ - * $Id: hostlist.h,v 1.8 2008-01-29 19:09:12 chu11 Exp $ + * $Id$ + ***************************************************************************** + * $LSDId: hostlist.h 7428 2008-05-23 16:08:31Z grondo $ ***************************************************************************** * Copyright (C) 2002 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). @@ -27,6 +29,8 @@ #ifndef _HOSTLIST_H #define _HOSTLIST_H +#include + /* Notes: * * If WITH_LSD_FATAL_ERROR_FUNC is defined, the linker will expect to