Esempio n. 1
0
/*
 * updown_event_setup
 *
 * updown event module setup function.
 */
static int
updown_event_setup(void)
{
  if (!(node_states = hash_create(UPDOWN_HASH_SIZE,
                                  (hash_key_f)hash_key_string,
                                  (hash_cmp_f)strcmp,
                                  (hash_del_f)free)))
    {
      CEREBRO_ERR(("hash_create: %s", strerror(errno)));
      goto cleanup;
    }
  
  if (!(node_states_nodenames = list_create((ListDelF)free)))
    {
      CEREBRO_ERR(("list_create: %s", strerror(errno)));
      goto cleanup;
    }

  return 0;

 cleanup:
  if (node_states)
    {
      hash_destroy(node_states);
      node_states = NULL;
    }
  if (node_states_nodenames)
    {
      list_destroy(node_states_nodenames);
      node_states_nodenames = NULL;
    }
  return -1;
}
/*
 * cerebro_get_loadavgs
 *
 * Read load averages
 */
int
cerebro_metric_get_loadavgs(float *loadavg1,
			    float *loadavg5,
			    float *loadavg15)
{
  int len, fd = -1;
  char buf[LOADAVG_BUFLEN];
  struct timeval now;
  int rv = -1;

  if (gettimeofday(&now, NULL) < 0)
    {
      CEREBRO_ERR(("gettimeofday: %s", strerror(errno)));
      goto cleanup;
    }

  if ((now.tv_sec - last_read) > LOADVAG_CACHETIMEOUT) 
    {
      if ((fd = open(LOADAVG_FILE, O_RDONLY, 0)) < 0)
	{
	  CEREBRO_ERR(("open: %s", strerror(errno)));
	  goto cleanup;
	}
      
      memset(buf, '\0', LOADAVG_BUFLEN);
      if ((len = read(fd, buf, LOADAVG_BUFLEN)) < 0)
	{
	  CEREBRO_ERR(("read: %s", strerror(errno)));
	  goto cleanup;
	}
      
      if (sscanf(buf, 
		 "%f %f %f", 
		 &cache_loadavg1, 
		 &cache_loadavg5, 
		 &cache_loadavg15) != 3)
	{
	  CEREBRO_DBG(("loadavg file parse error"));
	  goto cleanup;
	}

      last_read = now.tv_sec;
    }

  if (loadavg1)
    *loadavg1 = cache_loadavg1;

  if (loadavg5)
    *loadavg5 = cache_loadavg5;

  if (loadavg15)
    *loadavg15 = cache_loadavg15;

  rv = 0;
 cleanup:
  /* ignore potential error, just return result */
  if (fd >= 0)
    close(fd);
  return rv;
}
/*
 * _event_server_err_only_response
 *
 * respond to the event_server_request with an error
 *
 * Return 0 on success, -1 on error
 */
static int
_event_server_err_only_response(int fd, 
                                int32_t version, 
                                u_int32_t err_code)
{
  struct cerebro_event_server_response res;
  char buf[CEREBRO_MAX_PACKET_LEN];
  int res_len;

  assert(fd >= 0
         && err_code >= CEREBRO_EVENT_SERVER_PROTOCOL_ERR_SUCCESS
         && err_code <= CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);

  memset(&res, '\0', CEREBRO_EVENT_SERVER_RESPONSE_LEN);
  res.version = version;
  res.err_code = err_code;
  res.end = CEREBRO_EVENT_SERVER_PROTOCOL_IS_LAST_RESPONSE;

  if ((res_len = _event_server_response_marshall(&res, 
                                                 buf, 
                                                 CEREBRO_MAX_PACKET_LEN)) < 0)
    return -1;

  if (fd_write_n(fd, buf, res_len) < 0)
    {
      CEREBRO_ERR(("fd_write_n: %s", strerror(errno)));
      return -1;
    }

  return 0;
}
/* 
 * _readline
 * 
 * read a line from the hostsfile.  Buffer guaranteed to be null
 * terminated.
 *
 * - fd - file descriptor to read from
 * - buf - buffer pointer
 * - buflen - buffer length
 *
 * Return amount of data read into the buffer, -1 on error
 */
static int
_readline(int fd, char *buf, unsigned int buflen)
{
  int len;

  if (fd <= 0 || !buf || !buflen)
    {
      CEREBRO_DBG(("invalid parameters"));
      return -1;
    }

  if ((len = fd_read_line(fd, buf, buflen)) < 0)
    {
      CEREBRO_ERR(("fd_read_line: %s", strerror(errno)));
      return -1;
    }
  
  /* buflen - 1 b/c fd_read_line guarantees null termination */
  if (len >= (buflen-1))
    {
      CEREBRO_DBG(("fd_read_line: line truncation"));
      return -1;
    }

  return len;
}
/*
 * _respond_with_event_names
 *
 * Return 0 on success, -1 on error
 */
