Ejemplo n.º 1
0
void 
cerebrod_event_update_node_received_time(struct cerebrod_node_data *nd,
                                         u_int32_t received_time)
{
  struct cerebrod_event_node_timeout *ntd;
#if CEREBRO_DEBUG
  int rv;
#endif /* CEREBRO_DEBUG */

  assert(nd);
  assert(received_time);

  if (!event_index)
    return;

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

  Pthread_mutex_lock(&event_node_timeout_data_lock);
  if ((ntd = Hash_find(event_node_timeout_data_index, nd->nodename)))
    {
      ntd->last_received_time = received_time;
      ntd->timeout_occurred = 0;
    }
  Pthread_mutex_unlock(&event_node_timeout_data_lock);
}
Ejemplo n.º 2
0
/* 
 * _hostrange_output
 *
 * Output metric data in hostrange format.  The algorithm involves
 * using the metric_value as a hash key.  Each hash item will then
 * store the hosts with the same metric_value/key.
 */
static void
_hostrange_output(List l)
{
#if CEREBRO_DEBUG
  const char *func = __FUNCTION__;
#endif /* CEREBRO_DEBUG */
  struct node_metric_data *data = NULL;
  ListIterator litr = NULL;
  unsigned int count;
  hash_t h;

  assert(l);

  count = List_count(l);

#if CEREBRO_DEBUG
  if (!count)
    err_exit("%s: invalid count", func);
#endif /* CEREBRO_DEBUG */

  h = Hash_create(count, 
                  (hash_key_f)hash_key_string,
                  (hash_cmp_f)strcmp,
                  (hash_del_f)_hostrange_data_destroy);

  litr = List_iterator_create(l);

  while ((data = list_next(litr)))
    {
      char buf[CEREBRO_STAT_BUFLEN];
      struct hostrange_data *hd;

      _metric_value_str(data->metric_value_type,
                        data->metric_value_len,
                        data->metric_value, 
                        buf, 
                        CEREBRO_STAT_BUFLEN);

      if (!(hd = Hash_find(h, buf)))
        {
          hd = Malloc(sizeof(struct hostrange_data));
          hd->hl = Hostlist_create(NULL);
          hd->key = Strdup(buf);

          Hash_insert(h, hd->key, hd);
        }

      Hostlist_push(hd->hl, data->nodename);
    }

  Hash_for_each(h, _hostrange_output_data, NULL);

  /* No need to destroy list iterator, caller will destroy List */
  Hash_destroy(h);
}
Ejemplo n.º 3
0
/* 
 * cerebrod_monitor_modules_update
 *
 * Send metric data to the appropriate monitor modules, if necessary.
 * The struct cerebrod_node_data lock should already be locked.
 */
void
cerebrod_monitor_modules_update(const char *nodename,
                                struct cerebrod_node_data *nd,
                                const char *metric_name,
                                struct cerebrod_message_metric *mm)
{
  struct cerebrod_monitor_module_info *monitor_module;
  struct cerebrod_monitor_module_list *ml;
#if CEREBRO_DEBUG
  int rv;
#endif /* CEREBRO_DEBUG */
  
  assert(nodename && nd && metric_name && mm);

  if (!monitor_index)
    return;

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

