コード例 #1
0
ファイル: postgresql.c プロジェクト: absperf/collectd
static int c_psql_check_connection (c_psql_database_t *db)
{
	/* "ping" */
	PQclear (PQexec (db->conn, "SELECT 42;"));

	if (CONNECTION_OK != PQstatus (db->conn)) {
		PQreset (db->conn);

		/* trigger c_release() */
		if (0 == db->conn_complaint.interval)
			db->conn_complaint.interval = 1;

		if (CONNECTION_OK != PQstatus (db->conn)) {
			c_complain (LOG_ERR, &db->conn_complaint,
					"Failed to connect to database %s: %s",
					db->database, PQerrorMessage (db->conn));
			return -1;
		}

		db->proto_version = PQprotocolVersion (db->conn);
		if (3 > db->proto_version)
			log_warn ("Protocol version %d does not support parameters.",
					db->proto_version);
	}

	db->server_version = PQserverVersion (db->conn);

	c_release (LOG_INFO, &db->conn_complaint,
			"Successfully reconnected to database %s", PQdb (db->conn));
	return 0;
} /* c_psql_check_connection */
コード例 #2
0
ファイル: write_riemann.c プロジェクト: EMSL-MSC/collectd
/* host->lock must be held when calling this function. */
static int wrr_connect(struct riemann_host *host) /* {{{ */
{
  char const *node;
  int port;

  if (host->client)
    return 0;

  node = (host->node != NULL) ? host->node : RIEMANN_HOST;
  port = (host->port) ? host->port : RIEMANN_PORT;

  host->client = NULL;

  host->client = riemann_client_create(
      host->client_type, node, port, RIEMANN_CLIENT_OPTION_TLS_CA_FILE,
      host->tls_ca_file, RIEMANN_CLIENT_OPTION_TLS_CERT_FILE,
      host->tls_cert_file, RIEMANN_CLIENT_OPTION_TLS_KEY_FILE,
      host->tls_key_file, RIEMANN_CLIENT_OPTION_NONE);
  if (host->client == NULL) {
    c_complain(LOG_ERR, &host->init_complaint,
               "write_riemann plugin: Unable to connect to Riemann at %s:%d",
               node, port);
    return -1;
  }
#if RCC_VERSION_NUMBER >= 0x010800
  if (host->timeout.tv_sec != 0) {
    if (riemann_client_set_timeout(host->client, &host->timeout) != 0) {
      riemann_client_free(host->client);
      host->client = NULL;
      c_complain(LOG_ERR, &host->init_complaint,
                 "write_riemann plugin: Unable to connect to Riemann at %s:%d",
                 node, port);
      return -1;
    }
  }
#endif

  set_sock_opts(riemann_client_get_fd(host->client));

  c_release(LOG_INFO, &host->init_complaint,
            "write_riemann plugin: Successfully connected to %s:%d", node,
            port);

  return 0;
} /* }}} int wrr_connect */
コード例 #3
0
ファイル: virt.c プロジェクト: 4thAce/collectd
static int
lv_read (void)
{
    time_t t;
    int i;

    if (conn == NULL) {
        /* `conn_string == NULL' is acceptable. */
        conn = virConnectOpenReadOnly (conn_string);
        if (conn == NULL) {
            c_complain (LOG_ERR, &conn_complain,
                    PLUGIN_NAME " plugin: Unable to connect: "
                    "virConnectOpenReadOnly failed.");
            return -1;
        }
    }
    c_release (LOG_NOTICE, &conn_complain,
            PLUGIN_NAME " plugin: Connection established.");

    time (&t);

    /* Need to refresh domain or device lists? */
    if ((last_refresh == (time_t) 0) ||
            ((interval > 0) && ((last_refresh + interval) <= t))) {
        if (refresh_lists () != 0) {
            if (conn != NULL)
                virConnectClose (conn);
            conn = NULL;
            return -1;
        }
        last_refresh = t;
    }

#if 0
    for (i = 0; i < nr_domains; ++i)
        fprintf (stderr, "domain %s\n", virDomainGetName (domains[i]));
    for (i = 0; i < nr_block_devices; ++i)
        fprintf  (stderr, "block device %d %s:%s\n",
                  i, virDomainGetName (block_devices[i].dom),
                  block_devices[i].path);
    for (i = 0; i < nr_interface_devices; ++i)
        fprintf (stderr, "interface device %d %s:%s\n",
                 i, virDomainGetName (interface_devices[i].dom),
                 interface_devices[i].path);
#endif

    /* Get CPU usage, memory, VCPU usage for each domain. */
    for (i = 0; i < nr_domains; ++i) {
        virDomainInfo info;
        virVcpuInfoPtr vinfo = NULL;
        virDomainMemoryStatPtr minfo = NULL;
        int status;
        int j;

        status = virDomainGetInfo (domains[i], &info);
        if (status != 0)
        {
            ERROR (PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.",
                    status);
            continue;
        }

        if (info.state != VIR_DOMAIN_RUNNING)
        {
            /* only gather stats for running domains */
            continue;
        }

        cpu_submit (info.cpuTime, domains[i], "virt_cpu_total");
        memory_submit ((gauge_t) info.memory * 1024, domains[i]);

        vinfo = malloc (info.nrVirtCpu * sizeof (vinfo[0]));
        if (vinfo == NULL) {
            ERROR (PLUGIN_NAME " plugin: malloc failed.");
            continue;
        }

        status = virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu,
                /* cpu map = */ NULL, /* cpu map length = */ 0);
        if (status < 0)
        {
            ERROR (PLUGIN_NAME " plugin: virDomainGetVcpus failed with status %i.",
                    status);
            sfree (vinfo);
            continue;
        }

        for (j = 0; j < info.nrVirtCpu; ++j)
            vcpu_submit (vinfo[j].cpuTime,
                    domains[i], vinfo[j].number, "virt_vcpu");

        sfree (vinfo);

        minfo = malloc (VIR_DOMAIN_MEMORY_STAT_NR * sizeof (virDomainMemoryStatStruct));
        if (minfo == NULL) {
            ERROR ("virt plugin: malloc failed.");
            continue;
        }

        status =  virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);

        if (status < 0) {
            ERROR ("virt plugin: virDomainMemoryStats failed with status %i.",
                    status);
            sfree (minfo);
            continue;
        }

        for (j = 0; j < status; j++) {
            memory_stats_submit ((gauge_t) minfo[j].val * 1024, domains[i], minfo[j].tag);
        }

        sfree (minfo);
    }


    /* Get block device stats for each domain. */
    for (i = 0; i < nr_block_devices; ++i) {
        struct _virDomainBlockStats stats;

        if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path,
                    &stats, sizeof stats) != 0)
            continue;

        if ((stats.rd_req != -1) && (stats.wr_req != -1))
            submit_derive2 ("disk_ops",
                    (derive_t) stats.rd_req, (derive_t) stats.wr_req,
                    block_devices[i].dom, block_devices[i].path);

        if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1))
            submit_derive2 ("disk_octets",
                    (derive_t) stats.rd_bytes, (derive_t) stats.wr_bytes,
                    block_devices[i].dom, block_devices[i].path);
    } /* for (nr_block_devices) */

    /* Get interface stats for each domain. */
    for (i = 0; i < nr_interface_devices; ++i) {
        struct _virDomainInterfaceStats stats;
        char *display_name = NULL;


        switch (interface_format) {
            case if_address:
                display_name = interface_devices[i].address;
                break;
            case if_number:
                display_name = interface_devices[i].number;
                break;
            case if_name:
            default:
                display_name = interface_devices[i].path;
        }

        if (virDomainInterfaceStats (interface_devices[i].dom,
                    interface_devices[i].path,
                    &stats, sizeof stats) != 0)
            continue;

	if ((stats.rx_bytes != -1) && (stats.tx_bytes != -1))
	    submit_derive2 ("if_octets",
		    (derive_t) stats.rx_bytes, (derive_t) stats.tx_bytes,
		    interface_devices[i].dom, display_name);

	if ((stats.rx_packets != -1) && (stats.tx_packets != -1))
	    submit_derive2 ("if_packets",
		    (derive_t) stats.rx_packets, (derive_t) stats.tx_packets,
		    interface_devices[i].dom, display_name);

	if ((stats.rx_errs != -1) && (stats.tx_errs != -1))
	    submit_derive2 ("if_errors",
		    (derive_t) stats.rx_errs, (derive_t) stats.tx_errs,
		    interface_devices[i].dom, display_name);

	if ((stats.rx_drop != -1) && (stats.tx_drop != -1))
	    submit_derive2 ("if_dropped",
		    (derive_t) stats.rx_drop, (derive_t) stats.tx_drop,
		    interface_devices[i].dom, display_name);
    } /* for (nr_interface_devices) */

    return 0;
}
コード例 #4
0
ファイル: snmp.c プロジェクト: kmiku7/collectd
static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
{
  struct snmp_pdu *req;
  struct snmp_pdu *res;
  struct variable_list *vb;

  const data_set_t *ds;

  size_t oid_list_len = data->values_len + 1;
  /* Holds the last OID returned by the device. We use this in the GETNEXT
   * request to proceed. */
  oid_t oid_list[oid_list_len];
  /* Set to false when an OID has left its subtree so we don't re-request it
   * again. */
  _Bool oid_list_todo[oid_list_len];

  int status;
  size_t i;

  /* `value_list_head' and `value_list_tail' implement a linked list for each
   * value. `instance_list_head' and `instance_list_tail' implement a linked list of
   * instance names. This is used to jump gaps in the table. */
  csnmp_list_instances_t *instance_list_head;
  csnmp_list_instances_t *instance_list_tail;
  csnmp_table_values_t **value_list_head;
  csnmp_table_values_t **value_list_tail;

  DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)",
      host->name, data->name);

  if (host->sess_handle == NULL)
  {
    DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL");
    return (-1);
  }

  ds = plugin_get_ds (data->type);
  if (!ds)
  {
    ERROR ("snmp plugin: DataSet `%s' not defined.", data->type);
    return (-1);
  }

  if (ds->ds_num != data->values_len)
  {
    ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
        data->type, ds->ds_num, data->values_len);
    return (-1);
  }
  assert (data->values_len > 0);

  /* We need a copy of all the OIDs, because GETNEXT will destroy them. */
  memcpy (oid_list, data->values, data->values_len * sizeof (oid_t));
  if (data->instance.oid.oid_len > 0)
    memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t));
  else /* no InstanceFrom option specified. */
    oid_list_len--;

  for (i = 0; i < oid_list_len; i++)
    oid_list_todo[i] = 1;

  /* We're going to construct n linked lists, one for each "value".
   * value_list_head will contain pointers to the heads of these linked lists,
   * value_list_tail will contain pointers to the tail of the lists. */
  value_list_head = calloc (data->values_len, sizeof (*value_list_head));
  value_list_tail = calloc (data->values_len, sizeof (*value_list_tail));
  if ((value_list_head == NULL) || (value_list_tail == NULL))
  {
    ERROR ("snmp plugin: csnmp_read_table: calloc failed.");
    sfree (value_list_head);
    sfree (value_list_tail);
    return (-1);
  }

  instance_list_head = NULL;
  instance_list_tail = NULL;

  status = 0;
  while (status == 0)
  {
    int oid_list_todo_num;

    req = snmp_pdu_create (SNMP_MSG_GETNEXT);
    if (req == NULL)
    {
      ERROR ("snmp plugin: snmp_pdu_create failed.");
      status = -1;
      break;
    }

    oid_list_todo_num = 0;
    for (i = 0; i < oid_list_len; i++)
    {
      /* Do not rerequest already finished OIDs */
      if (!oid_list_todo[i])
        continue;
      oid_list_todo_num++;
      snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);
    }

    if (oid_list_todo_num == 0)
    {
      /* The request is still empty - so we are finished */
      DEBUG ("snmp plugin: all variables have left their subtree");
      status = 0;
      break;
    }

    res = NULL;
    status = snmp_sess_synch_response (host->sess_handle, req, &res);
    if ((status != STAT_SUCCESS) || (res == NULL))
    {
      char *errstr = NULL;

      snmp_sess_error (host->sess_handle, NULL, NULL, &errstr);

      c_complain (LOG_ERR, &host->complaint,
          "snmp plugin: host %s: snmp_sess_synch_response failed: %s",
          host->name, (errstr == NULL) ? "Unknown problem" : errstr);

      if (res != NULL)
        snmp_free_pdu (res);
      res = NULL;

      /* snmp_synch_response already freed our PDU */
      req = NULL;
      sfree (errstr);
      csnmp_host_close_session (host);

      status = -1;
      break;
    }

    status = 0;
    assert (res != NULL);
    c_release (LOG_INFO, &host->complaint,
        "snmp plugin: host %s: snmp_sess_synch_response successful.",
        host->name);

    vb = res->variables;
    if (vb == NULL)
    {
      status = -1;
      break;
    }

    for (vb = res->variables, i = 0; (vb != NULL); vb = vb->next_variable, i++)
    {
      /* Calculate value index from todo list */
      while ((i < oid_list_len) && !oid_list_todo[i])
        i++;

      /* An instance is configured and the res variable we process is the
       * instance value (last index) */
      if ((data->instance.oid.oid_len > 0) && (i == data->values_len))
      {
        if ((vb->type == SNMP_ENDOFMIBVIEW)
            || (snmp_oid_ncompare (data->instance.oid.oid,
                data->instance.oid.oid_len,
                vb->name, vb->name_length,
                data->instance.oid.oid_len) != 0))
        {
          DEBUG ("snmp plugin: host = %s; data = %s; Instance left its subtree.",
              host->name, data->name);
          oid_list_todo[i] = 0;
          continue;
        }

        /* Allocate a new `csnmp_list_instances_t', insert the instance name and
         * add it to the list */
        if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail,
              res, host, data) != 0)
        {
          ERROR ("snmp plugin: host %s: csnmp_instance_list_add failed.",
              host->name);
          status = -1;
          break;
        }
      }
      else /* The variable we are processing is a normal value */
      {
        csnmp_table_values_t *vt;
        oid_t vb_name;
        oid_t suffix;
        int ret;

        csnmp_oid_init (&vb_name, vb->name, vb->name_length);

        /* Calculate the current suffix. This is later used to check that the
         * suffix is increasing. This also checks if we left the subtree */
        ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
        if (ret != 0)
        {
          DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
              "Value probably left its subtree.",
              host->name, data->name, i);
          oid_list_todo[i] = 0;
          continue;
        }

        /* Make sure the OIDs returned by the agent are increasing. Otherwise our
         * table matching algorithm will get confused. */
        if ((value_list_tail[i] != NULL)
            && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
        {
          DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
              "Suffix is not increasing.",
              host->name, data->name, i);
          oid_list_todo[i] = 0;
          continue;
        }

        vt = malloc (sizeof (*vt));
        if (vt == NULL)
        {
          ERROR ("snmp plugin: malloc failed.");
          status = -1;
          break;
        }
        memset (vt, 0, sizeof (*vt));

        vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
            data->scale, data->shift, host->name, data->name);
        memcpy (&vt->suffix, &suffix, sizeof (vt->suffix));
        vt->next = NULL;

        if (value_list_tail[i] == NULL)
          value_list_head[i] = vt;
        else
          value_list_tail[i]->next = vt;
        value_list_tail[i] = vt;
      }

      /* Copy OID to oid_list[i] */
      memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length);
      oid_list[i].oid_len = vb->name_length;

    } /* for (vb = res->variables ...) */

    if (res != NULL)
      snmp_free_pdu (res);
    res = NULL;
  } /* while (status == 0) */

  if (res != NULL)
    snmp_free_pdu (res);
  res = NULL;

  if (req != NULL)
    snmp_free_pdu (req);
  req = NULL;

  if (status == 0)
    csnmp_dispatch_table (host, data, instance_list_head, value_list_head);

  /* Free all allocated variables here */
  while (instance_list_head != NULL)
  {
    csnmp_list_instances_t *next = instance_list_head->next;
    sfree (instance_list_head);
    instance_list_head = next;
  }

  for (i = 0; i < data->values_len; i++)
  {
    while (value_list_head[i] != NULL)
    {
      csnmp_table_values_t *next = value_list_head[i]->next;
      sfree (value_list_head[i]);
      value_list_head[i] = next;
    }
  }

  sfree (value_list_head);
  sfree (value_list_tail);

  return (0);
} /* int csnmp_read_table */
コード例 #5
0
ファイル: snmp.c プロジェクト: haojunyu/collectd
static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
{
  struct snmp_pdu *req;
  struct snmp_pdu *res;
  struct variable_list *vb;

  const data_set_t *ds;
  oid_t *oid_list;
  uint32_t oid_list_len;

  int status;
  int i;

  /* `value_table' and `value_table_ptr' implement a linked list for each
   * value. `instance_list' and `instance_list_ptr' implement a linked list of
   * instance names. This is used to jump gaps in the table. */
  csnmp_list_instances_t *instance_list;
  csnmp_list_instances_t *instance_list_ptr;
  csnmp_table_values_t **value_table;
  csnmp_table_values_t **value_table_ptr;

  DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)",
      host->name, data->name);

  if (host->sess_handle == NULL)
  {
    DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL");
    return (-1);
  }

  ds = plugin_get_ds (data->type);
  if (!ds)
  {
    ERROR ("snmp plugin: DataSet `%s' not defined.", data->type);
    return (-1);
  }

  if (ds->ds_num != data->values_len)
  {
    ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
	data->type, ds->ds_num, data->values_len);
    return (-1);
  }

  /* We need a copy of all the OIDs, because GETNEXT will destroy them. */
  oid_list_len = data->values_len + 1;
  oid_list = (oid_t *) malloc (sizeof (oid_t) * (oid_list_len));
  if (oid_list == NULL)
  {
    ERROR ("snmp plugin: csnmp_read_table: malloc failed.");
    return (-1);
  }
  memcpy (oid_list, data->values, data->values_len * sizeof (oid_t));
  if (data->instance.oid.oid_len > 0)
    memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t));
  else
    oid_list_len--;

  /* Allocate the `value_table' */
  value_table = (csnmp_table_values_t **) malloc (sizeof (csnmp_table_values_t *)
      * 2 * data->values_len);
  if (value_table == NULL)
  {
    ERROR ("snmp plugin: csnmp_read_table: malloc failed.");
    sfree (oid_list);
    return (-1);
  }
  memset (value_table, '\0', sizeof (csnmp_table_values_t *) * 2 * data->values_len);
  value_table_ptr = value_table + data->values_len;
  
  instance_list = NULL;
  instance_list_ptr = NULL;

  status = 0;
  while (status == 0)
  {
    req = snmp_pdu_create (SNMP_MSG_GETNEXT);
    if (req == NULL)
    {
      ERROR ("snmp plugin: snmp_pdu_create failed.");
      status = -1;
      break;
    }

    for (i = 0; (uint32_t) i < oid_list_len; i++)
      snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);

    res = NULL;
    status = snmp_sess_synch_response (host->sess_handle, req, &res);

    if ((status != STAT_SUCCESS) || (res == NULL))
    {
      char *errstr = NULL;

      snmp_sess_error (host->sess_handle, NULL, NULL, &errstr);

      c_complain (LOG_ERR, &host->complaint,
	  "snmp plugin: host %s: snmp_sess_synch_response failed: %s",
	  host->name, (errstr == NULL) ? "Unknown problem" : errstr);

      if (res != NULL)
	snmp_free_pdu (res);
      res = NULL;

      sfree (errstr);
      csnmp_host_close_session (host);

      status = -1;
      break;
    }
    status = 0;
    assert (res != NULL);
    c_release (LOG_INFO, &host->complaint,
	"snmp plugin: host %s: snmp_sess_synch_response successful.",
	host->name);

    vb = res->variables;
    if (vb == NULL)
    {
      status = -1;
      break;
    }

    /* Check if all values (and possibly the instance) have left their
     * subtree */
    if (csnmp_check_res_left_subtree (host, data, res) != 0)
    {
      status = 0;
      break;
    }

    /* if an instance-OID is configured.. */
    if (data->instance.oid.oid_len > 0)
    {
      /* Allocate a new `csnmp_list_instances_t', insert the instance name and
       * add it to the list */
      if (csnmp_instance_list_add (&instance_list, &instance_list_ptr,
	    res) != 0)
      {
	ERROR ("snmp plugin: csnmp_instance_list_add failed.");
	status = -1;
	break;
      }

      /* Set vb on the last variable */
      for (vb = res->variables;
	  (vb != NULL) && (vb->next_variable != NULL);
	  vb = vb->next_variable)
	/* do nothing */;
      assert (vb != NULL);

      /* Copy OID to oid_list[data->values_len] */
      memcpy (oid_list[data->values_len].oid, vb->name,
	  sizeof (oid) * vb->name_length);
      oid_list[data->values_len].oid_len = vb->name_length;
    }

    for (vb = res->variables, i = 0;
	(vb != NULL) && (i < data->values_len);
	vb = vb->next_variable, i++)
    {
      csnmp_table_values_t *vt;

      /* Check if we left the subtree */
      if (snmp_oid_ncompare (data->values[i].oid,
	    data->values[i].oid_len,
	    vb->name, vb->name_length,
	    data->values[i].oid_len) != 0)
      {
	DEBUG ("snmp plugin: host = %s; data = %s; Value %i left its subtree.",
	    host->name, data->name, i);
	continue;
      }

      if ((value_table_ptr[i] != NULL)
	  && (vb->name[vb->name_length - 1] <= value_table_ptr[i]->subid))
      {
	DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
	    "SUBID is not increasing.",
	    host->name, data->name, i);
	continue;
      }

      vt = (csnmp_table_values_t *) malloc (sizeof (csnmp_table_values_t));
      if (vt == NULL)
      {
	ERROR ("snmp plugin: malloc failed.");
	status = -1;
	break;
      }

      vt->subid = vb->name[vb->name_length - 1];
      vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
	  data->scale, data->shift);
      vt->next = NULL;

      if (value_table_ptr[i] == NULL)
	value_table[i] = vt;
      else
	value_table_ptr[i]->next = vt;
      value_table_ptr[i] = vt;

      /* Copy OID to oid_list[i + 1] */
      memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length);
      oid_list[i].oid_len = vb->name_length;
    } /* for (i = data->values_len) */

    if (res != NULL)
      snmp_free_pdu (res);
    res = NULL;
  } /* while (status == 0) */

  if (res != NULL)
    snmp_free_pdu (res);
  res = NULL;

  if (status == 0)
    csnmp_dispatch_table (host, data, instance_list, value_table);

  /* Free all allocated variables here */
  while (instance_list != NULL)
  {
    instance_list_ptr = instance_list->next;
    sfree (instance_list);
    instance_list = instance_list_ptr;
  }

  for (i = 0; i < data->values_len; i++)
  {
    csnmp_table_values_t *tmp;
    while (value_table[i] != NULL)
    {
      tmp = value_table[i]->next;
      sfree (value_table[i]);
      value_table[i] = tmp;
    }
  }

  sfree (value_table);
  sfree (oid_list);

  return (0);
} /* int csnmp_read_table */
コード例 #6
0
ファイル: write_graphite.c プロジェクト: timl/collectd
static int wg_callback_init (struct wg_callback *cb)
{
    struct addrinfo ai_hints;
    struct addrinfo *ai_list;
    struct addrinfo *ai_ptr;
    cdtime_t now;
    int status;

    char connerr[1024] = "";

    if (cb->sock_fd > 0)
        return (0);

    /* Don't try to reconnect too often. By default, one reconnection attempt
     * is made per second. */
    now = cdtime ();
    if ((now - cb->last_connect_time) < WG_MIN_RECONNECT_INTERVAL)
        return (EAGAIN);
    cb->last_connect_time = now;

    memset (&ai_hints, 0, sizeof (ai_hints));
#ifdef AI_ADDRCONFIG
    ai_hints.ai_flags |= AI_ADDRCONFIG;
#endif
    ai_hints.ai_family = AF_UNSPEC;

    if (0 == strcasecmp ("tcp", cb->protocol))
        ai_hints.ai_socktype = SOCK_STREAM;
    else
        ai_hints.ai_socktype = SOCK_DGRAM;

    ai_list = NULL;

    status = getaddrinfo (cb->node, cb->service, &ai_hints, &ai_list);
    if (status != 0)
    {
        ERROR ("write_graphite plugin: getaddrinfo (%s, %s, %s) failed: %s",
                cb->node, cb->service, cb->protocol, gai_strerror (status));
        return (-1);
    }

    assert (ai_list != NULL);
    for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
    {
        cb->sock_fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
                ai_ptr->ai_protocol);
        if (cb->sock_fd < 0) {
            char errbuf[1024];
            snprintf (connerr, sizeof (connerr), "failed to open socket: %s",
                    sstrerror (errno, errbuf, sizeof (errbuf)));
            continue;
        }

        status = connect (cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
        if (status != 0)
        {
            char errbuf[1024];
            snprintf (connerr, sizeof (connerr), "failed to connect to remote "
                    "host: %s", sstrerror (errno, errbuf, sizeof (errbuf)));
            close (cb->sock_fd);
            cb->sock_fd = -1;
            continue;
        }

        break;
    }

    freeaddrinfo (ai_list);

    if (cb->sock_fd < 0)
    {
        if (connerr[0] == '\0')
            /* this should not happen but try to get a message anyway */
            sstrerror (errno, connerr, sizeof (connerr));
        c_complain (LOG_ERR, &cb->init_complaint,
                  "write_graphite plugin: Connecting to %s:%s via %s failed. "
                  "The last error was: %s", cb->node, cb->service, cb->protocol, connerr);
        return (-1);
    }
    else
    {
        c_release (LOG_INFO, &cb->init_complaint,
                "write_graphite plugin: Successfully connected to %s:%s via %s.",
                cb->node, cb->service, cb->protocol);
    }

    /* wg_force_reconnect_check does not flush the buffer before closing a
     * sending socket, so only call wg_reset_buffer() if the socket was closed
     * for a different reason (tracked in cb->reconnect_interval_reached). */
    if (!cb->reconnect_interval_reached || (cb->send_buf_free == 0))
        wg_reset_buffer (cb);
    else
        cb->reconnect_interval_reached = 0;

    return (0);
}
コード例 #7
0
ファイル: libvirt.c プロジェクト: gnosek/collectd
static int
lv_read (void)
{
    time_t t;
    int i;

    if (conn == NULL) {
        /* `conn_string == NULL' is acceptable. */
        conn = virConnectOpenReadOnly (conn_string);
        if (conn == NULL) {
            c_complain (LOG_ERR, &conn_complain,
                    "libvirt plugin: Unable to connect: "
                    "virConnectOpenReadOnly failed.");
            return -1;
        }
    }
    c_release (LOG_NOTICE, &conn_complain,
            "libvirt plugin: Connection established.");

    time (&t);

    /* Need to refresh domain or device lists? */
    if ((last_refresh == (time_t) 0) ||
            ((interval > 0) && ((last_refresh + interval) <= t))) {
        if (refresh_lists () != 0) {
            if (conn != NULL)
                virConnectClose (conn);
            conn = NULL;
            return -1;
        }
        last_refresh = t;
    }

#if 0
    for (i = 0; i < nr_domains; ++i)
        fprintf (stderr, "domain %s\n", virDomainGetName (domains[i]));
    for (i = 0; i < nr_block_devices; ++i)
        fprintf  (stderr, "block device %d %s:%s\n",
                  i, virDomainGetName (block_devices[i].dom),
                  block_devices[i].path);
    for (i = 0; i < nr_interface_devices; ++i)
        fprintf (stderr, "interface device %d %s:%s\n",
                 i, virDomainGetName (interface_devices[i].dom),
                 interface_devices[i].path);
#endif

    /* Get CPU usage, VCPU usage for each domain. */
    for (i = 0; i < nr_domains; ++i) {
        virDomainInfo info;
        virVcpuInfoPtr vinfo = NULL;
        int j;

        if (virDomainGetInfo (domains[i], &info) != 0)
            continue;

        cpu_submit (info.cpuTime, domains[i], "virt_cpu_total");

        vinfo = malloc (info.nrVirtCpu * sizeof vinfo[0]);
        if (vinfo == NULL) {
            ERROR ("libvirt plugin: malloc failed.");
            continue;
        }

        if (virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu,
                    NULL, 0) != 0) {
            sfree (vinfo);
            continue;
        }

        for (j = 0; j < info.nrVirtCpu; ++j)
            vcpu_submit (vinfo[j].cpuTime,
                    domains[i], vinfo[j].number, "virt_vcpu");

        sfree (vinfo);
    }

    /* Get block device stats for each domain. */
    for (i = 0; i < nr_block_devices; ++i) {
        struct _virDomainBlockStats stats;

        if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path,
                    &stats, sizeof stats) != 0)
            continue;

        if ((stats.rd_req != -1) && (stats.wr_req != -1))
            submit_derive2 ("disk_ops",
                    (derive_t) stats.rd_req, (derive_t) stats.wr_req,
                    block_devices[i].dom, block_devices[i].path);

        if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1))
            submit_derive2 ("disk_octets",
                    (derive_t) stats.rd_bytes, (derive_t) stats.wr_bytes,
                    block_devices[i].dom, block_devices[i].path);
    } /* for (nr_block_devices) */

    /* Get interface stats for each domain. */
    for (i = 0; i < nr_interface_devices; ++i) {
        struct _virDomainInterfaceStats stats;
        char *display_name = interface_devices[i].path;

        if (interface_format == if_address)
            display_name = interface_devices[i].address;

        if (virDomainInterfaceStats (interface_devices[i].dom,
                    interface_devices[i].path,
                    &stats, sizeof stats) != 0)
            continue;

	if ((stats.rx_bytes != -1) && (stats.tx_bytes != -1))
	    submit_derive2 ("if_octets",
		    (derive_t) stats.rx_bytes, (derive_t) stats.tx_bytes,
		    interface_devices[i].dom, display_name);

	if ((stats.rx_packets != -1) && (stats.tx_packets != -1))
	    submit_derive2 ("if_packets",
		    (derive_t) stats.rx_packets, (derive_t) stats.tx_packets,
		    interface_devices[i].dom, display_name);

	if ((stats.rx_errs != -1) && (stats.tx_errs != -1))
	    submit_derive2 ("if_errors",
		    (derive_t) stats.rx_errs, (derive_t) stats.tx_errs,
		    interface_devices[i].dom, display_name);

	if ((stats.rx_drop != -1) && (stats.tx_drop != -1))
	    submit_derive2 ("if_dropped",
		    (derive_t) stats.rx_drop, (derive_t) stats.tx_drop,
		    interface_devices[i].dom, display_name);
    } /* for (nr_interface_devices) */

    return 0;
}
コード例 #8
0
ファイル: ping.c プロジェクト: baryluk/collectd
static void *ping_thread (void *arg) /* {{{ */
{
  static pingobj_t *pingobj = NULL;

  struct timeval  tv_begin;
  struct timeval  tv_end;
  struct timespec ts_wait;
  struct timespec ts_int;

  hostlist_t *hl;
  int count;

  c_complain_t complaint = C_COMPLAIN_INIT_STATIC;

  pthread_mutex_lock (&ping_lock);

  pingobj = ping_construct ();
  if (pingobj == NULL)
  {
    ERROR ("ping plugin: ping_construct failed.");
    ping_thread_error = 1;
    pthread_mutex_unlock (&ping_lock);
    return ((void *) -1);
  }

  if (ping_source != NULL)
    if (ping_setopt (pingobj, PING_OPT_SOURCE, (void *) ping_source) != 0)
      ERROR ("ping plugin: Failed to set source address: %s",
          ping_get_error (pingobj));

#ifdef HAVE_OPING_1_3
  if (ping_device != NULL)
    if (ping_setopt (pingobj, PING_OPT_DEVICE, (void *) ping_device) != 0)
      ERROR ("ping plugin: Failed to set device: %s",
          ping_get_error (pingobj));
#endif

  ping_setopt (pingobj, PING_OPT_TIMEOUT, (void *) &ping_timeout);
  ping_setopt (pingobj, PING_OPT_TTL, (void *) &ping_ttl);

  if (ping_data != NULL)
    ping_setopt (pingobj, PING_OPT_DATA, (void *) ping_data);

  /* Add all the hosts to the ping object. */
  count = 0;
  for (hl = hostlist_head; hl != NULL; hl = hl->next)
  {
    int tmp_status;
    tmp_status = ping_host_add (pingobj, hl->host);
    if (tmp_status != 0)
      WARNING ("ping plugin: ping_host_add (%s) failed: %s",
          hl->host, ping_get_error (pingobj));
    else
      count++;
  }

  if (count == 0)
  {
    ERROR ("ping plugin: No host could be added to ping object. Giving up.");
    ping_thread_error = 1;
    pthread_mutex_unlock (&ping_lock);
    return ((void *) -1);
  }

  /* Set up `ts_int' */
  {
    double temp_sec;
    double temp_nsec;

    temp_nsec = modf (ping_interval, &temp_sec);
    ts_int.tv_sec  = (time_t) temp_sec;
    ts_int.tv_nsec = (long) (temp_nsec * 1000000000L);
  }

  while (ping_thread_loop > 0)
  {
    int status;
    _Bool send_successful = 0;

    if (gettimeofday (&tv_begin, NULL) < 0)
    {
      char errbuf[1024];
      ERROR ("ping plugin: gettimeofday failed: %s",
          sstrerror (errno, errbuf, sizeof (errbuf)));
      ping_thread_error = 1;
      break;
    }

    pthread_mutex_unlock (&ping_lock);

    status = ping_send (pingobj);
    if (status < 0)
    {
      c_complain (LOG_ERR, &complaint, "ping plugin: ping_send failed: %s",
          ping_get_error (pingobj));
    }
    else
    {
      c_release (LOG_NOTICE, &complaint, "ping plugin: ping_send succeeded.");
      send_successful = 1;
    }

    pthread_mutex_lock (&ping_lock);

    if (ping_thread_loop <= 0)
      break;

    if (send_successful)
      (void) ping_dispatch_all (pingobj);

    if (gettimeofday (&tv_end, NULL) < 0)
    {
      char errbuf[1024];
      ERROR ("ping plugin: gettimeofday failed: %s",
          sstrerror (errno, errbuf, sizeof (errbuf)));
      ping_thread_error = 1;
      break;
    }

    /* Calculate the absolute time until which to wait and store it in
     * `ts_wait'. */
    time_calc (&ts_wait, &ts_int, &tv_begin, &tv_end);

    pthread_cond_timedwait (&ping_cond, &ping_lock, &ts_wait);
    if (ping_thread_loop <= 0)
      break;
  } /* while (ping_thread_loop > 0) */

  pthread_mutex_unlock (&ping_lock);
  ping_destroy (pingobj);

  return ((void *) 0);
} /* }}} void *ping_thread */
コード例 #9
0
ファイル: snmp.c プロジェクト: adrahon/collectd
static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
{
  struct snmp_pdu *req;
  struct snmp_pdu *res;
  struct variable_list *vb;

  const data_set_t *ds;
  oid_t *oid_list;
  uint32_t oid_list_len;

  int status;
  int i;

  /* `value_list_head' and `value_list_tail' implement a linked list for each
   * value. `instance_list_head' and `instance_list_tail' implement a linked list of
   * instance names. This is used to jump gaps in the table. */
  csnmp_list_instances_t *instance_list_head;
  csnmp_list_instances_t *instance_list_tail;
  csnmp_table_values_t **value_list_head;
  csnmp_table_values_t **value_list_tail;

  DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)",
      host->name, data->name);

  if (host->sess_handle == NULL)
  {
    DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL");
    return (-1);
  }

  ds = plugin_get_ds (data->type);
  if (!ds)
  {
    ERROR ("snmp plugin: DataSet `%s' not defined.", data->type);
    return (-1);
  }

  if (ds->ds_num != data->values_len)
  {
    ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
        data->type, ds->ds_num, data->values_len);
    return (-1);
  }

  /* We need a copy of all the OIDs, because GETNEXT will destroy them. */
  oid_list_len = data->values_len + 1;
  oid_list = (oid_t *) malloc (sizeof (oid_t) * (oid_list_len));
  if (oid_list == NULL)
  {
    ERROR ("snmp plugin: csnmp_read_table: malloc failed.");
    return (-1);
  }
  memcpy (oid_list, data->values, data->values_len * sizeof (oid_t));
  if (data->instance.oid.oid_len > 0)
    memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t));
  else
    oid_list_len--;

  /* We're going to construct n linked lists, one for each "value".
   * value_list_head will contain pointers to the heads of these linked lists,
   * value_list_tail will contain pointers to the tail of the lists. */
  value_list_head = calloc (data->values_len, sizeof (*value_list_head));
  value_list_tail = calloc (data->values_len, sizeof (*value_list_tail));
  if ((value_list_head == NULL) || (value_list_tail == NULL))
  {
    ERROR ("snmp plugin: csnmp_read_table: calloc failed.");
    sfree (oid_list);
    sfree (value_list_head);
    sfree (value_list_tail);
    return (-1);
  }

  instance_list_head = NULL;
  instance_list_tail = NULL;

  status = 0;
  while (status == 0)
  {
    req = snmp_pdu_create (SNMP_MSG_GETNEXT);
    if (req == NULL)
    {
      ERROR ("snmp plugin: snmp_pdu_create failed.");
      status = -1;
      break;
    }

    for (i = 0; (uint32_t) i < oid_list_len; i++)
      snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);

    res = NULL;
    status = snmp_sess_synch_response (host->sess_handle, req, &res);

    if ((status != STAT_SUCCESS) || (res == NULL))
    {
      char *errstr = NULL;

      snmp_sess_error (host->sess_handle, NULL, NULL, &errstr);

      c_complain (LOG_ERR, &host->complaint,
          "snmp plugin: host %s: snmp_sess_synch_response failed: %s",
          host->name, (errstr == NULL) ? "Unknown problem" : errstr);

      if (res != NULL)
        snmp_free_pdu (res);
      res = NULL;

      sfree (errstr);
      csnmp_host_close_session (host);

      status = -1;
      break;
    }
    status = 0;
    assert (res != NULL);
    c_release (LOG_INFO, &host->complaint,
        "snmp plugin: host %s: snmp_sess_synch_response successful.",
        host->name);

    vb = res->variables;
    if (vb == NULL)
    {
      status = -1;
      break;
    }

    /* Check if all values (and possibly the instance) have left their
     * subtree */
    if (csnmp_check_res_left_subtree (host, data, res) != 0)
    {
      status = 0;
      break;
    }

    /* Copy the OID of the value used as instance to oid_list, if an instance
     * is configured. */
    if (data->instance.oid.oid_len > 0)
    {
      /* Allocate a new `csnmp_list_instances_t', insert the instance name and
       * add it to the list */
      if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail,
	    res, host, data) != 0)
      {
        ERROR ("snmp plugin: csnmp_instance_list_add failed.");
        status = -1;
        break;
      }

      /* The instance OID is added to the list of OIDs to GET from the
       * snmp agent last, so set vb on the last variable returned and copy
       * that OID. */
      for (vb = res->variables;
          (vb != NULL) && (vb->next_variable != NULL);
          vb = vb->next_variable)
        /* do nothing */;
      assert (vb != NULL);

      /* Copy the OID of the instance value to oid_list[data->values_len].
       * "oid_list" is used for the next GETNEXT request. */
      memcpy (oid_list[data->values_len].oid, vb->name,
          sizeof (oid) * vb->name_length);
      oid_list[data->values_len].oid_len = vb->name_length;
    }

    /* Iterate over all the (non-instance) values returned by the agent. The
     * (i < value_len) check will make sure we're not handling the instance OID
     * twice. */
    for (vb = res->variables, i = 0;
        (vb != NULL) && (i < data->values_len);
        vb = vb->next_variable, i++)
    {
      csnmp_table_values_t *vt;
      oid_t vb_name;
      oid_t suffix;

      csnmp_oid_init (&vb_name, vb->name, vb->name_length);

      /* Calculate the current suffix. This is later used to check that the
       * suffix is increasing. This also checks if we left the subtree */
      status = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
      if (status != 0)
      {
        DEBUG ("snmp plugin: host = %s; data = %s; Value %i failed. "
            "It probably left its subtree.",
            host->name, data->name, i);
        continue;
      }

      /* Make sure the OIDs returned by the agent are increasing. Otherwise our
       * table matching algorithm will get confused. */
      if ((value_list_tail[i] != NULL)
          && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
      {
        DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
            "Suffix is not increasing.",
            host->name, data->name, i);
        continue;
      }

      vt = malloc (sizeof (*vt));
      if (vt == NULL)
      {
        ERROR ("snmp plugin: malloc failed.");
        status = -1;
        break;
      }
      memset (vt, 0, sizeof (*vt));

      vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
          data->scale, data->shift, host->name, data->name);
      memcpy (&vt->suffix, &suffix, sizeof (vt->suffix));
      vt->next = NULL;

      if (value_list_tail[i] == NULL)
        value_list_head[i] = vt;
      else
        value_list_tail[i]->next = vt;
      value_list_tail[i] = vt;

      /* Copy OID to oid_list[i + 1] */
      memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length);
      oid_list[i].oid_len = vb->name_length;
    } /* for (i = data->values_len) */

    if (res != NULL)
      snmp_free_pdu (res);
    res = NULL;
  } /* while (status == 0) */

  if (res != NULL)
    snmp_free_pdu (res);
  res = NULL;

  if (status == 0)
    csnmp_dispatch_table (host, data, instance_list_head, value_list_head);

  /* Free all allocated variables here */
  while (instance_list_head != NULL)
  {
    csnmp_list_instances_t *next = instance_list_head->next;
    sfree (instance_list_head);
    instance_list_head = next;
  }

  for (i = 0; i < data->values_len; i++)
  {
    while (value_list_head[i] != NULL)
    {
      csnmp_table_values_t *next = value_list_head[i]->next;
      sfree (value_list_head[i]);
      value_list_head[i] = next;
    }
  }

  sfree (value_list_head);
  sfree (value_list_tail);
  sfree (oid_list);

  return (0);
} /* int csnmp_read_table */