コード例 #1
0
ファイル: logqueue-disk.c プロジェクト: Achint08/syslog-ng
static void
_push_tail(LogQueue *s, LogMessage *msg, const LogPathOptions *path_options)
{
  LogQueueDisk *self = (LogQueueDisk *) s;
  LogPathOptions local_options = *path_options;
  g_static_mutex_lock(&self->super.lock);
  if (self->push_tail)
    {
      if (self->push_tail(self, msg, &local_options, path_options))
        {
          log_queue_push_notify (&self->super);
          stats_counter_inc(self->super.stored_messages);
          log_msg_ack(msg, &local_options, AT_PROCESSED);
          log_msg_unref(msg);
          g_static_mutex_unlock(&self->super.lock);
          return;
        }
    }
  stats_counter_inc (self->super.dropped_messages);

  if (path_options->flow_control_requested)
    log_msg_ack(msg, path_options, AT_SUSPENDED);
  else
    log_msg_drop(msg, path_options, AT_PROCESSED);

  g_static_mutex_unlock(&self->super.lock);
}
コード例 #2
0
  static void
log_writer_queue(LogPipe *s, LogMessage *lm, const LogPathOptions *path_options)
{
  LogWriter *self = (LogWriter *) s;

  if (self->options->suppress > 0 && log_writer_last_msg_check(self, lm, path_options))
    return;

  stats_counter_inc(self->processed_messages);
  if (!log_queue_push_tail(self->queue, lm, path_options))
  {
    /* drop incoming message, we must ack here, otherwise the sender might
     * block forever, however this should not happen unless the sum of
     * window_sizes of sources feeding this writer exceeds log_fifo_size
     * or if flow control is not turned on.
     */

    /* we don't send a message here since the system is draining anyway */

    stats_counter_inc(self->dropped_messages);
    msg_debug("Destination queue full, dropping message",
        evt_tag_int("queue_len", log_queue_get_length(self->queue)),
        evt_tag_int("mem_fifo_size", self->options->mem_fifo_size),
        NULL);
    log_msg_drop(lm, path_options);
    return;
  }
}
コード例 #3
0
ファイル: driver.c プロジェクト: essodjolo/syslog-ng-3.4
void
log_dest_driver_queue_method(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data)
{
  LogDestDriver *self = (LogDestDriver *) s;

  stats_counter_inc(self->super.processed_group_messages);
  stats_counter_inc(self->queued_global_messages);
  log_pipe_forward_msg(s, msg, path_options);
}
コード例 #4
0
ファイル: afamqp.c プロジェクト: Turneliusz/syslog-ng-3.5
static gboolean
afamqp_worker_insert(LogThrDestDriver *s)
{
    AMQPDestDriver *self = (AMQPDestDriver *)s;
    gboolean success;
    LogMessage *msg;
    LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;

    afamqp_dd_connect(self, TRUE);

    success = log_queue_pop_head(s->queue, &msg, &path_options, FALSE, FALSE);
    if (!success)
        return TRUE;

    msg_set_context(msg);
    success = afamqp_worker_publish (self, msg);
    msg_set_context(NULL);

    if (success)
    {
        stats_counter_inc(s->stored_messages);
        step_sequence_number(&self->seq_num);
        log_msg_ack(msg, &path_options);
        log_msg_unref(msg);
    }
    else
        log_queue_push_head(s->queue, msg, &path_options);

    return success;
}
コード例 #5
0
ファイル: driver.c プロジェクト: essodjolo/syslog-ng-3.4
void
log_src_driver_queue_method(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data)
{
  LogSrcDriver *self = (LogSrcDriver *) s;
  GlobalConfig *cfg = log_pipe_get_config(s);

  /* $SOURCE */

  if (msg->flags & LF_LOCAL)
    afinter_postpone_mark(cfg->mark_freq);

  log_msg_set_value(msg, LM_V_SOURCE, self->super.group, self->group_len);
  stats_counter_inc(self->super.processed_group_messages);
  stats_counter_inc(self->received_global_messages);
  log_pipe_forward_msg(s, msg, path_options);
}
コード例 #6
0
ファイル: logthrdestdrv.c プロジェクト: jbfuzier/syslog-ng
void
log_threaded_dest_driver_message_drop(LogThrDestDriver *self,
                                      LogMessage *msg)
{
  stats_counter_inc(self->dropped_messages);
  log_threaded_dest_driver_message_accept(self, msg);
}
コード例 #7
0
ファイル: logqueue-fifo.c プロジェクト: aneutrals/syslog-ng
static void
log_queue_fifo_rewind_backlog(LogQueue *s, guint rewind_count)
{
  LogQueueFifo *self = (LogQueueFifo *) s;
  guint pos;

  if (rewind_count > self->qbacklog_len)
    rewind_count = self->qbacklog_len;

  for (pos = 0; pos < rewind_count; pos++)
    {
      LogMessageQueueNode *node = iv_list_entry(self->qbacklog.prev, LogMessageQueueNode, list);
      /*
       * Because the message go to the backlog only in case of pop_head
       * and pop_head add ack and ref when it pushes the message into the backlog
       * The rewind must decrease the ack and ref too
       */
      iv_list_del_init(&node->list);
      iv_list_add(&node->list, &self->qoverflow_output);

      self->qbacklog_len--;
      self->qoverflow_output_len++;
      stats_counter_inc(self->super.stored_messages);
    }
}
コード例 #8
0
ファイル: tags.c プロジェクト: jszigetvari/syslog-ng
void
log_tags_inc_counter(LogTagId id)
{
  g_static_mutex_lock(&log_tags_lock);

  if (id < log_tags_num)
    stats_counter_inc(log_tags_list[id].counter);

  g_static_mutex_unlock(&log_tags_lock);
}
コード例 #9
0
ファイル: logqueue-fifo.c プロジェクト: aneutrals/syslog-ng
/* move items from the per-thread input queue to the lock-protected "wait" queue */
static void
log_queue_fifo_move_input_unlocked(LogQueueFifo *self, gint thread_id)
{
  gint queue_len;

  /* since we're in the input thread, queue_len will be racy. It can
   * increase due to log_queue_fifo_push_head() and can also decrease as
   * items are removed from the output queue using log_queue_pop_head().
   *
   * The only reason we're using it here is to check for qoverflow
   * overflows, however the only side-effect of the race (if lost) is that
   * we would lose a couple of message too many or add some more messages to
   * qoverflow than permitted by the user.  Since if flow-control is used,
   * the fifo size should be sized larger than the potential window sizes,
   * otherwise we can lose messages anyway, this is not deemed a cost to
   * justify proper locking in this case.
   */

  queue_len = log_queue_fifo_get_length(&self->super);
  if (queue_len + self->qoverflow_input[thread_id].len > self->qoverflow_size)
    {
      /* slow path, the input thread's queue would overflow the queue, let's drop some messages */

      LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
      gint i;
      gint n;

      /* NOTE: MAX is needed here to ensure that the lost race on queue_len
       * doesn't result in n < 0 */
      n = self->qoverflow_input[thread_id].len - MAX(0, (self->qoverflow_size - queue_len));

      for (i = 0; i < n; i++)
        {
          LogMessageQueueNode *node = iv_list_entry(self->qoverflow_input[thread_id].items.next, LogMessageQueueNode, list);
          LogMessage *msg = node->msg;

          iv_list_del(&node->list);
          self->qoverflow_input[thread_id].len--;
          path_options.ack_needed = node->ack_needed;
          stats_counter_inc(self->super.dropped_messages);
          log_msg_free_queue_node(node);
          log_msg_drop(msg, &path_options);
        }
      msg_debug("Destination queue full, dropping messages",
                evt_tag_int("queue_len", queue_len),
                evt_tag_int("log_fifo_size", self->qoverflow_size),
                evt_tag_int("count", n),
                evt_tag_str("persist_name", self->super.persist_name),
                NULL);
    }
  stats_counter_add(self->super.stored_messages, self->qoverflow_input[thread_id].len);
  iv_list_splice_tail_init(&self->qoverflow_input[thread_id].items, &self->qoverflow_wait);
  self->qoverflow_wait_len += self->qoverflow_input[thread_id].len;
  self->qoverflow_input[thread_id].len = 0;
}
コード例 #10
0
static void
_push_head (LogQueueDisk *s, LogMessage *msg, const LogPathOptions *path_options)
{
  LogQueueDiskNonReliable *self = (LogQueueDiskNonReliable *) s;

  g_static_mutex_lock(&self->super.super.lock);
  g_queue_push_head (self->qout, LOG_PATH_OPTIONS_TO_POINTER (path_options));
  g_queue_push_head (self->qout, msg);
  stats_counter_inc (self->super.super.stored_messages);
  g_static_mutex_unlock(&self->super.super.lock);
}
コード例 #11
0
ファイル: afmongodb.c プロジェクト: balabit/syslog-ng-3.4
static gboolean
afmongodb_worker_insert (MongoDBDestDriver *self)
{
  gboolean success;
  guint8 *oid;
  LogMessage *msg;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;

  afmongodb_dd_connect(self, TRUE);

  success = log_queue_pop_head(self->queue, &msg, &path_options, FALSE, FALSE);
  if (!success)
    return TRUE;

  msg_set_context(msg);

  bson_reset (self->bson);

  oid = mongo_util_oid_new_with_time (self->last_msg_stamp, self->seq_num);
  bson_append_oid (self->bson, "_id", oid);
  g_free (oid);

  value_pairs_walk(self->vp,
                   afmongodb_vp_obj_start,
                   afmongodb_vp_process_value,
                   afmongodb_vp_obj_end,
                   msg, self->seq_num, self->bson);
  bson_finish (self->bson);

  if (!mongo_sync_cmd_insert_n(self->conn, self->ns, 1,
                               (const bson **)&self->bson))
    {
      msg_error("Network error while inserting into MongoDB",
                evt_tag_int("time_reopen", self->time_reopen),
                NULL);
      success = FALSE;
    }

  msg_set_context(NULL);

  if (success)
    {
      stats_counter_inc(self->stored_messages);
      step_sequence_number(&self->seq_num);
      log_msg_ack(msg, &path_options);
      log_msg_unref(msg);
    }
  else
    {
      log_queue_push_head(self->queue, msg, &path_options);
    }

  return success;
}
コード例 #12
0
ファイル: logwriter.c プロジェクト: create-iv/syslog-ng
/**
 * log_writer_is_msg_suppressed:
 *
 * This function is called to suppress duplicate messages from a given host.
 *
 * Locking notes:
 *
 * There's a strict ordering requirement between suppress_lock and
 * interacting with the main loop (which ml_batched_timer beind
 * suppress_timer is doing).
 *
 * The reason is that the main thread (running
 * the main loop) sometimes acquires suppress_lock (at suppress timer
 * expiration) and while blocking on suppress_lock it cannot service
 * main_loop_calls()
 *
 * This function makes it sure that ml_batched_timer_update/cancel calls are
 * only done with the suppress lock released.
 *
 * If we do this, we might have a few unfortunate side effects due to races
 * that we also try to handle:
 *
 * Two messages race, one of these matches the recorded last message,
 * the other doesn't. In this case, moving the update on the suppress_timer
 * outside of the lock region might cause two different races:
 *
 * 1) matching message comes first, then non-matching
 *
 * This case the suppress_lock protected region decides that the suppress
 * timer needs to fire (#1) and then the other decides that it needs to
 * be cancelled. (#2)
 *
 * If these are processed in order, then we are the same as if the two was
 * also protected by the mutex (which is ok)
 *
 * If they are reversed, e.g. we first cancels the timer and the second arms it,
 * then we might have a timer wakeup which will find no suppressed messages
 * to report (as the non-matching message will set last_msg_count to zero). This
 * spurious wakeup should be handled by the expiration callback.
 *
 * 1) non-matching message comes first, then matching
 *
 * This is simply a message reordering case, e.g. we don't
 * want any suppressions to be emitted.
 *
 * In this case the locked regions finds that neither messages matched
 * the recorded one, thus both times they decide to cancel the timer, which
 * is ok. Timer cancellation can be reordered as they will have the same
 * effect anyway.
 *
 * Returns TRUE to indicate that the message is to be suppressed.
 **/