  if ((ml = Hash_find(monitor_index, metric_name)))
    {
      ListIterator itr = NULL;

      Pthread_mutex_lock(&(ml->monitor_list_lock));
      itr = List_iterator_create(ml->monitor_list);
      Pthread_mutex_unlock(&(ml->monitor_list_lock));

      while ((monitor_module = list_next(itr)))
	{
	  Pthread_mutex_lock(&monitor_module->monitor_lock);
	  monitor_module_metric_update(monitor_handle,
				       monitor_module->index,
				       nodename,
				       metric_name,
				       mm->metric_value_type,
				       mm->metric_value_len,
				       mm->metric_value);
	  Pthread_mutex_unlock(&monitor_module->monitor_lock);
	}

      Pthread_mutex_lock(&(ml->monitor_list_lock));
      List_iterator_destroy(itr);
      Pthread_mutex_unlock(&(ml->monitor_list_lock));
    }
}
Ejemplo n.º 4
0
static void
_delete_event_connection_fd(int fd)
{
  struct cerebrod_event_connection_data *ecd;
  ListIterator eitr;
#if CEREBRO_DEBUG
  int rv;
#endif /* CEREBRO_DEBUG */

  assert(fd >= 0);

#if CEREBRO_DEBUG
  /* Should be called with lock already set */
  rv = Pthread_mutex_trylock(&event_connections_lock);
  if (rv != EBUSY)
    CEREBROD_EXIT(("mutex not locked: rv=%d", rv));
#endif /* CEREBRO_DEBUG */
  
  eitr = List_iterator_create(event_connections);
  while ((ecd = list_next(eitr)))
    {
      if (ecd->fd == fd)
        {
          List connections;
          if ((connections = Hash_find(event_connections_index, 
                                       ecd->event_name)))
            {
              ListIterator citr;
              int *fdPtr;

              citr = List_iterator_create(connections);
              while ((fdPtr = list_next(citr)))
                {
                  if (*fdPtr == fd) 
                    {
                      List_delete(citr);
                      break;
                    }
                }
              List_iterator_destroy(citr);
            }
          List_delete(eitr);
          break;
        }
    }
  List_iterator_destroy(eitr);
}
Ejemplo n.º 5
0
void *thread_operator(void *attr){
    int rc;
    int my_id = (int) attr;
    
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
    void *socket = zmq_socket(server_pool.context, ZMQ_REP);
    zmq_connect(socket, ZMQ_INPROC_ADDR);
    pthread_cleanup_push((void (*)(void *)) zmq_close, socket);
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        
        zmq_msg_t reply_msgs[DCS_SERVER_REPLY_COUNT];
        
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
        for(int i = 0; i < DCS_SERVER_REPLY_COUNT; i++){
            zmq_msg_init_size(&reply_msgs[i], DCS_SERVER_REPLY_SIZE);
            memcpy(zmq_msg_data(&reply_msgs[i]), &server_replys[i], DCS_SERVER_REPLY_SIZE);
        }
        pthread_cleanup_push(thread_operator_msg_clean, reply_msgs);
            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        
            if(!server_pool.no_barr){
                rc = pthread_barrier_wait(&server_pool.proxy_barr);
                if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
                    syslog(LOG_ERR, "Thread #%d cannot wait on barrier.", my_id);
            }
            
            while(1){
                int        reply_id = DCS_SERVER_REPLY_OK;
                zmq_msg_t  client_msg;
                char      *message;
                size_t     msg_size;
                unsigned char digest[MSG_DIGEST_SIZE];
                char      *domain;
                char      *md5sum;
                char      *sep;
                HASH_ELEMENT *comp;
                
                pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
                zmq_msg_init(&client_msg);
                pthread_cleanup_push((void (*)(void *)) zmq_msg_close, &client_msg);
                    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
                    
                    zmq_msg_recv(&client_msg, socket, 0);
                    message  = (char *) zmq_msg_data(&client_msg);
                    msg_size = zmq_msg_size(&client_msg);
                    DEBUGMSG(syslog(LOG_DEBUG, "msg_size = %d\n", msg_size));
                    if(msg_size >= MSG_DIGEST_SIZE + 1 + 1 + 2){
                        //~ проверка размера сообщения здесь!!!
                        //~ decrypt and verify message here!
                        //~ message = func(message)
                        memset(digest, '\0', MSG_DIGEST_SIZE);
                        rc = msg_digest(message + MSG_DIGEST_SIZE, MSG_SALT_PATH,
                                        msg_size - MSG_DIGEST_SIZE, digest);
                        if(rc){
                            DEBUGMSG(syslog(LOG_DEBUG, "msg_digest failed!!!"));
                        }
                        if(memcmp(message, digest, MSG_DIGEST_SIZE) == 0){
                            message += MSG_DIGEST_SIZE;
                            DEBUGMSG(syslog(LOG_DEBUG, "Thread #%d catch message: '%s'\n", my_id, message + 1));
                            
                            switch(*message){
                                case DCS_CLIENT_REQ_MD5:
                                    message++;
                                    sep = strchr(message, MSG_SEPARATOR);
                                    if(sep){
                                        *sep   = '\0';
                                        domain = message;
                                        md5sum = sep + 1;
                                        /* Проверки на длину md5-сум!!! */
                                        comp = Hash_find(&server_pool.hash, domain,
                                            (size_t) (unsigned int) sep - (unsigned int) message);
                                        if(comp){
                                            if(memcmp(md5sum, comp->val, HASH_ELEMENT_VAL_SIZE) != 0){
                                                /* Суммы различны, подать сюда полный список деталей! */
                                                reply_id = DCS_SERVER_REPLY_FULL;
                                                DEBUGMSG(syslog(LOG_DEBUG, "Суммы различны\n"));
                                            }
                                            else{
                                                //~ Суммы совпали, всё хорошо.
                                                reply_id = DCS_SERVER_REPLY_OK;
                                            }
                                        }
                                        else{ /* Компьютера в хэше нет. */
                                            reply_id = DCS_SERVER_REPLY_FULL;
                                            DEBUGMSG(syslog(LOG_DEBUG, "Компьютера в хэше нет\n"));
                                        }
                                    }
                                    break;
                                case DCS_CLIENT_REQ_FULL:
                                    message++;
                                    sep = strchr(message, MSG_SEPARATOR);
                                    if(sep){
                                        *sep   = '\0';
                                        domain = message;
                                        size_t domain_size;
                                        CL_Detail *details;
                                        size_t     details_count;
                                        unsigned char *hwdata = (unsigned char *) sep + 1;
                                        msg_size -= (MSG_DIGEST_SIZE + 2 + (
                                                (size_t) (unsigned int) sep - (unsigned int) message));
                                        
                                        domain_size = (size_t) ((unsigned int) sep - (unsigned int) message);
                                        /* Считаем md5 */
                                        MD5_CTX mdcontext;
                                        MD5Init(&mdcontext);
                                        MD5Update(&mdcontext, hwdata, msg_size);
                                        MD5Final(digest, &mdcontext);
                                        /* Ищем комп в хэше */
                                        comp = Hash_find(&server_pool.hash, domain, domain_size);
                                        if(!comp){ /* Компьютера в хэше нет - новый компьютер. */
                                            DEBUGMSG(syslog(LOG_DEBUG, "Новая машина!"));
                                            //~ details = (CL_Detail *) calloc(sizeof(CL_Detail), 40);
                                            details = (CL_Detail *) malloc(sizeof(CL_Detail) * 40);
                                            
                                            unsigned char *hwdata_p = hwdata;
                                            for(int i = 0; i < 40; i++){
                                                details[i].vendor_id = get_uint16_from(hwdata_p);
                                                hwdata_p += sizeof(details[i].vendor_id);
                                                details[i].device_id = get_uint16_from(hwdata_p);
                                                hwdata_p += sizeof(details[i].device_id);
                                                details[i].subsystem_id = get_uint32_from(hwdata_p);
                                                hwdata_p += sizeof(details[i].subsystem_id);
                                                details[i].class_code = get_uint32_from(hwdata_p);
                                                hwdata_p += sizeof(details[i].class_code);
                                                details[i].revision = get_uint8_from(hwdata_p);
                                                hwdata_p += sizeof(details[i].revision);
                                                memcpy(&details[i].bus_addr, hwdata_p, sizeof(details[i].bus_addr));
                                                hwdata_p += sizeof(details[i].bus_addr);
                                                details[i].serial_length = get_uint32_from(hwdata_p);
                                                hwdata_p += sizeof(details[i].serial_length);
                                                DEBUGMSG(syslog(LOG_DEBUG, "Detail: %.4x:%.4x:%.8x (rev %.2x) [class: %.6x] Bus: '%s', SL '%u'",
                                                                    details[i].vendor_id,
                                                                    details[i].device_id,
                                                                    details[i].subsystem_id,
                                                                    details[i].revision,
                                                                    details[i].class_code,
                                                                    details[i].bus_addr,
                                                                    details[i].serial_length
                                                ));
                                                memcpy(&details[i].serial, hwdata_p, details[i].serial_length);
                                                hwdata_p += details[i].serial_length;
                                                details[i].serial[details[i].serial_length] = '\0';
                                                details[i].params_length = get_uint32_from(hwdata_p);
                                                hwdata_p += sizeof(details[i].params_length);
                                                DEBUGMSG(syslog(LOG_DEBUG, "HERE4! params_length: %d", details[i].params_length));
                                                details[i].params = (char *) calloc(sizeof(char), details[i].params_length);
                                                memcpy(details[i].params, hwdata_p, details[i].params_length);
                                                hwdata_p += details[i].params_length;
                                                details[i].params[details[i].params_length] = '\0';
                                                
                                                DEBUGMSG(syslog(LOG_DEBUG, "Detail: %.4x:%.4x:%.8x (%.2x) [%.6x]: '%s', '%s'",
                                                                    details[i].vendor_id,
                                                                    details[i].device_id,
                                                                    details[i].subsystem_id,
                                                                    details[i].revision,
                                                                    details[i].class_code,
                                                                    details[i].serial,
                                                                    details[i].params
                                                ));
                                                if((unsigned int) (hwdata_p - hwdata) >= msg_size){
                                                    details_count = i + 1;
                                                    details = (CL_Detail *) realloc(details, sizeof(CL_Detail) * details_count);
                                                    break;
                                                }
                                            }
                                            /* Хэшируем результат */
                                            comp = Hash_insert(&server_pool.hash,
                                                               domain, domain_size,
                                                               (char *) digest, MSG_DIGEST_SIZE);
                                            if(!comp){
                                                DEBUGMSG(syslog(LOG_DEBUG, "Hash insert error: %d\n", errno));
                                                break;
                                            }
                                        }
                                        else{
                                            /* Есть в кэше, проверим md5 */
                                            if(memcmp(comp->val, digest, HASH_ELEMENT_VAL_SIZE) == 0){
                                                DEBUGMSG(syslog(LOG_DEBUG, "Суммы одинаковые, наверное ошибочный запрос\n"));
                                            }
                                            else{ /* Суммы различны (так и должно быть) - обновляем! */
                                                memcpy(comp->val, digest, HASH_ELEMENT_VAL_SIZE);
                                            }
                                        }
                                        sync_comp(comp, details, details_count);
                                    }
                                    break;
                                default:
                                    DEBUGMSG(syslog(LOG_DEBUG, "default = %02x\n", *message));
                                    break;
                            }
                        }
                        else{
                            DEBUGMSG(syslog(LOG_DEBUG, "memcmp failed!"));
                        }
                    }
                    
                pthread_cleanup_pop(1); /* zmq_msg_close() */
                DEBUGMSG(syslog(LOG_DEBUG, "Reply %d: '%.2x'\n", reply_id, *((unsigned int *) zmq_msg_data(&reply_msgs[reply_id]))));
                zmq_msg_send(&reply_msgs[reply_id], socket, 0);
            }
        pthread_cleanup_pop(0); /* thread_operator_msg_clean */
    pthread_cleanup_pop(0); /* zmq_close */
    pthread_exit(NULL);
}
Ejemplo n.º 6
0
void
cerebrod_event_modules_update(const char *nodename,
                              struct cerebrod_node_data *nd,
                              const char *metric_name,
                              struct cerebrod_message_metric *mm)
{
  struct cerebrod_event_module_info *event_module;
  struct cerebrod_event_module_list *el;
#if CEREBRO_DEBUG
  int rv;
#endif /* CEREBRO_DEBUG */
  
