Whamcloud - gitweb
b=17997
authorzhanghc <zhanghc>
Sun, 15 Mar 2009 16:31:11 +0000 (16:31 +0000)
committerzhanghc <zhanghc>
Sun, 15 Mar 2009 16:31:11 +0000 (16:31 +0000)
new implementation for lshowmount

i=adilger
i=hongchao.zhang

lustre/utils/Makefile.am
lustre/utils/hash.c [deleted file]
lustre/utils/hash.h [deleted file]
lustre/utils/hostlist.c [deleted file]
lustre/utils/hostlist.h [deleted file]
lustre/utils/lshowmount.c
lustre/utils/lshowmount.h [deleted file]
lustre/utils/nidlist.c [new file with mode: 0644]
lustre/utils/nidlist.h [new file with mode: 0644]
lustre/utils/thread.c [deleted file]
lustre/utils/thread.h [deleted file]

index 709a7e5..39182e8 100644 (file)
@@ -39,8 +39,7 @@ loadgen_SOURCES = loadgen.c lustre_cfg.c obd.c
 loadgen_LDADD := $(LIBREADLINE) $(LIBPTLCTL) $(PTHREAD_LIBS)
 loadgen_DEPENDENCIES := $(LIBPTLCTL)
 
-lshowmount_SOURCES    = lshowmount.h lshowmount.c hash.c hash.h \
-                       thread.c thread.h hostlist.c hostlist.h
+lshowmount_SOURCES    = lshowmount.c nidlist.c nidlist.h
 
 if EXT2FS_DEVEL
 EXT2FSLIB = -lext2fs
