Code

Merge branch 'collectd-5.1' into collectd-5.2
authorFlorian Forster <octo@collectd.org>
Sun, 7 Apr 2013 17:23:27 +0000 (19:23 +0200)
committerFlorian Forster <octo@collectd.org>
Sun, 7 Apr 2013 17:23:27 +0000 (19:23 +0200)
1  2 
src/snmp.c

diff --combined src/snmp.c
index c4d043b9e70283e13136b20fd6e71e0805155aa7,38a24cd3b29c18ac632af562a61ce62d6cca48d6..045f09b13b41bd3a3eab2562e16d76618fefe72e
@@@ -896,71 -896,6 +896,6 @@@ static value_t csnmp_value_list_to_valu
    return (ret);
  } /* value_t csnmp_value_list_to_value */
  
- /* Returns true if all OIDs have left their subtree */
- static int csnmp_check_res_left_subtree (const host_definition_t *host,
-     const data_definition_t *data,
-     struct snmp_pdu *res)
- {
-   struct variable_list *vb;
-   int num_checked;
-   int num_left_subtree;
-   int i;
-   vb = res->variables;
-   if (vb == NULL)
-     return (-1);
-   num_checked = 0;
-   num_left_subtree = 0;
-   /* check all the variables and count how many have left their subtree */
-   for (vb = res->variables, i = 0;
-       (vb != NULL) && (i < data->values_len);
-       vb = vb->next_variable, i++)
-   {
-     num_checked++;
-     if ((vb->type == SNMP_ENDOFMIBVIEW)
-         || (snmp_oid_ncompare (data->values[i].oid,
-             data->values[i].oid_len,
-             vb->name, vb->name_length,
-             data->values[i].oid_len) != 0))
-       num_left_subtree++;
-   }
-   /* check if enough variables have been returned */
-   if (i < data->values_len)
-   {
-     ERROR ("snmp plugin: host %s: Expected %i variables, but got only %i",
-         host->name, data->values_len, i);
-     return (-1);
-   }
-   if (data->instance.oid.oid_len > 0)
-   {
-     if (vb == NULL)
-     {
-       ERROR ("snmp plugin: host %s: Expected one more variable for "
-           "the instance..", host->name);
-       return (-1);
-     }
-     num_checked++;
-     if (snmp_oid_ncompare (data->instance.oid.oid,
-           data->instance.oid.oid_len,
-           vb->name, vb->name_length,
-           data->instance.oid.oid_len) != 0)
-       num_left_subtree++;
-   }
-   DEBUG ("snmp plugin: csnmp_check_res_left_subtree: %i of %i variables have "
-       "left their subtree",
-       num_left_subtree, num_checked);
-   if (num_left_subtree >= num_checked)
-     return (1);
-   return (0);
- } /* int csnmp_check_res_left_subtree */
  static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
      const struct variable_list *vb, size_t dst_size)
  {
@@@ -1264,11 -1199,18 +1199,18 @@@ static int csnmp_read_table (host_defin
    struct variable_list *vb;
  
    const data_set_t *ds;
-   oid_t *oid_list;
-   uint32_t oid_list_len;
+   uint32_t oid_list_len = (uint32_t) (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;
    int i;
+   uint32_t j;
  
    /* `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
    }
  
    /* 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
+   else /* no InstanceFrom option specified. */
      oid_list_len--;
  
+   for (j = 0; j < oid_list_len; j++)
+     oid_list_todo[j] = 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. */
    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);
    status = 0;
    while (status == 0)
    {
+     int oid_list_todo_num;
      req = snmp_pdu_create (SNMP_MSG_GETNEXT);
      if (req == NULL)
      {
        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);
+     oid_list_todo_num = 0;
+     for (j = 0; j < oid_list_len; j++)
+     {
+       /* Do not rerequest already finished OIDs */
+       if (!oid_list_todo[j])
+         continue;
+       oid_list_todo_num++;
+       snmp_add_null_var (req, oid_list[j].oid, oid_list[j].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;
        status = -1;
        break;
      }
      status = 0;
      assert (res != NULL);
      c_release (LOG_INFO, &host->complaint,
        break;
      }
  
-     /* Check if all values (and possibly the instance) have left their
-      * subtree */
-     if (csnmp_check_res_left_subtree (host, data, res) != 0)
+     for (vb = res->variables, i = 0; (vb != NULL); vb = vb->next_variable, i++)
      {
-       status = 0;
-       break;
-     }
+       /* Calculate value index from todo list */
+       while (!oid_list_todo[i] && (i < oid_list_len))
+         i++;
  
-     /* 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)
+       /* 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))
        {
-         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;
+         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: csnmp_instance_list_add failed.");
+           status = -1;
+           break;
+         }
        }
-       /* 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))
+       else /* The variable we are processing is a normal value */
        {
-         DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
-             "Suffix is not increasing.",
-             host->name, data->name, i);
-         continue;
-       }
+         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 */
+         int ret;
+         ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
+         if (ret != 0)
+         {
+           DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+               "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 = %i; "
+               "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 = malloc (sizeof (*vt));
-       if (vt == NULL)
-       {
-         ERROR ("snmp plugin: malloc failed.");
-         status = -1;
-         break;
+         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;
        }
-       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] */
+       /* 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 (i = data->values_len) */
+     } /* for (vb = res->variables ...) */
  
      if (res != NULL)
        snmp_free_pdu (res);
  
    sfree (value_list_head);
    sfree (value_list_tail);
-   sfree (oid_list);
  
    return (0);
  } /* int csnmp_read_table */
@@@ -1643,7 -1590,7 +1590,7 @@@ static int csnmp_read_host (user_data_
    host = ud->data;
  
    if (host->interval == 0)
 -    host->interval = interval_g;
 +    host->interval = plugin_get_interval ();
  
    time_start = cdtime ();
  
    if ((time_end - time_start) > host->interval)
    {
      WARNING ("snmp plugin: Host `%s' should be queried every %.3f "
-       "seconds, but reading all values takes %.3f seconds.",
-       host->name,
-       CDTIME_T_TO_DOUBLE (host->interval),
-       CDTIME_T_TO_DOUBLE (time_end - time_start));
+         "seconds, but reading all values takes %.3f seconds.",
+         host->name,
+         CDTIME_T_TO_DOUBLE (host->interval),
+         CDTIME_T_TO_DOUBLE (time_end - time_start));
    }
  
    if (success == 0)