X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fsnmp.c;h=300647659a7e31b6b539abfe953e56c8ccaec73c;hb=20a7434400053998709109592ef17aa8c87a35ab;hp=2c4c930cb652dce0c5f3a7642a12b5f347a561d3;hpb=7c6b8505e5557622158574c8dce8ba53c53cec72;p=collectd.git diff --git a/src/snmp.c b/src/snmp.c index 2c4c930c..30064765 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -64,16 +64,16 @@ struct host_definition_s char *community; int version; void *sess_handle; - int16_t skip_num; - int16_t skip_left; + uint32_t interval; + time_t next_update; data_definition_t **data_list; int data_list_len; - enum /****************************************************/ - { /* This host.. */ - STATE_IDLE, /* - just sits there until `skip_left < interval_g' */ - STATE_WAIT, /* - waits to be queried. */ - STATE_BUSY /* - is currently being queried. */ - } state; /****************************************************/ + enum /******************************************************/ + { /* This host.. */ + STATE_IDLE, /* - just sits there until `next_update < interval_g' */ + STATE_WAIT, /* - waits to be queried. */ + STATE_BUSY /* - is currently being queried. */ + } state; /******************************************************/ struct host_definition_s *next; }; typedef struct host_definition_s host_definition_t; @@ -456,8 +456,6 @@ static int csnmp_config_add_host_collect (host_definition_t *host, static int csnmp_config_add_host_interval (host_definition_t *hd, oconfig_item_t *ci) { - int interval; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { @@ -465,10 +463,9 @@ static int csnmp_config_add_host_interval (host_definition_t *hd, oconfig_item_t return (-1); } - interval = (int) ci->values[0].value.number; - hd->skip_num = interval; - if (hd->skip_num < 0) - hd->skip_num = 0; + hd->interval = (int) ci->values[0].value.number; + if (hd->interval < 0) + hd->interval = 0; return (0); } /* int csnmp_config_add_host_interval */ @@ -499,8 +496,8 @@ static int csnmp_config_add_host (oconfig_item_t *ci) } hd->sess_handle = NULL; - hd->skip_num = 0; - hd->skip_left = 0; + hd->interval = 0; + hd->next_update = 0; hd->state = STATE_IDLE; for (i = 0; i < ci->children_num; i++) @@ -596,24 +593,10 @@ static int csnmp_config (oconfig_item_t *ci) static void csnmp_host_close_session (host_definition_t *host) { - int status; - if (host->sess_handle == NULL) return; - status = snmp_sess_close (host->sess_handle); - - if (status != 0) - { - char *errstr = NULL; - - snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); - - ERROR ("snmp plugin: snmp_sess_close failed: %s", - (errstr == NULL) ? "Unknown problem" : errstr); - sfree (errstr); - } - + snmp_sess_close (host->sess_handle); host->sess_handle = NULL; } /* void csnmp_host_close_session */ @@ -639,8 +622,8 @@ static void csnmp_host_open_session (host_definition_t *host) snmp_error (&sess, NULL, NULL, &errstr); - ERROR ("snmp plugin: snmp_sess_open failed: %s", - (errstr == NULL) ? "Unknown problem" : errstr); + ERROR ("snmp plugin: host %s: snmp_sess_open failed: %s", + host->name, (errstr == NULL) ? "Unknown problem" : errstr); sfree (errstr); } } /* void csnmp_host_open_session */ @@ -654,6 +637,9 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type) if ((vl->type == ASN_INTEGER) || (vl->type == ASN_UINTEGER) || (vl->type == ASN_COUNTER) +#ifdef ASN_TIMETICKS + || (vl->type == ASN_TIMETICKS) +#endif || (vl->type == ASN_GAUGE)) { temp = (uint32_t) *vl->val.integer; @@ -725,7 +711,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat vl.host[sizeof (vl.host) - 1] = '\0'; strcpy (vl.plugin, "snmp"); - vl.interval = host->skip_num; + vl.interval = host->interval; vl.time = time (NULL); for (instance_list_ptr = instance_list; @@ -789,6 +775,12 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) 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) { @@ -842,15 +834,22 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) for (i = 0; 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) + if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); - ERROR ("snmp plugin: snmp_sess_synch_response failed: %s", - (errstr == NULL) ? "Unknown problem" : errstr); + ERROR ("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; @@ -862,6 +861,10 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) vb = res->variables; if (vb == NULL) { + if (res != NULL) + snmp_free_pdu (res); + res = NULL; + status = -1; break; } @@ -870,13 +873,23 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) if (snmp_oid_ncompare (data->instance.oid.oid, data->instance.oid.oid_len, vb->name, vb->name_length, data->instance.oid.oid_len) != 0) + { + if (res != NULL) + snmp_free_pdu (res); + res = NULL; + break; + } /* Allocate a new `csnmp_list_instances_t', insert the instance name and * add it to the list */ il = (csnmp_list_instances_t *) malloc (sizeof (csnmp_list_instances_t)); if (il == NULL) { + if (res != NULL) + snmp_free_pdu (res); + res = NULL; + status = -1; break; } @@ -1025,6 +1038,12 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) DEBUG ("snmp plugin: csnmp_read_value (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) { @@ -1057,7 +1076,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) strncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance)); vl.type_instance[sizeof (vl.type_instance) - 1] = '\0'; - vl.interval = host->skip_num; + vl.interval = host->interval; req = snmp_pdu_create (SNMP_MSG_GET); if (req == NULL) @@ -1069,17 +1088,24 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) for (i = 0; i < data->values_len; i++) snmp_add_null_var (req, data->values[i].oid, data->values[i].oid_len); + + res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); - if (status != STAT_SUCCESS) + if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); - ERROR ("snmp plugin: snmp_sess_synch_response failed: %s", - (errstr == NULL) ? "Unknown problem" : errstr); - csnmp_host_close_session (host); + ERROR ("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); return (-1); } @@ -1088,10 +1114,12 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) for (vb = res->variables; vb != NULL; vb = vb->next_variable) { +#if COLLECT_DEBUG char buffer[1024]; snprint_variable (buffer, sizeof (buffer), vb->name, vb->name_length, vb); DEBUG ("snmp plugin: Got this variable: %s", buffer); +#endif /* COLLECT_DEBUG */ for (i = 0; i < data->values_len; i++) if (snmp_oid_compare (data->values[i].oid, data->values[i].oid_len, @@ -1099,7 +1127,9 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) vl.values[i] = csnmp_value_list_to_value (vb, ds->ds[i].type); } /* for (res->variables) */ - snmp_free_pdu (res); + if (res != NULL) + snmp_free_pdu (res); + res = NULL; DEBUG ("snmp plugin: -> plugin_dispatch_values (%s, &vl);", data->type); plugin_dispatch_values (data->type, &vl); @@ -1111,8 +1141,12 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) static int csnmp_read_host (host_definition_t *host) { int i; + time_t time_start; + time_t time_end; - DEBUG ("snmp plugin: csnmp_read_host (%s);", host->name); + time_start = time (NULL); + DEBUG ("snmp plugin: csnmp_read_host (%s) started at %u;", host->name, + (unsigned int) time_start); if (host->sess_handle == NULL) csnmp_host_open_session (host); @@ -1130,6 +1164,16 @@ static int csnmp_read_host (host_definition_t *host) csnmp_read_value (host, data); } + time_end = time (NULL); + DEBUG ("snmp plugin: csnmp_read_host (%s) finished at %u;", host->name, + (unsigned int) time_end); + if ((time_end - time_start) > host->interval) + { + WARNING ("snmp plugin: Host `%s' should be queried every %i seconds, " + "but reading all values takes %i seconds.", + host->name, host->interval, time_end - time_start); + } + return (0); } /* int csnmp_read_host */ @@ -1168,7 +1212,10 @@ static int csnmp_init (void) int i; if (host_head == NULL) + { + NOTICE ("snmp plugin: No host has been defined."); return (-1); + } call_snmp_init_once (); @@ -1176,18 +1223,18 @@ static int csnmp_init (void) for (host = host_head; host != NULL; host = host->next) { threads_num++; - /* We need to initialize `skip_num' here, because `interval_g' isn't + /* We need to initialize `interval' here, because `interval_g' isn't * initialized during `configure'. */ - host->skip_left = interval_g; - if (host->skip_num == 0) + host->next_update = time (NULL); + if (host->interval == 0) { - host->skip_num = interval_g; + host->interval = interval_g; } - else if (host->skip_num < interval_g) + else if (host->interval < interval_g) { - host->skip_num = interval_g; + host->interval = interval_g; WARNING ("snmp plugin: Data for host `%s' will be collected every %i seconds.", - host->name, host->skip_num); + host->name, host->interval); } csnmp_host_open_session (host); @@ -1203,7 +1250,10 @@ static int csnmp_init (void) threads = (pthread_t *) malloc (threads_num * sizeof (pthread_t)); if (threads == NULL) + { + ERROR ("snmp plugin: malloc failed."); return (-1); + } memset (threads, '\0', threads_num * sizeof (pthread_t)); for (i = 0; i < threads_num; i++) @@ -1231,13 +1281,12 @@ static int csnmp_read (void) if (host->state != STATE_IDLE) continue; - host->skip_left -= interval_g; - if (host->skip_left >= interval_g) + /* Skip this host if the next or a later iteration will be sufficient. */ + if (host->next_update >= (now + interval_g)) continue; host->state = STATE_WAIT; - - host->skip_left = host->skip_num; + host->next_update = now + host->interval; } /* for (host) */ pthread_cond_broadcast (&host_cond);