diff --git a/lustre/utils/hash.c b/lustre/utils/hash.c
deleted file mode 100644 (file)
index 0717176..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-/*****************************************************************************
- *  $Id: hash.c,v 1.1.2.1 2008/11/21 15:27:33 yangsheng Exp $
- *****************************************************************************
- *  Copyright (C) 2003-2005 The Regents of the University of California.
- *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- *  Written by Chris Dunlap <cdunlap@llnl.gov>.
- *
- *  This file is from LSD-Tools, the LLNL Software Development Toolbox.
- *
- *  This 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.
- *
- *  This 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;
- *  if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
- *  Fifth Floor, Boston, MA  02110-1301  USA.
- *****************************************************************************
- *  Refer to "hash.h" for documentation on public functions.
- *****************************************************************************/
-
-
-#if HAVE_CONFIG_H
-#  include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "thread.h"
-#include "hash.h"
-
-
-/*****************************************************************************
- *  Constants
- *****************************************************************************/
-
-#define HASH_ALLOC      1024
-#define HASH_DEF_SIZE   1213
-#define HASH_MAGIC      0xDEADBEEF
-
-
-/*****************************************************************************
- *  Data Types
- *****************************************************************************/
-
-struct hash_node {
-    struct hash_node   *next;           /* next node in list                 */
-    void               *data;           /* ptr to hashed item                */
-    const void         *hkey;           /* ptr to hashed item's key          */
-};
-
-struct hash {
-    int                 count;          /* number of items in hash table     */
-    int                 size;           /* num slots allocated in hash table */
-    struct hash_node  **table;          /* hash table array of node ptrs     */
-    hash_cmp_f          cmp_f;          /* key comparison function           */
-    hash_del_f          del_f;          /* item deletion function            */
-    hash_key_f          key_f;          /* key hash function                 */
-#if WITH_PTHREADS
-    pthread_mutex_t     mutex;          /* mutex to protect access to hash   */
-#endif /* WITH_PTHREADS */
-#ifndef NDEBUG
-    unsigned int        magic;          /* sentinel for asserting validity   */
-#endif /* NDEBUG */
-};
-
-
-/*****************************************************************************
- *  Prototypes
- *****************************************************************************/
-
-static struct hash_node * hash_node_alloc (void);
-
-static void hash_node_free (struct hash_node *node);
-
-
-/*****************************************************************************
- *  Variables
- *****************************************************************************/
-
-#if 0
-static struct hash_node *hash_free_list = NULL;
-#endif
-
-#if WITH_PTHREADS
-static pthread_mutex_t hash_free_lock = PTHREAD_MUTEX_INITIALIZER;
-#endif /* WITH_PTHREADS */
-
-
-/*****************************************************************************
- *  Macros
- *****************************************************************************/
-
-#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) (abort ())
-#  endif /* !lsd_fatal_error */
-#endif /* !WITH_LSD_FATAL_ERROR_FUNC */
-
-#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 */
-
-
-/*****************************************************************************
- *  Functions
- *****************************************************************************/
-
-hash_t
-hash_create (int size, hash_key_f key_f, hash_cmp_f cmp_f, hash_del_f del_f)
-{
-    hash_t h;
-
-    if (!cmp_f || !key_f) {
-        errno = EINVAL;
-        return (NULL);
-    }
-    if (size <= 0) {
-        size = HASH_DEF_SIZE;
-    }
-    if (!(h = malloc (sizeof (*h)))) {
-        return (lsd_nomem_error (__FILE__, __LINE__, "hash_create"));
-    }
-    if (!(h->table = calloc (size, sizeof (struct hash_node *)))) {
-        free (h);
-        return (lsd_nomem_error (__FILE__, __LINE__, "hash_create"));
-    }
-    h->count = 0;
-    h->size = size;
-    h->cmp_f = cmp_f;
-    h->del_f = del_f;
-    h->key_f = key_f;
-    lsd_mutex_init (&h->mutex);
-    assert (h->magic = HASH_MAGIC);     /* set magic via assert abuse */
-    return (h);
-}
-
-
-void
-hash_destroy (hash_t h)
-{
-    int i;
-    struct hash_node *p, *q;
-
-    if (!h) {
-        errno = EINVAL;
-        return;
-    }
-    lsd_mutex_lock (&h->mutex);
-    assert (h->magic == HASH_MAGIC);
-    for (i = 0; i < h->size; i++) {
-        for (p = h->table[i]; p != NULL; p = q) {
-            q = p->next;
-            if (h->del_f)
-                h->del_f (p->data);
-            hash_node_free (p);
-        }
-    }
-    assert (h->magic = ~HASH_MAGIC);    /* clear magic via assert abuse */
-    lsd_mutex_unlock (&h->mutex);
-    lsd_mutex_destroy (&h->mutex);
-    free (h->table);
-    free (h);
-    return;
-}
-
-
-int
-hash_is_empty (hash_t h)
-{
-    int n;
-
-    if (!h) {
-        errno = EINVAL;
-        return (0);
-    }
-    lsd_mutex_lock (&h->mutex);
-    assert (h->magic == HASH_MAGIC);
-    n = h->count;
-    lsd_mutex_unlock (&h->mutex);
-    return (n == 0);
-}
-
-
-int
-hash_count (hash_t h)
-{
-    int n;
-
-    if (!h) {
-        errno = EINVAL;
-        return (0);
-    }
-    lsd_mutex_lock (&h->mutex);
-    assert (h->magic == HASH_MAGIC);
-    n = h->count;
-    lsd_mutex_unlock (&h->mutex);
-    return (n);
-}
-
-
-void *
-hash_find (hash_t h, const void *key)
-{
-    unsigned int slot;
-    struct hash_node *p;
-    void *data = NULL;
-
-    if (!h || !key) {
-        errno = EINVAL;
-        return (NULL);
-    }
-    errno = 0;
-    lsd_mutex_lock (&h->mutex);
-    assert (h->magic == HASH_MAGIC);
-    slot = h->key_f (key) % h->size;
-    for (p = h->table[slot]; p != NULL; p = p->next) {
-        if (!h->cmp_f (p->hkey, key)) {
-            data = p->data;
-            break;
-        }
-    }
-    lsd_mutex_unlock (&h->mutex);
-    return (data);
-}
-
-
-void *
-hash_insert (hash_t h, const void *key, void *data)
-{
-    struct hash_node *p;
-    unsigned int slot;
-
-    if (!h || !key || !data) {
-        errno = EINVAL;
-        return (NULL);
-    }
-    lsd_mutex_lock (&h->mutex);
-    assert (h->magic == HASH_MAGIC);
-    slot = h->key_f (key) % h->size;
-    for (p = h->table[slot]; p != NULL; p = p->next) {
-        if (!h->cmp_f (p->hkey, key)) {
-            errno = EEXIST;
-            data = NULL;
-            goto end;
-        }
-    }
-    if (!(p = hash_node_alloc ())) {
-        data = lsd_nomem_error (__FILE__, __LINE__, "hash_insert");
-        goto end;
-    }
-    p->hkey = key;
-    p->data = data;
-    p->next = h->table[slot];
-    h->table[slot] = p;
-    h->count++;
-
-end:
-    lsd_mutex_unlock (&h->mutex);
-    return (data);
-}
-
-
-void *
-hash_remove (hash_t h, const void *key)
-{
-    struct hash_node **pp;
-    struct hash_node *p;
-    unsigned int slot;
-    void *data = NULL;
-
-    if (!h || !key) {
-        errno = EINVAL;
-        return (NULL);
-    }
-    errno = 0;
-    lsd_mutex_lock (&h->mutex);
-    assert (h->magic == HASH_MAGIC);
-    slot = h->key_f (key) % h->size;
-    for (pp = &(h->table[slot]); (p = *pp) != NULL; pp = &((*pp)->next)) {
-        if (!h->cmp_f (p->hkey, key)) {
-            data = p->data;
-            *pp = p->next;
-            hash_node_free (p);
-            h->count--;
-            break;
-        }
-    }
-    lsd_mutex_unlock (&h->mutex);
-    return (data);
-}
-
-
-int
-hash_delete_if (hash_t h, hash_arg_f arg_f, void *arg)
-{
-    int i;
-    struct hash_node **pp;
-    struct hash_node *p;
-    int n = 0;
-
-    if (!h || !arg_f) {
-        errno = EINVAL;
-        return (-1);
-    }
-    lsd_mutex_lock (&h->mutex);
-    assert (h->magic == HASH_MAGIC);
-    for (i = 0; i < h->size; i++) {
-        pp = &(h->table[i]);
-        while ((p = *pp) != NULL) {
-            if (arg_f (p->data, p->hkey, arg) > 0) {
-                if (h->del_f)
-                    h->del_f (p->data);
-                *pp = p->next;
-                hash_node_free (p);
-                h->count--;
-                n++;
-            }
-            else {
-                pp = &(p->next);
-            }
-        }
-    }
-    lsd_mutex_unlock (&h->mutex);
-    return (n);
-}
-
-
-int
-hash_for_each (hash_t h, hash_arg_f arg_f, void *arg)
-{
-    int i;
-    struct hash_node *p;
-    int n = 0;
-
-    if (!h || !arg_f) {
-        errno = EINVAL;
-        return (-1);
-    }
-    lsd_mutex_lock (&h->mutex);
-    assert (h->magic == HASH_MAGIC);
-    for (i = 0; i < h->size; i++) {
-        for (p = h->table[i]; p != NULL; p = p->next) {
-            if (arg_f (p->data, p->hkey, arg) > 0) {
-                n++;
-            }
-        }
-    }
-    lsd_mutex_unlock (&h->mutex);
-    return (n);
-}
-
-
-/*****************************************************************************
- *  Hash Functions
- *****************************************************************************/
-
-unsigned int
-hash_key_string (const char *str)
-{
-    unsigned char *p;
-    unsigned int hval = 0;
-    const unsigned int multiplier = 31;
-
-    for (p = (unsigned char *) str; *p != '\0'; p++) {
-        hval += (multiplier * hval) + *p;
-    }
-    return (hval);
-}
-
-
-/*****************************************************************************
- *  Internal Functions
- *****************************************************************************/
-
-static struct hash_node *
-hash_node_alloc (void)
-{
-/*  Allocates a hash node from the freelist.
- *  Memory is allocated in chunks of HASH_ALLOC.
- *  Returns a ptr to the object, or NULL if memory allocation fails.
- */
-#if 0
-    int i;
-#endif
-    struct hash_node *p = NULL;
-
-    assert (HASH_ALLOC > 0);
-    lsd_mutex_lock (&hash_free_lock);
-#if 0
-    if (!hash_free_list) {
-        if ((hash_free_list = malloc (HASH_ALLOC * sizeof (*p)))) {
-            for (i = 0; i < HASH_ALLOC - 1; i++)
-                hash_free_list[i].next = &hash_free_list[i+1];
-            hash_free_list[i].next = NULL;
-        }
-    }
-    if (hash_free_list) {
-        p = hash_free_list;
-        hash_free_list = p->next;
-    }
-    else {
-        errno = ENOMEM;
-    }
-#else
-    if (!(p = malloc (sizeof(*p))))
-        errno = ENOMEM;
-#endif
-    lsd_mutex_unlock (&hash_free_lock);
-    return (p);
-}
-
-
-static void
-hash_node_free (struct hash_node *node)
-{
-/*  De-allocates the object [node], returning it to the freelist.
- */
-    assert (node != NULL);
-    memset (node, 0, sizeof (*node));
-    lsd_mutex_lock (&hash_free_lock);
-#if 0
-    node->next = hash_free_list;
-    hash_free_list = node;
-#else
-    free (node);
-#endif
-    lsd_mutex_unlock (&hash_free_lock);
-    return;
-}
diff --git a/lustre/utils/hash.h b/lustre/utils/hash.h
deleted file mode 100644 (file)
index 9926c4a..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*****************************************************************************
- *  $Id: hash.h,v 1.1.2.1 2008/11/21 15:27:33 yangsheng Exp $
- *****************************************************************************
- *  Copyright (C) 2003-2005 The Regents of the University of California.
- *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- *  Written by Chris Dunlap <cdunlap@llnl.gov>.
- *
- *  This file is from LSD-Tools, the LLNL Software Development Toolbox.
- *
- *  This 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.
- *
- *  This 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;
- *  if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
- *  Fifth Floor, Boston, MA  02110-1301  USA.
- *****************************************************************************/
-
-
-#ifndef LSD_HASH_H
-#define LSD_HASH_H
-
-
-/*****************************************************************************
- *  Notes
- *****************************************************************************/
-/*
- *  If an item's key is modified after insertion, the hash will be unable to
- *  locate it if the new key should hash to a different slot in the table.
- *
- *  If NDEBUG is not defined, internal debug code will be enabled; this is
- *  intended for development use only.  Production code should define NDEBUG.
- *
- *  If WITH_LSD_FATAL_ERROR_FUNC is defined, the linker will expect to
- *  find an external lsd_fatal_error(file,line,mesg) function.  By default,
- *  lsd_fatal_error(file,line,mesg) is a macro definition that aborts.
- *  This macro may be redefined to invoke another routine instead.
- *
- *  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.
- */
-
-
-/*****************************************************************************
- *  Data Types
- *****************************************************************************/
-
-typedef struct hash * hash_t;
-/*
- *  Hash table opaque data type.
- */
-
-typedef unsigned int (*hash_key_f) (const void *key);
-/*
- *  Function prototype for the hash function responsible for converting
- *    the data's [key] into an unsigned integer hash value.
- */
-
-typedef int (*hash_cmp_f) (const void *key1, const void *key2);
-/*
- *  Function prototype for comparing two keys.
- *  Returns zero if both keys are equal; o/w, returns nonzero.
- */
-
-typedef void (*hash_del_f) (void *data);
-/*
- *  Function prototype for de-allocating a data item stored within a hash.
- *  This function is responsible for freeing all memory associated with
- *    the [data] item, including any subordinate items.
- */
-
-typedef int (*hash_arg_f) (void *data, const void *key, void *arg);
-/*
- *  Function prototype for operating on each element in the hash table.
- *  The function will be invoked once for each [data] item in the hash,
- *    with the item's [key] and the specified [arg] being passed in as args.
- */
-
-
-/*****************************************************************************
- *  Functions
- *****************************************************************************/
-
-hash_t hash_create (int size,
-    hash_key_f key_f, hash_cmp_f cmp_f, hash_del_f del_f);
-/*
- *  Creates and returns a new hash table on success.
- *    Returns lsd_nomem_error() with errno=ENOMEM if memory allocation fails.
- *    Returns NULL with errno=EINVAL if [keyf] or [cmpf] is not specified.
- *  The [size] is the number of slots in the table; a larger table requires
- *    more memory, but generally provide quicker access times.  If set <= 0,
- *    the default size is used.
- *  The [keyf] function converts a key into a hash value.
- *  The [cmpf] function determines whether two keys are equal.
- *  The [delf] function de-allocates memory used by items in the hash;
- *    if set to NULL, memory associated with these items will not be freed
- *    when the hash is destroyed.
- */
-
-void hash_destroy (hash_t h);
-/*
- *  Destroys hash table [h].  If a deletion function was specified when the
- *    hash was created, it will be called for each item contained within.
- *  Abadoning a hash without calling hash_destroy() will cause a memory leak.
- */
-
-int hash_is_empty (hash_t h);
-/*
- *  Returns non-zero if hash table [h] is empty; o/w, returns zero.
- */
-
-int hash_count (hash_t h);
-/*
- *  Returns the number of items in hash table [h].
- */
-
-void * hash_find (hash_t h, const void *key);
-/*
- *  Searches for the item corresponding to [key] in hash table [h].
- *  Returns a ptr to the found item's data on success.
- *    Returns NULL with errno=0 if no matching item is found.
- *    Returns NULL with errno=EINVAL if [key] is not specified.
- */
-
-void * hash_insert (hash_t h, const void *key, void *data);
-/*
- *  Inserts [data] with the corresponding [key] into hash table [h];
- *    note that it is permissible for [key] to be set equal to [data].
- *  Returns a ptr to the inserted item's data on success.
- *    Returns NULL with errno=EEXIST if [key] already exists in the hash.
- *    Returns NULL with errno=EINVAL if [key] or [data] is not specified.
- *    Returns lsd_nomem_error() with errno=ENOMEM if memory allocation fails.
- */
-
-void * hash_remove (hash_t h, const void *key);
-/*
- *  Removes the item corresponding to [key] from hash table [h].
- *  Returns a ptr to the removed item's data on success.
- *    Returns NULL with errno=0 if no matching item is found.
- *    Returns NULL with errno=EINVAL if [key] is not specified.
- */
-
-int hash_delete_if (hash_t h, hash_arg_f argf, void *arg);
-/*
- *  Conditionally deletes (and de-allocates) items from hash table [h].
- *  The [argf] function is invoked once for each item in the hash, with
- *    [arg] being passed in as an argument.  Items for which [argf] returns
- *    greater-than-zero are deleted.
- *  Returns the number of items deleted.
- *    Returns -1 with errno=EINVAL if [argf] is not specified.
- */
-
-int hash_for_each (hash_t h, hash_arg_f argf, void *arg);
-/*
- *  Invokes the [argf] function once for each item in hash table [h],
- *    with [arg] being passed in as an argument.
- *  Returns the number of items for which [argf] returns greater-than-zero.
- *    Returns -1 with errno=EINVAL if [argf] is not specified.
- */
-
-unsigned int hash_key_string (const char *str);
-/*
- *  A hash_key_f function that hashes the string [str].
- */
-
-
-#endif /* !LSD_HASH_H */
diff --git a/lustre/utils/hostlist.c b/lustre/utils/hostlist.c
deleted file mode 100644 (file)
index cbddfd2..0000000
+++ /dev/null
@@ -1,2687 +0,0 @@
-/*****************************************************************************\
- *  $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
- */
diff --git a/lustre/utils/hostlist.h b/lustre/utils/hostlist.h
deleted file mode 100644 (file)
index abf599b..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-/*****************************************************************************\
- *  $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 */
index 4b2675f..40d219f 100644 (file)
@@ -1,3 +1,44 @@
+/* -*- 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
- */
diff --git a/lustre/utils/lshowmount.h b/lustre/utils/lshowmount.h
deleted file mode 100644 (file)
index 06e1c5d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __LSHOWMOUNT_H
-#define __LSHOWMOUNT_H
-
-#define PROC_DIR_MGS          "/proc/fs/lustre/mgs"
-#define PROC_DIR_MDS          "/proc/fs/lustre/mds"
-#define PROC_DIR_OST          "/proc/fs/lustre/obdfilter"
-#define PROC_EXPORTS          "exports"
-#define PROC_NID              "nid"
-#define NID_MAX               1024
-#define LNET_NETWORK_TYPE_MAX 32
-#define NETWORK_MAX           128
-
-#endif
-
-/*
- * vi:tabstop=4 shiftwidth=4 expandtab
- */
diff --git a/lustre/utils/nidlist.c b/lustre/utils/nidlist.c
new file mode 100644 (file)
index 0000000..fb0cbec
--- /dev/null
@@ -0,0 +1,334 @@
+/* -*- 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/nidlist.c
+ *
+ * Author: Jim Garlick <garlick@llnl.gov>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include "nidlist.h"
+
+struct nl_struct {
+       char **nids;
+       int len;
+       int count;
+};
+#define NL_CHUNK       64
+
+extern char *prog;
+
+static void nl_oom(void)
+{
+       fprintf(stderr, "%s: out of memory\n", prog);
+       exit(1);
+}
+
+NIDList nl_create(void)
+{
+       struct nl_struct *nl;
+
+       if (!(nl = malloc(sizeof(struct nl_struct))))
+               nl_oom();
+       nl->len = NL_CHUNK;
+       if (!(nl->nids = malloc(nl->len * sizeof(char *))))
+               nl_oom();
+       nl->count = 0;
+
+       return nl;
+}
+
+void nl_destroy(NIDList nl)
+{
+       int i;
+
+       for (i = 0; i < nl->count; i++)
+               free(nl->nids[i]);
+       free(nl->nids);
+       free(nl);
+}
+
+static void nl_grow(NIDList nl, int n)
+{
+       nl->len += n;
+       if (!(nl->nids = realloc(nl->nids, nl->len * sizeof(char *))))
+               nl_oom();
+}
+
+void nl_add(NIDList nl, char *nid)
+{
+       char *cp;
+
+       if (!(cp = strdup(nid)))
+               nl_oom();
+       if (nl->count == nl->len)
+               nl_grow(nl, NL_CHUNK);
+       nl->nids[nl->count++] = cp;
+}
+
+int nl_count(NIDList nl)
+{
+        return nl->count;
+}
+
+static char *nl_nid_addr(char *nid)
+{
+       char *addr, *p;
+
+       if (!(addr = strdup(nid)))
+               nl_oom();
+       if ((p = strchr(addr, '@')))
+               *p = '\0';
+
+       return addr;
+}
+
+static int nl_nid_parse_addr(char *addr)
+{
+       int o;
+
+       for (o = strlen(addr); o > 0; o--)
+                if (!isdigit(addr[o - 1]))
+                       break;
+
+       return o;
+}
+
+static int nl_cmp_addr(char *nid1, char *nid2, int *cflagp)
+{
+       char *p1 = nl_nid_addr(nid1);
+       char *p2 = nl_nid_addr(nid2);
+       int res, o1, o2, cflag = 0;
+
+       o1 = nl_nid_parse_addr(p1);
+       o2 = nl_nid_parse_addr(p2);
+
+       if (o1 == o2 && (res = strncmp(p1, p2, o1)) == 0) {
+               res = strtoul(&p1[o1], NULL, 10) - strtoul(&p2[o2], NULL, 10);
+                if (cflagp && strlen(&p1[o1]) > 0 && strlen(&p2[o2]) > 0)
+                        cflag = 1;
+       } else
+                res = strcmp(p1, p2);
+       free(p1);
+       free(p2);
+       if (cflagp)
+               *cflagp = cflag;
+       return res;
+}
+
+static int nl_cmp_lnet(char *nid1, char *nid2)
+{
+       char *s1 = strchr(nid1, '@');
+       char *s2 = strchr(nid2, '@');
+
+       return strcmp(s1 ? s1 + 1 : "", s2 ? s2 + 1 : "");
+}
+
+static int nl_cmp(const void *p1, const void *p2)
+{
+       int res;
+
+       if ((res = nl_cmp_lnet(*(char **)p1, *(char **)p2)) == 0)
+               res = nl_cmp_addr(*(char **)p1, *(char **)p2, NULL);
+       return res;
+}
+
+void nl_sort(NIDList nl)
+{
+       qsort(nl->nids, nl->count, sizeof(char *), nl_cmp);
+}
+
+void nl_uniq(NIDList nl)
+{
+       int i, j;
+
+       for (i = 1; i < nl->count; i++) {
+               if (!strcmp(nl->nids[i], nl->nids[i - 1])) {
+                       free(nl->nids[i]);
+                       for (j = i; j < nl->count - 1; j++)
+                               nl->nids[j] = nl->nids[j + 1];
+                       nl->count--;
+                       i--;
+               }
+       }
+}
+
+static char *nl_nid_lookup_ipaddr(char *nid)
+{
+        struct addrinfo *ai, *aip;
+        char name[NI_MAXHOST] = "";
+        char *p, *addr, *lnet = NULL, *res = NULL;
+        int len, x;
+
+        addr = nl_nid_addr(nid);
+        if (sscanf(addr, "%d.%d.%d.%d", &x, &x, &x, &x) == 4) {
+                if ((p = strchr(nid, '@')))
+                        lnet = p + 1;
+                if (getaddrinfo(addr, NULL, NULL, &ai) == 0) {
+                        for (aip = ai; aip != NULL; aip = aip->ai_next) {
+                                if (getnameinfo(aip->ai_addr, aip->ai_addrlen,
+                                    name, sizeof(name), NULL, 0,
+                                    NI_NAMEREQD | NI_NOFQDN) == 0) {
+                                        if ((p = strchr(name, '.')))
+                                                *p = '\0';
+                                        len = strlen(name) + strlen(lnet) + 2;
+                                        if (!(res = malloc(len)))
+                                                nl_oom();
+                                        snprintf(res, len, "%s@%s", name, lnet);
+                                        break;
+                                }
+                        }
+                        freeaddrinfo(ai);
+                }
+        }
+        free(addr);
+
+        return res;
+}
+
+void nl_lookup_ip(NIDList nl)
+{
+       int i;
+        char *new;
+
+       for (i = 0; i < nl->count; i++) {
+                if ((new = nl_nid_lookup_ipaddr(nl->nids[i]))) {
+                        free(nl->nids[i]);
+                        nl->nids[i] = new;
+                }
+        }
+}
+
+char *nl_string(NIDList nl, char *sep)
+{
+       int seplen = strlen(sep);
+       int i, len = 1;
+       char *s;
+
+       for (i = 0; i < nl->count; i++)
+               len += strlen(nl->nids[i]) + seplen;
+       if (!(s = malloc(len)))
+               nl_oom();
+       s[0] = '\0';
+       for (i = 0; i < nl->count; i++) {
+               if (i > 0)
+                       strcat(s, sep);
+               strcat(s, nl->nids[i]);
+       }
+       return s;
+}
+
+static void nl_strxcat(char *s, char **nids, int len)
+{
+       int i, o, lastn = 0;
+       char *base, *p, *lnet = NULL, *savedn = NULL;
+
+       if ((p = strchr(nids[0], '@')))
+               lnet = p + 1;
+        base = nl_nid_addr(nids[0]);
+        o = nl_nid_parse_addr(base);
+       base[o] = '\0';
+       for (i = 0; i < len; i++) {
+               char *addr = nl_nid_addr(nids[i]);
+               int n = strtoul(&addr[o], NULL, 10);
+
+               if (i == 0)
+                       sprintf(s + strlen(s), "%s[%s", base, &addr[o]);
+               else if (i < len) {
+                       if (n == lastn + 1) {
+                               if (savedn)
+                                       free(savedn);
+                               if (!(savedn = strdup(&addr[o])))
+                                       nl_oom();
+                       } else {
+                               if (savedn) {
+                                       sprintf(s + strlen(s), "-%s", savedn);
+                                       free(savedn);
+                                       savedn = NULL;
+                               }
+                               sprintf(s + strlen(s), ",%s", &addr[o]);
+                       }
+               }
+               if (i == len - 1) {
+                       if (savedn) {
+                               sprintf(s + strlen(s), "-%s", savedn);
+                               free(savedn);
+                       }
+                       strcat(s, "]");
+                       if (lnet)
+                               sprintf(s + strlen(s), "@%s", lnet);
+               }
+               free(addr);
+               lastn = n;
+       }
+       free(base);
+}
+
+char *nl_xstring(NIDList nl, char *sep)
+{
+       int seplen = strlen(sep);
+       int cflag, i, j, len = 1;
+       char *s;
+
+       for (i = 0; i < nl->count; i++)
+               len += strlen(nl->nids[i]) + seplen;
+       if (!(s = malloc(len)))
+               nl_oom();
+       s[0] = '\0';
+       for (i = 0; i < nl->count; i++) {
+               if (i > 0)
+                       strcat(s, sep);
+               for (j = i + 1; j < nl->count; j++) {
+                       if (nl_cmp_lnet(nl->nids[i], nl->nids[j]) != 0)
+                               break;
+                       (void)nl_cmp_addr(nl->nids[i], nl->nids[j], &cflag);
+                       if (!cflag)
+                               break;
+               }
+               if (j - i > 1)
+                       nl_strxcat(s, &nl->nids[i], j - i);
+               else
+                       strcat(s, nl->nids[i]);
+               i += j - i - 1;
+       }
+       return s;
+}
diff --git a/lustre/utils/nidlist.h b/lustre/utils/nidlist.h
new file mode 100644 (file)
index 0000000..1978736
--- /dev/null
@@ -0,0 +1,56 @@
+/* -*- 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/nidlist.h
+ *
+ * Author: Jim Garlick <garlick@llnl.gov>
+ */
+
+#ifndef NIDLIST_H
+#define NIDLIST_H
+
+typedef struct nl_struct *NIDList;
+
+NIDList nl_create(void);
+void nl_destroy(NIDList nl);
+void nl_add(NIDList nl, char *nid);
+int nl_count(NIDList nl);
+void nl_lookup_ip(NIDList nl);
+void nl_sort(NIDList nl);
+void nl_uniq(NIDList nl);
+char *nl_string(NIDList nl, char *sep);
+char *nl_xstring(NIDList nl, char *sep);
+
+#endif
diff --git a/lustre/utils/thread.c b/lustre/utils/thread.c
deleted file mode 100644 (file)
index 64701ec..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*****************************************************************************
- *  $Id: thread.c,v 1.1.2.1 2008/11/21 15:27:33 yangsheng Exp $
- *****************************************************************************
- *  Copyright (C) 2003 The Regents of the University of California.
- *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- *  Written by Chris Dunlap <cdunlap@llnl.gov>.
- *
- *  This file is from LSD-Tools, the LLNL Software Development Toolbox.
- *
- *  LSD-Tools 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.
- *
- *  LSD-Tools 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 LSD-Tools; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
- *****************************************************************************/
-
-
-#if HAVE_CONFIG_H
-#  include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <assert.h>
-#include <errno.h>
-#include <pthread.h>
-#include "thread.h"
-
-
-#if WITH_PTHREADS
-#ifndef NDEBUG
-int
-lsd_mutex_is_locked (pthread_mutex_t *mutex)
-{
-/*  Returns true if the mutex is locked; o/w, returns false.
- */
-    int rc;
-
-    assert (mutex != NULL);
-    rc = pthread_mutex_trylock (mutex);
-    return (rc == EBUSY ? 1 : 0);
-}
-#endif /* !NDEBUG */
-#endif /* WITH_PTHREADS */
diff --git a/lustre/utils/thread.h b/lustre/utils/thread.h
deleted file mode 100644 (file)
index 35bdde9..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*****************************************************************************
- *  $Id: thread.h,v 1.1.2.1 2008/11/21 15:27:33 yangsheng Exp $
- *****************************************************************************
- *  Copyright (C) 2003 The Regents of the University of California.
- *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- *  Written by Chris Dunlap <cdunlap@llnl.gov>.
- *
- *  This file is from LSD-Tools, the LLNL Software Development Toolbox.
- *
- *  LSD-Tools 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.
- *
- *  LSD-Tools 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 LSD-Tools; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
- *****************************************************************************/
-
-
-#ifndef LSD_THREAD_H
-#define LSD_THREAD_H
-
-#if WITH_PTHREADS
-#  include <errno.h>
-#  include <pthread.h>
-#  include <stdlib.h>
-#endif /* WITH_PTHREADS */
-
-
-/*****************************************************************************
- *  Macros
- *****************************************************************************/
-
-#if WITH_PTHREADS
-
-#  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) (abort ())
-#    endif /* !lsd_fatal_error */
-#  endif /* !WITH_LSD_FATAL_ERROR_FUNC */
-
-#  define lsd_mutex_init(pmutex)                                              \
-     do {                                                                     \
-         int e = pthread_mutex_init (pmutex, NULL);                           \
-         if (e != 0) {                                                        \
-             errno = e;                                                       \
-             lsd_fatal_error (__FILE__, __LINE__, "mutex_init");              \
-             abort ();                                                        \
-         }                                                                    \
-     } while (0)
-
-#  define lsd_mutex_lock(pmutex)                                              \
-     do {                                                                     \
-         int e = pthread_mutex_lock (pmutex);                                 \
-         if (e != 0) {                                                        \
-             errno = e;                                                       \
-             lsd_fatal_error (__FILE__, __LINE__, "mutex_lock");              \
-             abort ();                                                        \
-         }                                                                    \
-     } while (0)
-
-#  define lsd_mutex_unlock(pmutex)                                            \
-     do {                                                                     \
-         int e = pthread_mutex_unlock (pmutex);                               \
-         if (e != 0) {                                                        \
-             errno = e;                                                       \
-             lsd_fatal_error (__FILE__, __LINE__, "mutex_unlock");            \
-             abort ();                                                        \
-         }                                                                    \
-     } while (0)
-
-#  define lsd_mutex_destroy(pmutex)                                           \
-     do {                                                                     \
-         int e = pthread_mutex_destroy (pmutex);                              \
-         if (e != 0) {                                                        \
-             errno = e;                                                       \
-             lsd_fatal_error (__FILE__, __LINE__, "mutex_destroy");           \
-             abort ();                                                        \
-         }                                                                    \
-     } while (0)
-
-#  ifndef NDEBUG
-     int lsd_mutex_is_locked (pthread_mutex_t *pmutex);
-#  endif /* !NDEBUG */
-
-#else /* !WITH_PTHREADS */
-
-#  define lsd_mutex_init(mutex)
-#  define lsd_mutex_lock(mutex)
-#  define lsd_mutex_unlock(mutex)
-#  define lsd_mutex_destroy(mutex)
-#  define lsd_mutex_is_locked(mutex) (1)
-
-#endif /* !WITH_PTHREADS */
-
-
-#endif /* !LSD_THREAD_H */