static gboolean
log_writer_is_msg_suppressed(LogWriter *self, LogMessage *lm)
{
  gboolean need_to_arm_suppress_timer;
  gboolean need_to_cancel_suppress_timer = FALSE;

  if (self->options->suppress <= 0)
    return FALSE;

  g_static_mutex_lock(&self->suppress_lock);
  if (self->last_msg)
    {
      if (_is_time_within_the_suppress_timeout(self, lm) &&
          _is_message_a_repetition(lm, self->last_msg) &&
          !_is_message_a_mark(lm))
        {

          stats_counter_inc(self->suppressed_messages);
          self->last_msg_count++;
          
          /* we only create the timer if this is the first suppressed message, otherwise it is already running. */
          need_to_arm_suppress_timer = self->last_msg_count == 1;
          g_static_mutex_unlock(&self->suppress_lock);

          /* this has to be outside of suppress_lock */
          if (need_to_arm_suppress_timer)
            log_writer_arm_suppress_timer(self);

          msg_debug("Suppressing duplicate message",
                    evt_tag_str("host", log_msg_get_value(lm, LM_V_HOST, NULL)),
                    evt_tag_str("msg", log_msg_get_value(lm, LM_V_MESSAGE, NULL)));
          return TRUE;
        }
      else
        {
          if (self->last_msg_count)
            log_writer_emit_suppress_summary(self);
          else
            log_writer_release_last_message(self);
          need_to_cancel_suppress_timer = TRUE;
        }
    }

  log_writer_record_last_message(self, lm);
  g_static_mutex_unlock(&self->suppress_lock);
  if (need_to_cancel_suppress_timer)
    ml_batched_timer_cancel(&self->suppress_timer);
  return FALSE;
}
コード例 #13
0
/*
 * stats_instant_inc_dynamic_counter
 * @timestamp: if non-negative, an associated timestamp will be created and set
 *
 * Instantly create (if not exists) and increment a dynamic counter.
 */