static void *
_respond_with_event_names(void *arg)
{
  struct cerebrod_event_names_response_data enr;
  List responses = NULL;
  int fd;

  assert(arg);

  fd = *((int *)arg);
  
  if (!event_names)
    goto end_response;

  if (!List_count(event_names))
    goto end_response;

  if (!(responses = list_create((ListDelF)free)))
    {
      CEREBRO_ERR(("list_create: %s", strerror(errno)));
      _event_server_err_only_response(fd,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_VERSION,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
      goto cleanup;
    }

  enr.fd = fd;
  enr.responses = responses;

  /* Event names is not changeable - so no need for a lock */
  if (list_for_each(event_names, _event_names_callback, &enr) < 0)
    {
      _event_server_err_only_response(fd,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_VERSION,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
      goto cleanup;
    }

  if (_send_event_names(fd, responses) < 0)
    {
      _event_server_err_only_response(fd,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_VERSION,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
      goto cleanup;
    }

 end_response:
  if (_send_event_names_end_response(fd) < 0)
    goto cleanup;

 cleanup:
  if (responses)
    list_destroy(responses);
  Free(arg);
  /* ignore potential error, we're done sendin */
  close(fd);
  return NULL;
}
/*
 * _event_server_setup_socket
 *
 * Create and setup the server socket.  Do not use wrappers in this
 * function.  We want to give the server additional chances to
 * "survive" an error condition.
 *
 * Returns file descriptor on success, -1 on error
 *
 * Note: num parameter unused in this function, here only to match function prototype
 */
static int
_event_server_setup_socket(int num)
{
  struct sockaddr_in addr;
  int fd, optval = 1;

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
      CEREBRO_ERR(("socket: %s", strerror(errno)));
      goto cleanup;
    }

  /* For quick start/restart */
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) < 0)
    {
      CEREBRO_ERR(("setsockopt: %s", strerror(errno)));
      goto cleanup;
    }

  memset(&addr, '\0', sizeof(struct sockaddr_in));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(conf.event_server_port);
  addr.sin_addr.s_addr = htonl(INADDR_ANY);

  if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
    {
      CEREBRO_ERR(("bind: %s", strerror(errno)));
      goto cleanup;
    }

  if (listen(fd, CEREBROD_EVENT_SERVER_BACKLOG) < 0)
    {
      CEREBRO_ERR(("listen: %s", strerror(errno)));
      goto cleanup;
    }

  return fd;

 cleanup:
  /* ignore potential error, just return error */
  close(fd);
  return -1;
}
Esempio n. 7
0
/* 
 * _create_entry
 *
 * Create an entry in the node_states hash
 */
static int *
_create_entry(const char *nodename)
{
  char *nodePtr = NULL;
  int *state = NULL;

  if (!(state = (int *)malloc(sizeof(int))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }
  
  if (!(nodePtr = (char *)malloc(CEREBRO_MAX_NODENAME_LEN + 1)))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }

  strncpy(nodePtr, nodename, CEREBRO_MAX_NODENAME_LEN);
  
  if (!list_append(node_states_nodenames, nodePtr))
    {
      CEREBRO_DBG(("list_append: %s", strerror(errno)));
      goto cleanup;
    }

  if (!hash_insert(node_states, nodePtr, state))
    {
      CEREBRO_DBG(("hash_insert: %s", strerror(errno)));
      goto cleanup;
    }

  *state = UPDOWN_EVENT_STATE_INIT;
  return state;

 cleanup:
  free(nodePtr);
  free(state);
  return NULL;
}
/*
 * _event_names_callback
 *
 * Callback function to create event name responses
 *
 * Return 0 on success, -1 on error
 */
