Ejemplo n.º 1
0
/*
 * _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)
    {
      CEREBROD_ERR(("fd_write_n: %s", strerror(errno)));
      return -1;
    }

  return 0;
}
Ejemplo n.º 2
0
/*
 * _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)))
    {
      CEREBROD_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;
}
Ejemplo n.º 3
0
/*
 * _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)
    {
      CEREBROD_ERR(("socket: %s", strerror(errno)));
      goto cleanup;
    }

  /* For quick start/restart */
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) < 0)
    {
      CEREBROD_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)
    {
      CEREBROD_ERR(("bind: %s", strerror(errno)));
      goto cleanup;
    }

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

  return fd;

 cleanup:
  /* ignore potential error, just return error */
  close(fd);
  return -1;
}
Ejemplo n.º 4
0
/*
 * _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))))
    {
      CEREBROD_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))
    {
      CEREBROD_ERR(("list_append: %s", strerror(errno)));
      goto cleanup;
    }

  return 0;

 cleanup:
  if (res)
    free(res);
  return -1;
}
Ejemplo n.º 5
0
/*
 * _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)
    {
      CEREBROD_ERR(("fd_write_n: %s", strerror(errno)));
      return -1;
    }

  return 0;
}
Ejemplo n.º 6
0
/*
 * Under almost any circumstance, don't return a -1 error, cerebro can
 * go on without loading monitor modules. The listener_data_init_lock
 * should already be set.
 */
