Exemple #1
0
static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */
{
    amqp_exchange_declare_ok_t *ed_ret;

    if (conf->exchange_type == NULL)
        return (0);

    ed_ret = amqp_exchange_declare (conf->connection,
            /* channel     = */ CAMQP_CHANNEL,
            /* exchange    = */ amqp_cstring_bytes (conf->exchange),
            /* type        = */ amqp_cstring_bytes (conf->exchange_type),
            /* passive     = */ 0,
            /* durable     = */ 0,
            /* auto_delete = */ 1,
            /* arguments   = */ AMQP_EMPTY_TABLE);
    if ((ed_ret == NULL) && camqp_is_error (conf))
    {
        char errbuf[1024];
        ERROR ("amqp plugin: amqp_exchange_declare failed: %s",
                camqp_strerror (conf, errbuf, sizeof (errbuf)));
        camqp_close_connection (conf);
        return (-1);
    }

    INFO ("amqp plugin: Successfully created exchange \"%s\" "
            "with type \"%s\".",
            conf->exchange, conf->exchange_type);

    return (0);
} /* }}} int camqp_create_exchange */
Exemple #2
0
static int camqp_read_header(camqp_config_t *conf) /* {{{ */
{
  int status;
  amqp_frame_t frame;
  amqp_basic_properties_t *properties;
  char *content_type;

  status = amqp_simple_wait_frame(conf->connection, &frame);
  if (status < 0) {
    status = (-1) * status;
    ERROR("amqp plugin: amqp_simple_wait_frame failed: %s", STRERROR(status));
    camqp_close_connection(conf);
    return status;
  }

  if (frame.frame_type != AMQP_FRAME_HEADER) {
    NOTICE("amqp plugin: Unexpected frame type: %#" PRIx8, frame.frame_type);
    return -1;
  }

  properties = frame.payload.properties.decoded;
  content_type = camqp_bytes_cstring(&properties->content_type);
  if (content_type == NULL) {
    ERROR("amqp plugin: Unable to determine content type.");
    return -1;
  }

  status = camqp_read_body(conf, (size_t)frame.payload.properties.body_size,
                           content_type);

  sfree(content_type);
  return status;
} /* }}} int camqp_read_header */
Exemple #3
0
static void *camqp_subscribe_thread (void *user_data) /* {{{ */
{
    camqp_config_t *conf = user_data;
    int status;

    cdtime_t interval = plugin_get_interval ();

    while (subscriber_threads_running)
    {
        amqp_frame_t frame;

        status = camqp_connect (conf);
        if (status != 0)
        {
            struct timespec ts_interval;
            ERROR ("amqp plugin: camqp_connect failed. "
                    "Will sleep for %.3f seconds.",
                    CDTIME_T_TO_DOUBLE (interval));
            CDTIME_T_TO_TIMESPEC (interval, &ts_interval);
            nanosleep (&ts_interval, /* remaining = */ NULL);
            continue;
        }

        status = amqp_simple_wait_frame (conf->connection, &frame);
        if (status < 0)
        {
            struct timespec ts_interval;
            ERROR ("amqp plugin: amqp_simple_wait_frame failed. "
                    "Will sleep for %.3f seconds.",
                    CDTIME_T_TO_DOUBLE (interval));
            camqp_close_connection (conf);
            CDTIME_T_TO_TIMESPEC (interval, &ts_interval);
            nanosleep (&ts_interval, /* remaining = */ NULL);
            continue;
        }

        if (frame.frame_type != AMQP_FRAME_METHOD)
        {
            DEBUG ("amqp plugin: Unexpected frame type: %#"PRIx8,
                    frame.frame_type);
            continue;
        }

        if (frame.payload.method.id != AMQP_BASIC_DELIVER_METHOD)
        {
            DEBUG ("amqp plugin: Unexpected method id: %#"PRIx32,
                    frame.payload.method.id);
            continue;
        }

        camqp_read_header (conf);

        amqp_maybe_release_buffers (conf->connection);
    } /* while (subscriber_threads_running) */

    camqp_config_free (conf);
    pthread_exit (NULL);
    return (NULL);
} /* }}} void *camqp_subscribe_thread */
Exemple #4
0
/*
 * Subscribing code
 */