static int
_event_names_callback(void *data, void *arg)
{
  struct cerebrod_event_names_response_data *enr;
  struct cerebro_event_server_response *res = NULL;
  char *event_name;

  assert(data && arg);

  event_name = (char *)data;
  enr = (struct cerebrod_event_names_response_data *)arg;

  if (!(res = malloc(sizeof(struct cerebro_event_server_response))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }

  memset(res, '\0', sizeof(struct cerebro_event_server_response));
  res->version = CEREBRO_EVENT_SERVER_PROTOCOL_VERSION;
  res->err_code = CEREBRO_EVENT_SERVER_PROTOCOL_ERR_SUCCESS;
  res->end = CEREBRO_EVENT_SERVER_PROTOCOL_IS_NOT_LAST_RESPONSE;
  /* strncpy, b/c terminating character not required */
  strncpy(res->event_name, event_name, CEREBRO_MAX_EVENT_NAME_LEN);

  if (!list_append(enr->responses, res))
    {
      CEREBRO_ERR(("list_append: %s", strerror(errno)));
      goto cleanup;
    }

  return 0;

 cleanup:
  if (res)
    free(res);
  return -1;
}
Esempio n. 9
0
/* 
 * _create_event
 *
 * Create an event
 */
static struct cerebro_event *
_create_event(const char *nodename, int state)
{
  struct cerebro_event *event = NULL;

  if (!(event = (struct cerebro_event *)malloc(sizeof(struct cerebro_event))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }

  event->version = CEREBRO_EVENT_PROTOCOL_VERSION;
  event->err_code = CEREBRO_EVENT_SERVER_PROTOCOL_ERR_SUCCESS;
  strncpy(event->nodename, nodename, CEREBRO_MAX_NODENAME_LEN);
  strncpy(event->event_name, UPDOWN_EVENT_NAME, CEREBRO_MAX_EVENT_NAME_LEN);
  event->event_value_type = CEREBRO_DATA_VALUE_TYPE_INT32;
  event->event_value_len = sizeof(int32_t);
  if (!(event->event_value = malloc(sizeof(int32_t))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }
  
  *((int *)event->event_value) = state;

  return event;

 cleanup:
  if (event)
    {
      if (event->event_value)
        free(event->event_value);
      free(event);
    }
  return NULL;
}
/*
 * bytesin_metric_get_metric_value
 *
 * bytesin metric module get_metric_value function
 */
static int
bytesin_metric_get_metric_value(unsigned int *metric_value_type,
				unsigned int *metric_value_len,
				void **metric_value)
{
  u_int64_t bytesinval;
  u_int64_t *bytesinptr = NULL;
  int rv = -1;

  if (!metric_value_type || !metric_value_len || !metric_value)
    {
      CEREBRO_DBG(("invalid parameters"));
      return -1;
    }
  
  if (cerebro_metric_get_network(&bytesinval,
                                 NULL,
                                 NULL,
                                 NULL,
                                 NULL,
                                 NULL) < 0)
    goto cleanup;
  
  if (!(bytesinptr = (u_int64_t *)malloc(sizeof(u_int64_t))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }
  
  *bytesinptr = bytesinval;

  *metric_value_type = CEREBRO_DATA_VALUE_TYPE_U_INT64;
  *metric_value_len = sizeof(u_int64_t);
  *metric_value = (void *)bytesinptr;

  rv = 0;
 cleanup:
  if (rv < 0 && bytesinptr)
    free(bytesinptr);
  return rv;
}
Esempio n. 11
0
/*
 * txerrs_metric_get_metric_value
 *
 * txerrs metric module get_metric_value function
 */
static int
txerrs_metric_get_metric_value(unsigned int *metric_value_type,
			       unsigned int *metric_value_len,
			       void **metric_value)
{
  u_int32_t txerrsval;
  u_int32_t *txerrsptr = NULL;
  int rv = -1;

  if (!metric_value_type || !metric_value_len || !metric_value)
    {
      CEREBRO_DBG(("invalid parameters"));
      return -1;
    }
  
  if (cerebro_metric_get_network(NULL,
                                 NULL,
                                 NULL,
                                 NULL,
                                 NULL,
                                 &txerrsval) < 0)
    goto cleanup;
  
  if (!(txerrsptr = (u_int32_t *)malloc(sizeof(u_int32_t))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }
  
  *txerrsptr = txerrsval;

  *metric_value_type = CEREBRO_DATA_VALUE_TYPE_U_INT32;
  *metric_value_len = sizeof(u_int32_t);
  *metric_value = (void *)txerrsptr;

  rv = 0;
 cleanup:
  if (rv < 0 && txerrsptr)
    free(txerrsptr);
  return rv;
}
/*
 * genders_clusterlist_node_in_cluster
 *
 * genders clusterlist module node_in_cluster function
 */
static int
genders_clusterlist_node_in_cluster(const char *node)
{
  char nodebuf[CEREBRO_MAX_NODENAME_LEN+1];
  char *nodePtr = NULL;
  int flag;

  if (!gh)
    {
      CEREBRO_DBG(("gh null"));
      return -1;
    }

  if (!node)
    {
      CEREBRO_DBG(("invalid parameters"));
      return -1;
    }

  /* Shorten hostname if necessary */
  if (strchr(node, '.'))
    {
      char *p;

      memset(nodebuf, '\0', CEREBRO_MAX_NODENAME_LEN+1);
      strncpy(nodebuf, node, CEREBRO_MAX_NODENAME_LEN);
      p = strchr(nodebuf, '.');
      *p = '\0';
      nodePtr = nodebuf;
    }
  else
    nodePtr = (char *)node;

  if ((flag = genders_isnode(gh, nodePtr)) < 0)
    {
      CEREBRO_ERR(("genders_isnode: %s", genders_errormsg(gh)));
      return -1;
    }

  return flag;
}
/*
 * _event_server_response_send
 *
 * respond to the event_server_request with an error
 *
 * Return 0 on success, -1 on error
 */
static int
_event_server_response_send(int fd, 
                            struct cerebro_event_server_response *res)
{
  char buf[CEREBRO_MAX_PACKET_LEN];
  int res_len;

  assert(fd >= 0 && res);

  if ((res_len = _event_server_response_marshall(res, 
                                                 buf, 
                                                 CEREBRO_MAX_PACKET_LEN)) < 0)
    return -1;

  if (fd_write_n(fd, buf, res_len) < 0)
    {
      CEREBRO_ERR(("fd_write_n: %s", strerror(errno)));
      return -1;
    }

  return 0;
}
/*
 * swaptotal_metric_get_metric_value
 *
 * swaptotal metric module get_metric_value function
 */
static int
swaptotal_metric_get_metric_value(unsigned int *metric_value_type,
                                  unsigned int *metric_value_len,
                                  void **metric_value)
{
  u_int32_t swaptotalval;
  u_int32_t *swaptotalptr = NULL;
  int rv = -1;

  if (!metric_value_type || !metric_value_len || !metric_value)
    {
      CEREBRO_DBG(("invalid parameters"));
      return -1;
    }
  
  if (cerebro_metric_get_memory(NULL,
				NULL,
				&swaptotalval,
				NULL) < 0)
    goto cleanup;
  
  if (!(swaptotalptr = (u_int32_t *)malloc(sizeof(u_int32_t))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }
  
  *swaptotalptr = swaptotalval;

  *metric_value_type = CEREBRO_DATA_VALUE_TYPE_U_INT32;
  *metric_value_len = sizeof(u_int32_t);
  *metric_value = (void *)swaptotalptr;

  rv = 0;
 cleanup:
  if (rv < 0 && swaptotalptr)
    free(swaptotalptr);
  return rv;
}
/*
 * loadavg1_metric_get_metric_value
 *
 * loadavg1 metric module get_metric_value function
 */
static int
loadavg1_metric_get_metric_value(unsigned int *metric_value_type,
                                 unsigned int *metric_value_len,
                                 void **metric_value)
{
  float loadavg1;
  float *loadavgptr = NULL;
  int rv = -1;

  if (!metric_value_type || !metric_value_len || !metric_value)
    {
      CEREBRO_DBG(("invalid parameters"));
      return -1;
    }

  if (cerebro_metric_get_loadavgs(&loadavg1, NULL, NULL) < 0)
    goto cleanup;
  
  if (!(loadavgptr = (float *)malloc(sizeof(float))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }

  *loadavgptr = loadavg1;

  *metric_value_type = CEREBRO_DATA_VALUE_TYPE_FLOAT;
  *metric_value_len = sizeof(float);
  *metric_value = (void *)loadavgptr;

  rv = 0;
 cleanup:
  if (rv < 0 && loadavgptr)
    free(loadavgptr);
  return rv;
}
Esempio n. 16
0
/*
 * cerebro_metric_get_network
 *
 * Read network statistics
 */
int
cerebro_metric_get_network(u_int64_t *bytesin,
		       u_int64_t *bytesout,
		       u_int32_t *packetsin,
		       u_int32_t *packetsout,
		       u_int32_t *rxerrs,
		       u_int32_t *txerrs)
{
  int len, fd = -1;
  char buf[NETWORK_BUFLEN];
  struct timeval now;
  u_int64_t total_bytesin = 0;
  u_int64_t total_bytesout = 0;
  u_int32_t total_packetsin = 0;
  u_int32_t total_packetsout = 0;
  u_int32_t total_rxerrs = 0;
  u_int32_t total_txerrs = 0;
  char *parseptr;
  int rv = -1;

  if (gettimeofday(&now, NULL) < 0)
    {
      CEREBRO_ERR(("gettimeofday: %s", strerror(errno)));
      goto cleanup;
    }

  if ((now.tv_sec - last_read) > NETWORK_CACHETIMEOUT)
    {
      if ((fd = open(NETWORK_FILE, O_RDONLY, 0)) < 0)
	{
	  CEREBRO_ERR(("open: %s", strerror(errno)));
	  goto cleanup;
	}
      
      memset(buf, '\0', NETWORK_BUFLEN);
      if ((len = read(fd, buf, NETWORK_BUFLEN)) < 0)
	{
	  CEREBRO_ERR(("read: %s", strerror(errno)));
	  goto cleanup;
	}

      /* skip the first two lines of the file, which are headers, and
       * skip the local loopback interface 
       */
      parseptr = buf;
      if (!(parseptr = strstr(parseptr, "\n")))
	{
	  CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	  goto cleanup;
	}
      parseptr++;
      if (!(parseptr = strstr(parseptr, "\n")))
	{
	  CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	  goto cleanup;
	}
      parseptr++;
      if (!(parseptr = strstr(parseptr, "\n")))
	{
	  CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	  goto cleanup;
	}
      parseptr++;

      while (strstr(parseptr, "\n"))
	{
	  u_int64_t rx_bytes;
	  u_int64_t tx_bytes;
	  u_int32_t rx_packets, rx_errs;
	  u_int32_t tx_packets, tx_errs;
	  u_int32_t temp;
	  char *strptr;
  
	  /* skip the device name */
	  if (!(strptr = strstr(parseptr, ":")))
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
	  strptr++;
	  
	  rx_bytes = strtoull(strptr, &strptr, 10);
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
	  rx_packets = strtoul(strptr, &strptr, 10);
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
	  rx_errs = strtoul(strptr, &strptr, 10);
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
 	  temp = strtoul(strptr, &strptr, 10); /* drop */
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
 	  temp = strtoul(strptr, &strptr, 10); /* fifo */
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
 	  temp = strtoul(strptr, &strptr, 10); /* frame */
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
 	  temp = strtoul(strptr, &strptr, 10); /* compressed */
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
 	  temp = strtoul(strptr, &strptr, 10); /* multicast */
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
	  tx_bytes = strtoull(strptr, &strptr, 10);
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
	  tx_packets = strtoul(strptr, &strptr, 10);
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
	  tx_errs = strtoul(strptr, &strptr, 10);
	  if (!strptr)
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
		
	  total_bytesin += rx_bytes;
	  total_packetsin += rx_packets;
	  total_rxerrs += rx_errs;
	  total_bytesout += tx_bytes;
	  total_packetsout += tx_packets;
	  total_txerrs += tx_errs;

	  if (!(parseptr = strstr(parseptr, "\n")))
	    {
	      CEREBRO_ERR(("%s parse error", NETWORK_FILE));
	      goto cleanup;
	    }
	  parseptr++;
	}

      cache_bytesin = total_bytesin;
      cache_bytesout = total_bytesout;
      cache_packetsin = total_packetsin;
      cache_packetsout = total_packetsout;
      cache_rxerrs = total_rxerrs;
      cache_txerrs = total_txerrs;

      last_read = now.tv_sec;
    }

  if (bytesin)
    *bytesin = cache_bytesin;
  if (bytesout)
    *bytesout = cache_bytesout;
  if (packetsin)
    *packetsin = cache_packetsin;
  if (packetsout)
    *packetsout = cache_packetsout;
  if (rxerrs)
    *rxerrs = cache_rxerrs;
  if (txerrs)
    *txerrs = cache_txerrs;

  rv = 0;
 cleanup:
  /* ignore potential error, just return result */
  if (fd >= 0)
    close(fd);
  return rv;
}
Esempio n. 17
0
/* 
 * _load_config_file
 *
 * Read and load configuration file
 *
 * Returns data in structure and 0 on success, -1 on error
 */
static int
_load_config_file(struct cerebro_config *conf, unsigned int *errnum)
{
  char *config_file = NULL;

  struct conffile_option options[] =
    {
      /*
       * Libcerebro configuration
       */
      {
        "cerebro_metric_server",
        CONFFILE_OPTION_LIST_STRING,
        -1,
        _cb_cerebro_metric_server,
        CEREBRO_CONFIG_CEREBRO_METRIC_SERVERS_MAX,
        0,
        &(conf->cerebro_metric_server_flag),
        conf,
        0
      },
      {
        "cerebro_event_server",
        CONFFILE_OPTION_LIST_STRING,
        -1,
        _cb_cerebro_event_server,
        CEREBRO_CONFIG_CEREBRO_EVENT_SERVERS_MAX,
        0,
        &(conf->cerebro_event_server_flag),
        conf,
        0
      },
      {
	"cerebro_timeout_len", 
	CONFFILE_OPTION_INT, 
	-1,
	conffile_int, 
	1, 
	0, 
	&(conf->cerebro_timeout_len_flag),
	&(conf->cerebro_timeout_len), 
	0
      },
      {
	"cerebro_flags", 
	CONFFILE_OPTION_INT, 
	-1,
	conffile_int, 
	1, 
	0, 
	&(conf->cerebro_flags_flag),
	&(conf->cerebro_flags), 
	0
      },
      /*
       * Cerebrod configuration
       */
      {
	"cerebrod_heartbeat_frequency", 
	CONFFILE_OPTION_LIST_INT, 
	-1,
	_cb_cerebrod_heartbeat_freq, 
	1, 
	0, 
	&(conf->cerebrod_heartbeat_frequency_flag),
	conf, 
	0
      },
      {
	"cerebrod_speak", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_speak_flag),
	&conf->cerebrod_speak, 
	0
      },
      {
	"cerebrod_speak_message_config",
	CONFFILE_OPTION_LIST_STRING, 
	-1,
	_cb_cerebrod_speak_message_config, 
	CEREBRO_CONFIG_SPEAK_MESSAGE_CONFIG_MAX, 
	0, 
	&(conf->cerebrod_speak_message_config_flag),
	conf, 
	0
      },
      {
	"cerebrod_speak_message_ttl", 
	CONFFILE_OPTION_INT, 
	-1,
	conffile_int, 
	1, 
	0, 
	&(conf->cerebrod_speak_message_ttl_flag),
	&(conf->cerebrod_speak_message_ttl), 
	0
      },
      {
	"cerebrod_listen", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_listen_flag),
	&conf->cerebrod_listen, 
	0
      },
      {
	"cerebrod_listen_threads", 
	CONFFILE_OPTION_INT, 
	-1,
	conffile_int, 
	1, 
	0, 
	&(conf->cerebrod_listen_threads_flag),
	&(conf->cerebrod_listen_threads), 
	0
      },
      {
	"cerebrod_listen_message_config",
	CONFFILE_OPTION_LIST_STRING, 
	-1,
	_cb_cerebrod_listen_message_config, 
	CEREBRO_CONFIG_LISTEN_MESSAGE_CONFIG_MAX, 
	0, 
	&(conf->cerebrod_listen_message_config_flag),
	conf, 
	0
      },
      {
	"cerebrod_metric_controller", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_metric_controller_flag),
	&conf->cerebrod_metric_controller, 
	0
      },
      {
	"cerebrod_metric_server", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_metric_server_flag),
	&conf->cerebrod_metric_server, 
	0
      },
      {
	"cerebrod_metric_server_port", 
	CONFFILE_OPTION_INT, 
	-1,
	conffile_int, 
	1, 
	0, 
	&(conf->cerebrod_metric_server_port_flag),
	&(conf->cerebrod_metric_server_port), 
	0
      },
      {
	"cerebrod_event_server", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_event_server_flag),
	&conf->cerebrod_event_server, 
	0
      },
      {
	"cerebrod_event_server_port", 
	CONFFILE_OPTION_INT, 
	-1,
	conffile_int, 
	1, 
	0, 
	&(conf->cerebrod_event_server_port_flag),
	&(conf->cerebrod_event_server_port), 
	0
      },
      {
	"cerebrod_forward_message_config",
	CONFFILE_OPTION_LIST_STRING, 
	-1,
	_cb_cerebrod_forward_message_config, 
	CEREBRO_CONFIG_FORWARD_MESSAGE_CONFIG_MAX, 
	0, 
	&(conf->cerebrod_forward_message_config_flag),
	conf, 
	0
      },
      {
	"cerebrod_forward_message_ttl", 
	CONFFILE_OPTION_INT, 
	-1,
	conffile_int, 
	1, 
	0, 
	&(conf->cerebrod_forward_message_ttl_flag),
	&(conf->cerebrod_forward_message_ttl), 
	0
      },
      {
	"cerebrod_forward_host_accept", 
	CONFFILE_OPTION_LIST_STRING, 
	-1,
	_cb_cerebrod_forward_host_accept, 
	CEREBRO_CONFIG_FORWARD_HOST_ACCEPT_MAX, 
	0, 
	&(conf->cerebrod_forward_host_accept_flag),
	conf, 
	0
      },
      {
	"cerebrod_metric_module_exclude", 
	CONFFILE_OPTION_LIST_STRING, 
	-1,
	_cb_cerebrod_module_exclude, 
	CEREBRO_CONFIG_METRIC_MODULE_EXCLUDE_MAX, 
	0, 
	&(conf->cerebrod_metric_module_exclude_flag),
	conf, 
	0
      },
      {
	"cerebrod_monitor_module_exclude", 
	CONFFILE_OPTION_LIST_STRING, 
	-1,
	_cb_cerebrod_module_exclude, 
	CEREBRO_CONFIG_MONITOR_MODULE_EXCLUDE_MAX, 
	0, 
	&(conf->cerebrod_monitor_module_exclude_flag),
	conf, 
	0
      },
      {
	"cerebrod_event_module_exclude", 
	CONFFILE_OPTION_LIST_STRING, 
	-1,
	_cb_cerebrod_module_exclude, 
	CEREBRO_CONFIG_EVENT_MODULE_EXCLUDE_MAX, 
	0, 
	&(conf->cerebrod_event_module_exclude_flag),
	conf, 
	0
      },
      {
	"cerebrod_speak_debug", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_speak_debug_flag),
	&conf->cerebrod_speak_debug, 
	0
      },
      {
	"cerebrod_listen_debug", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_listen_debug_flag),
	&conf->cerebrod_listen_debug, 
	0
      },
      {
	"cerebrod_metric_controller_debug", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_metric_controller_debug_flag),
	&conf->cerebrod_metric_controller_debug, 
	0
      },
      {
	"cerebrod_metric_server_debug", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_metric_server_debug_flag),
	&conf->cerebrod_metric_server_debug, 
	0
      },
      {
	"cerebrod_event_server_debug", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_event_server_debug_flag),
	&conf->cerebrod_event_server_debug, 
	0
      },
      {
	"cerebrod_gettimeofday_workaround", 
	CONFFILE_OPTION_BOOL, 
	-1,
	conffile_bool, 
	1, 
	0, 
	&(conf->cerebrod_gettimeofday_workaround_flag),
	&conf->cerebrod_gettimeofday_workaround, 
	0
      },