int
cerebrod_event_modules_setup(void)
{
  int i, event_module_count, event_index_len, event_index_count = 0;
  struct cerebrod_event_module_list *el = NULL;
#if CEREBRO_DEBUG
  int rv;
#endif /* CEREBRO_DEBUG */

  assert(listener_data);

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

  if (!conf.event_server)
    return 0;

  if (!(event_handle = event_modules_load()))
    {
      CEREBROD_DBG(("event_modules_load"));
      goto cleanup;
    }

  if ((event_module_count = event_modules_count(event_handle)) < 0)
    {
      CEREBROD_DBG(("event_modules_count"));
      goto cleanup;
    }

  if (!event_module_count)
    {
      if (conf.debug && conf.event_server_debug)
        {
          Pthread_mutex_lock(&debug_output_mutex);
          fprintf(stderr, "**************************************\n");
          fprintf(stderr, "* No Event Modules Found\n");
          fprintf(stderr, "**************************************\n");
          Pthread_mutex_unlock(&debug_output_mutex);
        }
      goto cleanup;
    }

  /* Each event module may want multiple metrics and/or offer multiple
   * event names.  We'll assume there will never be more than 2 per
   * event module, and that will be enough to avoid all hash
   * collisions.
   */
  event_index_len = event_module_count * 2;

  event_index = Hash_create(event_index_len,
                            (hash_key_f)hash_key_string,
                            (hash_cmp_f)strcmp,
                            (hash_del_f)_cerebrod_event_module_list_destroy);

  event_names = List_create((ListDelF)_Free);

  event_module_timeouts = List_create((ListDelF)_cerebrod_event_module_timeout_data_destroy);
  event_module_timeout_index = Hash_create(event_module_count,
					   (hash_key_f)hash_key_string,
					   (hash_cmp_f)strcmp,
					   (hash_del_f)list_destroy);

  for (i = 0; i < event_module_count; i++)
    {
      struct cerebrod_event_module *event_module;
      char *module_name, *module_metric_names, *module_event_names;
      char *metricPtr, *metricbuf;
      char *eventnamePtr, *eventbuf;
      int timeout;

      module_name = event_module_name(event_handle, i);

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

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

          if (found_exclude)
            {
              if (conf.debug && conf.event_server_debug)
                {
                  Pthread_mutex_lock(&debug_output_mutex);
                  fprintf(stderr, "**************************************\n");
                  fprintf(stderr, "* Skip Event Module: %s\n", module_name);
                  fprintf(stderr, "**************************************\n");
                  Pthread_mutex_unlock(&debug_output_mutex);
                }
              CEREBROD_ERR(("Dropping event module: %s", module_name));
              continue;
            }
        }

      if (conf.debug && conf.event_server_debug)
        {
          Pthread_mutex_lock(&debug_output_mutex);
          fprintf(stderr, "**************************************\n");
          fprintf(stderr, "* Setup Event Module: %s\n", module_name);
          fprintf(stderr, "**************************************\n");
          Pthread_mutex_unlock(&debug_output_mutex);
        }

      if (event_module_setup(event_handle, i) < 0)
        {
          CEREBROD_DBG(("event_module_setup failed: %s", module_name));
          continue;
        }

      if (!(module_metric_names = event_module_metric_names(event_handle, i)) < 0)
        {
          CEREBROD_DBG(("event_module_metric_names failed: %s", module_name));
          event_module_cleanup(event_handle, i);
          continue;
        }

      if (!(module_event_names = event_module_event_names(event_handle, i)) < 0)
        {
          CEREBROD_DBG(("event_module_event_names failed: %s", module_name));
          event_module_cleanup(event_handle, i);
          continue;
        }
      
      if ((timeout = event_module_timeout_length(event_handle, i)) < 0)
        {
          CEREBROD_DBG(("event_module_timeout_length failed: %s", module_name));
          event_module_cleanup(event_handle, i);
          continue;
        }

      event_module = Malloc(sizeof(struct cerebrod_event_module_info));
      event_module->metric_names = Strdup(module_metric_names);
      event_module->event_names = Strdup(module_event_names);
      event_module->index = i;
      Pthread_mutex_init(&(event_module->event_lock), NULL);

      /* The monitoring module may support multiple metrics */
          
      metricPtr = strtok_r(event_module->metric_names, ",", &metricbuf);
      while (metricPtr)
        {
          if (!(el = Hash_find(event_index, metricPtr)))
            {
              el = (struct cerebrod_event_module_list *)Malloc(sizeof(struct cerebrod_event_module_list));
              el->event_list = List_create((ListDelF)_cerebrod_event_module_info_destroy);
              Pthread_mutex_init(&(el->event_list_lock), NULL);

              List_append(el->event_list, event_module);
              Hash_insert(event_index, metricPtr, el);
              event_index_count++;
            }
          else
            List_append(el->event_list, event_module);
          
          metricPtr = strtok_r(NULL, ",", &metricbuf);
        }

      /* The monitoring module may support multiple event names */

      eventnamePtr = strtok_r(event_module->event_names, ",", &eventbuf);
      while (eventnamePtr)
        {
          if (!list_find_first(event_names,
                               (ListFindF)_cerebrod_name_strcmp,
                               eventnamePtr))
            {
              List_append(event_names, eventnamePtr);
              if (conf.debug && conf.event_server_debug)
                {
                  Pthread_mutex_lock(&debug_output_mutex);
                  fprintf(stderr, "**************************************\n");
                  fprintf(stderr, "* Event Name: %s\n", eventnamePtr);
                  fprintf(stderr, "**************************************\n");
                  Pthread_mutex_unlock(&debug_output_mutex);
                }
            }
          eventnamePtr = strtok_r(NULL, ",", &eventbuf);
        }

      if (timeout)
        {
          struct cerebrod_event_module_timeout_data *mtd;
          List modules_list;

          if (!(mtd = List_find_first(event_module_timeouts, 
                                      _event_module_timeout_data_find_callback, 
                                      &timeout)))
            {
              char strbuf[64];

              mtd = (struct cerebrod_event_module_timeout_data *)Malloc(sizeof(struct cerebrod_event_module_timeout_data));
              mtd->timeout = timeout;
              snprintf(strbuf, 64, "%d", timeout);
              mtd->timeout_str = Strdup(strbuf);

              List_append(event_module_timeouts, mtd);
              
              if (timeout < event_module_timeout_min)
                event_module_timeout_min = timeout;
            }

          if (!(modules_list = Hash_find(event_module_timeout_index, 
                                         mtd->timeout_str)))
            {
              modules_list = List_create((ListDelF)NULL);
              List_append(modules_list, event_module);
              Hash_insert(event_module_timeout_index,
                          mtd->timeout_str,
                          modules_list);
            }
          else
            List_append(modules_list, event_module);
        }
    }
  
  List_sort(event_module_timeouts, _event_module_timeout_data_compare);

  if (!event_index_count)
    goto cleanup;

  if (_setup_event_node_timeout_data() < 0)
    goto cleanup;

  /* 
   * Since the cerebrod listener is started before any of the event
   * threads (node_timeout, queue_monitor, server), this must be
   * created in here (which is called by the listener) to avoid a
   * possible race of modules creating events before the event_queue
   * is created.
   */
  event_queue = List_create((ListDelF)cerebrod_event_to_send_destroy);

  return 1;
  
 cleanup:
  if (event_handle)
    {
      event_modules_unload(event_handle);
      event_handle = NULL;
    }
  if (event_index)
    {
      Hash_destroy(event_index);
      event_index = NULL;
    }
  if (event_names)
    {
      List_destroy(event_names);
      event_names = NULL;
    }
  return 0;
}
Ejemplo n.º 7
0
void *
cerebrod_listener(void *arg)
{
  char buf[CEREBRO_MAX_PACKET_LEN];

  _cerebrod_listener_initialize();

  for (;;)
    {
      struct cerebrod_message *msg;
      char nodename_buf[CEREBRO_MAX_NODENAME_LEN+1];
      char nodename_key[CEREBRO_MAX_NODENAME_LEN+1];
      struct timeval tv;
      int in_cluster_flag, i, count;
      fd_set readfds;
      int recv_len = 0;
      int maxfd = 0;

      FD_ZERO(&readfds);
      Pthread_mutex_lock(&listener_fds_lock);
      for (i = 0; i < conf.listen_message_config_len; i++)
        {
          if (listener_fds[i] > maxfd)
            maxfd = listener_fds[i];
          FD_SET(listener_fds[i], &readfds);
        }

      count = Select(maxfd + 1, &readfds, NULL, NULL, NULL);

      for (i = 0; i < conf.listen_message_config_len; i++)
        {
          if (FD_ISSET(listener_fds[i], &readfds))
            {
              if ((recv_len = recvfrom(listener_fds[i], 
                                       buf, 
                                       CEREBRO_MAX_PACKET_LEN, 
                                       0, 
                                       NULL, 
                                       NULL)) < 0)
                listener_fds[i] = cerebrod_reinit_socket(listener_fds[i], 
                                                         i,
                                                         _listener_setup_socket, 
                                                         "listener: recvfrom");
              break;
            }
        }
      Pthread_mutex_unlock(&listener_fds_lock);

      /* No packet read */
      if (recv_len <= 0)
	continue;

      if (recv_len >= CEREBRO_MAX_PACKET_LEN)
        {
	  CEREBROD_DBG(("received truncated packet"));
          continue;
        }

      if (_cerebrod_message_check_version(buf, recv_len) < 0)
        {
	  CEREBROD_DBG(("received invalid version packet"));
          continue;
        }

      if (!(msg = _cerebrod_message_unmarshall(buf, recv_len)))
        {
	  CEREBROD_DBG(("received unmarshallable packet"));
          continue;
        }

      _cerebrod_message_dump(msg, "Received Message");
      
      /* Guarantee ending '\0' character */
      memset(nodename_buf, '\0', CEREBRO_MAX_NODENAME_LEN+1);
      memcpy(nodename_buf, msg->nodename, CEREBRO_MAX_NODENAME_LEN);

      if (!strlen(nodename_buf))
        {
          CEREBROD_DBG(("received null nodename"));
          cerebrod_message_destroy(msg);
          continue;
        }

      if (found_clusterlist_module)
        {
          if ((in_cluster_flag = clusterlist_module_node_in_cluster(clusterlist_handle,
                                                                    nodename_buf)) < 0)
            CEREBROD_EXIT(("clusterlist_module_node_in_cluster: %s", nodename_buf));

          /* Second chance, is this data being forwarded from another host */
          if (!in_cluster_flag)
            {
              if (Hostlist_find(conf.forward_host_accept, nodename_buf) >= 0)
                in_cluster_flag++;
            }
        }
      else
        /* must assume it is in the cluster */
        /* Note, there is no need to handle 'forward_host_accept' under this case, 
         * since we don't know if it is in the cluster or not anyways.
         */
        in_cluster_flag = 1;
      
      if (!in_cluster_flag)
	{
	  CEREBROD_DBG(("received non-cluster packet: %s", nodename_buf));
          cerebrod_message_destroy(msg);
	  continue;
	}
      
      memset(nodename_key, '\0', CEREBRO_MAX_NODENAME_LEN+1);

      if (found_clusterlist_module)
        {
          if (clusterlist_module_get_nodename(clusterlist_handle,
                                              nodename_buf,
                                              nodename_key, 
                                              CEREBRO_MAX_NODENAME_LEN+1) < 0)
            {
              CEREBROD_DBG(("clusterlist_module_get_nodename: %s", nodename_buf));
              cerebrod_message_destroy(msg);
              continue;
            }
        }
      else
        memcpy(nodename_key, nodename_buf, CEREBRO_MAX_NODENAME_LEN+1);

      Gettimeofday(&tv, NULL);
      cerebrod_listener_data_update(nodename_key, msg, tv.tv_sec);

      /* Forward data as necessary.  Note, there is no need to
       * marshall data, it should already be marshalled when we
       * read it earlier.
       */
      for (i = 0; i < conf.forward_message_config_len; i++)
        {
          /* if the forward destination is local to the machine, don't forward */
          if (conf.forward_message_config[i].ip_is_local)
            continue;

          if (!forwarding_info[i].hosts
              || hostlist_find(forwarding_info[i].hosts, nodename_key) >= 0)
            {
              struct sockaddr *addr;
              struct sockaddr_in msgaddr;
              unsigned int addrlen;
              int rv;
              
              memset(&msgaddr, '\0', sizeof(struct sockaddr_in));
              msgaddr.sin_family = AF_INET;
              msgaddr.sin_port = htons(conf.forward_message_config[i].destination_port);
              memcpy(&msgaddr.sin_addr,
                     &conf.forward_message_config[i].ip_in_addr,
                     sizeof(struct in_addr));
              
              addr = (struct sockaddr *)&msgaddr;
              addrlen = sizeof(struct sockaddr_in);
              
              _cerebrod_message_dump(msg, "Forwarding Message");

              Pthread_mutex_lock(&forwarding_info[i].lock);
              
              if ((rv = sendto(forwarding_info[i].fd,
                               buf,
                               recv_len,
                               0,
                               addr,
                               addrlen)) != recv_len)
                {
                  if (rv < 0)
                    forwarding_info[i].fd = cerebrod_reinit_socket(forwarding_info[i].fd,
                                                                   i,
                                                                   _forwarding_setup_socket,
                                                                   "forwarding: sendto");
                  else
                    CEREBROD_ERR(("sendto: invalid bytes sent"));
                }
              
              Pthread_mutex_unlock(&forwarding_info[i].lock);
            }
        }

      cerebrod_message_destroy(msg);
    }

  return NULL;			/* NOT REACHED */
}
Ejemplo n.º 8
0
/* 
 * _forwarding_setup_socket
 *
 * Create and setup the forwarding socket.  Do not use wrappers in
 * this function.  We want to give the daemon additional chances to
 * "survive" an error condition.
 *
 * In this socket setup function, 'num' is used as the message config
 * and forwarding info index.
 * 
 * Returns file descriptor on success, -1 on error
 */