void
stats_register_and_increment_dynamic_counter(gint stats_level, gint component, const gchar *id, const gchar *instance, time_t timestamp)
{
  StatsCounterItem *counter, *stamp;
  StatsCluster *handle;

  g_assert(stats_locked);
  handle = stats_register_dynamic_counter(stats_level, component, id, instance, SC_TYPE_PROCESSED, &counter);
  stats_counter_inc(counter);
  if (timestamp >= 0)
    {
      stats_register_associated_counter(handle, SC_TYPE_STAMP, &stamp);
      stats_counter_set(stamp, timestamp);
      stats_unregister_dynamic_counter(handle, SC_TYPE_STAMP, &stamp);
    }
  stats_unregister_dynamic_counter(handle, SC_TYPE_PROCESSED, &counter);
}
コード例 #14
0
ファイル: logqueue-fifo.c プロジェクト: aneutrals/syslog-ng
/*
 * Put an item back to the front of the queue.
 *
 * This is assumed to be called only from the output thread.
 *
 * NOTE: It consumes the reference passed by the caller.
 */
static void
log_queue_fifo_push_head(LogQueue *s, LogMessage *msg, const LogPathOptions *path_options)
{
  LogQueueFifo *self = (LogQueueFifo *) s;
  LogMessageQueueNode *node;

  /* we don't check limits when putting items "in-front", as it
   * normally happens when we start processing an item, but at the end
   * can't deliver it. No checks, no drops either. */

  node = log_msg_alloc_dynamic_queue_node(msg, path_options);
  iv_list_add(&node->list, &self->qoverflow_output);
  self->qoverflow_output_len++;
  log_msg_unref(msg);

  stats_counter_inc(self->super.stored_messages);
}
コード例 #15
0
ファイル: logwriter.c プロジェクト: asdwsda/syslog-ng
/**
 * log_writer_is_msg_suppressed:
 *
 * This function is called to suppress duplicate messages from a given host.
 *
 * Returns TRUE to indicate that the message is to be suppressed.
 **/
static gboolean
log_writer_is_msg_suppressed(LogWriter *self, LogMessage *lm)
{
  if (self->options->suppress <= 0)
    return FALSE;

  g_static_mutex_lock(&self->suppress_lock);
  if (self->last_msg)
    {
      if (self->last_msg->timestamps[LM_TS_RECVD].tv_sec >= lm->timestamps[LM_TS_RECVD].tv_sec - self->options->suppress &&
          strcmp(log_msg_get_value(self->last_msg, LM_V_MESSAGE, NULL), log_msg_get_value(lm, LM_V_MESSAGE, NULL)) == 0 &&
          strcmp(log_msg_get_value(self->last_msg, LM_V_HOST, NULL), log_msg_get_value(lm, LM_V_HOST, NULL)) == 0 &&
          strcmp(log_msg_get_value(self->last_msg, LM_V_PROGRAM, NULL), log_msg_get_value(lm, LM_V_PROGRAM, NULL)) == 0 &&
          strcmp(log_msg_get_value(self->last_msg, LM_V_PID, NULL), log_msg_get_value(lm, LM_V_PID, NULL)) == 0 &&
          strcmp(log_msg_get_value(lm, LM_V_MESSAGE, NULL), "-- MARK --") != 0)
        {
          stats_counter_inc(self->suppressed_messages);
          self->last_msg_count++;
          
          if (self->last_msg_count == 1)
            {
              /* we only create the timer if this is the first suppressed message, otherwise it is already running. */

              log_writer_arm_suppress_timer(self);
            }
          g_static_mutex_unlock(&self->suppress_lock);

          msg_debug("Suppressing duplicate message",
                    evt_tag_str("host", log_msg_get_value(lm, LM_V_HOST, NULL)),
                    evt_tag_str("msg", log_msg_get_value(lm, LM_V_MESSAGE, NULL)),
                    NULL);
          return TRUE;
        }

      if (self->last_msg_count)
        log_writer_emit_suppress_summary(self);
      else
        log_writer_release_last_message(self);
    }

  log_writer_record_last_message(self, lm);
  g_static_mutex_unlock(&self->suppress_lock);
  return FALSE;
}
コード例 #16
0
static void
_rewind_backlog (LogQueueDisk *s, guint rewind_count)
{
  guint i;
  LogQueueDiskNonReliable *self = (LogQueueDiskNonReliable *) s;

  rewind_count = MIN(rewind_count, _get_message_number_in_queue(self->qbacklog));

  for (i = 0; i < rewind_count; i++)
    {
      gpointer ptr_opt = g_queue_pop_tail (self->qbacklog);
      gpointer ptr_msg = g_queue_pop_tail (self->qbacklog);

      g_queue_push_head (self->qout, ptr_opt);
      g_queue_push_head (self->qout, ptr_msg);

      stats_counter_inc (self->super.super.stored_messages);
    }
}
コード例 #17
0
  static void
