**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_cmd_putval.h"
#include "utils_format_json.h"
#include "utils_format_graphite.h"
-#include <pthread.h>
-
#include <amqp.h>
#include <amqp_framing.h>
char *exchange;
char *routing_key;
+ /* Number of seconds to wait before connection is retried */
+ int connection_retry_delay;
+
/* publish only */
uint8_t delivery_mode;
_Bool store_rates;
switch (r.reply_type)
{
case AMQP_RESPONSE_NORMAL:
- sstrncpy (buffer, "Success", sizeof (buffer));
+ sstrncpy (buffer, "Success", buffer_size);
break;
case AMQP_RESPONSE_NONE:
- sstrncpy (buffer, "Missing RPC reply type", sizeof (buffer));
+ sstrncpy (buffer, "Missing RPC reply type", buffer_size);
break;
case AMQP_RESPONSE_LIBRARY_EXCEPTION:
return (sstrerror (r.library_error, buffer, buffer_size));
#endif
else
- sstrncpy (buffer, "End of stream", sizeof (buffer));
+ sstrncpy (buffer, "End of stream", buffer_size);
break;
case AMQP_RESPONSE_SERVER_EXCEPTION:
/* type = */ amqp_cstring_bytes (conf->exchange_type),
/* passive = */ 0,
/* durable = */ 0,
+#if defined(AMQP_VERSION) && AMQP_VERSION >= 0x00060000
+ /* auto delete = */ 0,
+ /* internal = */ 0,
+#endif
/* arguments = */ argument_table);
if ((ed_ret == NULL) && camqp_is_error (conf))
{
static int camqp_connect (camqp_config_t *conf) /* {{{ */
{
+ static time_t last_connect_time = 0;
+
amqp_rpc_reply_t reply;
int status;
#ifdef HAVE_AMQP_TCP_SOCKET
if (conf->connection != NULL)
return (0);
+ time_t now = time(NULL);
+ if (now < (last_connect_time + conf->connection_retry_delay))
+ {
+ DEBUG("amqp plugin: skipping connection retry, "
+ "ConnectionRetryDelay: %d", conf->connection_retry_delay);
+ return(1);
+ }
+ else
+ {
+ DEBUG ("amqp plugin: retrying connection");
+ last_connect_time = now;
+ }
+
conf->connection = amqp_new_connection ();
if (conf->connection == NULL)
{
static int camqp_shutdown (void) /* {{{ */
{
- size_t i;
-
DEBUG ("amqp plugin: Shutting down %zu subscriber threads.",
subscriber_threads_num);
subscriber_threads_running = 0;
- for (i = 0; i < subscriber_threads_num; i++)
+ for (size_t i = 0; i < subscriber_threads_num; i++)
{
/* FIXME: Sending a signal is not very elegant here. Maybe find out how
* to use a timeout in the thread and check for the variable in regular
continue;
}
- status = camqp_read_header (conf);
+ camqp_read_header (conf);
amqp_maybe_release_buffers (conf->connection);
} /* while (subscriber_threads_running) */
if (tmp == NULL)
{
ERROR ("amqp plugin: realloc failed.");
- camqp_config_free (conf);
+ sfree (subscriber_threads);
return (ENOMEM);
}
subscriber_threads = tmp;
char errbuf[1024];
ERROR ("amqp plugin: pthread_create failed: %s",
sstrerror (status, errbuf, sizeof (errbuf)));
- camqp_config_free (conf);
return (status);
}
static int camqp_write_locked (camqp_config_t *conf, /* {{{ */
const char *buffer, const char *routing_key)
{
- amqp_basic_properties_t props;
int status;
status = camqp_connect (conf);
if (status != 0)
return (status);
- memset (&props, 0, sizeof (props));
- props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG
- | AMQP_BASIC_DELIVERY_MODE_FLAG
- | AMQP_BASIC_APP_ID_FLAG;
+ amqp_basic_properties_t props = {
+ ._flags = AMQP_BASIC_CONTENT_TYPE_FLAG
+ | AMQP_BASIC_DELIVERY_MODE_FLAG
+ | AMQP_BASIC_APP_ID_FLAG,
+ .delivery_mode = conf->delivery_mode,
+ .app_id = amqp_cstring_bytes("collectd")
+ };
+
if (conf->format == CAMQP_FORMAT_COMMAND)
props.content_type = amqp_cstring_bytes("text/collectd");
else if (conf->format == CAMQP_FORMAT_JSON)
props.content_type = amqp_cstring_bytes("text/graphite");
else
assert (23 == 42);
- props.delivery_mode = conf->delivery_mode;
- props.app_id = amqp_cstring_bytes("collectd");
status = amqp_basic_publish(conf->connection,
/* channel = */ 1,
if ((ds == NULL) || (vl == NULL) || (conf == NULL))
return (EINVAL);
- memset (buffer, 0, sizeof (buffer));
-
if (conf->routing_key != NULL)
{
sstrncpy (routing_key, conf->routing_key, sizeof (routing_key));
}
else
{
- size_t i;
ssnprintf (routing_key, sizeof (routing_key), "collectd/%s/%s/%s/%s/%s",
vl->host,
vl->plugin, vl->plugin_instance,
/* Switch slashes (the only character forbidden by collectd) and dots
* (the separation character used by AMQP). */
- for (i = 0; routing_key[i] != 0; i++)
+ for (size_t i = 0; routing_key[i] != 0; i++)
{
if (routing_key[i] == '.')
routing_key[i] = '/';
{
camqp_config_t *conf;
int status;
- int i;
- conf = malloc (sizeof (*conf));
+ conf = calloc (1, sizeof (*conf));
if (conf == NULL)
{
- ERROR ("amqp plugin: malloc failed.");
+ ERROR ("amqp plugin: calloc failed.");
return (ENOMEM);
}
/* Initialize "conf" {{{ */
- memset (conf, 0, sizeof (*conf));
conf->publish = publish;
conf->name = NULL;
conf->format = CAMQP_FORMAT_COMMAND;
conf->password = NULL;
conf->exchange = NULL;
conf->routing_key = NULL;
+ conf->connection_retry_delay = 0;
+
/* publish only */
conf->delivery_mode = CAMQP_DM_VOLATILE;
conf->store_rates = 0;
return (status);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
conf->escape_char = tmp_buff[0];
sfree (tmp_buff);
}
+ else if (strcasecmp ("ConnectionRetryDelay", child->key) == 0)
+ status = cf_util_get_int (child, &conf->connection_retry_delay);
else
WARNING ("amqp plugin: Ignoring unknown "
"configuration option \"%s\".", child->key);
static int camqp_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;