static int
_forwarding_setup_socket(int num)
{
  struct sockaddr_in addr;
  unsigned int optlen;
  int fd, optval = 1;

  assert(num >= 0 && num < conf.forward_message_config_len);

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

  if (conf.forward_message_config[num].ip_is_multicast)
    {
      /* XXX: Probably lots of portability problems here */
      struct ip_mreqn imr;

      memset(&imr, '\0', sizeof(struct ip_mreqn));
      memcpy(&imr.imr_multiaddr,
             &conf.forward_message_config[num].ip_in_addr,
             sizeof(struct in_addr));
      memcpy(&imr.imr_address,
             &conf.forward_message_config[num].network_interface_in_addr,
             sizeof(struct in_addr));
      imr.imr_ifindex = conf.forward_message_config[num].network_interface_index;

      optlen = sizeof(struct ip_mreqn);
      if (setsockopt(fd, SOL_IP, IP_MULTICAST_IF, &imr, optlen) < 0)
        {
          CEREBROD_ERR(("setsockopt: %s", strerror(errno)));
          goto cleanup;
        }

      /* Turn off loopback for forwarding, since we already 
       * have the data.
       */
      optval = 0;
      optlen = sizeof(optval);
      if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &optval, optlen) < 0)
        {
          CEREBROD_ERR(("setsockopt: %s", strerror(errno)));
          goto cleanup;
        }

      optval = conf.forward_message_ttl;
      optlen = sizeof(optval);
      if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &optval, optlen) < 0)
        {
          CEREBROD_ERR(("setsockopt: %s", strerror(errno)));
          goto cleanup;
        }
    }

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

  memset(&addr, '\0', sizeof(struct sockaddr_in));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(conf.forward_message_config[num].source_port);
  memcpy(&addr.sin_addr,
         &conf.forward_message_config[num].network_interface_in_addr,
         sizeof(struct in_addr));
  if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
    {
      CEREBROD_ERR(("bind: %s", strerror(errno)));
      goto cleanup;
    }

  return fd;

 cleanup:
  /* ignore potential error, we're in the error path already */
  close(fd);
  return -1;
}
Ejemplo n.º 9
0
/*
 * _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))))
    {
      CEREBROD_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))))
    {
      CEREBROD_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))
    {
      CEREBROD_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)))
        {
          CEREBROD_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))
        {
          CEREBROD_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))
    {
      CEREBROD_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;
}
Ejemplo n.º 10
0
/* 
 * Under almost any circumstance, don't return a -1 error, cerebro can
 * go on without loading monitor modules. The listener_data_init_lock
 * should already be set.
 */