log_writer_last_msg_flush(LogWriter *self)
{
  LogMessage *m;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
  gchar hostname[256];
  gchar buf[1024];
  gssize len;
  const gchar *p;

  msg_debug("Suppress timer elapsed, emitting suppression summary", 
      NULL);

  getlonghostname(hostname, sizeof(hostname));
  m = log_msg_new_empty();
  m->timestamps[LM_TS_STAMP] = m->timestamps[LM_TS_RECVD];
  m->pri = self->last_msg->pri;
  m->flags = LF_INTERNAL | LF_LOCAL;

  p = log_msg_get_value(self->last_msg, LM_V_HOST, &len);
  log_msg_set_value(m, LM_V_HOST, p, len);
  p = log_msg_get_value(self->last_msg, LM_V_PROGRAM, &len);
  log_msg_set_value(m, LM_V_PROGRAM, p, len);

  len = g_snprintf(buf, sizeof(buf), "Last message '%.20s' repeated %d times, supressed by syslog-ng on %s",
      log_msg_get_value(self->last_msg, LM_V_MESSAGE, NULL),
      self->last_msg_count,
      hostname);
  log_msg_set_value(m, LM_V_MESSAGE, buf, len);

  path_options.flow_control = FALSE;
  if (!log_queue_push_tail(self->queue, m, &path_options))
  {
    stats_counter_inc(self->dropped_messages);
    msg_debug("Destination queue full, dropping suppressed message",
        evt_tag_int("queue_len", log_queue_get_length(self->queue)),
        evt_tag_int("mem_fifo_size", self->options->mem_fifo_size),
        NULL);
    log_msg_drop(m, &path_options);
  }

  log_writer_last_msg_release(self);
}
コード例 #18
0
ファイル: logwriter.c プロジェクト: tiltti/syslog-ng-3.4
/* NOTE: runs in the reader thread */
static void
log_writer_queue(LogPipe *s, LogMessage *lm, const LogPathOptions *path_options, gpointer user_data)
{
  LogWriter *self = (LogWriter *) s;
  LogPathOptions local_options;

  if (!path_options->flow_control_requested &&
      (self->suspended || !(self->flags & LW_SOFT_FLOW_CONTROL)))
    {
      /* NOTE: this code ACKs the message back if there's a write error in
       * order not to hang the client in case of a disk full */

      path_options = log_msg_break_ack(lm, path_options, &local_options);
    }
  if (self->options->suppress > 0 && log_writer_last_msg_check(self, lm, path_options))
    return;

  stats_counter_inc(self->processed_messages);
  log_queue_push_tail(self->queue, lm, path_options);
}
コード例 #19
0
ファイル: logthrdestdrv.c プロジェクト: jbfuzier/syslog-ng
static void
log_threaded_dest_driver_queue(LogPipe *s, LogMessage *msg,
                               const LogPathOptions *path_options,
                               gpointer user_data)
{
  LogThrDestDriver *self = (LogThrDestDriver *)s;
  LogPathOptions local_options;

  if (!path_options->flow_control_requested)
    path_options = log_msg_break_ack(msg, path_options, &local_options);

  if (self->queue_method)
    self->queue_method(self);

  log_msg_add_ack(msg, path_options);
  log_queue_push_tail(self->queue, log_msg_ref(msg), path_options);

  stats_counter_inc(self->processed_messages);

  log_dest_driver_queue_method(s, msg, path_options, user_data);
}
コード例 #20
0
/**
 * log_writer_last_msg_check:
 *
 * This function is called to suppress duplicate messages from a given host.
 *
 * Returns TRUE to indicate that the message was consumed.
 **/
  static gboolean