#if CEREBRO_DEBUG
      {
	"cerebrod_alternate_hostname", 
	CONFFILE_OPTION_STRING, 
	-1,
	_cb_cerebrod_alternate_hostname, 
	1, 
	0, 
	&(conf->cerebrod_alternate_hostname_flag),
        conf,
	0
      },
#endif /* CEREBRO_DEBUG */
    };
  conffile_t cf = NULL;
  int num;
  
  if (!(cf = conffile_handle_create()))
    {
      CEREBRO_ERR(("conffile_handle_create"));
      if (errnum)
        *errnum = CEREBRO_ERR_OUTMEM;
      goto cleanup;
    }
  
  if (!config_debug_config_file)
    config_file = CEREBRO_CONFIG_FILE_DEFAULT;
  else
    config_file = config_debug_config_file;

  memset(conf, '\0', sizeof(struct cerebro_config));
  num = sizeof(options)/sizeof(struct conffile_option);
  if (conffile_parse(cf, config_file, options, num, NULL, 0, 0) < 0)
    {
      char buf[CONFFILE_MAX_ERRMSGLEN];

      /* Its not an error if the default configuration file doesn't exist */
      if (!strcmp(config_file, CEREBRO_CONFIG_FILE_DEFAULT) 
	  && conffile_errnum(cf) == CONFFILE_ERR_EXIST)
	goto out;

      if (conffile_errmsg(cf, buf, CONFFILE_MAX_ERRMSGLEN) < 0)
	CEREBRO_DBG(("conffile_parse: %d", conffile_errnum(cf)));
      else
	CEREBRO_DBG(("conffile_parse: %s", buf));
	
      if (errnum)
        *errnum = CEREBRO_ERR_CONFIG_FILE;
      goto cleanup;
    }
  
 out:
  conffile_handle_destroy(cf);
  return 0;
  
 cleanup:
  memset(conf, '\0', sizeof(struct cerebro_config));
  conffile_handle_destroy(cf);
  return -1;
}
/*
 * _event_server_service_connection
 *
 * Service a connection from a client to receive event packets.  Use
 * wrapper functions minimally, b/c we want to return errors to the
 * user instead of exitting with errors.
 *
 */