  assert(nodename && nd && metric_name && mm);

  if (!event_index)
    return;

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

  /*
   * This function may be called by multiple threads by the listener.
   *
   * The event_index is setup at the beginning and is only read, not
   * written to.  However, the lists stored inside the event_index
   * need to called w/ thread safety (due to the nature of the list
   * API).
   *
   */

  if ((el = Hash_find(event_index, metric_name)))
    {
      struct cerebro_event *event = NULL;
      ListIterator itr = NULL;
      int rv;

      Pthread_mutex_lock(&(el->event_list_lock));
      itr = List_iterator_create(el->event_list);
      Pthread_mutex_unlock(&(el->event_list_lock));

      while ((event_module = list_next(itr)))
	{
	  Pthread_mutex_lock(&event_module->event_lock);
	  if ((rv = event_module_metric_update(event_handle,
                                               event_module->index,
                                               nodename,
                                               metric_name,
                                               mm->metric_value_type,
                                               mm->metric_value_len,
                                               mm->metric_value,
                                               &event)) < 0)
            {
              CEREBROD_DBG(("event_module_metric_update"));
              goto loop_next;
            }

          if (rv && event)
            cerebrod_queue_event(event, event_module->index);

        loop_next:
	  Pthread_mutex_unlock(&event_module->event_lock);
	}

      Pthread_mutex_lock(&(el->event_list_lock));
      List_iterator_destroy(itr);
      Pthread_mutex_unlock(&(el->event_list_lock));
    }
}
Ejemplo n.º 7
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.º 8
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.º 9
0
void *
cerebrod_event_queue_monitor(void *arg)
{
  List temp_event_queue;

  _event_queue_monitor_initialize();

  /* Don't bother if there isn't an event queue (i.e. no event modules) */
  if (!event_queue)
    return NULL;

  temp_event_queue = List_create((ListDelF)cerebrod_event_to_send_destroy);

  /* 
   * achu: The listener and thus event update initialization is
   * started after this thread is started.  So the and event_index may
   * not be set up the first time this loop is reached.  
   *
   * However, it must be set after the condition is signaled, b/c the
   * listener (and thus event update code) and event node timeout
   * thread begin after the listener is setup.
   *
   * Thus, we put the event_queue assert inside the loop.
   */
  for (;;)
    {
      struct cerebrod_event_to_send *ets;
      ListIterator eitr;
      ListIterator titr;

      Pthread_mutex_lock(&event_queue_lock);
      assert(event_queue);
      while (list_count(event_queue) == 0)
        Pthread_cond_wait(&event_queue_cond, &event_queue_lock);

      /* Debug dumping in the below loop can race with the debug
       * dumping from the listener, b/c of racing on the
       * event_queue_lock.  To avoid this race, we copy the data off
       * the event_queue, so the event_queue_lock can be freed up.
       */

      eitr = List_iterator_create(event_queue);
      while ((ets = list_next(eitr)))
        {
          List_append(temp_event_queue, ets);
          List_remove(eitr);
        }
      List_iterator_destroy(eitr);
      Pthread_mutex_unlock(&event_queue_lock);

      titr = List_iterator_create(temp_event_queue);
      while ((ets = list_next(titr)))
        {
          List connections;

          _event_dump(ets->event);
          
          Pthread_mutex_lock(&event_connections_lock);
          if ((connections = Hash_find(event_connections_index, ets->event_name)))
            {
              char buf[CEREBRO_MAX_PACKET_LEN];
              int elen;

              if ((elen = _event_marshall(ets->event, 
                                          buf, 
                                          CEREBRO_MAX_PACKET_LEN)) > 0)
                {
                  ListIterator citr;
                  int *fd;

                  citr = List_iterator_create(connections);
                  while ((fd = list_next(citr)))
                    {
                      if (fd_write_n(*fd, buf, elen) < 0)
                        {
                          CEREBROD_DBG(("fd_write_n: %s", strerror(errno)));
                          if (errno == EPIPE
                              || errno == EINVAL
                              || errno == EBADF
                              || errno == ENODEV
                              || errno == ENETDOWN
                              || errno == ENETUNREACH)
                            {
                              if (conf.event_server_debug)
                                {
                                  Pthread_mutex_lock(&debug_output_mutex);
                                  fprintf(stderr, "**************************************\n");
                                  fprintf(stderr, "* Event Connection Died: errno = %d\n", errno);
                                  fprintf(stderr, "**************************************\n");
                                  Pthread_mutex_unlock(&debug_output_mutex);
                                }
                              List_delete(citr);
                            }
                          continue;
                        }
                    }
                  List_iterator_destroy(citr);
                }
            }
          Pthread_mutex_unlock(&event_connections_lock);

          List_delete(titr);
        }
      
      List_iterator_destroy(titr);
    }

  List_destroy(temp_event_queue);

  return NULL;			/* NOT REACHED */
}
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;
}