static int camqp_read_body(camqp_config_t *conf, /* {{{ */
                           size_t body_size, const char *content_type) {
  char body[body_size + 1];
  char *body_ptr;
  size_t received;
  amqp_frame_t frame;
  int status;

  memset(body, 0, sizeof(body));
  body_ptr = &body[0];
  received = 0;

  while (received < body_size) {
    status = amqp_simple_wait_frame(conf->connection, &frame);
    if (status < 0) {
      status = (-1) * status;
      ERROR("amqp plugin: amqp_simple_wait_frame failed: %s", STRERROR(status));
      camqp_close_connection(conf);
      return status;
    }

    if (frame.frame_type != AMQP_FRAME_BODY) {
      NOTICE("amqp plugin: Unexpected frame type: %#" PRIx8, frame.frame_type);
      return -1;
    }

    if ((body_size - received) < frame.payload.body_fragment.len) {
      WARNING("amqp plugin: Body is larger than indicated by header.");
      return -1;
    }

    memcpy(body_ptr, frame.payload.body_fragment.bytes,
           frame.payload.body_fragment.len);
    body_ptr += frame.payload.body_fragment.len;
    received += frame.payload.body_fragment.len;
  } /* while (received < body_size) */

  if (strcasecmp("text/collectd", content_type) == 0) {
    status = cmd_handle_putval(stderr, body);
    if (status != 0)
      ERROR("amqp plugin: cmd_handle_putval failed with status %i.", status);
    return status;
  } else if (strcasecmp("application/json", content_type) == 0) {
    ERROR("amqp plugin: camqp_read_body: Parsing JSON data has not "
          "been implemented yet. FIXME!");
    return 0;
  } else {
    ERROR("amqp plugin: camqp_read_body: Unknown content type \"%s\".",
          content_type);
    return EINVAL;
  }

  /* not reached */
  return 0;
} /* }}} int camqp_read_body */
Exemple #5
0
static void *camqp_subscribe_thread (void *user_data) /* {{{ */
{
    camqp_config_t *conf = user_data;
    int status;

    while (subscriber_threads_running)
    {
        amqp_frame_t frame;

        status = camqp_connect (conf);
        if (status != 0)
        {
            ERROR ("amqp plugin: camqp_connect failed. "
                    "Will sleep for %i seconds.", interval_g);
            sleep (interval_g);
            continue;
        }

        status = amqp_simple_wait_frame (conf->connection, &frame);
        if (status < 0)
        {
            ERROR ("amqp plugin: amqp_simple_wait_frame failed. "
                    "Will sleep for %i seconds.", interval_g);
            camqp_close_connection (conf);
            sleep (interval_g);
            continue;
        }

        if (frame.frame_type != AMQP_FRAME_METHOD)
        {
            DEBUG ("amqp plugin: Unexpected frame type: %#"PRIx8,
                    frame.frame_type);
            continue;
        }

        if (frame.payload.method.id != AMQP_BASIC_DELIVER_METHOD)
        {
            DEBUG ("amqp plugin: Unexpected method id: %#"PRIx32,
                    frame.payload.method.id);
            continue;
        }

        status = camqp_read_header (conf);

        amqp_maybe_release_buffers (conf->connection);
    } /* while (subscriber_threads_running) */

    camqp_config_free (conf);
    pthread_exit (NULL);
} /* }}} void *camqp_subscribe_thread */
Exemple #6
0
/* XXX: You must hold "conf->lock" when calling this function! */
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;
    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("application/json");
    else if (conf->format == CAMQP_FORMAT_GRAPHITE)
        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,
                amqp_cstring_bytes(CONF(conf, exchange)),
                amqp_cstring_bytes (routing_key),
                /* mandatory = */ 0,
                /* immediate = */ 0,
                &props,
                amqp_cstring_bytes(buffer));
    if (status != 0)
    {
        ERROR ("amqp plugin: amqp_basic_publish failed with status %i.",
                status);
        camqp_close_connection (conf);
    }

    return (status);
} /* }}} int camqp_write_locked */
Exemple #7
0
static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */
{
    amqp_exchange_declare_ok_t *ed_ret;
    amqp_table_t argument_table;
    struct amqp_table_entry_t_ argument_table_entries[1];

    if (conf->exchange_type == NULL)
        return (0);

    /* Valid arguments: "auto_delete", "internal" */
    argument_table.num_entries = STATIC_ARRAY_SIZE (argument_table_entries);
    argument_table.entries = argument_table_entries;
    argument_table_entries[0].key = amqp_cstring_bytes ("auto_delete");
    argument_table_entries[0].value.kind = AMQP_FIELD_KIND_BOOLEAN;
    argument_table_entries[0].value.value.boolean = 1;

    ed_ret = amqp_exchange_declare (conf->connection,
            /* channel     = */ CAMQP_CHANNEL,
            /* exchange    = */ amqp_cstring_bytes (conf->exchange),
            /* 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))
    {
        char errbuf[1024];
        ERROR ("amqp plugin: amqp_exchange_declare failed: %s",
                camqp_strerror (conf, errbuf, sizeof (errbuf)));
        camqp_close_connection (conf);
        return (-1);
    }

    INFO ("amqp plugin: Successfully created exchange \"%s\" "
            "with type \"%s\".",
            conf->exchange, conf->exchange_type);

    return (0);
} /* }}} int camqp_create_exchange */
Exemple #8
0
static void camqp_config_free (void *ptr) /* {{{ */
{
    camqp_config_t *conf = ptr;

    if (conf == NULL)
        return;

    camqp_close_connection (conf);

    sfree (conf->name);
    sfree (conf->host);
    sfree (conf->vhost);
    sfree (conf->user);
    sfree (conf->password);
    sfree (conf->exchange);
    sfree (conf->exchange_type);
    sfree (conf->queue);
    sfree (conf->routing_key);

    sfree (conf);
} /* }}} void camqp_config_free */
Exemple #9
0
static int camqp_setup_queue (camqp_config_t *conf) /* {{{ */
{
    amqp_queue_declare_ok_t *qd_ret;
    amqp_basic_consume_ok_t *cm_ret;

    qd_ret = amqp_queue_declare (conf->connection,
            /* channel     = */ CAMQP_CHANNEL,
            /* queue       = */ (conf->queue != NULL)
            ? amqp_cstring_bytes (conf->queue)
            : AMQP_EMPTY_BYTES,
            /* passive     = */ 0,
            /* durable     = */ 0,
            /* exclusive   = */ 0,
            /* auto_delete = */ 1,
            /* arguments   = */ AMQP_EMPTY_TABLE);
    if (qd_ret == NULL)
    {
        ERROR ("amqp plugin: amqp_queue_declare failed.");
        camqp_close_connection (conf);
        return (-1);
    }

    if (conf->queue == NULL)
    {
        conf->queue = camqp_bytes_cstring (&qd_ret->queue);
        if (conf->queue == NULL)
        {
            ERROR ("amqp plugin: camqp_bytes_cstring failed.");
            camqp_close_connection (conf);
            return (-1);
        }

        INFO ("amqp plugin: Created queue \"%s\".", conf->queue);
    }
    DEBUG ("amqp plugin: Successfully created queue \"%s\".", conf->queue);

    /* bind to an exchange */
    if (conf->exchange != NULL)
    {
        amqp_queue_bind_ok_t *qb_ret;

        assert (conf->queue != NULL);
        qb_ret = amqp_queue_bind (conf->connection,
                /* channel     = */ CAMQP_CHANNEL,
                /* queue       = */ amqp_cstring_bytes (conf->queue),
                /* exchange    = */ amqp_cstring_bytes (conf->exchange),
                /* routing_key = */ (conf->routing_key != NULL)
                ? amqp_cstring_bytes (conf->routing_key)
                : AMQP_EMPTY_BYTES,
                /* arguments   = */ AMQP_EMPTY_TABLE);
        if ((qb_ret == NULL) && camqp_is_error (conf))
        {
            char errbuf[1024];
            ERROR ("amqp plugin: amqp_queue_bind failed: %s",
                    camqp_strerror (conf, errbuf, sizeof (errbuf)));
            camqp_close_connection (conf);
            return (-1);
        }

        DEBUG ("amqp plugin: Successfully bound queue \"%s\" to exchange \"%s\".",
                conf->queue, conf->exchange);
    } /* if (conf->exchange != NULL) */

    cm_ret = amqp_basic_consume (conf->connection,
            /* channel      = */ CAMQP_CHANNEL,
            /* queue        = */ amqp_cstring_bytes (conf->queue),
            /* consumer_tag = */ AMQP_EMPTY_BYTES,
            /* no_local     = */ 0,
            /* no_ack       = */ 1,
            /* exclusive    = */ 0,
            /* arguments    = */ AMQP_EMPTY_TABLE
        );
    if ((cm_ret == NULL) && camqp_is_error (conf))
    {
        char errbuf[1024];
        ERROR ("amqp plugin: amqp_basic_consume failed: %s",
                    camqp_strerror (conf, errbuf, sizeof (errbuf)));
        camqp_close_connection (conf);
        return (-1);
    }

    return (0);
} /* }}} int camqp_setup_queue */
Exemple #10
0
/* XXX: You must hold "conf->lock" when calling this function! */
static int camqp_write_locked (camqp_config_t *conf, /* {{{ */
        const char *buffer, const char *routing_key)
{
    int status;

    status = camqp_connect (conf);
    if (status != 0)
        return (status);

    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("application/json");
    else if (conf->format == CAMQP_FORMAT_GRAPHITE)
        props.content_type = amqp_cstring_bytes("text/graphite");
    else
        assert (23 == 42);

    status = amqp_basic_publish(conf->connection,
                /* channel = */ 1,
                amqp_cstring_bytes(CONF(conf, exchange)),
                amqp_cstring_bytes (routing_key),
                /* mandatory = */ 0,
                /* immediate = */ 0,
                &props,
                amqp_cstring_bytes(buffer));
    if (status != 0)
    {
        ERROR ("amqp plugin: amqp_basic_publish failed with status %i.",
                status);
        camqp_close_connection (conf);
    }

    return (status);
} /* }}} int camqp_write_locked */

static int camqp_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
        user_data_t *user_data)
{
    camqp_config_t *conf = user_data->data;
    char routing_key[6 * DATA_MAX_NAME_LEN];
    char buffer[8192];
    int status;

    if ((ds == NULL) || (vl == NULL) || (conf == NULL))
        return (EINVAL);

    if (conf->routing_key != NULL)
    {
        sstrncpy (routing_key, conf->routing_key, sizeof (routing_key));
    }
    else
    {
        ssnprintf (routing_key, sizeof (routing_key), "collectd/%s/%s/%s/%s/%s",
                vl->host,
                vl->plugin, vl->plugin_instance,
                vl->type, vl->type_instance);

        /* Switch slashes (the only character forbidden by collectd) and dots
         * (the separation character used by AMQP). */
        for (size_t i = 0; routing_key[i] != 0; i++)
        {
            if (routing_key[i] == '.')
                routing_key[i] = '/';
            else if (routing_key[i] == '/')
                routing_key[i] = '.';
        }
    }

    if (conf->format == CAMQP_FORMAT_COMMAND)
    {
        status = create_putval (buffer, sizeof (buffer), ds, vl);
        if (status != 0)
        {
            ERROR ("amqp plugin: create_putval failed with status %i.",
                    status);
            return (status);
        }
    }
    else if (conf->format == CAMQP_FORMAT_JSON)
    {
        size_t bfree = sizeof (buffer);
        size_t bfill = 0;

        format_json_initialize (buffer, &bfill, &bfree);
        format_json_value_list (buffer, &bfill, &bfree, ds, vl, conf->store_rates);
        format_json_finalize (buffer, &bfill, &bfree);
    }
    else if (conf->format == CAMQP_FORMAT_GRAPHITE)
    {
        status = format_graphite (buffer, sizeof (buffer), ds, vl,
                    conf->prefix, conf->postfix, conf->escape_char,
                    conf->graphite_flags);
        if (status != 0)
        {
            ERROR ("amqp plugin: format_graphite failed with status %i.",
                    status);
            return (status);
        }
    }
    else
    {
        ERROR ("amqp plugin: Invalid format (%i).", conf->format);
        return (-1);
    }

    pthread_mutex_lock (&conf->lock);
    status = camqp_write_locked (conf, buffer, routing_key);
    pthread_mutex_unlock (&conf->lock);

    return (status);
} /* }}} int camqp_write */