log_writer_last_msg_check(LogWriter *self, LogMessage *lm, const LogPathOptions *path_options)
{
  if (self->last_msg)
  {
    if (self->last_msg->timestamps[LM_TS_RECVD].time.tv_sec >= lm->timestamps[LM_TS_RECVD].time.tv_sec - self->options->suppress &&
        strcmp(log_msg_get_value(self->last_msg, LM_V_MESSAGE, NULL), log_msg_get_value(lm, LM_V_MESSAGE, NULL)) == 0 &&
        strcmp(log_msg_get_value(self->last_msg, LM_V_HOST, NULL), log_msg_get_value(lm, LM_V_HOST, NULL)) == 0 &&
        strcmp(log_msg_get_value(self->last_msg, LM_V_PROGRAM, NULL), log_msg_get_value(lm, LM_V_PROGRAM, NULL)) == 0 &&
        strcmp(log_msg_get_value(self->last_msg, LM_V_PID, NULL), log_msg_get_value(lm, LM_V_PID, NULL)) == 0 &&
        strcmp(log_msg_get_value(lm, LM_V_MESSAGE, NULL), "-- MARK --") != 0)
    {
      stats_counter_inc(self->suppressed_messages);
      msg_debug("Suppressing duplicate message",
          evt_tag_str("host", log_msg_get_value(lm, LM_V_HOST, NULL)),
          evt_tag_str("msg", log_msg_get_value(lm, LM_V_MESSAGE, NULL)),
          NULL);
      self->last_msg_count++;

      if (self->last_msg_count == 1)
      {
        /* we only create the timer if there's at least one suppressed message */
        self->last_msg_timerid = g_timeout_add(self->options->suppress * 1000, last_msg_timer, self);
      }
      log_msg_drop(lm, path_options);
      return TRUE;
    }

    if (self->last_msg_count)
      log_writer_last_msg_flush(self);
    else
      log_writer_last_msg_release(self);
  }

  log_writer_last_msg_record(self, lm);

  return FALSE;
}
コード例 #21
0
ファイル: logwriter.c プロジェクト: asdwsda/syslog-ng
/* NOTE: runs in the reader thread */
static void
log_writer_queue(LogPipe *s, LogMessage *lm, const LogPathOptions *path_options, gpointer user_data)
{
  LogWriter *self = (LogWriter *) s;
  LogPathOptions local_options;
  gint mark_mode = self->options->mark_mode;

  if (!path_options->flow_control_requested &&
      (self->suspended || !(self->flags & LW_SOFT_FLOW_CONTROL)))
    {
      /* NOTE: this code ACKs the message back if there's a write error in
       * order not to hang the client in case of a disk full */

      path_options = log_msg_break_ack(lm, path_options, &local_options);
    }

  if (log_writer_is_msg_suppressed(self, lm))
    {
      log_msg_drop(lm, path_options);
      return;
    }

  if (mark_mode != MM_INTERNAL && (lm->flags & LF_INTERNAL) && (lm->flags & LF_MARK))
    {
      /* drop MARK messages generated by internal() in case our mark-mode != internal */
      log_msg_drop(lm, path_options);
      return;
    }

  if (mark_mode == MM_DST_IDLE || (mark_mode == MM_HOST_IDLE && !(lm->flags & LF_LOCAL)))
    {
      /* in dst-idle and host-idle most, messages postpone the MARK itself */
      log_writer_postpone_mark_timer(self);
    }

  stats_counter_inc(self->processed_messages);
  log_queue_push_tail(self->queue, lm, path_options);
}
コード例 #22
0
ファイル: logwriter.c プロジェクト: asdwsda/syslog-ng
/* this is the callback function that gets called when the MARK timeout
 * elapsed. It runs in the main thread.
 */
