+++ /dev/null
-/*****************************************************************************\
- * $Id: hostlist.c,v 1.1.2.1 2008/11/21 15:27:33 yangsheng Exp $
- *****************************************************************************
- * Copyright (C) 2002 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Mark Grondona <mgrondona@llnl.gov>
- * UCRL-CODE-2002-040.
- *
- * This file is part of SLURM, a resource management program.
- * For details, see <http://www.llnl.gov/linux/slurm/>.
- *
- * SLURM is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along
- * with SLURM; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-\*****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-# if HAVE_STRING_H
-# include <string.h>
-# endif
-# if HAVE_PTHREAD_H
-# include <pthread.h>
-# endif
-#else /* !HAVE_CONFIG_H */
-# include <string.h>
-# include <pthread.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <errno.h>
-#include <ctype.h>
-#include <sys/param.h>
-#include <unistd.h>
-
-#include "hostlist.h"
-
-/*
- * lsd_fatal_error : fatal error macro
- */
-#ifdef WITH_LSD_FATAL_ERROR_FUNC
-# undef lsd_fatal_error
- extern void lsd_fatal_error(char *file, int line, char *mesg);
-#else /* !WITH_LSD_FATAL_ERROR_FUNC */
-# ifndef lsd_fatal_error
-# define lsd_fatal_error(file, line, mesg) \
- do { \
- fprintf(stderr, "ERROR: [%s:%d] %s: %s\n", \
- file, line, mesg, strerror(errno)); \
- } while (0)
-# endif /* !lsd_fatal_error */
-#endif /* !WITH_LSD_FATAL_ERROR_FUNC */
-
-/*
- * lsd_nonmem_error
- */
-#ifdef WITH_LSD_NOMEM_ERROR_FUNC
-# undef lsd_nomem_error
- extern void * lsd_nomem_error(char *file, int line, char *mesg);
-#else /* !WITH_LSD_NOMEM_ERROR_FUNC */
-# ifndef lsd_nomem_error
-# define lsd_nomem_error(file, line, mesg) (NULL)
-# endif /* !lsd_nomem_error */
-#endif /* !WITH_LSD_NOMEM_ERROR_FUNC */
-
-/*
- * OOM helper function
- * Automatically call lsd_nomem_error with appropriate args
- * and set errno to ENOMEM
- */
-#define out_of_memory(mesg) \
- do { \
- errno = ENOMEM; \
- return(lsd_nomem_error(__FILE__, __LINE__, mesg)); \
- } while (0)
-
-/*
- * Some constants and tunables:
- */
-
-/* number of elements to allocate when extending the hostlist array */
-#define HOSTLIST_CHUNK 16
-
-/* max host range: anything larger will be assumed to be an error */
-#define MAX_RANGE 16384 /* 16K Hosts */
-
-/* max host suffix value */
-#define MAX_HOST_SUFFIX 1<<25
-
-/* max number of ranges that will be processed between brackets */
-#define MAX_RANGES 10240 /* 10K Ranges */
-
-/* size of internal hostname buffer (+ some slop), hostnames will probably
- * be truncated if longer than MAXHOSTNAMELEN */
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 64
-#endif
-
-/* max size of internal hostrange buffer */
-#define MAXHOSTRANGELEN 1024
-
-/* ----[ Internal Data Structures ]---- */
-
-/* hostname type: A convenience structure used in parsing single hostnames */
-struct hostname_components {
- char *hostname; /* cache of initialized hostname */
- char *prefix; /* hostname prefix */
- unsigned long num; /* numeric suffix */
-
- /* string representation of numeric suffix
- * points into `hostname' */
- char *suffix;
-};
-
-typedef struct hostname_components *hostname_t;
-
-/* hostrange type: A single prefix with `hi' and `lo' numeric suffix values */
-struct hostrange_components {
- char *prefix; /* alphanumeric prefix: */
-
- /* beginning (lo) and end (hi) of suffix range */
- unsigned long lo, hi;
-
- /* width of numeric output format
- * (pad with zeros up to this width) */
- int width;
-
- /* If singlehost is 1, `lo' and `hi' are invalid */
- unsigned singlehost:1;
-};
-
-typedef struct hostrange_components *hostrange_t;
-
-/* The hostlist type: An array based list of hostrange_t's */
-struct hostlist {
-#ifndef NDEBUG
-#define HOSTLIST_MAGIC 57005
- int magic;
-#endif
-#if WITH_PTHREADS
- pthread_mutex_t mutex;
-#endif /* WITH_PTHREADS */
-
- /* current number of elements available in array */
- int size;
-
- /* current number of ranges stored in array */
- int nranges;
-
- /* current number of hosts stored in hostlist */
- int nhosts;
-
- /* pointer to hostrange array */
- hostrange_t *hr;
-
- /* list of iterators */
- struct hostlist_iterator *ilist;
-
-};
-
-
-/* a hostset is a wrapper around a hostlist */
-struct hostset {
- hostlist_t hl;
-};
-
-struct hostlist_iterator {
-#ifndef NDEBUG
- int magic;
-#endif
- /* hostlist we are traversing */
- hostlist_t hl;
-
- /* current index of iterator in hl->hr[] */
- int idx;
-
- /* current hostrange object in list hl, i.e. hl->hr[idx] */
- hostrange_t hr;
-
- /* current depth we've traversed into range hr */
- int depth;
-
- /* next ptr for lists of iterators */
- struct hostlist_iterator *next;
-};
-
-
-/* ---- ---- */
-
-/* ------[ static function prototypes ]------ */
-
-static void _error(char *file, int line, char *mesg, ...);
-static char * _next_tok(char *, char **);
-static int _zero_padded(unsigned long, int);
-static int _width_equiv(unsigned long, int *, unsigned long, int *);
-
-static int host_prefix_end(const char *);
-static hostname_t hostname_create(const char *);
-static void hostname_destroy(hostname_t);
-static int hostname_suffix_is_valid(hostname_t);
-static int hostname_suffix_width(hostname_t);
-
-static hostrange_t hostrange_new(void);
-static hostrange_t hostrange_create_single(const char *);
-static hostrange_t hostrange_create(char *, unsigned long, unsigned long, int);
-static unsigned long hostrange_count(hostrange_t);
-static hostrange_t hostrange_copy(hostrange_t);
-static void hostrange_destroy(hostrange_t);
-static hostrange_t hostrange_delete_host(hostrange_t, unsigned long);
-static int hostrange_cmp(hostrange_t, hostrange_t);
-static int hostrange_prefix_cmp(hostrange_t, hostrange_t);
-static int hostrange_within_range(hostrange_t, hostrange_t);
-static int hostrange_width_combine(hostrange_t, hostrange_t);
-static int hostrange_empty(hostrange_t);
-static char * hostrange_pop(hostrange_t);
-static char * hostrange_shift(hostrange_t);
-static int hostrange_join(hostrange_t, hostrange_t);
-static hostrange_t hostrange_intersect(hostrange_t, hostrange_t);
-static int hostrange_hn_within(hostrange_t, hostname_t);
-static size_t hostrange_to_string(hostrange_t hr, size_t, char *, char *);
-static size_t hostrange_numstr(hostrange_t, size_t, char *);
-
-static hostlist_t hostlist_new(void);
-static hostlist_t _hostlist_create_bracketed(const char *, char *, char *);
-static int hostlist_resize(hostlist_t, size_t);
-static int hostlist_expand(hostlist_t);
-static int hostlist_push_range(hostlist_t, hostrange_t);
-static int hostlist_push_hr(hostlist_t, char *, unsigned long,
- unsigned long, int);
-static int hostlist_insert_range(hostlist_t, hostrange_t, int);
-static void hostlist_delete_range(hostlist_t, int n);
-static void hostlist_coalesce(hostlist_t hl);
-static void hostlist_collapse(hostlist_t hl);
-static hostlist_t _hostlist_create(const char *, char *, char *);
-static void hostlist_shift_iterators(hostlist_t, int, int, int);
-static int _attempt_range_join(hostlist_t, int);
-static int _is_bracket_needed(hostlist_t, int);
-
-static hostlist_iterator_t hostlist_iterator_new(void);
-static void _iterator_advance(hostlist_iterator_t);
-static void _iterator_advance_range(hostlist_iterator_t);
-
-static int hostset_find_host(hostset_t, const char *);
-
-/* ------[ macros ]------ */
-
-#ifdef WITH_PTHREADS
-# define mutex_init(mutex) \
- do { \
- int e = pthread_mutex_init(mutex, NULL); \
- if (e) { \
- errno = e; \
- lsd_fatal_error(__FILE__, __LINE__, "hostlist mutex init:"); \
- abort(); \
- } \
- } while (0)
-
-# define mutex_lock(mutex) \
- do { \
- int e = pthread_mutex_lock(mutex); \
- if (e) { \
- errno = e; \
- lsd_fatal_error(__FILE__, __LINE__, "hostlist mutex lock:"); \
- abort(); \
- } \
- } while (0)
-
-# define mutex_unlock(mutex) \
- do { \
- int e = pthread_mutex_unlock(mutex); \
- if (e) { \
- errno = e; \
- lsd_fatal_error(__FILE__, __LINE__, "hostlist mutex unlock:"); \
- abort(); \
- } \
- } while (0)
-
-# define mutex_destroy(mutex) \
- do { \
- int e = pthread_mutex_destroy(mutex); \
- if (e) { \
- errno = e; \
- lsd_fatal_error(__FILE__, __LINE__, "hostlist mutex destroy:"); \
- abort(); \
- } \
- } while (0)
-
-#else /* !WITH_PTHREADS */
-
-# define mutex_init(mutex)
-# define mutex_lock(mutex)
-# define mutex_unlock(mutex)
-# define mutex_destroy(mutex)
-
-#endif /* WITH_PTHREADS */
-
-#define LOCK_HOSTLIST(_hl) \
- do { \
- assert(_hl != NULL); \
- mutex_lock(&(_hl)->mutex); \
- assert((_hl)->magic == HOSTLIST_MAGIC); \
- } while (0)
-
-#define UNLOCK_HOSTLIST(_hl) \
- do { \
- mutex_unlock(&(_hl)->mutex); \
- } while (0)
-
-#define seterrno_ret(_errno, _rc) \
- do { \
- errno = _errno; \
- return _rc; \
- } while (0)
-
-/* ------[ Function Definitions ]------ */
-
-/* ----[ general utility functions ]---- */
-
-
-/*
- * Varargs capable error reporting via lsd_fatal_error()
- */
-static void _error(char *file, int line, char *msg, ...)
-{
- va_list ap;
- char buf[1024];
- int len = 0;
- va_start(ap, msg);
-
- len = vsnprintf(buf, 1024, msg, ap);
- if ((len < 0) || (len > 1024))
- buf[1023] = '\0';
-
- lsd_fatal_error(file, line, buf);
-
- va_end(ap);
- 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
- * Returns a pointer to the next token; additionally advance *str
- * to the next separator.
- *
- * next_tok was taken directly from pdsh courtesy of Jim Garlick.
- * (with modifications to support bracketed hostlists, i.e.:
- * xxx[xx,xx,xx] is a single token)
- *
- */
-static char * _next_tok(char *sep, char **str)
-{
- char *tok;
-
- /* push str past any leading separators */
- while (**str != '\0' && strchr(sep, **str) != '\0')
- (*str)++;
-
- if (**str == '\0')
- return NULL;
-
- /* 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));
-
- /* nullify consecutive separators and push str beyond them */
- while (**str != '\0' && strchr(sep, **str) != '\0')
- *(*str)++ = '\0';
-
- return tok;
-}
-
-
-/* return the number of zeros needed to pad "num" to "width"
- */
-static int _zero_padded(unsigned long num, int width)
-{
- int n = 1;
- while (num /= 10L)
- n++;
- return width > n ? width - n : 0;
-}
-
-/* test whether two format `width' parameters are "equivalent"
- * The width arguments "wn" and "wm" for integers "n" and "m"
- * are equivalent if:
- *
- * o wn == wm OR
- *
- * o applying the same format width (either wn or wm) to both of
- * 'n' and 'm' will not change the zero padding of *either* 'm' nor 'n'.
- *
- * If this function returns 1 (or true), the appropriate width value
- * (either 'wm' or 'wn') will have been adjusted such that both format
- * widths are equivalent.
- */
-static int _width_equiv(unsigned long n, int *wn, unsigned long m, int *wm)
-{
- int npad, nmpad, mpad, mnpad;
-
- if (wn == wm)
- return 1;
-
- npad = _zero_padded(n, *wn);
- nmpad = _zero_padded(n, *wm);
- mpad = _zero_padded(m, *wm);
- mnpad = _zero_padded(m, *wn);
-
- if (npad != nmpad && mpad != mnpad)
- return 0;
-
- if (npad != nmpad) {
- if (mpad == mnpad) {
- *wm = *wn;
- return 1;
- } else
- return 0;
- } else { /* mpad != mnpad */
- if (npad == nmpad) {
- *wn = *wm;
- return 1;
- } else
- return 0;
- }
-
- /* not reached */
-}
-
-
-/* ----[ hostname_t functions ]---- */
-
-/*
- * return the location of the last char in the hostname prefix
- */
-static int host_prefix_end(const char *hostname)
-{
- int idx = strlen(hostname) - 1;
-
- while (idx >= 0 && isdigit((char) hostname[idx]))
- idx--;
- return idx;
-}
-
-/*
- * create a hostname_t object from a string hostname
- */
-static hostname_t hostname_create(const char *hostname)
-{
- hostname_t hn = NULL;
- char *p = '\0';
- int idx = 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");
- }
-
- hn->num = 0;
- hn->prefix = NULL;
- hn->suffix = NULL;
-
- if (idx == strlen(hostname) - 1) {
- if ((hn->prefix = strdup(hostname)) == NULL) {
- hostname_destroy(hn);
- out_of_memory("hostname prefix create");
- }
- return hn;
- }
-
- hn->suffix = hn->hostname + idx + 1;
- hn->num = strtoul(hn->suffix, &p, 10);
-
- if ((*p == '\0') && (hn->num <= MAX_HOST_SUFFIX)) {
- if (!(hn->prefix = malloc((idx + 2) * sizeof(char)))) {
- hostname_destroy(hn);
- out_of_memory("hostname prefix create");
- }
- memcpy(hn->prefix, hostname, idx + 1);
- hn->prefix[idx + 1] = '\0';
- } else {
- if (!(hn->prefix = strdup(hostname))) {
- hostname_destroy(hn);
- out_of_memory("hostname prefix create");
- }
- hn->suffix = NULL;
- }
-
- return hn;
-}
-
-/* free a hostname object
- */
-static void hostname_destroy(hostname_t hn)
-{
- if (hn == NULL)
- return;
- hn->suffix = NULL;
- if (hn->hostname)
- free(hn->hostname);
- if (hn->prefix)
- free(hn->prefix);
- free(hn);
-}
-
-/* return true if the hostname has a valid numeric suffix
- */
-static int hostname_suffix_is_valid(hostname_t hn)
-{
- return hn->suffix != NULL;
-}
-
-/* return the width (in characters) of the numeric part of the hostname
- */
-static int hostname_suffix_width(hostname_t hn)
-{
- assert(hn->suffix != NULL);
- return (int) strlen(hn->suffix);
-}
-
-
-/* ----[ hostrange_t functions ]---- */
-
-/* allocate a new hostrange object
- */
-static hostrange_t hostrange_new(void)
-{
- hostrange_t new = (hostrange_t) malloc(sizeof(*new));
- if (!new)
- out_of_memory("hostrange create");
- return new;
-}
-
-/* Create a hostrange_t containing a single host without a valid suffix
- * hr->prefix will represent the entire hostname.
- */
-static hostrange_t hostrange_create_single(const char *prefix)
-{
- hostrange_t new;
-
- assert(prefix != NULL);
-
- if ((new = hostrange_new()) == NULL)
- goto error1;
-
- if ((new->prefix = strdup(prefix)) == NULL)
- goto error2;
-
- new->singlehost = 1;
- new->lo = 0L;
- new->hi = 0L;
- new->width = 0;
-
- return new;
-
- error2:
- free(new);
- error1:
- out_of_memory("hostrange create single");
-}
-
-
-/* Create a hostrange object with a prefix, hi, lo, and format width
- */
-static hostrange_t
-hostrange_create(char *prefix, unsigned long lo, unsigned long hi, int width)
-{
- hostrange_t new;
-
- assert(prefix != NULL);
-
- if ((new = hostrange_new()) == NULL)
- goto error1;
-
- if ((new->prefix = strdup(prefix)) == NULL)
- goto error2;
-
- new->lo = lo;
- new->hi = hi;
- new->width = width;
-
- new->singlehost = 0;
-
- return new;
-
- error2:
- free(new);
- error1:
- out_of_memory("hostrange create");
-}
-
-
-/* Return the number of hosts stored in the hostrange object
- */
-static unsigned long hostrange_count(hostrange_t hr)
-{
- assert(hr != NULL);
- if (hr->singlehost)
- return 1;
- else
- return hr->hi - hr->lo + 1;
-}
-
-/* Copy a hostrange object
- */
-static hostrange_t hostrange_copy(hostrange_t hr)
-{
- assert(hr != NULL);
-
- if (hr->singlehost)
- return hostrange_create_single(hr->prefix);
- else
- return hostrange_create(hr->prefix, hr->lo, hr->hi,
- hr->width);
-}
-
-
-/* free memory allocated by the hostrange object
- */
-static void hostrange_destroy(hostrange_t hr)
-{
- if (hr == NULL)
- return;
- if (hr->prefix)
- free(hr->prefix);
- free(hr);
-}
-
-/* hostrange_delete_host() deletes a specific host from the range.
- * If the range is split into two, the greater range is returned,
- * and `hi' of the lesser range is adjusted accordingly. If the
- * highest or lowest host is deleted from a range, NULL is returned
- * and the hostrange hr is adjusted properly.
- */
-static hostrange_t hostrange_delete_host(hostrange_t hr, unsigned long n)
-{
- hostrange_t new = NULL;
-
- assert(hr != NULL);
- assert(n >= hr->lo && n <= hr->hi);
-
- if (n == hr->lo)
- hr->lo++;
- else if (n == hr->hi)
- hr->hi--;
- else {
- if (!(new = hostrange_copy(hr)))
- out_of_memory("hostrange copy");
- hr->hi = n - 1;
- new->lo = n + 1;
- }
-
- return new;
-}
-
-/* hostrange_cmp() is used to sort hostrange objects. It will
- * sort based on the following (in order):
- * o result of strcmp on prefixes
- * o if widths are compatible, then:
- * sort based on lowest suffix in range
- * else
- * sort based on width */
-static int hostrange_cmp(hostrange_t h1, hostrange_t h2)
-{
- int retval;
-
- assert(h1 != NULL);
- assert(h2 != NULL);
-
- if ((retval = hostrange_prefix_cmp(h1, h2)) == 0)
- retval = hostrange_width_combine(h1, h2) ?
- h1->lo - h2->lo : h1->width - h2->width;
-
- return retval;
-}
-
-
-/* compare the prefixes of two hostrange objects.
- * returns:
- * < 0 if h1 prefix is less than h2 OR h1 == NULL.
- *
- * 0 if h1's prefix and h2's prefix match,
- * UNLESS, either h1 or h2 (NOT both) do not have a valid suffix.
- *
- * > 0 if h1's prefix is greater than h2's OR h2 == NULL. */
-static int hostrange_prefix_cmp(hostrange_t h1, hostrange_t h2)
-{
- int retval;
- if (h1 == NULL)
- return 1;
- if (h2 == NULL)
- return -1;
-
- retval = strcmp(h1->prefix, h2->prefix);
- return retval == 0 ? h2->singlehost - h1->singlehost : retval;
-}
-
-/* returns true if h1 and h2 would be included in the same bracketed hostlist.
- * h1 and h2 will be in the same bracketed list iff:
- *
- * 1. h1 and h2 have same prefix
- * 2. neither h1 nor h2 are singlet hosts (i.e. invalid suffix)
- *
- * (XXX: Should incompatible widths be placed in the same bracketed list?
- * There's no good reason not to, except maybe aesthetics)
- */
-static int hostrange_within_range(hostrange_t h1, hostrange_t h2)
-{
- if (hostrange_prefix_cmp(h1, h2) == 0)
- return h1->singlehost || h2->singlehost ? 0 : 1;
- else
- return 0;
-}
-
-
-/* compare two hostrange objects to determine if they are width
- * compatible, returns:
- * 1 if widths can safely be combined
- * 0 if widths cannot be safely combined
- */
-static int hostrange_width_combine(hostrange_t h0, hostrange_t h1)
-{
- assert(h0 != NULL);
- assert(h1 != NULL);
-
- return _width_equiv(h0->lo, &h0->width, h1->lo, &h1->width);
-}
-
-
-/* Return true if hostrange hr contains no hosts, i.e. hi < lo
- */
-static int hostrange_empty(hostrange_t hr)
-{
- assert(hr != NULL);
- return ((hr->hi < hr->lo) || (hr->hi == (unsigned long) -1));
-}
-
-/* return the string representation of the last host in hostrange hr
- * and remove that host from the range (i.e. decrement hi if possible)
- *
- * Returns NULL if malloc fails OR there are no more hosts left
- */
-static char *hostrange_pop(hostrange_t hr)
-{
- size_t size = 0;
- char *host = NULL;
-
- assert(hr != NULL);
-
- if (hr->singlehost) {
- hr->lo++; /* effectively set count == 0 */
- host = strdup(hr->prefix);
- } else if (hostrange_count(hr) > 0) {
- size = strlen(hr->prefix) + hr->width + 16;
- if (!(host = (char *) malloc(size * sizeof(char))))
- out_of_memory("hostrange pop");
- snprintf(host, size, "%s%0*lu", hr->prefix,
- hr->width, hr->hi--);
- }
-
- return host;
-}
-
-/* Same as hostrange_pop(), but remove host from start of range */
-static char *hostrange_shift(hostrange_t hr)
-{
- size_t size = 0;
- char *host = NULL;
-
- assert(hr != NULL);
-
- if (hr->singlehost) {
- hr->lo++;
- if (!(host = strdup(hr->prefix)))
- out_of_memory("hostrange shift");
- } else if (hostrange_count(hr) > 0) {
- size = strlen(hr->prefix) + hr->width + 16;
- if (!(host = (char *) malloc(size * sizeof(char))))
- out_of_memory("hostrange shift");
- snprintf(host, size, "%s%0*lu", hr->prefix,
- hr->width, hr->lo++);
- }
-
- return host;
-}
-
-
-/* join two hostrange objects.
- *
- * returns:
- *
- * -1 if ranges do not overlap (including incompatible zero padding)
- * 0 if ranges join perfectly
- * >0 number of hosts that were duplicated in h1 and h2
- *
- * h2 will be coalesced into h1 if rc >= 0
- *
- * it is assumed that h1->lo <= h2->lo, i.e. hr1 <= hr2
- *
- */
-static int hostrange_join(hostrange_t h1, hostrange_t h2)
-{
- int duplicated = -1;
-
- assert(h1 != NULL);
- assert(h2 != NULL);
- assert(hostrange_cmp(h1, h2) <= 0);
-
- if (hostrange_prefix_cmp(h1, h2) == 0 &&
- hostrange_width_combine(h1, h2)) {
-
- if (h1->singlehost && h2->singlehost) { /* matching singlets */
- duplicated = 1;
- } else if (h1->hi == h2->lo - 1) { /* perfect join */
- h1->hi = h2->hi;
- duplicated = 0;
- } else if (h1->hi >= h2->lo) { /* some duplication */
- if (h1->hi < h2->hi) {
- duplicated = h1->hi - h2->lo + 1;
- h1->hi = h2->hi;
- } else
- duplicated = hostrange_count(h2);
- }
- }
-
- return duplicated;
-}
-
-/* hostrange intersect returns the intersection (common hosts)
- * of hostrange objects h1 and h2. If there is no intersection,
- * NULL is returned.
- *
- * It is assumed that h1 <= h2 (i.e. h1->lo <= h2->lo)
- */
-static hostrange_t hostrange_intersect(hostrange_t h1, hostrange_t h2)
-{
- hostrange_t new = NULL;
-
- assert(h1 != NULL);
- assert(h2 != NULL);
-
- if (h1->singlehost || h2->singlehost)
- return NULL;
-
- assert(hostrange_cmp(h1, h2) <= 0);
-
- if ((hostrange_prefix_cmp(h1, h2) == 0)
- && (h1->hi > h2->lo)
- && (hostrange_width_combine(h1, h2))) {
-
- if (!(new = hostrange_copy(h1)))
- return NULL;
- new->lo = h2->lo;
- new->hi = h2->hi < h1->hi ? h2->hi : h1->hi;
- }
-
- return new;
-}
-
-/* return 1 if hostname hn is within the hostrange hr
- * 0 if not.
- */
-static int hostrange_hn_within(hostrange_t hr, hostname_t hn)
-{
- int retval = 0;
-
- if (hr->singlehost && (strcmp(hn->hostname, hr->prefix) == 0))
- 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);
- }
- }
- return retval;
-}
-
-
-/* copy a string representation of the hostrange hr into buffer buf,
- * writing at most n chars including NUL termination
- */
-static size_t
-hostrange_to_string(hostrange_t hr, size_t n, char *buf, char *separator)
-{
- unsigned long i;
- int truncated = 0;
- int len = 0;
- char sep = separator == NULL ? ',' : separator[0];
-
- if (n == 0)
- return 0;
-
- if (hr->singlehost)
- return snprintf(buf, n, "%s", hr->prefix);
-
- for (i = hr->lo; i <= hr->hi; i++) {
- size_t m = (n - len) <= n ? n - len : 0; /* check for < 0 */
- int ret = snprintf(buf + len, m, "%s%0*lu",
- hr->prefix, hr->width, i);
- if (ret < 0 || ret >= m) {
- len = n;
- truncated = 1;
- break;
- }
- len+=ret;
- buf[len++] = sep;
- }
-
- if (truncated) {
- buf[n-1] = '\0';
- return -1;
- } else {
- /* back up over final separator */
- buf[--len] = '\0';
- return len;
- }
-}
-
-/* Place the string representation of the numeric part of hostrange into buf
- * writing at most n chars including NUL termination.
- */
-static size_t hostrange_numstr(hostrange_t hr, size_t n, char *buf)
-{
- int len = 0;
-
- assert(buf != NULL);
-
- if (hr->singlehost || n == 0)
- return 0;
-
- len = snprintf(buf, n, "%0*lu", hr->width, hr->lo);
-
- if ((len >= 0) && (len < n) && (hr->lo < hr->hi)) {
- int len2 = snprintf(buf+len, n-len, "-%0*lu", hr->width, hr->hi);
- if (len2 < 0)
- len = -1;
- else
- len += len2;
- }
-
- return len;
-}
-
-
-/* ----[ hostlist functions ]---- */
-
-/* Create a new hostlist object.
- * Returns an empty hostlist, or NULL if memory allocation fails.
- */
-static hostlist_t hostlist_new(void)
-{
- int i;
- hostlist_t new = (hostlist_t) malloc(sizeof(*new));
- if (!new)
- goto fail1;
-
- assert(new->magic = HOSTLIST_MAGIC);
- mutex_init(&new->mutex);
-
- new->hr = (hostrange_t *) malloc(HOSTLIST_CHUNK * sizeof(hostrange_t));
- if (!new->hr)
- goto fail2;
-
- /* set entries in hostrange array to NULL */
- for (i = 0; i < HOSTLIST_CHUNK; i++)
- new->hr[i] = NULL;
-
- new->size = HOSTLIST_CHUNK;
- new->nranges = 0;
- new->nhosts = 0;
- new->ilist = NULL;
- return new;
-
- fail2:
- free(new);
- fail1:
- out_of_memory("hostlist_create");
-}
-
-
-/* Resize the internal array used to store the list of hostrange objects.
- *
- * returns 1 for a successful resize,
- * 0 if call to _realloc fails
- *
- * It is assumed that the caller has the hostlist hl locked
- */
-static int hostlist_resize(hostlist_t hl, size_t newsize)
-{
- int i;
- size_t oldsize;
- assert(hl != NULL);
- assert(hl->magic == HOSTLIST_MAGIC);
- oldsize = hl->size;
- hl->size = newsize;
- hl->hr = realloc((void *) hl->hr, hl->size*sizeof(hostrange_t));
- if (!(hl->hr))
- return 0;
-
- for (i = oldsize; i < newsize; i++)
- hl->hr[i] = NULL;
-
- return 1;
-}
-
-/* Resize hostlist by one HOSTLIST_CHUNK
- * Assumes that hostlist hl is locked by caller
- */
-static int hostlist_expand(hostlist_t hl)
-{
- if (!hostlist_resize(hl, hl->size + HOSTLIST_CHUNK))
- return 0;
- else
- return 1;
-}
-
-/* Push a hostrange object onto hostlist hl
- * Returns the number of hosts successfully pushed onto hl
- * or -1 if there was an error allocating memory
- */
-static int hostlist_push_range(hostlist_t hl, hostrange_t hr)
-{
- hostrange_t tail;
- int retval;
-
- assert(hr != NULL);
- LOCK_HOSTLIST(hl);
-
- tail = (hl->nranges > 0) ? hl->hr[hl->nranges-1] : hl->hr[0];
-
- if (hl->size == hl->nranges && !hostlist_expand(hl))
- goto error;
-
- if (hl->nranges > 0
- && hostrange_prefix_cmp(tail, hr) == 0
- && tail->hi == hr->lo - 1
- && hostrange_width_combine(tail, hr)) {
- tail->hi = hr->hi;
- } else {
- if ((hl->hr[hl->nranges++] = hostrange_copy(hr)) == NULL)
- goto error;
- }
-
- retval = hl->nhosts += hostrange_count(hr);
-
- UNLOCK_HOSTLIST(hl);
-
- return retval;
-
- error:
- UNLOCK_HOSTLIST(hl);
- return -1;
-}
-
-
-
-/* Same as hostlist_push_range() above, but prefix, lo, hi, and width
- * are passed as args
- */
-static int
-hostlist_push_hr(hostlist_t hl, char *prefix, unsigned long lo,
- unsigned long hi, int width)
-{
- hostrange_t hr = hostrange_create(prefix, lo, hi, width);
- int retval = hostlist_push_range(hl, hr);
- hostrange_destroy(hr);
- return retval;
-}
-
-/* Insert a range object hr into position n of the hostlist hl
- * Assumes that hl->mutex is already held by calling process
- */
-static int hostlist_insert_range(hostlist_t hl, hostrange_t hr, int n)
-{
- int i;
- hostrange_t tmp;
- hostlist_iterator_t hli;
-
- assert(hl != NULL);
- assert(hl->magic == HOSTLIST_MAGIC);
- assert(hr != NULL);
-
- if (n > hl->nranges)
- return 0;
-
- if (hl->size == hl->nranges && !hostlist_expand(hl))
- return 0;
-
- /* copy new hostrange into slot "n" in array */
- tmp = hl->hr[n];
- hl->hr[n] = hostrange_copy(hr);
-
- /* push remaining hostrange entries up */
- for (i = n + 1; i < hl->nranges + 1; i++) {
- hostrange_t last = hl->hr[i];
- hl->hr[i] = tmp;
- tmp = last;
- }
- hl->nranges++;
-
- /* adjust hostlist iterators if needed */
- for (hli = hl->ilist; hli; hli = hli->next) {
- if (hli->idx >= n)
- hli->hr = hli->hl->hr[++hli->idx];
- }
-
- return 1;
-}
-
-/* Delete the range at position n in the range array
- * Assumes the hostlist lock is already held.
- */
-static void hostlist_delete_range(hostlist_t hl, int n)
-{
- int i;
- hostrange_t old;
-
- assert(hl != NULL);
- assert(hl->magic == HOSTLIST_MAGIC);
- assert(n < hl->nranges && n >= 0);
-
- old = hl->hr[n];
- for (i = n; i < hl->nranges - 1; i++)
- hl->hr[i] = hl->hr[i + 1];
- hl->nranges--;
- hl->hr[hl->nranges] = NULL;
- hostlist_shift_iterators(hl, n, 0, 1);
-
- /* XXX caller responsible for adjusting nhosts */
- /* hl->nhosts -= hostrange_count(old) */
-
- hostrange_destroy(old);
-}
-
-#if WANT_RECKLESS_HOSTRANGE_EXPANSION
-
-/* The reckless hostrange expansion function.
- * See comment in hostlist.h:hostlist_create() for more info on
- * the different choices for hostlist notation.
- */
-hostlist_t _hostlist_create(const char *hostlist, char *sep, char *r_op)
-{
- char *str, *orig;
- char *tok, *cur;
- int high, low, fmt = 0;
- char prefix[256] = "";
- int pos = 0;
- int error = 0;
- char range_op = r_op[0];/* XXX support > 1 char range ops in future? */
-
- hostlist_t new = hostlist_new();
-
- orig = str = strdup(hostlist);
-
- /* return an empty list if an empty string was passed in */
- if (str == NULL || strlen(str) == 0)
- goto done;
-
- /* Use hostlist_create_bracketed if we see "[" */
- if (strchr(str, '[') != NULL)
- return _hostlist_create_bracketed(hostlist, sep, r_op);
-
- while ((tok = _next_tok(sep, &str)) != NULL) {
-
- /* save the current string for error messages */
- cur = tok;
-
- high = low = 0;
-
- /* find end of alpha part
- * do this by finding last occurence of range_op in str */
- pos = strlen(tok) - 1;
- if (strstr(tok, r_op) != '\0') {
- while (pos >= 0 && (char) tok[pos] != range_op)
- pos--;
- }
-
- /* now back up past any digits */
- while (pos >= 0 && isdigit((char) tok[--pos])) {;}
-
- /* Check for valid x-y range (x must be a digit)
- * Reset pos if the range is not valid */
- if (!isdigit((char) tok[++pos]))
- pos = strlen(tok) - 1;
-
- /* create prefix string
- * if prefix will be zero length, but prefix already exists
- * use the previous prefix and fmt
- */
- if ((pos > 0) || (prefix[0] == '\0')) {
- memcpy(prefix, tok, (size_t) pos * sizeof(char));
- prefix[pos] = '\0';
-
- /* push pointer past prefix */
- tok += pos;
-
- /* count number of digits for ouput fmt */
- for (fmt = 0; isdigit(tok[fmt]); ++fmt) {;}
-
- if (fmt == 0)
- error = 1;
-
- } else
- tok += pos;
-
- /* get lower bound */
- low = strtoul(tok, (char **) &tok, 10);
-
- if (*tok == range_op) { /* now get range upper bound */
- /* push pointer past range op */
- ++tok;
-
- /* find length of alpha part */
- for (pos = 0; tok[pos] && !isdigit(tok[pos]); ++pos) {;}
-
- /* alpha part must match prefix or error
- * this could mean we've got something like "rtr1-a2"
- * so just record an error
- */
- if (pos > 0) {
- if (pos != strlen(prefix) ||
- strncmp(prefix, tok, pos) != 0)
- error = 1;
- }
-
- if (*tok != '\0')
- tok += pos;
-
- /* make sure we have digits to the end */
- for (pos = 0; tok[pos] && isdigit((char) tok[pos]); ++pos) {;}
-
- if (pos > 0) { /* we have digits to process */
- high = strtoul(tok, (char **) &tok, 10);
- } else { /* bad boy, no digits */
- error = 1;
- }
-
- if ((low > high) || (high - low > MAX_RANGE))
- error = 1;
-
- } else { /* single value */
- high = 0; /* special case, ugh. */
- }
-
- /* error if:
- * 1. we are not at end of string
- * 2. upper bound equals lower bound
- */
- if (*tok != '\0' || high == low)
- error = 1;
-
- if (error) { /* assume this is not a range on any error */
- hostlist_push_host(new, cur);
- } else {
- if (high < low)
- high = low;
- hostlist_push_hr(new, prefix, low, high, fmt);
- }
-
- error = 0;
- }
-
- done:
- free(orig);
-
- return new;
-}
-
-#else /* !WANT_RECKLESS_HOSTRANGE_EXPANSION */
-
-hostlist_t _hostlist_create(const char *hostlist, char *sep, char *r_op)
-{
- return _hostlist_create_bracketed(hostlist, sep, r_op);
-}
-
-#endif /* WANT_RECKLESS_HOSTRANGE_EXPANSION */
-
-struct _range {
- unsigned long lo, hi;
- int width;
-};
-
-/* Grab a single range from str
- * returns 1 if str contained a valid number or range,
- * 0 if conversion of str to a range failed.
- */
-static int _parse_single_range(const char *str, struct _range *range)
-{
- char *p, *q;
- char *orig = strdup(str);
- if (!orig)
- seterrno_ret(ENOMEM, 0);
-
- if ((p = strchr(str, '-'))) {
- *p++ = '\0';
- if (*p == '-') /* do NOT allow negative numbers */
- goto error;
- }
- range->lo = strtoul(str, &q, 10);
- if (q == str)
- goto error;
-
- range->hi = (p && *p) ? strtoul(p, &q, 10) : range->lo;
-
- if (q == p || *q != '\0')
- goto error;
-
- if (range->lo > range->hi)
- goto error;
-
- if (range->hi - range->lo + 1 > MAX_RANGE ) {
- _error(__FILE__, __LINE__, "Too many hosts in range `%s'", orig);
- free(orig);
- seterrno_ret(ERANGE, 0);
- }
-
- free(orig);
- range->width = strlen(str);
- return 1;
-
- error:
- _error(__FILE__, __LINE__, "Invalid range: `%s'", orig);
- free(orig);
- seterrno_ret(EINVAL, 0);
-}
-
-
-/*
- * Convert 'str' containing comma separated digits and ranges into an array
- * of struct _range types (max 'len' elements).
- *
- * Return number of ranges created, or -1 on error.
- */
-static int _parse_range_list(char *str, struct _range *ranges, int len)
-{
- char *p;
- int count = 0;
-
- while (str) {
- if (count == len)
- return -1;
- if ((p = strchr(str, ',')))
- *p++ = '\0';
- if (!_parse_single_range(str, &ranges[count++]))
- return -1;
- str = p;
- }
- return count;
-}
-
-static void
-_push_range_list(hostlist_t hl, char *pfx, struct _range *rng,
- int n)
-{
- int i;
- for (i = 0; i < n; i++) {
- hostlist_push_hr(hl, pfx, rng->lo, rng->hi, rng->width);
- rng++;
- }
-}
-
-static void
-_push_range_list_with_suffix(hostlist_t hl, char *pfx, char *sfx,
- struct _range *rng, int n)
-{
- int i;
- unsigned long j;
- for (i = 0; i < n; i++) {
- for (j = rng->lo; j <= rng->hi; j++) {
- char host[4096];
- hostrange_t hr;
- snprintf (host, 4096, "%s%0*lu%s", pfx, rng->width, j, sfx);
- hr = hostrange_create_single (host);
- hostlist_push_range (hl, hr);
- /*
- * hr is copied in hostlist_push_range. Need to free here.
- */
- hostrange_destroy (hr);
- }
- rng++;
- }
-}
-
-/*
- * Create a hostlist from a string with brackets '[' ']' to aid
- * detection of ranges and compressed lists
- */
-static hostlist_t
-_hostlist_create_bracketed(const char *hostlist, char *sep, char *r_op)
-{
- hostlist_t new = hostlist_new();
- struct _range ranges[MAX_RANGES];
- int nr, err;
- char *p, *tok, *str, *orig;
- char cur_tok[1024];
-
- if (hostlist == NULL)
- return new;
-
- if (!(orig = str = strdup(hostlist))) {
- hostlist_destroy(new);
- return NULL;
- }
-
- while ((tok = _next_tok(sep, &str)) != NULL) {
- strncpy(cur_tok, tok, 1024);
-
- if ((p = strchr(tok, '[')) != NULL) {
- char *q, *prefix = tok;
- *p++ = '\0';
-
- if ((q = strchr(p, ']'))) {
- *q = '\0';
- nr = _parse_range_list(p, ranges, MAX_RANGES);
- if (nr < 0)
- goto error;
-
- if (*(++q) != '\0')
- _push_range_list_with_suffix (new, prefix, q, ranges, nr);
- else
- _push_range_list(new, prefix, ranges, nr);
-
-
- } else
- hostlist_push_host(new, cur_tok);
-
- } else
- hostlist_push_host(new, cur_tok);
- }
-
- free(orig);
- return new;
-
- error:
- err = errno;
- hostlist_destroy(new);
- free(orig);
- seterrno_ret(err, NULL);
-}
-
-
-
-hostlist_t hostlist_create(const char *str)
-{
- return _hostlist_create(str, "\t, ", "-");
-}
-
-
-hostlist_t hostlist_copy(const hostlist_t hl)
-{
- int i;
- hostlist_t new;
-
- if (hl == NULL)
- return NULL;
-
- LOCK_HOSTLIST(hl);
- if (!(new = hostlist_new()))
- goto done;
-
- new->nranges = hl->nranges;
- new->nhosts = hl->nhosts;
- if (new->nranges > new->size)
- hostlist_resize(new, new->nranges);
-
- for (i = 0; i < hl->nranges; i++)
- new->hr[i] = hostrange_copy(hl->hr[i]);
-
- done:
- UNLOCK_HOSTLIST(hl);
- return new;
-}
-
-
-void hostlist_destroy(hostlist_t hl)
-{
- int i;
- if (hl == NULL)
- return;
- LOCK_HOSTLIST(hl);
- while (hl->ilist) {
- mutex_unlock(&hl->mutex);
- hostlist_iterator_destroy(hl->ilist);
- mutex_lock(&hl->mutex);
- }
- for (i = 0; i < hl->nranges; i++)
- hostrange_destroy(hl->hr[i]);
- free(hl->hr);
- assert(hl->magic = 0x1);
- UNLOCK_HOSTLIST(hl);
- mutex_destroy(&hl->mutex);
- free(hl);
-}
-
-
-int hostlist_push(hostlist_t hl, const char *hosts)
-{
- hostlist_t new;
- int retval;
- if (hosts == NULL)
- return 0;
- new = hostlist_create(hosts);
- if (!new)
- return 0;
- mutex_lock(&new->mutex);
- retval = new->nhosts;
- mutex_unlock(&new->mutex);
- hostlist_push_list(hl, new);
- hostlist_destroy(new);
- return retval;
-}
-
-int hostlist_push_host(hostlist_t hl, const char *str)
-{
- hostrange_t hr;
- hostname_t hn;
-
- if (str == NULL)
- return 0;
-
- hn = hostname_create(str);
-
- if (hostname_suffix_is_valid(hn)) {
- hr = hostrange_create(hn->prefix, hn->num, hn->num,
- hostname_suffix_width(hn));
- } else
- hr = hostrange_create_single(str);
-
- hostlist_push_range(hl, hr);
-
- hostrange_destroy(hr);
- hostname_destroy(hn);
-
- return 1;
-}
-
-int hostlist_push_list(hostlist_t h1, hostlist_t h2)
-{
- int i, n = 0;
-
- if (h2 == NULL)
- return 0;
-
- LOCK_HOSTLIST(h2);
-
- for (i = 0; i < h2->nranges; i++)
- n += hostlist_push_range(h1, h2->hr[i]);
-
- UNLOCK_HOSTLIST(h2);
-
- return n;
-}
-
-
-char *hostlist_pop(hostlist_t hl)
-{
- char *host = NULL;
-
- LOCK_HOSTLIST(hl);
- if (hl->nhosts > 0) {
- hostrange_t hr = hl->hr[hl->nranges - 1];
- host = hostrange_pop(hr);
- hl->nhosts--;
- if (hostrange_empty(hr)) {
- hostrange_destroy(hl->hr[--hl->nranges]);
- hl->hr[hl->nranges] = NULL;
- }
- }
- UNLOCK_HOSTLIST(hl);
- return host;
-}
-
-/* find all iterators affected by a shift (or deletion) at
- * hl->hr[idx], depth, with the deletion of n ranges */
-static void
-hostlist_shift_iterators(hostlist_t hl, int idx, int depth, int n)
-{
- hostlist_iterator_t i;
- for (i = hl->ilist; i; i = i->next) {
- if (n == 0) {
- if (i->idx == idx && i->depth >= depth)
- i->depth = i->depth > -1 ? i->depth - 1 : -1;
- } else {
- if (i->idx >= idx) {
- if ((i->idx -= n) >= 0)
- i->hr = i->hl->hr[i->idx];
- else
- hostlist_iterator_reset(i);
- }
- }
- }
-}
-
-char *hostlist_shift(hostlist_t hl)
-{
- char *host = NULL;
-
- LOCK_HOSTLIST(hl);
-
- if (hl->nhosts > 0) {
- hostrange_t hr = hl->hr[0];
-
- host = hostrange_shift(hr);
- hl->nhosts--;
-
- if (hostrange_empty(hr)) {
- hostlist_delete_range(hl, 0);
- /* hl->nranges--; */
- } else
- hostlist_shift_iterators(hl, 0, 0, 0);
- }
-
- UNLOCK_HOSTLIST(hl);
-
- return host;
-}
-
-
-char *hostlist_pop_range(hostlist_t hl)
-{
- int i;
- char buf[MAXHOSTRANGELEN + 1];
- hostlist_t hltmp;
- hostrange_t tail;
-
- LOCK_HOSTLIST(hl);
- if (hl->nranges < 1 || !(hltmp = hostlist_new())) {
- UNLOCK_HOSTLIST(hl);
- return NULL;
- }
-
- i = hl->nranges - 2;
- tail = hl->hr[hl->nranges - 1];
- while (i >= 0 && hostrange_within_range(tail, hl->hr[i]))
- i--;
-
- for (i++; i < hl->nranges; i++) {
- hostlist_push_range(hltmp, hl->hr[i]);
- hostrange_destroy(hl->hr[i]);
- hl->hr[i] = NULL;
- }
- hl->nhosts -= hltmp->nhosts;
- hl->nranges -= hltmp->nranges;
-
- UNLOCK_HOSTLIST(hl);
- hostlist_ranged_string(hltmp, MAXHOSTRANGELEN, buf);
- hostlist_destroy(hltmp);
- return strdup(buf);
-}
-
-
-char *hostlist_shift_range(hostlist_t hl)
-{
- int i;
- char buf[1024];
- hostlist_t hltmp = hostlist_new();
- if (!hltmp)
- return NULL;
-
- LOCK_HOSTLIST(hl);
-
- if (hl->nranges == 0) {
- hostlist_destroy(hltmp);
- UNLOCK_HOSTLIST(hl);
- return NULL;
- }
-
- i = 0;
- do {
- hostlist_push_range(hltmp, hl->hr[i]);
- hostrange_destroy(hl->hr[i]);
- } while ( (++i < hl->nranges)
- && hostrange_within_range(hltmp->hr[0], hl->hr[i]) );
-
- hostlist_shift_iterators(hl, i, 0, hltmp->nranges);
-
- /* shift rest of ranges back in hl */
- for (; i < hl->nranges; i++) {
- hl->hr[i - hltmp->nranges] = hl->hr[i];
- hl->hr[i] = NULL;
- }
- hl->nhosts -= hltmp->nhosts;
- hl->nranges -= hltmp->nranges;
-
- UNLOCK_HOSTLIST(hl);
-
- hostlist_ranged_string(hltmp, 1024, buf);
- hostlist_destroy(hltmp);
-
- return strdup(buf);
-}
-
-/* XXX: Note: efficiency improvements needed */
-int hostlist_delete(hostlist_t hl, const char *hosts)
-{
- int n = 0;
- char *hostname = NULL;
- hostlist_t hltmp;
-
- if (!(hltmp = hostlist_create(hosts)))
- seterrno_ret(EINVAL, 0);
-
- while ((hostname = hostlist_pop(hltmp)) != NULL) {
- n += hostlist_delete_host(hl, hostname);
- free(hostname);
- }
- hostlist_destroy(hltmp);
-
- return n;
-}
-
-
-/* XXX watch out! poor implementation follows! (fix it at some point) */
-int hostlist_delete_host(hostlist_t hl, const char *hostname)
-{
- int n = hostlist_find(hl, hostname);
- if (n >= 0)
- hostlist_delete_nth(hl, n);
- return n >= 0 ? 1 : 0;
-}
-
-
-static char *
-_hostrange_string(hostrange_t hr, int depth)
-{
- char buf[MAXHOSTNAMELEN + 16];
- int len = snprintf(buf, MAXHOSTNAMELEN + 15, "%s", hr->prefix);
-
- if (!hr->singlehost)
- snprintf(buf+len, MAXHOSTNAMELEN+15 - len, "%0*lu",
- hr->width, hr->lo + depth);
- return strdup(buf);
-}
-
-char * hostlist_nth(hostlist_t hl, int n)
-{
- char *host = NULL;
- int i, count;
-
- LOCK_HOSTLIST(hl);
- count = 0;
- for (i = 0; i < hl->nranges; i++) {
- int num_in_range = hostrange_count(hl->hr[i]);
-
- if (n <= (num_in_range - 1 + count)) {
- host = _hostrange_string(hl->hr[i], n - count);
- break;
- } else
- count += num_in_range;
- }
-
- UNLOCK_HOSTLIST(hl);
-
- return host;
-}
-
-
-int hostlist_delete_nth(hostlist_t hl, int n)
-{
- int i, count;
-
- LOCK_HOSTLIST(hl);
- assert(n >= 0 && n <= hl->nhosts);
-
- count = 0;
-
- for (i = 0; i < hl->nranges; i++) {
- int num_in_range = hostrange_count(hl->hr[i]);
- hostrange_t hr = hl->hr[i];
-
- if (n <= (num_in_range - 1 + count)) {
- unsigned long num = hr->lo + n - count;
- hostrange_t new;
-
- if (hr->singlehost) { /* this wasn't a range */
- hostlist_delete_range(hl, i);
- } else if ((new = hostrange_delete_host(hr, num))) {
- hostlist_insert_range(hl, new, i + 1);
- hostrange_destroy(new);
- } else if (hostrange_empty(hr))
- hostlist_delete_range(hl, i);
-
- goto done;
- } else
- count += num_in_range;
-
- }
-
- done:
- UNLOCK_HOSTLIST(hl);
- hl->nhosts--;
- return 1;
-}
-
-int hostlist_count(hostlist_t hl)
-{
- int retval;
- LOCK_HOSTLIST(hl);
- retval = hl->nhosts;
- UNLOCK_HOSTLIST(hl);
- return retval;
-}
-
-int hostlist_find(hostlist_t hl, const char *hostname)
-{
- int i, count, ret = -1;
- hostname_t hn;
-
- if (!hostname)
- return -1;
-
- hn = hostname_create(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
- count += hostrange_count(hl->hr[i]);
- }
-
- done:
- UNLOCK_HOSTLIST(hl);
- hostname_destroy(hn);
- return ret;
-}
-
-/* hostrange compare with void * arguments to allow use with
- * libc qsort()
- */
-int _cmp(const void *hr1, const void *hr2)
-{
- hostrange_t *h1 = (hostrange_t *) hr1;
- hostrange_t *h2 = (hostrange_t *) hr2;
- return hostrange_cmp((hostrange_t) * h1, (hostrange_t) * h2);
-}
-
-
-void hostlist_sort(hostlist_t hl)
-{
- hostlist_iterator_t i;
- LOCK_HOSTLIST(hl);
-
- if (hl->nranges <= 1) {
- UNLOCK_HOSTLIST(hl);
- return;
- }
-
- qsort(hl->hr, hl->nranges, sizeof(hostrange_t), &_cmp);
-
- /* reset all iterators */
- for (i = hl->ilist; i; i = i->next)
- hostlist_iterator_reset(i);
-
- UNLOCK_HOSTLIST(hl);
-
- hostlist_coalesce(hl);
-
-}
-
-
-/* search through hostlist for ranges that can be collapsed
- * does =not= delete any hosts
- */
-static void hostlist_collapse(hostlist_t hl)
-{
- int i;
-
- LOCK_HOSTLIST(hl);
- for (i = hl->nranges - 1; i > 0; i--) {
- hostrange_t hprev = hl->hr[i - 1];
- hostrange_t hnext = hl->hr[i];
-
- if (hostrange_prefix_cmp(hprev, hnext) == 0 &&
- hprev->hi == hnext->lo - 1 &&
- hostrange_width_combine(hprev, hnext)) {
- hprev->hi = hnext->hi;
- hostlist_delete_range(hl, i);
- }
- }
- UNLOCK_HOSTLIST(hl);
-}
-
-/* search through hostlist (hl) for intersecting ranges
- * split up duplicates and coalesce ranges where possible
- */
-static void hostlist_coalesce(hostlist_t hl)
-{
- int i, j;
- hostrange_t new;
-
- LOCK_HOSTLIST(hl);
-
- for (i = hl->nranges - 1; i > 0; i--) {
-
- new = hostrange_intersect(hl->hr[i - 1], hl->hr[i]);
-
- if (new) {
- hostrange_t hprev = hl->hr[i - 1];
- hostrange_t hnext = hl->hr[i];
- j = i;
-
- if (new->hi < hprev->hi)
- hnext->hi = hprev->hi;
-
- hprev->hi = new->lo;
- hnext->lo = new->hi;
-
- if (hostrange_empty(hprev))
- hostlist_delete_range(hl, i);
-
- while (new->lo <= new->hi) {
- hostrange_t hr = hostrange_create( new->prefix,
- new->lo, new->lo,
- new->width );
-
- if (new->lo > hprev->hi)
- hostlist_insert_range(hl, hr, j++);
-
- if (new->lo < hnext->lo)
- hostlist_insert_range(hl, hr, j++);
-
- hostrange_destroy(hr);
-
- new->lo++;
- }
- i = hl->nranges;
- hostrange_destroy(new);
- }
- }
- UNLOCK_HOSTLIST(hl);
-
- hostlist_collapse(hl);
-
-}
-
-/* attempt to join ranges at loc and loc-1 in a hostlist */
-/* delete duplicates, return the number of hosts deleted */
-/* assumes that the hostlist hl has been locked by caller */
-/* returns -1 if no range join occurred */
-static int _attempt_range_join(hostlist_t hl, int loc)
-{
- int ndup;
- assert(hl != NULL);
- assert(hl->magic == HOSTLIST_MAGIC);
- assert(loc > 0);
- assert(loc < hl->nranges);
- ndup = hostrange_join(hl->hr[loc - 1], hl->hr[loc]);
- if (ndup >= 0) {
- hostlist_delete_range(hl, loc);
- hl->nhosts -= ndup;
- }
- return ndup;
-}
-
-void hostlist_uniq(hostlist_t hl)
-{
- int i = 1;
- hostlist_iterator_t hli;
- LOCK_HOSTLIST(hl);
- if (hl->nranges <= 1) {
- UNLOCK_HOSTLIST(hl);
- return;
- }
- qsort(hl->hr, hl->nranges, sizeof(hostrange_t), &_cmp);
-
- while (i < hl->nranges) {
- if (_attempt_range_join(hl, i) < 0) /* No range join occurred */
- i++;
- }
-
- /* reset all iterators */
- for (hli = hl->ilist; hli; hli = hli->next)
- hostlist_iterator_reset(hli);
-
- UNLOCK_HOSTLIST(hl);
-}
-
-
-size_t hostlist_deranged_string(hostlist_t hl, size_t n, char *buf)
-{
- int i;
- int len = 0;
- int truncated = 0;
-
- LOCK_HOSTLIST(hl);
- for (i = 0; i < hl->nranges; i++) {
- size_t m = (n - len) <= n ? n - len : 0;
- int ret = hostrange_to_string(hl->hr[i], m, buf + len, ",");
- if (ret < 0 || ret > m) {
- len = n;
- truncated = 1;
- break;
- }
- len+=ret;
- buf[len++] = ',';
- }
- UNLOCK_HOSTLIST(hl);
-
- buf[len > 0 ? --len : 0] = '\0';
- if (len == n)
- truncated = 1;
-
- return truncated ? -1 : len;
-}
-
-/* return true if a bracket is needed for the range at i in hostlist hl */
-static int _is_bracket_needed(hostlist_t hl, int i)
-{
- hostrange_t h1 = hl->hr[i];
- hostrange_t h2 = i < hl->nranges - 1 ? hl->hr[i + 1] : NULL;
- return hostrange_count(h1) > 1 || hostrange_within_range(h1, h2);
-}
-
-/* write the next bracketed hostlist, i.e. prefix[n-m,k,...]
- * into buf, writing at most n chars including the terminating '\0'
- *
- * leaves start pointing to one past last range object in bracketed list,
- * and returns the number of bytes written into buf.
- *
- * Assumes hostlist is locked.
- */
-static int
-_get_bracketed_list(hostlist_t hl, int *start, const size_t n, char *buf)
-{
- hostrange_t *hr = hl->hr;
- int i = *start;
- int m, len = 0;
- int bracket_needed = _is_bracket_needed(hl, i);
-
- len = snprintf(buf, n, "%s", hr[i]->prefix);
-
- if ((len < 0) || (len > n))
- return n; /* truncated, buffer filled */
-
- if (bracket_needed && len < n && len >= 0)
- buf[len++] = '[';
-
- do {
- m = (n - len) <= n ? n - len : 0;
- len += hostrange_numstr(hr[i], m, buf + len);
- if (len >= n)
- break;
- if (bracket_needed) /* Only need commas inside brackets */
- buf[len++] = ',';
- } while (++i < hl->nranges && hostrange_within_range(hr[i], hr[i-1]));
-
- if (bracket_needed && len < n && len > 0) {
-
- /* Add trailing bracket (change trailing "," from above to "]" */
- buf[len - 1] = ']';
-
- /* NUL terminate for safety, but do not add terminator to len */
- buf[len] = '\0';
-
- } else if (len >= n) {
- if (n > 0)
- buf[n-1] = '\0';
-
- } else {
- /* If len is > 0, NUL terminate (but do not add to len) */
- buf[len > 0 ? len : 0] = '\0';
- }
-
- *start = i;
- return len;
-}
-
-size_t hostlist_ranged_string(hostlist_t hl, size_t n, char *buf)
-{
- int i = 0;
- int len = 0;
- int truncated = 0;
-
- LOCK_HOSTLIST(hl);
- while (i < hl->nranges && len < n) {
- len += _get_bracketed_list(hl, &i, n - len, buf + len);
- if ((len > 0) && (len < n) && (i < hl->nranges))
- buf[len++] = ',';
- }
- UNLOCK_HOSTLIST(hl);
-
- /* NUL terminate */
- if (len >= n) {
- truncated = 1;
- if (n > 0)
- buf[n-1] = '\0';
- } else
- buf[len > 0 ? len : 0] = '\0';
-
- return truncated ? -1 : len;
-}
-
-/* ----[ hostlist iterator functions ]---- */
-
-static hostlist_iterator_t hostlist_iterator_new(void)
-{
- hostlist_iterator_t i = (hostlist_iterator_t) malloc(sizeof(*i));
- if (!i)
- return NULL;
- i->hl = NULL;
- i->hr = NULL;
- i->idx = 0;
- i->depth = -1;
- i->next = i;
- assert(i->magic = HOSTLIST_MAGIC);
- return i;
-}
-
-hostlist_iterator_t hostlist_iterator_create(hostlist_t hl)
-{
- hostlist_iterator_t i;
-
- if (!(i = hostlist_iterator_new()))
- out_of_memory("hostlist_iterator_create");
-
- LOCK_HOSTLIST(hl);
- i->hl = hl;
- i->hr = hl->hr[0];
- i->next = hl->ilist;
- hl->ilist = i;
- UNLOCK_HOSTLIST(hl);
- return i;
-}
-
-hostlist_iterator_t hostset_iterator_create(hostset_t set)
-{
- return hostlist_iterator_create(set->hl);
-}
-
-void hostlist_iterator_reset(hostlist_iterator_t i)
-{
- assert(i != NULL);
- assert(i->magic == HOSTLIST_MAGIC);
- i->idx = 0;
- i->hr = i->hl->hr[0];
- i->depth = -1;
- return;
-}
-
-void hostlist_iterator_destroy(hostlist_iterator_t i)
-{
- hostlist_iterator_t *pi;
- if (i == NULL)
- return;
- assert(i != NULL);
- assert(i->magic == HOSTLIST_MAGIC);
- LOCK_HOSTLIST(i->hl);
- for (pi = &i->hl->ilist; *pi; pi = &(*pi)->next) {
- assert((*pi)->magic == HOSTLIST_MAGIC);
- if (*pi == i) {
- *pi = (*pi)->next;
- break;
- }
- }
- UNLOCK_HOSTLIST(i->hl);
- assert(i->magic = 0x1);
- free(i);
-}
-
-static void _iterator_advance(hostlist_iterator_t i)
-{
- assert(i != NULL);
- assert(i->magic == HOSTLIST_MAGIC);
- if (i->idx > i->hl->nranges - 1)
- return;
- if (++(i->depth) > (i->hr->hi - i->hr->lo)) {
- i->depth = 0;
- i->hr = i->hl->hr[++i->idx];
- }
-}
-
-/* advance iterator to end of current range (meaning within "[" "]")
- * i.e. advance iterator past all range objects that could be represented
- * in on bracketed hostlist.
- */
-static void _iterator_advance_range(hostlist_iterator_t i)
-{
- int nr, j;
- hostrange_t *hr;
- assert(i != NULL);
- assert(i->magic == HOSTLIST_MAGIC);
-
- nr = i->hl->nranges;
- hr = i->hl->hr;
- j = i->idx;
- if (++i->depth > 0) {
- while (++j < nr && hostrange_within_range(i->hr, hr[j])) {;}
- i->idx = j;
- i->hr = i->hl->hr[i->idx];
- i->depth = 0;
- }
-}
-
-char *hostlist_next(hostlist_iterator_t i)
-{
- char *buf = NULL;
- char suffix[16];
- int len = 0;
- assert(i != NULL);
- assert(i->magic == HOSTLIST_MAGIC);
- LOCK_HOSTLIST(i->hl);
- _iterator_advance(i);
-
- if (i->idx > i->hl->nranges - 1) {
- UNLOCK_HOSTLIST(i->hl);
- return NULL;
- }
-
- suffix[0] = '\0';
-
- if (!i->hr->singlehost)
- snprintf (suffix, 15, "%0*lu", i->hr->width, i->hr->lo + i->depth);
-
- len = strlen (i->hr->prefix) + strlen (suffix) + 1;
- if (!(buf = malloc (len)))
- out_of_memory("hostlist_next");
-
- buf[0] = '\0';
- strcat (buf, i->hr->prefix);
- strcat (buf, suffix);
-
- UNLOCK_HOSTLIST(i->hl);
- return (buf);
-}
-
-char *hostlist_next_range(hostlist_iterator_t i)
-{
- char buf[MAXHOSTRANGELEN + 1];
- int j;
-
- assert(i != NULL);
- assert(i->magic == HOSTLIST_MAGIC);
- LOCK_HOSTLIST(i->hl);
-
- _iterator_advance_range(i);
-
- if (i->idx > i->hl->nranges - 1) {
- UNLOCK_HOSTLIST(i->hl);
- return NULL;
- }
-
- j = i->idx;
- _get_bracketed_list(i->hl, &j, MAXHOSTRANGELEN, buf);
-
- UNLOCK_HOSTLIST(i->hl);
-
- return strdup(buf);
-}
-
-int hostlist_remove(hostlist_iterator_t i)
-{
- hostrange_t new;
- assert(i != NULL);
- assert(i->magic == HOSTLIST_MAGIC);
- LOCK_HOSTLIST(i->hl);
- new = hostrange_delete_host(i->hr, i->hr->lo + i->depth);
- if (new) {
- hostlist_insert_range(i->hl, new, i->idx + 1);
- hostrange_destroy(new);
- i->hr = i->hl->hr[++i->idx];
- i->depth = -1;
- } else if (hostrange_empty(i->hr)) {
- hostlist_delete_range(i->hl, i->idx);
- } else
- i->depth--;
-
- i->hl->nhosts--;
- UNLOCK_HOSTLIST(i->hl);
-
- return 1;
-}
-
-/* ----[ hostset functions ]---- */
-
-hostset_t hostset_create(const char *hostlist)
-{
- hostset_t new;
-
- if (!(new = (hostset_t) malloc(sizeof(*new))))
- goto error1;
-
- if (!(new->hl = hostlist_create(hostlist)))
- goto error2;
-
- hostlist_uniq(new->hl);
- return new;
-
- error2:
- free(new);
- error1:
- return NULL;
-}
-
-hostset_t hostset_copy(const hostset_t set)
-{
- hostset_t new;
- if (!(new = (hostset_t) malloc(sizeof(*new))))
- goto error1;
-
- if (!(new->hl = hostlist_copy(set->hl)))
- goto error2;
-
- return new;
- error2:
- free(new);
- error1:
- return NULL;
-}
-
-void hostset_destroy(hostset_t set)
-{
- if (set == NULL)
- return;
- hostlist_destroy(set->hl);
- free(set);
-}
-
-/* inserts a single range object into a hostset
- * Assumes that the set->hl lock is already held
- * Updates hl->nhosts
- */
-static int hostset_insert_range(hostset_t set, hostrange_t hr)
-{
- int i = 0;
- int inserted = 0;
- int nhosts = 0;
- int ndups = 0;
- hostlist_t hl;
-
- hl = set->hl;
-
- if (hl->size == hl->nranges && !hostlist_expand(hl))
- return 0;
-
- nhosts = hostrange_count(hr);
-
- for (i = 0; i < hl->nranges; i++) {
- if (hostrange_cmp(hr, hl->hr[i]) <= 0) {
-
- if ((ndups = hostrange_join(hr, hl->hr[i])) >= 0)
- hostlist_delete_range(hl, i);
- else if (ndups < 0)
- ndups = 0;
-
- hostlist_insert_range(hl, hr, i);
-
- /* now attempt to join hr[i] and hr[i-1] */
- if (i > 0) {
- int m;
- if ((m = _attempt_range_join(hl, i)) > 0)
- ndups += m;
- }
- hl->nhosts += nhosts - ndups;
- inserted = 1;
- break;
- }
- }
-
- if (inserted == 0) {
- hl->hr[hl->nranges++] = hostrange_copy(hr);
- hl->nhosts += nhosts;
- if (hl->nranges > 1) {
- if ((ndups = _attempt_range_join(hl, hl->nranges - 1)) <= 0)
- ndups = 0;
- }
- }
-
- /*
- * Return the number of unique hosts inserted
- */
- return nhosts - ndups;
-}
-
-int hostset_insert(hostset_t set, const char *hosts)
-{
- int i, n = 0;
- hostlist_t hl = hostlist_create(hosts);
- if (!hl)
- return 0;
-
- hostlist_uniq(hl);
- LOCK_HOSTLIST(set->hl);
- for (i = 0; i < hl->nranges; i++)
- n += hostset_insert_range(set, hl->hr[i]);
- UNLOCK_HOSTLIST(set->hl);
- hostlist_destroy(hl);
- return n;
-}
-
-
-/* linear search through N ranges for hostname "host"
- * */
-static int hostset_find_host(hostset_t set, const char *host)
-{
- int i;
- int retval = 0;
- hostname_t hn;
- 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)) {
- retval = 1;
- goto done;
- }
- }
- done:
- UNLOCK_HOSTLIST(set->hl);
- hostname_destroy(hn);
- return retval;
-}
-
-int hostset_within(hostset_t set, const char *hosts)
-{
- int nhosts, nfound;
- hostlist_t hl;
- char *hostname;
-
- assert(set->hl->magic == HOSTLIST_MAGIC);
-
- hl = hostlist_create(hosts);
- nhosts = hostlist_count(hl);
- nfound = 0;
-
- while ((hostname = hostlist_pop(hl)) != NULL) {
- nfound += hostset_find_host(set, hostname);
- free(hostname);
- }
-
- hostlist_destroy(hl);
-
- return (nhosts == nfound);
-}
-
-int hostset_delete(hostset_t set, const char *hosts)
-{
- return hostlist_delete(set->hl, hosts);
-}
-
-int hostset_delete_host(hostset_t set, const char *hostname)
-{
- return hostlist_delete_host(set->hl, hostname);
-}
-
-char *hostset_shift(hostset_t set)
-{
- return hostlist_shift(set->hl);
-}
-
-char *hostset_pop(hostset_t set)
-{
- return hostlist_pop(set->hl);
-}
-
-char *hostset_shift_range(hostset_t set)
-{
- return hostlist_shift_range(set->hl);
-}
-
-char *hostset_pop_range(hostset_t set)
-{
- return hostlist_pop_range(set->hl);
-}
-
-int hostset_count(hostset_t set)
-{
- return hostlist_count(set->hl);
-}
-
-size_t hostset_ranged_string(hostset_t set, size_t n, char *buf)
-{
- return hostlist_ranged_string(set->hl, n, buf);
-}
-
-size_t hostset_deranged_string(hostset_t set, size_t n, char *buf)
-{
- return hostlist_deranged_string(set->hl, n, buf);
-}
-
-#if TEST_MAIN
-
-int hostlist_nranges(hostlist_t hl)
-{
- return hl->nranges;
-}
-
-int hostset_nranges(hostset_t set)
-{
- return set->hl->nranges;
-}
-
-/* test iterator functionality on the list of hosts represented
- * by list
- */
-int iterator_test(char *list)
-{
- int j;
- char buf[1024];
- hostlist_t hl = hostlist_create(list);
- hostset_t set = hostset_create(list);
-
- hostlist_iterator_t i = hostlist_iterator_create(hl);
- hostlist_iterator_t seti = hostset_iterator_create(set);
- hostlist_iterator_t i2 = hostlist_iterator_create(hl);
- char *host;
-
-
- hostlist_ranged_string(hl, 1024, buf);
- printf("iterator_test: hl = `%s' passed in `%s'\n", buf, list);
- host = hostlist_next(i);
- printf("first host in list hl = `%s'\n", host);
- free(host);
-
- /* forge ahead three hosts with i2 */
- for (j = 0; j < 4; j++) {
- host = hostlist_next(i2);
- free(host);
- }
-
- host = hostlist_shift(hl);
- printf("result of shift(hl) = `%s'\n", host);
- free(host);
- host = hostlist_next(i);
- printf("next host in list hl = `%s'\n", host);
- free(host);
- host = hostlist_next(i2);
- printf("next host for i2 = `%s'\n", host);
- free(host);
-
- hostlist_iterator_destroy(i);
-
- hostlist_destroy(hl);
- hostset_destroy(set);
- return 1;
-}
-
-int main(int ac, char **av)
-{
- char buf[1024000];
- int i;
- char *str;
-
- hostlist_t hl1, hl2, hl3;
- hostset_t set, set1;
- hostlist_iterator_t iter, iter2;
-
- if (!(hl1 = hostlist_create(ac > 1 ? av[1] : NULL)))
- perror("hostlist_create");
- if (!(set = hostset_create(ac > 1 ? av[1] : NULL)))
- perror("hostlist_create");
-
- hl3 = hostlist_create("f[0-5]");
- hostlist_delete(hl3, "f[1-3]");
- hostlist_ranged_string(hl3, 102400, buf);
- printf("after delete = `%s'\n", buf);
- hostlist_destroy(hl3);
-
- for (i = 2; i < ac; i++) {
- hostlist_push(hl1, av[i]);
- hostset_insert(set, av[i]);
- }
-
- hostlist_ranged_string(hl1, 102400, buf);
- printf("ranged = `%s'\n", buf);
-
- iterator_test(buf);
-
- hostlist_deranged_string(hl1, 10240, buf);
- printf("deranged = `%s'\n", buf);
-
- hostset_ranged_string(set, 1024, buf);
- printf("hostset = `%s'\n", buf);
-
- hostlist_sort(hl1);
- hostlist_ranged_string(hl1, 1024, buf);
- printf("sorted = `%s'\n", buf);
-
- hostlist_uniq(hl1);
- hostlist_ranged_string(hl1, 1024, buf);
- printf("uniqed = `%s'\n", buf);
-
- hl2 = hostlist_copy(hl1);
- printf("pop_range: ");
- while ((str = hostlist_pop_range(hl2))) {
- printf("`%s' ", str);
- free(str);
- }
- hostlist_destroy(hl2);
- printf("\n");
-
- hl2 = hostlist_copy(hl1);
- printf("shift_range: ");
- while ((str = hostlist_shift_range(hl2))) {
- printf("`%s' ", str);
- free(str);
- }
- hostlist_destroy(hl2);
- printf("\n");
-
- iter = hostset_iterator_create(set);
- iter2 = hostset_iterator_create(set);
- hostlist_iterator_destroy(iter2);
-
- printf("next: ");
- while ((str = hostlist_next(iter))) {
- printf("`%s' ", str);
- free(str);
- }
- printf("\n");
-
- hostlist_iterator_reset(iter);
- printf("next_range: ");
- while ((str = hostlist_next_range(iter))) {
- printf("`%s' ", str);
- free(str);
- }
- printf("\n");
-
- printf("nranges = %d\n", hostset_nranges(set));
-
- hostset_ranged_string(set, 1024, buf);
- printf("set = %s\n", buf);
-
- hostset_destroy(set);
- hostlist_destroy(hl1);
- return 0;
-}
-
-#endif /* TEST_MAIN */
-
-/*
- * vi: tabstop=4 shiftwidth=4 expandtab
- */
+++ /dev/null
-/*****************************************************************************\
- * $Id: hostlist.h,v 1.1.2.1 2008/11/21 15:27:33 yangsheng Exp $
- *****************************************************************************
- * Copyright (C) 2002 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Mark Grondona <mgrondona@llnl.gov>
- * UCRL-CODE-2002-040.
- *
- * This file is part of SLURM, a resource management program.
- * For details, see <http://www.llnl.gov/linux/slurm/>.
- *
- * SLURM is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along
- * with SLURM; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-\*****************************************************************************/
-
-#ifndef _HOSTLIST_H
-#define _HOSTLIST_H
-
-/* Notes:
- *
- * If WITH_LSD_FATAL_ERROR_FUNC is defined, the linker will expect to
- * find and external lsd_fatal_error(file,line,mesg) function. By default,
- * lsd_fatal_error(file,line,mesg) is a macro definition that outputs an
- * error message to stderr. This macro may be redefined to invoke another
- * routine instead. e.g.:
- *
- * #define lsd_fatal_error(file,line,mesg) \
- * error("%s:%s %s\n",file,line,mesg);
- *
- * If WITH_LSD_NOMEM_ERROR_FUNC is defined, the linker will expect to
- * find an external lsd_nomem_error(file,line,mesg) function. By default,
- * lsd_nomem_error(file,line,mesg) is a macro definition that returns NULL.
- * This macro may be redefined to invoke another routine instead.
- *
- * If WITH_PTHREADS is defined, these routines will be thread-safe.
- *
- */
-
-/* The hostlist opaque data type
- *
- * A hostlist is a list of hostnames optimized for a prefixXXXX style
- * naming convention, where XXXX is a decimal, numeric suffix.
- */
-typedef struct hostlist * hostlist_t;
-
-/* A hostset is a special case of a hostlist. It:
- *
- * 1. never contains duplicates
- * 2. is always sorted
- * (Note: sort occurs first on alphanumeric prefix -- where prefix
- * matches, numeric suffixes will be sorted *by value*)
- */
-typedef struct hostset * hostset_t;
-
-/* The hostlist iterator type (may be used with a hostset as well)
- * used for non-destructive access to hostlist members.
- *
- */
-typedef struct hostlist_iterator * hostlist_iterator_t;
-
-/* ----[ hostlist_t functions: ]---- */
-
-/* ----[ hostlist creation and destruction ]---- */
-
-/*
- * hostlist_create():
- *
- * Create a new hostlist from a string representation.
- *
- * The string representation (str) may contain one or more hostnames or
- * bracketed hostlists separated by either `,' or whitespace. A bracketed
- * hostlist is denoted by a common prefix followed by a list of numeric
- * ranges contained within brackets: e.g. "tux[0-5,12,20-25]"
- *
- * Note: if this module is compiled with WANT_RECKLESS_HOSTRANGE_EXPANSION
- * defined, a much more loose interpretation of host ranges is used.
- * Reckless hostrange expansion allows all of the following (in addition to
- * bracketed hostlists):
- *
- * o tux0-5,tux12,tux20-25
- * o tux0-tux5,tux12,tux20-tux25
- * o tux0-5,12,20-25
- *
- * If str is NULL, and empty hostlist is created and returned.
- *
- * If the create fails, hostlist_create() returns NULL.
- *
- * The returned hostlist must be freed with hostlist_destroy()
- *
- */
-hostlist_t hostlist_create(const char *hostlist);
-
-/* hostlist_copy():
- *
- * Allocate a copy of a hostlist object. Returned hostlist must be freed
- * with hostlist_destroy.
- */
-hostlist_t hostlist_copy(const hostlist_t hl);
-
-/* hostlist_destroy():
- *
- * Destroy a hostlist object. Frees all memory allocated to the hostlist.
- */
-void hostlist_destroy(hostlist_t hl);
-
-
-/* ----[ hostlist list operations ]---- */
-
-/* hostlist_push():
- *
- * push a string representation of hostnames onto a hostlist.
- *
- * The hosts argument may take the same form as in hostlist_create()
- *
- * Returns the number of hostnames inserted into the list,
- * or 0 on failure.
- */
-int hostlist_push(hostlist_t hl, const char *hosts);
-
-
-/* hostlist_push_host():
- *
- * Push a single host onto the hostlist hl.
- * This function is more efficient than hostlist_push() for a single
- * hostname, since the argument does not need to be checked for ranges.
- *
- * return value is 1 for success, 0 for failure.
- */
-int hostlist_push_host(hostlist_t hl, const char *host);
-
-
-/* hostlist_push_list():
- *
- * Push a hostlist (hl2) onto another list (hl1)
- *
- * Returns 1 for success, 0 for failure.
- *
- */
-int hostlist_push_list(hostlist_t hl1, hostlist_t hl2);
-
-
-/* hostlist_pop():
- *
- * Returns the string representation of the last host pushed onto the list
- * or NULL if hostlist is empty or there was an error allocating memory.
- * The host is removed from the hostlist.
- *
- * Note: Caller is responsible for freeing the returned memory.
- */
-char * hostlist_pop(hostlist_t hl);
-
-
-char * hostlist_nth(hostlist_t hl, int n);
-
-/* hostlist_shift():
- *
- * Returns the string representation of the first host in the hostlist
- * or NULL if the hostlist is empty or there was an error allocating memory.
- * The host is removed from the hostlist.
- *
- * Note: Caller is responsible for freeing the returned memory.
- */
-char * hostlist_shift(hostlist_t hl);
-
-
-/* hostlist_pop_range():
- *
- * Pop the last bracketed list of hosts of the hostlist hl.
- * Returns the string representation in bracketed list form.
- * All hosts associated with the returned list are removed
- * from hl.
- *
- * Caller is responsible for freeing returned memory
- */
-char * hostlist_pop_range(hostlist_t hl);
-
-/* hostlist_shift_range():
- *
- * Shift the first bracketed hostlist (improperly: range) off the
- * hostlist hl. Returns the string representation in bracketed list
- * form. All hosts associated with the list are removed from the
- * hostlist.
- *
- * Caller is responsible for freeing returned memory.
- */
-char * hostlist_shift_range(hostlist_t hl);
-
-
-/* hostlist_find():
- *
- * Searches hostlist hl for the first host matching hostname
- * and returns position in list if found.
- *
- * Returns -1 if host is not found.
- *
- */
-int hostlist_find(hostlist_t hl, const char *hostname);
-
-/* hostlist_delete():
- *
- * Deletes all hosts in the list represented by `hosts'
- *
- * Returns the number of hosts successfully deleted
- */
-int hostlist_delete(hostlist_t hl, const char *hosts);
-
-
-/* hostlist_delete_host():
- *
- * Deletes the first host that matches `hostname' from the hostlist hl.
- * Note: "hostname" argument cannot contain a range of hosts
- * (see hostlist_delete() for this functionality.)
- *
- * Returns 1 if successful, 0 if hostname is not found in list.
- */
-int hostlist_delete_host(hostlist_t hl, const char *hostname);
-
-
-/* hostlist_delete_nth():
- *
- * Deletes the host from position n in the hostlist.
- *
- * Returns 1 if successful 0 on error.
- *
- */
-int hostlist_delete_nth(hostlist_t hl, int n);
-
-
-/* hostlist_count():
- *
- * Return the number of hosts in hostlist hl.
- */
-int hostlist_count(hostlist_t hl);
-
-/* hostlist_is_empty(): return true if hostlist is empty. */
-#define hostlist_is_empty(__hl) ( hostlist_count(__hl) == 0 )
-
-/* ----[ Other hostlist operations ]---- */
-
-/* hostlist_sort():
- *
- * Sort the hostlist hl.
- *
- */
-void hostlist_sort(hostlist_t hl);
-
-/* hostlist_uniq():
- *
- * Sort the hostlist hl and remove duplicate entries.
- *
- */
-void hostlist_uniq(hostlist_t hl);
-
-
-/* ----[ hostlist print functions ]---- */
-
-/* hostlist_ranged_string():
- *
- * Write the string representation of the hostlist hl into buf,
- * writing at most n chars. Returns the number of bytes written,
- * or -1 if truncation occurred.
- *
- * The result will be NULL terminated.
- *
- * hostlist_ranged_string() will write a bracketed hostlist representation
- * where possible.
- */
-size_t hostlist_ranged_string(hostlist_t hl, size_t n, char *buf);
-size_t hostset_ranged_string(hostset_t hs, size_t n, char *buf);
-
-/* hostlist_deranged_string():
- *
- * Writes the string representation of the hostlist hl into buf,
- * writing at most n chars. Returns the number of bytes written,
- * or -1 if truncation occurred.
- *
- * hostlist_deranged_string() will not attempt to write a bracketed
- * hostlist representation. Every hostname will be explicitly written.
- */
-size_t hostlist_deranged_string(hostlist_t hl, size_t n, char *buf);
-size_t hostset_deranged_string(hostset_t hs, size_t n, char *buf);
-
-
-/* ----[ hostlist utility functions ]---- */
-
-
-/* hostlist_nranges():
- *
- * Return the number of ranges currently held in hostlist hl.
- */
-int hostlist_nranges(hostlist_t hl);
-
-
-/* ----[ hostlist iterator functions ]---- */
-
-/* hostlist_iterator_create():
- *
- * Creates and returns a hostlist iterator used for non destructive
- * access to a hostlist or hostset. Returns NULL on failure.
- */
-hostlist_iterator_t hostlist_iterator_create(hostlist_t hl);
-
-/* hostset_iterator_create():
- *
- * Same as hostlist_iterator_create(), but creates a hostlist_iterator
- * from a hostset.
- */
-hostlist_iterator_t hostset_iterator_create(hostset_t set);
-
-/* hostlist_iterator_destroy():
- *
- * Destroys a hostlist iterator.
- */
-void hostlist_iterator_destroy(hostlist_iterator_t i);
-
-/* hostlist_iterator_reset():
- *
- * Reset an iterator to the beginning of the list.
- */
-void hostlist_iterator_reset(hostlist_iterator_t i);
-
-/* hostlist_next():
- *
- * Returns a pointer to the next hostname on the hostlist
- * or NULL at the end of the list
- *
- * The caller is responsible for freeing the returned memory.
- */
-char * hostlist_next(hostlist_iterator_t i);
-
-
-/* hostlist_next_range():
- *
- * Returns the next bracketed hostlist or NULL if the iterator i is
- * at the end of the list.
- *
- * The caller is responsible for freeing the returned memory.
- *
- */
-char * hostlist_next_range(hostlist_iterator_t i);
-
-
-/* hostlist_remove():
- * Removes the last host returned by hostlist iterator i
- *
- * Returns 1 for success, 0 for failure.
- */
-int hostlist_remove(hostlist_iterator_t i);
-
-
-/* ----[ hostset operations ]---- */
-
-/* hostset_create():
- *
- * Create a new hostset object from a string representation of a list of
- * hosts. See hostlist_create() for valid hostlist forms.
- */
-hostset_t hostset_create(const char *hostlist);
-
-/* hostset_copy():
- *
- * Copy a hostset object. Returned set must be freed with hostset_destroy().
- */
-hostset_t hostset_copy(hostset_t set);
-
-/* hostset_destroy():
- */
-void hostset_destroy(hostset_t set);
-
-/* hostset_insert():
- * Add a host or list of hosts into hostset "set."
- *
- * Returns number of hosts successfully added to "set"
- * (insertion of a duplicate is not considered successful)
- */
-int hostset_insert(hostset_t set, const char *hosts);
-
-/* hostset_delete():
- * Delete a host or list of hosts from hostset "set."
- * Returns number of hosts deleted from set.
- */
-int hostset_delete(hostset_t set, const char *hosts);
-
-/* hostset_within():
- * Return 1 if all hosts specified by "hosts" are within the hostset "set"
- * Retrun 0 if every host in "hosts" is not in the hostset "set"
- */
-int hostset_within(hostset_t set, const char *hosts);
-
-/* hostset_shift():
- * hostset equivalent to hostlist_shift()
- */
-char * hostset_shift(hostset_t set);
-
-/* hostset_shift_range():
- * hostset eqivalent to hostlist_shift_range()
- */
-char * hostset_shift_range(hostset_t set);
-
-/* hostset_count():
- * Count the number of hosts currently in hostset
- */
-int hostset_count(hostset_t set);
-
-
-#endif /* !_HOSTLIST_H */
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/utils/lshowmount.h
+ *
+ * Author: Herb Wartens <wartens2@llnl.gov>
+ * Author: Jim Garlick <garlick@llnl.gov>
+ */
+
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
-#include "lshowmount.h"
-#include "hash.h"
-#include "hostlist.h"
-
-#define PROGNAME "lshowmount"
-
-extern int errno;
-static int enumerate = 0;
-static int lookup = 0;
-static int verbose = 0;
+#include <libgen.h>
-static int totalexports = 0;
-static int totalfailures = 0;
+#include "nidlist.h"
-static struct option long_options[] = {
- {"enumerate", 0, 0, 'e'},
- {"help", 0, 0, 'h'},
- {"lookup", 0, 0, 'l'},
- {"verbose", 0, 0, 'v'},
- {0, 0, 0, 0}
-};
-
-inline int
-lshowmount_hash_strcmp(const void *key1, const void *key2)
-{
- return strcmp((char *) key1, (char *) key2);
+#define PROC_DIRS { \
+ "/proc/fs/lustre/mgs", \
+ "/proc/fs/lustre/mds", \
+ "/proc/fs/lustre/obdfilter", \
+ NULL, \
}
+#define PROC_EXPORTS_TMPL "%s/%s/exports"
+#define PROC_UUID_TMPL "%s/%s/uuid"
-inline void
-lshowmount_hash_hostlist_freeitem(void *data)
-{
- hostlist_t hl = NULL;
+static void print_nids(NIDList nidlist, int lookup, int enumerate, int indent);
+static int lshowmount(int lookup, int enumerate, int verbose);
+static void read_exports(char *exports, NIDList nidlist);
- if (data == NULL) {
- return;
- }
+char *prog;
- hl = (hostlist_t) data;
- hostlist_destroy(hl);
-}
+#define OPTIONS "ehlv"
+static struct option long_options[] = {
+ {"enumerate", no_argument, 0, 'e'},
+ {"help", no_argument, 0, 'h'},
+ {"lookup", no_argument, 0, 'l'},
+ {"verbose", no_argument, 0, 'v'},
+ {0, 0, 0, 0},
+};
-inline int
-is_ipaddress(const char *str)
+static void usage(void)
{
- int rc = 0;
- int quad[4];
-
- rc = sscanf(str, "%d.%d.%d.%d", &quad[0], &quad[1], &quad[2], &quad[3]);
- if (rc == 4) {
- return 1;
- }
- return 0;
+ fprintf(stderr, "usage: %s [-e] [-h] [-l] [-v]\n", prog);
+ exit(1);
}
-inline void
-lshowmount_gethostname(const char *src, char *dst, int dstsize)
+int main(int argc, char **argv)
{
- struct hostent *hostptr = NULL;
- char tmpsrc[4];
- int rc = 0;
-
- memset(dst, 0, sizeof(char) * dstsize);
- if (lookup && is_ipaddress(src)) {
- rc = inet_pton(AF_INET, src, tmpsrc);
-
- if (rc <= 0) {
- strncpy(dst, src, dstsize);
- return;
+ int opt, optidx = 0;
+ int lopt = 0;
+ int vopt = 0;
+ int eopt = 0;
+
+ prog = basename(argv[0]);
+
+ while ((opt = getopt_long(argc, argv, OPTIONS, long_options, &optidx)) != -1) {
+ switch (opt) {
+ case 'e': /* --enumerate */
+ eopt = 1;
+ break;
+ case 'l': /* --lookup */
+ lopt = 1;
+ break;
+ case 'v': /* --verbose */
+ vopt = 1;
+ break;
+ case 'h': /* --help */
+ default:
+ usage();
+ }
}
- else {
- hostptr = gethostbyaddr(tmpsrc, 4, AF_INET);
- if (hostptr == NULL) {
- strncpy(dst, src, dstsize);
- return;
- }
- else {
- strncpy(dst, hostptr->h_name, dstsize);
- return;
- }
+
+ if (lshowmount(lopt, eopt, vopt) == 0) {
+ fprintf(stderr, "%s: lustre server modules not loaded\n", prog);
+ exit(1);
}
- }
- strncpy(dst, src, dstsize);
+ exit(0);
}
-void
-lshowmount_print_hosts(char** network,
- hash_t network_hash)
+static void print_nids(NIDList nidlist, int lookup, int enumerate, int indent)
{
- hostlist_t hl = NULL;
- hostlist_iterator_t itr = NULL;
- char *hosts = NULL;
- int numnets = 0, numhosts = 0, i = 0;
-
- if (network == NULL || network_hash == NULL) {
- return;
- }
-
- numnets = hash_count(network_hash);
- for (i = 0; i < numnets; i++) {
- errno = 0;
- hl = hash_remove(network_hash, network[i]);
- if (hl == NULL) {
- continue;
- }
- hostlist_uniq(hl);
- numhosts = hostlist_count(hl);
-
- if (numhosts > 0) {
- if (enumerate) {
- itr = hostlist_iterator_create(hl);
-
- /* setup argument */
- while ((hosts = hostlist_next(itr)) != NULL) {
- printf(" %s@%s\n", hosts, network[i]);
- }
- hostlist_iterator_destroy(itr);
- }
- else {
- hosts = malloc(sizeof(char) * (numhosts) * (NID_MAX+1));
- if (hosts == NULL) {
- fprintf(stderr, "warning: could not allocate buffer "
- "to print hostrange\n");
- return;
+ char *s, *sep = "\n", *pfx = "";
+
+ if (lookup)
+ nl_lookup_ip(nidlist);
+ nl_sort(nidlist);
+ nl_uniq(nidlist);
+ if (nl_count(nidlist) > 0) {
+ if (indent) {
+ sep = "\n ";
+ pfx = " ";
}
- hostlist_ranged_string(hl, sizeof(char) *
- numhosts *
- (NID_MAX+1), hosts);
- printf(" %s@%s\n", hosts, network[i]);
- free(hosts);
- hosts = NULL;
- }
+ if (enumerate)
+ s = nl_string(nidlist, sep);
+ else
+ s = nl_xstring(nidlist, sep);
+ printf("%s%s\n", pfx, s);
+ free(s);
}
- memset(network[i], 0, sizeof(char) * (LNET_NETWORK_TYPE_MAX+1));
- lshowmount_hash_hostlist_freeitem(hl);
- }
}
-void usage(void)
+static int lshowmount(int lookup, int enumerate, int verbose)
{
- fprintf(stderr, "usage: %s [-e] [-h] [-l] [-v]\n", PROGNAME);
-}
-
-int getclients(char* procpath,
- char** network,
- hash_t network_hash)
-{
- DIR *dirp, *dirp2;
- struct dirent *dp, *dp2;
- char path[PATH_MAX+1];
- char nid[NID_MAX+1], addr[NID_MAX+1];
- int size = PATH_MAX+1, sizeleft, sizeleft2;
- int tmplen, tmplen2, idx, rc = 0;
- char *tmp, *tmp2;
- hostlist_t hl;
-
- if (procpath == NULL) {
- return -1;
- }
-
- /* It is not an error if we cannot open
- * procpath since we are not sure if this
- * node is an mgs, mds, and/or oss */
- errno = 0;
- dirp = opendir(procpath);
- if (dirp == NULL) {
- return 0;
- }
-
- do {
- errno = 0;
- dp = readdir(dirp);
- if (dp != NULL) {
- if (dp->d_type != DT_DIR ||
- strncmp(dp->d_name, ".", 2) == 0 ||
- strncmp(dp->d_name, "..", 3) == 0) {
- continue;
- }
-
- sizeleft = size;
- tmp = path;
- memset(tmp, 0, sizeof(char) * sizeleft);
-
- strncpy(tmp, procpath, sizeleft);
- tmplen = strnlen(tmp, sizeleft);
- sizeleft -= tmplen;
- tmp += tmplen;
-
- strncpy(tmp, "/", sizeleft);
- tmplen = strnlen(tmp, sizeleft);
- sizeleft -= tmplen;
- tmp += tmplen;
-
- strncpy(tmp, dp->d_name, sizeleft);
- tmplen = strnlen(tmp, sizeleft);
- sizeleft -= tmplen;
- tmp += tmplen;
-
- strncpy(tmp, "/", sizeleft);
- tmplen = strnlen(tmp, sizeleft);
- sizeleft -= tmplen;
- tmp += tmplen;
-
- strncpy(tmp, PROC_EXPORTS, sizeleft);
- tmplen = strnlen(tmp, sizeleft);
- sizeleft -= tmplen;
- tmp += tmplen;
-
- errno = 0;
- dirp2 = opendir(path);
- if (dirp2 == NULL) {
- fprintf(stderr, "error: could not open: %s\n", path);
- rc = errno;
- continue;
- }
-
- do {
- errno = 0;
- dp2 = readdir(dirp2);
- if (dp2 != NULL) {
- if (strncmp(dp2->d_name, ".", 2) == 0 ||
- strncmp(dp2->d_name, "..", 3) == 0 ||
- dp2->d_type != DT_DIR) {
- continue;
- }
- totalexports++;
-
- sizeleft2 = sizeleft;
- tmp2 = tmp;
- memset(tmp2, 0, sizeof(char) * sizeleft2);
-
- strncpy(tmp2, "/", sizeleft2);
- tmplen2 = strnlen(tmp2, sizeleft2);
- sizeleft2 -= tmplen2;
- tmp2 += tmplen2;
-
- strncpy(tmp2, dp2->d_name, sizeleft2);
- tmplen2 = strnlen(tmp2, sizeleft2);
- sizeleft2 -= tmplen2;
- tmp2 += tmplen2;
-
- memset(nid, 0, sizeof(char) * (NID_MAX+1));
- strncpy(nid, basename(path), sizeof(char) * (NID_MAX+1));
- tmp2 = strrchr(nid, '@');
- if (tmp2 == NULL) {
- totalfailures++;
+ char *dirs[] = PROC_DIRS;
+ char exp[PATH_MAX + 1];
+ NIDList nidlist = NULL;
+ DIR *topdirp;
+ struct dirent *dp;
+ int i;
+ int opens = 0;
+
+ if (!verbose)
+ nidlist = nl_create();
+ for (i = 0; dirs[i] != NULL; i++) {
+ if ((topdirp = opendir(dirs[i])) == NULL)
continue;
- }
- *tmp2 = '\0';
- tmp2++;
- /* Note that tmp2 should now hold the lnet network */
-
- /* Check to see if this lnet network already has a hostset
- * associated with it */
- errno = 0;
- hl = hash_find(network_hash, tmp2);
- if (hl == NULL) {
- if (hash_count(network_hash) >= NETWORK_MAX) {
- (void)closedir(dirp2);
- return EINVAL;
- }
-
- /* Create a new hostset for this hash table and
- * insert the first part of the nid into it */
- idx = hash_count(network_hash);
- strncpy(network[idx], tmp2, LNET_NETWORK_TYPE_MAX);
- lshowmount_gethostname(nid, addr, NID_MAX+1);
- hl = hostlist_create(addr);
- hash_insert(network_hash, network[idx], hl);
- }
- else {
- lshowmount_gethostname(nid, addr, NID_MAX+1);
- hostlist_push_host(hl, addr);
- }
- }
- } while (dp2 != NULL);
- (void) closedir(dirp2);
-
- /* If the verbose option is set we want to print
- * out the hostlist for each mgs, mds, obdfilter */
- if (verbose) {
- printf("%s:\n", dp->d_name);
- if (totalfailures > 0) {
- fprintf(stderr, "failures %d of %d exports\n",
- totalfailures, totalexports);
+ while ((dp = readdir(topdirp))) {
+ if (dp->d_type != DT_DIR)
+ continue;
+ if (!strcmp(dp->d_name, "."))
+ continue;
+ if (!strcmp(dp->d_name, ".."))
+ continue;
+ sprintf(exp, PROC_EXPORTS_TMPL, dirs[i], dp->d_name);
+ if (verbose) {
+ nidlist = nl_create();
+ read_exports(exp, nidlist);
+ printf("%s:\n", dp->d_name);
+ print_nids(nidlist, lookup, enumerate, 1);
+ nl_destroy(nidlist);
+ } else
+ read_exports(exp, nidlist);
}
-
- if (!rc && totalfailures > 0) {
- rc = 1;
- }
-
- totalexports = totalfailures = 0;
- lshowmount_print_hosts(network, network_hash);
- }
+ closedir(topdirp);
+ opens++;
}
- } while (dp != NULL);
- (void) closedir(dirp);
-
- if (!rc && totalfailures > 0) {
- rc = 1;
- }
-
- return rc;
+ if (!verbose) {
+ print_nids(nidlist, lookup, enumerate, 0);
+ nl_destroy(nidlist);
+ }
+ return opens;
}
-int main(int argc, char **argv)
+static int empty_proc_file(char *path)
{
- int opt = 0;
- int optidx = 0;
- int i = 0, rc = 0, rc2 = 0, rc3 = 0;
- hash_t network_hash = NULL;
- char** network = NULL;
-
- while ((opt = getopt_long(argc, argv, "ehlv",long_options, &optidx)) != -1) {
- switch (opt) {
- case 'e':
- enumerate = 1;
- break;
- case 'h':
- usage();
- goto finish;
- break;
- case 'l':
- lookup = 1;
- break;
- case 'v':
- verbose = 1;
- break;
- default:
- usage();
- rc = -1;
- goto finish;
- break;
- }
- }
-
- /* Allocate memory for NETWORK_MAX total possible
- * lnet networks. Each network will have its own
- * hash table so that we can possibly create a ranged
- * string for it */
- network = malloc(sizeof(char *) * NETWORK_MAX);
- if (network == NULL) {
- rc = ENOMEM;
- goto finish;
- }
- memset(network, 0, sizeof(char *) * NETWORK_MAX);
- for (i = 0; i < NETWORK_MAX; i++) {
- network[i] = malloc(sizeof(char) * (LNET_NETWORK_TYPE_MAX+1));
- if (network[i] == NULL) {
- rc = ENOMEM;
- goto finish;
- }
- memset(network[i], 0, sizeof(char) * (LNET_NETWORK_TYPE_MAX+1));
- }
-
- /* Initialize the network_hash. This hash table will map
- * a particular network say elan1 or tcp2 to a hostset */
- network_hash = hash_create(0,
- (hash_key_f) hash_key_string,
- lshowmount_hash_strcmp,
- lshowmount_hash_hostlist_freeitem);
-
- rc = getclients(PROC_DIR_MGS, network, network_hash);
- rc2 = getclients(PROC_DIR_MDS, network, network_hash);
- rc3 = getclients(PROC_DIR_OST, network, network_hash);
- if (rc || rc2 || rc3) {
- rc = rc2 > rc ? rc2 : rc;
- rc = rc3 > rc ? rc3 : rc;
- }
-
- if (!verbose) {
- if (totalfailures > 0) {
- fprintf(stderr, "failures %d of %d exports\n",
- totalfailures, totalexports);
- }
- lshowmount_print_hosts(network, network_hash);
- }
+ int empty = 0;
+ char buf[36];
+ int fd;
+
+ if ((fd = open(path, O_RDONLY)) < 0 || read(fd, buf, sizeof(buf)) <= 0)
+ empty = 1;
+ if (fd >= 0)
+ close(fd);
+ return empty;
+}
-finish:
- hash_destroy(network_hash);
- if (network != NULL) {
- for (i = 0; i < NETWORK_MAX; i++) {
- if (network[i] != NULL) {
- free(network[i]);
- network[i] = NULL;
- }
+static void read_exports(char *exports, NIDList nidlist)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ char path[PATH_MAX + 1];
+
+ if ((dirp = opendir(exports))) {
+ while ((dp = readdir(dirp))) {
+ if (dp->d_type != DT_DIR)
+ continue;
+ if (!strcmp(dp->d_name, "."))
+ continue;
+ if (!strcmp(dp->d_name, ".."))
+ continue;
+ if (strchr(dp->d_name, '@') == NULL)
+ continue;
+ sprintf(path, PROC_UUID_TMPL, exports, dp->d_name);
+ if (empty_proc_file(path))
+ continue;
+
+ nl_add(nidlist, dp->d_name);
+ }
+ closedir(dirp);
}
- free(network);
- network = NULL;
- }
-
- return rc;
}
-
-/*
- * vi:tabstop=4 shiftwidth=4 expandtab
- */