static void
_event_server_service_connection(int fd)
{
  int recv_len;
  struct cerebro_event_server_request req;
  struct cerebrod_event_connection_data *ecd = NULL;
  char buf[CEREBRO_MAX_PACKET_LEN];
  char event_name_buf[CEREBRO_MAX_EVENT_NAME_LEN+1];
  char *event_name_ptr = NULL;
  int32_t version;
  int *fdptr = NULL;
  List connections = NULL;

  assert(fd >= 0);

  memset(&req, '\0', sizeof(struct cerebro_event_server_request));
  if ((recv_len = receive_data(fd,
                               CEREBRO_EVENT_SERVER_REQUEST_PACKET_LEN,
                               buf,
                               CEREBRO_MAX_PACKET_LEN,
                               CEREBRO_EVENT_SERVER_PROTOCOL_CLIENT_TIMEOUT_LEN,
                               NULL)) < 0)
    goto cleanup;

  if (recv_len < sizeof(version))
    goto cleanup;

  if (_event_server_request_check_version(buf, recv_len, &version) < 0)
    {
      _event_server_err_only_response(fd,
                                      version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_VERSION_INVALID);
      goto cleanup;
    }

  if (recv_len != CEREBRO_EVENT_SERVER_REQUEST_PACKET_LEN)
    {
      _event_server_err_only_response(fd,
                                      version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_PACKET_INVALID);
      goto cleanup;
    }

  if (_event_server_request_unmarshall(&req, buf, recv_len) < 0)
    {
      _event_server_err_only_response(fd,
                                      version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_PACKET_INVALID);
      goto cleanup;
    }

  _event_server_request_dump(&req);

  /* Guarantee ending '\0' character */
  memset(event_name_buf, '\0', CEREBRO_MAX_EVENT_NAME_LEN+1);
  memcpy(event_name_buf, req.event_name, CEREBRO_MAX_EVENT_NAME_LEN);

  if (!strlen(event_name_buf))
    {
      _event_server_err_only_response(fd,
                                      req.version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_EVENT_INVALID);
      goto cleanup;
    }

  /* Is it the special event-names request */
  if (!strcmp(event_name_buf, CEREBRO_EVENT_NAMES))
    {
      pthread_t thread;
      pthread_attr_t attr;
      int *arg;

      Pthread_attr_init(&attr);
      Pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
      Pthread_attr_setstacksize(&attr, CEREBROD_THREAD_STACKSIZE);
      arg = Malloc(sizeof(int));
      *arg = fd;
      Pthread_create(&thread,
                     &attr,
                     _respond_with_event_names,
                     (void *)arg);
      Pthread_attr_destroy(&attr);
      return;
    }

  if (!event_names)
    {
      _event_server_err_only_response(fd,
                                      req.version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_EVENT_INVALID);
      goto cleanup;
    }

  /* Event names is not changeable - so no need for a lock */
  if (!(event_name_ptr = list_find_first(event_names, 
                                         _event_names_compare,
                                         event_name_buf)))
    {
      _event_server_err_only_response(fd,
                                      req.version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_EVENT_INVALID);
      goto cleanup;
    }
  
  if (!(ecd = (struct cerebrod_event_connection_data *)malloc(sizeof(struct cerebrod_event_connection_data))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      _event_server_err_only_response(fd,
                                      req.version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
      goto cleanup;
    }
  
  ecd->event_name = event_name_ptr;
  ecd->fd = fd;
  
  if (!(fdptr = (int *)malloc(sizeof(int))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      _event_server_err_only_response(fd,
                                      req.version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
      goto cleanup;
    }
  *fdptr = fd;

  Pthread_mutex_lock(&event_connections_lock);
  if (!list_append(event_connections, ecd))
    {
      CEREBRO_ERR(("list_append: %s", strerror(errno)));
      _event_server_err_only_response(fd,
                                      req.version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
      goto cleanup;
    }

  if (!(connections = Hash_find(event_connections_index, 
                                ecd->event_name)))
    {
      if (!(connections = list_create((ListDelF)free)))
        {
          CEREBRO_ERR(("list_create: %s", strerror(errno)));
          _event_server_err_only_response(fd,
                                          req.version,
                                          CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
          goto cleanup;
        }

      if (!Hash_insert(event_connections_index, ecd->event_name, connections))
        {
          CEREBRO_ERR(("Hash_insert: %s", strerror(errno)));
          _event_server_err_only_response(fd,
                                          req.version,
                                          CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
          list_destroy(connections);
          goto cleanup;
        }
    }

  if (!list_append(connections, fdptr))
    {
      CEREBRO_ERR(("list_append: %s", strerror(errno)));
      _event_server_err_only_response(fd,
                                      req.version,
                                      CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR);
      goto cleanup;
    }

  Pthread_mutex_unlock(&event_connections_lock);
  /* Clear this pointer so we know it's stored away in a list */
  fdptr = NULL;

  _event_server_err_only_response(fd,
                                  req.version,
                                  CEREBRO_EVENT_SERVER_PROTOCOL_ERR_SUCCESS);

  return;
  
 cleanup:
  if (ecd)
    free(ecd);
  if (fdptr)
    free(fdptr);
  /* ignore potential error, we're in the error path already */
  close(fd);
  return;
}
/* 
 * hostsfile_clusterlist_setup
 *
 * hostsfile clusterlist module setup function.  Open hostsfile, read
 * each line of the hostsfile, and save hosts into hosts list.
 */
static int 
hostsfile_clusterlist_setup(void)
{
  int len, fd = -1;
  char buf[HOSTSFILE_PARSE_BUFLEN];
  char *p;

  if (hosts)
    {
      CEREBRO_DBG(("hosts non-null"));
      return 0;
    }

  if (!(hosts = list_create((ListDelF)free)))
    {
      CEREBRO_ERR(("list_create: %s", strerror(errno)));
      goto cleanup;
    }

  if ((fd = open(CEREBRO_CLUSTERLIST_HOSTSFILE_DEFAULT, O_RDONLY)) < 0)
    {
      CEREBRO_ERR(("hostsfile '%s' cannot be opened: %s", 
                   CEREBRO_CLUSTERLIST_HOSTSFILE_DEFAULT, strerror(errno)));
      goto cleanup;
    }
 
  while ((len = _readline(fd, buf, HOSTSFILE_PARSE_BUFLEN)) > 0)
    {
      char *hostPtr;
      char *str;

      if (!(len = _remove_comments(buf, len)))
        continue;

      if (len < 0)
        goto cleanup;

      if (!(len = _remove_trailing_whitespace(buf, len)))
        continue;

      if (len < 0)
        goto cleanup;

      if (!(hostPtr = _move_past_whitespace(buf)))
        goto cleanup;

      if (hostPtr[0] == '\0')
        continue;

      if (strchr(hostPtr, ' ') || strchr(hostPtr, '\t'))
        {
          cerebro_err_output("hostsfile host contains whitespace");
          goto cleanup;
        }

      if (strlen(hostPtr) > CEREBRO_MAX_NODENAME_LEN)
        {
          cerebro_err_output("hostsfile node '%s' exceeds max length", hostPtr);
          goto cleanup;
        }
      
      /* Shorten hostname if necessary */
      if ((p = strchr(hostPtr, '.')))
        *p = '\0';

      if (!(str = strdup(hostPtr)))
        {
          CEREBRO_ERR(("strdup: %s", strerror(errno)));
          goto cleanup;
        }

      if (!list_append(hosts, str))
        {
          CEREBRO_ERR(("list_append: %s", strerror(errno)));
          goto cleanup;
        }
    }
  
  if (len < 0)
    goto cleanup;

  /* ignore potential error, just return result */
  close(fd);
  return 0;

 cleanup:
  /* ignore potential error, just return result */
  close(fd);
  if (hosts)
    list_destroy(hosts);
  hosts = NULL;
  return -1;
}
/*
 * _setup_metric_modules
 *
 * Setup metric modules. Under almost any circumstance, don't return a
 * -1 error, cerebro can go on without loading metric modules.
 *
 * Returns 1 if modules are loaded, 0 if not, -1 on error
 */
static int
_setup_metric_modules(void)
{
    int i;
#if CEREBRO_DEBUG
#if !WITH_CEREBROD_NO_THREADS
    int rv;
#endif /* !WITH_CEREBROD_NO_THREADS */
#endif /* CEREBRO_DEBUG */

    assert(metric_list);

#if CEREBRO_DEBUG
#if !WITH_CEREBROD_NO_THREADS
    /* Should be called with lock already set */
    rv = Pthread_mutex_trylock(&metric_list_lock);
    if (rv != EBUSY)
        CEREBRO_EXIT(("mutex not locked: rv=%d", rv));
#endif /* !WITH_CEREBROD_NO_THREADS */
#endif /* CEREBRO_DEBUG */

    if (!(metric_handle = metric_modules_load()))
    {
        CEREBRO_DBG(("metric_modules_load"));
        goto cleanup;
    }

    if ((metric_handle_count = metric_modules_count(metric_handle)) < 0)
    {
        CEREBRO_DBG(("metric_module_count failed"));
        goto cleanup;
    }

    if (!metric_handle_count)
    {
#if CEREBRO_DEBUG
        if (conf.debug && conf.speak_debug)
        {
#if !WITH_CEREBROD_NO_THREADS
            Pthread_mutex_lock(&debug_output_mutex);
#endif /* !WITH_CEREBROD_NO_THREADS */
            fprintf(stderr, "**************************************\n");
            fprintf(stderr, "* No Metric Modules Found\n");
            fprintf(stderr, "**************************************\n");
#if !WITH_CEREBROD_NO_THREADS
            Pthread_mutex_unlock(&debug_output_mutex);
#endif /* !WITH_CEREBROD_NO_THREADS */
        }
#endif /* CEREBRO_DEBUG */
        goto cleanup;
    }

    for (i = 0; i < metric_handle_count; i++)
    {
        struct cerebrod_speaker_metric_info *metric_info;
#if !WITH_CEREBROD_NO_THREADS
        Cerebro_metric_thread_pointer threadPtr;
#endif /* !WITH_CEREBROD_NO_THREADS */
        char *module_name, *metric_name;
        int metric_period;
        u_int32_t metric_flags;

        module_name = metric_module_name(metric_handle, i);

        if (conf.metric_module_exclude_len)
        {
            int found_exclude = 0;
            int j;

            for (j = 0; j < conf.metric_module_exclude_len; j++)
            {
                if (!strcasecmp(conf.metric_module_exclude[j], module_name))
                {
                    found_exclude++;
                    break;
                }
            }

            if (found_exclude)
            {
#if CEREBRO_DEBUG
                if (conf.debug && conf.speak_debug)
                {
#if !WITH_CEREBROD_NO_THREADS
                    Pthread_mutex_lock(&debug_output_mutex);
#endif /* !WITH_CEREBROD_NO_THREADS */
                    fprintf(stderr, "**************************************\n");
                    fprintf(stderr, "* Skip Metric Module: %s\n", module_name);
                    fprintf(stderr, "**************************************\n");
#if !WITH_CEREBROD_NO_THREADS
                    Pthread_mutex_unlock(&debug_output_mutex);
#endif /* !WITH_CEREBROD_NO_THREADS */
                }
#endif /* CEREBRO_DEBUG */
                CEREBRO_ERR(("Dropping metric module: %s", module_name));
                continue;
            }
        }

#if CEREBRO_DEBUG
        if (conf.debug && conf.speak_debug)
        {
#if !WITH_CEREBROD_NO_THREADS
            Pthread_mutex_lock(&debug_output_mutex);
#endif /* !WITH_CEREBROD_NO_THREADS */
            fprintf(stderr, "**************************************\n");
            fprintf(stderr, "* Setup Metric Module: %s\n", module_name);
            fprintf(stderr, "**************************************\n");
#if !WITH_CEREBROD_NO_THREADS
            Pthread_mutex_unlock(&debug_output_mutex);
#endif /* !WITH_CEREBROD_NO_THREADS */
        }
#endif /* CEREBRO_DEBUG */

        if (metric_module_setup(metric_handle, i) < 0)
        {
            CEREBRO_DBG(("metric_module_setup: %s", module_name));
            continue;
        }

        if (!(metric_name = metric_module_get_metric_name(metric_handle, i)))
        {
            CEREBRO_DBG(("metric_module_get_metric_name: %s", module_name));
            metric_module_cleanup(metric_handle, i);
            continue;
        }

        if (metric_module_get_metric_period(metric_handle, i, &metric_period) < 0)
        {
            CEREBRO_DBG(("metric_module_get_metric_period: %s", module_name));
            metric_module_cleanup(metric_handle, i);
            continue;
        }

        if (metric_module_get_metric_flags(metric_handle, i, &metric_flags) < 0)
        {
            CEREBRO_DBG(("metric_module_get_metric_flags: %s", module_name));
            metric_module_cleanup(metric_handle, i);
            continue;
        }

        if (metric_flags & CEREBRO_METRIC_MODULE_FLAGS_SEND_ON_PERIOD
                && metric_period <= 0)
        {
            CEREBRO_DBG(("metric module period invalid: %s", module_name));
            metric_module_cleanup(metric_handle, i);
            continue;
        }

        if (metric_module_send_message_function_pointer(metric_handle, i, &cerebrod_send_message) < 0)
        {
            CEREBRO_DBG(("metric_module_send_message_function_pointer: %s", module_name));
            metric_module_cleanup(metric_handle, i);
            continue;
        }

        metric_info = Malloc(sizeof(struct cerebrod_speaker_metric_info));
        /* No need to Strdup() the name in this case */
        metric_info->metric_name = metric_name;
        metric_info->metric_origin = CEREBROD_METRIC_SPEAKER_ORIGIN_MODULE;

        metric_info->metric_period = metric_period;
        metric_info->metric_flags = metric_flags;
        metric_info->index = i;

        /*
         * If metric period is < 0, it presumably never will be sent
         * (metric is likely handled by a metric_thread), so set
         * next_call_time to UINT_MAX.
         *
         * If this is a metric that will be piggy-backed on heartbeats,
         * then initialize next_call_time to 0, so the data is sent on
         * the first heartbeat
         *
         * If this is a metric that will not be piggy-backed on
         * heartbeats, set the next_call_time to UINT_MAX.  Let the
         * speaker logic decide when packets should be sent.
         */
        if (metric_info->metric_period < 0
                || metric_info->metric_flags & CEREBRO_METRIC_MODULE_FLAGS_SEND_ON_PERIOD)
            metric_info->next_call_time = UINT_MAX;
        else
            metric_info->next_call_time = 0;

        List_append(metric_list, metric_info);
        metric_list_size++;

#if !WITH_CEREBROD_NO_THREADS
        if ((threadPtr = metric_module_get_metric_thread(metric_handle, i)))
        {
            pthread_t thread;
            pthread_attr_t attr;

            Pthread_attr_init(&attr);
            Pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
            Pthread_attr_setstacksize(&attr, CEREBROD_THREAD_STACKSIZE);
            Pthread_create(&thread, &attr, threadPtr, NULL);
            Pthread_attr_destroy(&attr);
        }
#endif /* !WITH_CEREBROD_NO_THREADS */
    }

    if (!metric_list_size)
        goto cleanup;

    cerebrod_speaker_data_metric_list_sort();
    return 1;

cleanup:
    if (metric_handle)
    {
        /* unload will call module cleanup functions */
        metric_modules_unload(metric_handle);
        metric_handle = NULL;
        metric_handle_count = 0;
    }
    metric_list_size = 0;
    return 0;
}
/*
 * hostsfile_clusterlist_get_all_nodes
 *
 * hostsfile clusterlist module get_all_nodes function
 */
static int
hostsfile_clusterlist_get_all_nodes(char ***nodes)
{
  char **nodelist = NULL;
  char *node;
  ListIterator itr = NULL;
  int numnodes, i = 0;

  if (!hosts)
    {
      CEREBRO_DBG(("hosts null"));
      return -1;
    }

  if (!nodes)
    {     
      CEREBRO_DBG(("invalid parameters"));
      return -1;
    }

  if (!(numnodes = list_count(hosts)))
    return 0;

  if (!(itr = list_iterator_create(hosts)))
    {
      CEREBRO_ERR(("list_iterator_create: %s", strerror(errno)));
      goto cleanup;
    }

  if (!(nodelist = (char **)malloc(sizeof(char *) * (numnodes + 1))))
    {
      CEREBRO_ERR(("malloc: %s", strerror(errno)));
      goto cleanup;
    }
  memset(nodelist, '\0', sizeof(char *) * (numnodes + 1));

  while ((node = list_next(itr)) && (i < numnodes))
    {
      if (!(nodelist[i] = strdup(node)))
        {
          CEREBRO_ERR(("strdup: %s", strerror(errno)));
          goto cleanup;
        }
      i++;
    }

  if (i > numnodes)
    {
      CEREBRO_DBG(("iterator count error"));
      goto cleanup;
    }

  list_iterator_destroy(itr);

  *nodes = nodelist;
  return numnodes;

 cleanup:
  if (itr)
    list_iterator_destroy(itr);
  if (nodelist)
    {
      int j;
      for (j = 0; j < i; j++)
        free(nodelist[j]);
      free(nodelist);
    }
  return -1;
}