static void
log_writer_mark_timeout(void *cookie)
{
  LogWriter *self = (LogWriter *)cookie;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
  const gchar *hostname;
  gsize hostname_len;
  LogMessage *msg;

  main_loop_assert_main_thread();

  msg = log_msg_new_mark();
  /* timeout: there was no new message on the writer or it is in periodical mode */
  hostname = resolve_sockaddr_to_hostname(&hostname_len, msg->saddr, &self->options->host_resolve_options);

  log_msg_set_value(msg, LM_V_HOST, hostname, hostname_len);

  /* set the current time in the message stamp */
  msg->timestamps[LM_TS_STAMP] = msg->timestamps[LM_TS_RECVD];

  if (!log_writer_is_msg_suppressed(self, msg))
    {
      log_queue_push_tail(self->queue, msg, &path_options);
      stats_counter_inc(self->processed_messages);
    }
  else
    {
      log_msg_drop(msg, &path_options);
    }

  /* we need to issue another MARK in all mark-mode cases that already
   * triggered this callback (dst-idle, host-idle, periodical).  The
   * original setup of the timer is at a different location:
   *   - log_writer_queue() for "*-idle" modes
   *   - log_writer_init() for periodical mode
   */
  log_writer_postpone_mark_timer(self);
}
コード例 #23
0
ファイル: afsql.c プロジェクト: balabit/syslog-ng-3.4
static gboolean
afsql_dd_insert_fail_handler(AFSqlDestDriver *self, LogMessage *msg,
                             LogPathOptions *path_options)
{
  if (self->failed_message_counter < self->num_retries - 1)
    {
      log_queue_push_head(self->queue, msg, path_options);

      /* database connection status sanity check after failed query */
      if (dbi_conn_ping(self->dbi_ctx) != 1)
        {
          const gchar *dbi_error;

          dbi_conn_error(self->dbi_ctx, &dbi_error);
          msg_error("Error, no SQL connection after failed query attempt",
                    evt_tag_str("type", self->type),
                    evt_tag_str("host", self->host),
                    evt_tag_str("port", self->port),
                    evt_tag_str("username", self->user),
                    evt_tag_str("database", self->database),
                    evt_tag_str("error", dbi_error),
                    NULL);
          return FALSE;
        }

      self->failed_message_counter++;
      return FALSE;
    }

  msg_error("Multiple failures while inserting this record into the database, message dropped",
            evt_tag_int("attempts", self->num_retries),
            NULL);
  stats_counter_inc(self->dropped_messages);
  log_msg_drop(msg, path_options);
  self->failed_message_counter = 0;
  return TRUE;
}
コード例 #24
0
static gboolean
perl_worker_eval(LogThrDestDriver *d)
{
  PerlDestDriver *self = (PerlDestDriver *)d;
  gboolean success, vp_ok;
  LogMessage *msg;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
  PerlInterpreter *my_perl = self->perl;
  int count;
  HV *kvmap;
  gpointer args[3];
  dSP;

  success = log_queue_pop_head(self->super.queue, &msg, &path_options, FALSE, FALSE);
  if (!success)
    return TRUE;

  msg_set_context(msg);

  ENTER;
  SAVETMPS;

  PUSHMARK(SP);

  kvmap = newHV();

  args[0] = self->perl;
  args[1] = kvmap;
  args[2] = self;
  vp_ok = value_pairs_foreach(self->vp, perl_worker_vp_add_one,
                              msg, self->seq_num, LTZ_SEND,
                              &self->template_options,
                              args);
  if (!vp_ok && (self->template_options.on_error & ON_ERROR_DROP_MESSAGE))
    goto exit;

  XPUSHs(sv_2mortal(newRV_noinc((SV *)kvmap)));

  PUTBACK;

  count = call_pv(self->queue_func_name, G_EVAL | G_SCALAR);

  SPAGAIN;

  msg_set_context(NULL);

  if (SvTRUE(ERRSV))
    {
      msg_error("Error while calling a Perl function",
                evt_tag_str("driver", self->super.super.super.id),
                evt_tag_str("script", self->filename),
                evt_tag_str("function", self->queue_func_name),
                evt_tag_str("error-message", SvPV_nolen(ERRSV)),
                NULL);
      (void) POPs;
      success = FALSE;
    }

  if (count != 1)
    {
      msg_error("Too many values returned by a Perl function",
                evt_tag_str("driver", self->super.super.super.id),
                evt_tag_str("script", self->filename),
                evt_tag_str("function", self->queue_func_name),
                evt_tag_int("returned-values", count),
                evt_tag_int("expected-values", 1),
                NULL);
      success = FALSE;
    }
  else
    {
      int r = POPi;

      success = (r != 0);
    }

 exit:
  PUTBACK;
  FREETMPS;
  LEAVE;

  if (success && vp_ok)
    {
      stats_counter_inc(self->super.stored_messages);
      step_sequence_number(&self->seq_num);
      log_msg_ack(msg, &path_options);
      log_msg_unref(msg);
    }
  else
    {
      stats_counter_inc(self->super.dropped_messages);
      step_sequence_number(&self->seq_num);
      log_msg_ack(msg, &path_options);
      log_msg_unref(msg);
    }

  return success;
}
コード例 #25
0
ファイル: logsource.c プロジェクト: algernon/syslog-ng
static void
log_source_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data)
{
  LogSource *self = (LogSource *) s;
  LogPathOptions local_options = *path_options;
  gint old_window_size;
  gint i;
  
  msg_set_context(msg);

  if (msg->timestamps[LM_TS_STAMP].tv_sec == -1 || !self->options->keep_timestamp)
    msg->timestamps[LM_TS_STAMP] = msg->timestamps[LM_TS_RECVD];
    
  g_assert(msg->timestamps[LM_TS_STAMP].zone_offset != -1);
  ack_tracker_track_msg(self->ack_tracker, msg);

  /* $HOST setup */
  log_source_mangle_hostname(self, msg);

  /* $PROGRAM override */
  if (self->options->program_override)
    {
      if (self->options->program_override_len < 0)
        self->options->program_override_len = strlen(self->options->program_override);
      log_msg_set_value(msg, LM_V_PROGRAM, self->options->program_override, self->options->program_override_len);
    }

  /* $HOST override */
  if (self->options->host_override)
    {
      if (self->options->host_override_len < 0)
        self->options->host_override_len = strlen(self->options->host_override);
      log_msg_set_value(msg, LM_V_HOST, self->options->host_override, self->options->host_override_len);
    }

  /* source specific tags */
  if (self->options->tags)
    {
      for (i = 0; i < self->options->tags->len; i++)
        {
          log_msg_set_tag_by_id(msg, g_array_index(self->options->tags, LogTagId, i));
        }
    }

  log_msg_set_tag_by_id(msg, self->options->source_group_tag);

  /* stats counters */
  if (stats_check_level(2))
    {
      stats_lock();

      stats_register_and_increment_dynamic_counter(2, SCS_HOST | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_HOST, NULL), msg->timestamps[LM_TS_RECVD].tv_sec);
      if (stats_check_level(3))
        {
          stats_register_and_increment_dynamic_counter(3, SCS_SENDER | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_HOST_FROM, NULL), msg->timestamps[LM_TS_RECVD].tv_sec);
          stats_register_and_increment_dynamic_counter(3, SCS_PROGRAM | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_PROGRAM, NULL), msg->timestamps[LM_TS_RECVD].tv_sec);
        }

      stats_unlock();
    }
  stats_syslog_process_message_pri(msg->pri);

  /* message setup finished, send it out */

  /* NOTE: we start by enabling flow-control, thus we need an acknowledgement */
  local_options.ack_needed = TRUE;
  log_msg_ref(msg);
  log_msg_add_ack(msg, &local_options);
  msg->ack_func = log_source_msg_ack;
    
  old_window_size = g_atomic_counter_exchange_and_add(&self->window_size, -1);

  /*
   * NOTE: this assertion validates that the source is not overflowing its
   * own flow-control window size, decreased above, by the atomic statement.
   *
   * If the _old_ value is zero, that means that the decrement operation
   * above has decreased the value to -1.
   */

  g_assert(old_window_size > 0);

  stats_counter_inc(self->recvd_messages);
  stats_counter_set(self->last_message_seen, msg->timestamps[LM_TS_RECVD].tv_sec);
  log_pipe_forward_msg(s, msg, &local_options);

  msg_set_context(NULL);

  if (accurate_nanosleep && self->threaded && self->window_full_sleep_nsec > 0 && !log_source_free_to_send(self))
    {
      struct timespec ts;

      /* wait one 0.1msec in the hope that the buffer clears up */
      ts.tv_sec = 0;
      ts.tv_nsec = self->window_full_sleep_nsec;
      nanosleep(&ts, NULL);
    }

}
コード例 #26
0
ファイル: afmongodb.c プロジェクト: pgit/syslog-ng-3.4
static gboolean
afmongodb_worker_insert (MongoDBDestDriver *self)
{
  gboolean success;
  guint8 *oid;
  LogMessage *msg;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;

  afmongodb_dd_connect(self, TRUE);

  g_mutex_lock(self->queue_mutex);
  log_queue_reset_parallel_push(self->queue);
  success = log_queue_pop_head(self->queue, &msg, &path_options, FALSE, FALSE);
  g_mutex_unlock(self->queue_mutex);
  if (!success)
    return TRUE;

  msg_set_context(msg);

  bson_reset (self->bson_sel);
  bson_reset (self->bson_upd);
  bson_reset (self->bson_set);

  oid = mongo_util_oid_new_with_time (self->last_msg_stamp, self->seq_num);
  bson_append_oid (self->bson_sel, "_id", oid);
  g_free (oid);
  bson_finish (self->bson_sel);

  value_pairs_foreach (self->vp, afmongodb_vp_foreach,
		       msg, self->seq_num, self->bson_set);

  bson_finish (self->bson_set);

  bson_append_document (self->bson_upd, "$set", self->bson_set);
  bson_finish (self->bson_upd);

  if (!mongo_sync_cmd_update (self->conn, self->ns, MONGO_WIRE_FLAG_UPDATE_UPSERT,
			      self->bson_sel, self->bson_upd))
    {
      msg_error ("Network error while inserting into MongoDB",
		 evt_tag_int("time_reopen", self->time_reopen),
		 NULL);
      success = FALSE;
    }

  msg_set_context(NULL);

  if (success)
    {
      stats_counter_inc(self->stored_messages);
      step_sequence_number(&self->seq_num);
      log_msg_ack(msg, &path_options);
      log_msg_unref(msg);
    }
  else
    {
      g_mutex_lock(self->queue_mutex);
      log_queue_push_head(self->queue, msg, &path_options);
      g_mutex_unlock(self->queue_mutex);
    }

  return success;
}
コード例 #27
0
/**
 * Assumed to be called from one of the input threads. If the thread_id
 * cannot be determined, the item is put directly in the wait queue.
 *
 * Puts the message to the queue, and logs an error if it caused the
 * queue to be full.
 *
 * It attempts to put the item to the per-thread input queue.
 *
 * NOTE: It consumes the reference passed by the caller.
 **/