int
cerebrod_monitor_modules_setup(void)
{
  int i, monitor_module_count, monitor_index_len, monitor_index_count = 0;
  struct cerebrod_monitor_module_list *ml = NULL;
#if CEREBRO_DEBUG
  int rv;
#endif /* CEREBRO_DEBUG */

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

  if (!(monitor_handle = monitor_modules_load()))
    {
      CEREBROD_DBG(("monitor_modules_load"));
      goto cleanup;
    }

  if ((monitor_module_count = monitor_modules_count(monitor_handle)) < 0)
    {
      CEREBROD_DBG(("monitor_modules_count"));
      goto cleanup;
    }

  if (!monitor_module_count)
    {
      if (conf.debug && conf.listen_debug)
        {
          Pthread_mutex_lock(&debug_output_mutex);
          fprintf(stderr, "**************************************\n");
          fprintf(stderr, "* No Monitor Modules Found\n");
          fprintf(stderr, "**************************************\n");
          Pthread_mutex_unlock(&debug_output_mutex);
        }
      goto cleanup;
    }
  
  /* Each monitor module may wish to monitor multiple metrics.  We'll
   * assume there will never be more than 2 metrics per monitor module, and
   * that will be enough to avoid all hash collisions.
   */
  monitor_index_len = monitor_module_count * 2;

  monitor_index = Hash_create(monitor_index_len, 
                              (hash_key_f)hash_key_string, 
                              (hash_cmp_f)strcmp, 
                              (hash_del_f)_cerebrod_monitor_module_list_destroy);

  for (i = 0; i < monitor_module_count; i++)
    {
      struct cerebrod_monitor_module_info *monitor_module;
      char *module_name, *metric_names;
      char *metricPtr, *metricbuf;

      module_name = monitor_module_name(monitor_handle, i);

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

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

          if (found_exclude)
            {
              if (conf.debug && conf.listen_debug)
                {
                  Pthread_mutex_lock(&debug_output_mutex);
                  fprintf(stderr, "**************************************\n");
                  fprintf(stderr, "* Skip Monitor Module: %s\n", module_name);
                  fprintf(stderr, "**************************************\n");
                  Pthread_mutex_unlock(&debug_output_mutex);
                }
              CEREBROD_ERR(("Dropping monitor module: %s", module_name));
              continue;
            }
        }

      if (conf.debug && conf.listen_debug)
        {
          Pthread_mutex_lock(&debug_output_mutex);
          fprintf(stderr, "**************************************\n");
          fprintf(stderr, "* Setup Monitor Module: %s\n", module_name);
          fprintf(stderr, "**************************************\n");
          Pthread_mutex_unlock(&debug_output_mutex);
        }

      if (monitor_module_setup(monitor_handle, i) < 0)
        {
          CEREBROD_DBG(("monitor_module_setup failed: %s", module_name));
          continue;
        }

      if (!(metric_names = monitor_module_metric_names(monitor_handle, i)) < 0)
        {
          CEREBROD_DBG(("monitor_module_metric_names failed: %s", module_name));
          monitor_module_cleanup(monitor_handle, i);
          continue;
        }

      monitor_module = Malloc(sizeof(struct cerebrod_monitor_module_info));
      monitor_module->metric_names = Strdup(metric_names);
      monitor_module->index = i;
      Pthread_mutex_init(&(monitor_module->monitor_lock), NULL);

      /* The monitoring module may support multiple metrics */
          
      metricPtr = strtok_r(monitor_module->metric_names, ",", &metricbuf);
      while (metricPtr)
        {
          if (!(ml = Hash_find(monitor_index, metricPtr)))
            {
              ml = (struct cerebrod_monitor_module_list *)Malloc(sizeof(struct cerebrod_monitor_module_list));
              ml->monitor_list = List_create((ListDelF)_cerebrod_monitor_module_info_destroy);
              Pthread_mutex_init(&(ml->monitor_list_lock), NULL);

              List_append(ml->monitor_list, monitor_module);
              Hash_insert(monitor_index, metricPtr, ml);
              monitor_index_count++;
            }
          else
            List_append(ml->monitor_list, monitor_module);
          
          metricPtr = strtok_r(NULL, ",", &metricbuf);
        }
    }

  if (!monitor_index_count)
    goto cleanup;

  return 1;

 cleanup:
  if (monitor_handle)
    {
      monitor_modules_unload(monitor_handle);
      monitor_handle = NULL;
    }
  if (monitor_index)
    {
      Hash_destroy(monitor_index);
      monitor_index = NULL;
    }
  return 0;
}
Ejemplo n.º 11
0
/* 
 * _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)
    CEREBROD_EXIT(("mutex not locked: rv=%d", rv));
#endif /* !WITH_CEREBROD_NO_THREADS */
#endif /* CEREBRO_DEBUG */

  if (!(metric_handle = metric_modules_load()))
    {
      CEREBROD_DBG(("metric_modules_load"));
      goto cleanup;
    }
  
  if ((metric_handle_count = metric_modules_count(metric_handle)) < 0)
    {
      CEREBROD_DBG(("metric_module_count failed"));
      goto cleanup;
    }
  
  if (!metric_handle_count)
    {
      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 */
        }
      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 (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 */
                }
              CEREBROD_ERR(("Dropping metric module: %s", module_name));
              continue;
            }
        }
      
      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 */
        }

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

      if (!(metric_name = metric_module_get_metric_name(metric_handle, i)))
        {
          CEREBROD_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)
        {
          CEREBROD_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)
        {
          CEREBROD_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)
        {
          CEREBROD_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)
        {
          CEREBROD_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;
}