static void
log_queue_fifo_push_tail(LogQueue *s, LogMessage *msg, const LogPathOptions *path_options)
{
  LogQueueFifo *self = (LogQueueFifo *) s;
  gint thread_id;
  LogMessageQueueNode *node;

  thread_id = main_loop_io_worker_thread_id();

  g_assert(thread_id < 0 || log_queue_max_threads > thread_id);

  /* NOTE: we don't use high-water marks for now, as log_fetch_limit
   * limits the number of items placed on the per-thread input queue
   * anyway, and any sane number decreased the performance measurably.
   *
   * This means that per-thread input queues contain _all_ items that
   * a single poll iteration produces. And once the reader is finished
   * (either because the input is depleted or because of
   * log_fetch_limit / window_size) the whole bunch is propagated to
   * the "wait" queue.
   */

  if (thread_id >= 0) {
      /* fastpath, use per-thread input FIFOs */
      if (!self->qoverflow_input[thread_id].finish_cb_registered)
        {
          /* this is the first item in the input FIFO, register a finish
           * callback to make sure it gets moved to the wait_queue if the
           * input thread finishes */

          main_loop_io_worker_register_finish_callback(&self->qoverflow_input[thread_id].cb);
          self->qoverflow_input[thread_id].finish_cb_registered = TRUE;
        }

      node = log_msg_alloc_queue_node(msg, path_options);
      iv_list_add_tail(&node->list, &self->qoverflow_input[thread_id].items);
      self->qoverflow_input[thread_id].len++;
      log_msg_unref(msg);
      return;
    }

  /* slow path, put the pending item and the whole input queue to the wait_queue */

  g_static_mutex_lock(&self->super.lock);
  
  if (thread_id >= 0)
    log_queue_fifo_move_input_unlocked(self, thread_id);
  
  if (log_queue_fifo_get_length(s) < self->qoverflow_size)
    {
      node = log_msg_alloc_queue_node(msg, path_options);

      iv_list_add_tail(&node->list, &self->qoverflow_wait);
      self->qoverflow_wait_len++;
      log_queue_push_notify(&self->super);

      stats_counter_inc(self->super.stored_messages);
      g_static_mutex_unlock(&self->super.lock);

      log_msg_unref(msg);
    }
  else
    {
      stats_counter_inc(self->super.dropped_messages);
      g_static_mutex_unlock(&self->super.lock);
      log_msg_drop(msg, path_options);

      msg_debug("Destination queue full, dropping message",
                evt_tag_int("queue_len", log_queue_fifo_get_length(&self->super)),
                evt_tag_int("log_fifo_size", self->qoverflow_size),
                NULL);
    }
  return;
}
コード例 #28
0
ファイル: afsql.c プロジェクト: algernon/syslog-ng-old
/**
 * afsql_dd_insert_db:
 *
 * This function is running in the database thread
 *
 * Returns: FALSE to indicate that the connection should be closed and
 * this destination suspended for time_reopen() time.
 **/
static gboolean
afsql_dd_insert_db(AFSqlDestDriver *self)
{
  GString *table = NULL;
  GString *insert_command = NULL;
  LogMessage *msg;
  gboolean success;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;

  if (!afsql_dd_ensure_initialized_connection(self))
    return FALSE;

  /* connection established, try to insert a message */
  success = log_queue_pop_head(self->queue, &msg, &path_options, FALSE, self->flags & AFSQL_DDF_EXPLICIT_COMMITS);
  if (!success)
    return TRUE;

  msg_set_context(msg);

  table = afsql_dd_ensure_accessible_database_table(self, msg);

  if (!table)
    {
      success = FALSE;
      goto out;
    }

  if (afsql_dd_should_start_new_transaction(self) && !afsql_dd_begin_txn(self))
    {
      success = FALSE;
      goto out;
    }

  insert_command = afsql_dd_build_insert_command(self, msg, table);
  success = afsql_dd_run_query(self, insert_command->str, FALSE, NULL);

  if (success && self->flush_lines_queued != -1)
    {
      self->flush_lines_queued++;

      if (afsql_dd_should_commit_transaction(self) && !afsql_dd_commit_txn(self))
        {
          /* Assuming that in case of error, the queue is rewound by afsql_dd_commit_txn() */

          g_string_free(insert_command, TRUE);
          msg_set_context(NULL);

          return FALSE;
        }
    }

 out:

  if (table != NULL)
    g_string_free(table, TRUE);

  if (insert_command != NULL)
    g_string_free(insert_command, TRUE);

  msg_set_context(NULL);

  if (success)
    {
      log_msg_ack(msg, &path_options);
      log_msg_unref(msg);
      step_sequence_number(&self->seq_num);
      self->failed_message_counter = 0;
    }
  else
    {
      if (self->failed_message_counter < self->num_retries - 1)
        {
          if (!afsql_dd_handle_insert_row_error_depending_on_connection_availability(self, msg, &path_options))
            return FALSE;

          self->failed_message_counter++;
        }
      else
        {
          msg_error("Multiple failures while inserting this record into the database, message dropped",
                    evt_tag_int("attempts", self->num_retries),
                    NULL);
          stats_counter_inc(self->dropped_messages);
          log_msg_drop(msg, &path_options);
          self->failed_message_counter = 0;
          success = TRUE;
        }
    }

  return success;
}
コード例 #29
0
ファイル: redis.c プロジェクト: algernon/syslog-ng-old
static gboolean
redis_worker_insert(LogThrDestDriver *s)
{
  RedisDriver *self = (RedisDriver *)s;
  gboolean success;
  LogMessage *msg;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
  redisReply *reply;
  const char *argv[5];
  size_t argvlen[5];
  int argc = 2;

  redis_dd_connect(self, TRUE);

  if (self->c->err)
    return FALSE;

  success = log_queue_pop_head(self->super.queue, &msg, &path_options, FALSE, FALSE);
  if (!success)
    return TRUE;

  msg_set_context(msg);

  log_template_format(self->key, msg, &self->template_options, LTZ_SEND,
                      self->seq_num, NULL, self->key_str);

  if (self->param1)
    log_template_format(self->param1, msg, &self->template_options, LTZ_SEND,
                        self->seq_num, NULL, self->param1_str);
  if (self->param2)
    log_template_format(self->param2, msg, &self->template_options, LTZ_SEND,
                        self->seq_num, NULL, self->param2_str);

  argv[0] = self->command->str;
  argvlen[0] = self->command->len;
  argv[1] = self->key_str->str;
  argvlen[1] = self->key_str->len;

  if (self->param1)
    {
      argv[2] = self->param1_str->str;
      argvlen[2] = self->param1_str->len;
      argc++;
    }

  if (self->param2)
    {
      argv[3] = self->param2_str->str;
      argvlen[3] = self->param2_str->len;
      argc++;
    }

  reply = redisCommandArgv(self->c, argc, argv, argvlen);

  msg_debug("REDIS command sent",
            evt_tag_str("driver", self->super.super.super.id),
            evt_tag_str("command", self->command->str),
            evt_tag_str("key", self->key_str->str),
            evt_tag_str("param1", self->param1_str->str),
            evt_tag_str("param2", self->param2_str->str),
            NULL);
  success = TRUE;

  freeReplyObject(reply);

  msg_set_context(NULL);

  if (success)
    {
      stats_counter_inc(self->super.stored_messages);
      step_sequence_number(&self->seq_num);
      log_msg_ack(msg, &path_options);
      log_msg_unref(msg);
    }
  else
    {
      log_queue_push_head(self->super.queue, msg, &path_options);
    }

  return success;
}
コード例 #30
0
ファイル: logsource.c プロジェクト: batk0/syslog-ng
static void
log_source_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data)
{
  LogSource *self = (LogSource *) s;
  gint i;
  
  msg_set_context(msg);

  if (msg->timestamps[LM_TS_STAMP].tv_sec == -1 || !self->options->keep_timestamp)
    msg->timestamps[LM_TS_STAMP] = msg->timestamps[LM_TS_RECVD];
    
  g_assert(msg->timestamps[LM_TS_STAMP].zone_offset != -1);

  /* $HOST setup */
  log_source_mangle_hostname(self, msg);

  /* $PROGRAM override */
  if (self->options->program_override)
    {
      if (self->options->program_override_len < 0)
        self->options->program_override_len = strlen(self->options->program_override);
      log_msg_set_value(msg, LM_V_PROGRAM, self->options->program_override, self->options->program_override_len);
    }

  /* $HOST override */
  if (self->options->host_override)
    {
      if (self->options->host_override_len < 0)
        self->options->host_override_len = strlen(self->options->host_override);
      log_msg_set_value(msg, LM_V_HOST, self->options->host_override, self->options->host_override_len);
    }

  /* source specific tags */
  if (self->options->tags)
    {
      for (i = 0; i < self->options->tags->len; i++)
        {
          log_msg_set_tag_by_id(msg, g_array_index(self->options->tags, LogTagId, i));
        }
    }

  log_msg_set_tag_by_id(msg, self->options->source_group_tag);

  /* stats counters */
  if (stats_check_level(2))
    {
      stats_lock();

      stats_register_and_increment_dynamic_counter(2, SCS_HOST | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_HOST, NULL), msg->timestamps[LM_TS_RECVD].tv_sec);
      if (stats_check_level(3))
        {
          stats_register_and_increment_dynamic_counter(3, SCS_SENDER | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_HOST_FROM, NULL), msg->timestamps[LM_TS_RECVD].tv_sec);
          stats_register_and_increment_dynamic_counter(3, SCS_PROGRAM | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_PROGRAM, NULL), msg->timestamps[LM_TS_RECVD].tv_sec);
        }

      stats_unlock();
    }
  stats_syslog_process_message_pri(msg->pri);

  /* message setup finished, send it out */


  stats_counter_inc(self->recvd_messages);
  stats_counter_set(self->last_message_seen, msg->timestamps[LM_TS_RECVD].tv_sec);
  log_pipe_forward_msg(s, msg, path_options);

  msg_set_context(NULL);

  if (accurate_nanosleep && self->threaded && self->window_full_sleep_nsec > 0 && !log_source_free_to_send(self))
    {
      struct timespec ts;

      /* wait one 0.1msec in the hope that the buffer clears up */
      ts.tv_sec = 0;
      ts.tv_nsec = self->window_full_sleep_nsec;
      nanosleep(&ts, NULL);
    }

}