예제 #1
0
static void
log_reader_update_watches(LogReader *self)
{
  GIOCondition cond;
  gboolean free_to_send;
  gboolean line_is_ready_in_buffer;

  main_loop_assert_main_thread();

  if (!log_reader_is_opened(self))
    return;

  log_reader_start_watches_if_stopped(self);

  free_to_send = log_source_free_to_send(&self->super);
  if (!free_to_send)
    {
      log_reader_suspend_until_awoken(self);
      return;
    }

  line_is_ready_in_buffer = log_proto_server_prepare(self->proto, &cond);
  if (self->immediate_check || line_is_ready_in_buffer)
    {
      log_reader_force_check_in_next_poll(self);
      return;
    }
  poll_events_update_watches(self->poll_events, cond);
}
예제 #2
0
static void
log_reader_init_watches(LogReader *self)
{
  gint fd;
  GIOCondition cond;

  log_proto_server_prepare(self->proto, &fd, &cond);

  IV_FD_INIT(&self->fd_watch);
  self->fd_watch.cookie = self;

  IV_TIMER_INIT(&self->follow_timer);
  self->follow_timer.cookie = self;
  self->follow_timer.handler = log_reader_io_follow_file;

  IV_TASK_INIT(&self->restart_task);
  self->restart_task.cookie = self;
  self->restart_task.handler = log_reader_io_process_input;

  IV_EVENT_INIT(&self->schedule_wakeup);
  self->schedule_wakeup.cookie = self;
  self->schedule_wakeup.handler = log_reader_wakeup_triggered;

  main_loop_io_worker_job_init(&self->io_job);
  self->io_job.user_data = self;
  self->io_job.work = (void (*)(void *)) log_reader_work_perform;
  self->io_job.completion = (void (*)(void *)) log_reader_work_finished;
}
예제 #3
0
static void
log_reader_update_watches(LogReader *self)
{
  GIOCondition cond;
  gint idle_timeout = -1;

  main_loop_assert_main_thread();

  log_reader_stop_idle_timer(self);

  if (!log_reader_is_opened(self))
    return;

  log_reader_start_watches_if_stopped(self);

  gboolean free_to_send = log_source_free_to_send(&self->super);
  if (!free_to_send)
    {
      log_reader_suspend_until_awoken(self);
      return;
    }

  LogProtoPrepareAction prepare_action = log_proto_server_prepare(self->proto, &cond, &idle_timeout);

  if (idle_timeout > 0)
    {
      iv_validate_now();

      self->idle_timer.expires = iv_now;
      self->idle_timer.expires.tv_sec += idle_timeout;

      iv_timer_register(&self->idle_timer);
    }

  if (self->immediate_check)
    {
      log_reader_force_check_in_next_poll(self);
      return;
    }

  switch (prepare_action)
    {
    case LPPA_POLL_IO:
      poll_events_update_watches(self->poll_events, cond);
      break;
    case LPPA_FORCE_SCHEDULE_FETCH:
      log_reader_force_check_in_next_poll(self);
      break;
    case LPPA_SUSPEND:
      log_reader_suspend_until_awoken(self);
      break;
    default:
      g_assert_not_reached();
      break;
    }
}
예제 #4
0
/* NOTE: the return value is only used during initialization, and it is not
 * expected that it'd change once it returns success */
static gboolean
log_reader_start_watches(LogReader *self)
{
  gint fd;
  GIOCondition cond;

  log_proto_server_prepare(self->proto, &fd, &cond);

  if (self->options->follow_freq > 0)
    {
      /* follow freq specified (only the file source does that, go into timed polling */

      /* NOTE: the fd may not be set here, as it may not have been opened yet */
      iv_timer_register(&self->follow_timer);
    }
  else
    {
      if (fd < 0)
        {
          msg_error("In order to poll non-yet-existing files, follow_freq() must be set",
                    NULL);
          return FALSE;
        }

      /* we have an FD, it is possible to poll it, register it  */
      self->fd_watch.fd = fd;
      if (self->pollable_state < 0)
        {
          self->pollable_state = !iv_fd_register_try(&self->fd_watch);
        }
      else if (self->pollable_state > 0)
        {
          iv_fd_register(&self->fd_watch);
        }

      if (self->pollable_state == 0)
        {
          msg_error("Unable to determine how to monitor this fd, follow_freq() not set and it is not possible to poll it with the current ivykis polling method, try changing IV_EXCLUDE_POLL_METHOD environment variable",
                    evt_tag_int("fd", fd),
                    NULL);
          return FALSE;
        }
    }

  log_reader_update_watches(self);
  return TRUE;
}
예제 #5
0
static void
log_reader_update_watches(LogReader *self)
{
  gint fd;
  GIOCondition cond;
  gboolean free_to_send;

  main_loop_assert_main_thread();
  
  self->suspended = FALSE;
  free_to_send = log_source_free_to_send(&self->super);
  if (!free_to_send ||
      self->immediate_check ||
      log_proto_server_prepare(self->proto, &fd, &cond))
    {
      /* we disable all I/O related callbacks here because we either know
       * that we can continue (e.g.  immediate_check == TRUE) or we know
       * that we can't continue even if data would be available (e.g.
       * free_to_send == FALSE)
       */

      self->immediate_check = FALSE;
      if (iv_fd_registered(&self->fd_watch))
        {
          iv_fd_set_handler_in(&self->fd_watch, NULL);
          iv_fd_set_handler_out(&self->fd_watch, NULL);

          /* we disable the error handler too, as it might be
           * triggered even when we don't want to read data
           * (e.g. log_source_free_to_send() is FALSE).
           *
           * And at least on Linux, it may happen that EPOLLERR is
           * set, while there's still data in the socket buffer.  Thus
           * in reaction to an EPOLLERR, we could possibly send
           * further messages without validating the
           * log_source_free_to_send() would allow us to, potentially
           * overflowing our window (and causing a failed assertion in
           * log_source_queue().
           */

          iv_fd_set_handler_err(&self->fd_watch, NULL);
        }

      if (iv_timer_registered(&self->follow_timer))
        iv_timer_unregister(&self->follow_timer);

      if (free_to_send)
        {
          /* we have data in our input buffer, we need to start working
           * on it immediately, without waiting for I/O events */
          if (!iv_task_registered(&self->restart_task))
            {
              iv_task_register(&self->restart_task);
            }
        }
      else
        {
          self->suspended = TRUE;
        }
      return;
    }

  if (iv_fd_registered(&self->fd_watch))
    {
      /* this branch is executed when our fd is connected to a non-file
       * source (e.g. TCP, UDP socket). We set up I/O callbacks here.
       * files cannot be polled using epoll, as it causes an I/O error
       * (thus abort in ivykis).
       */
      if (cond & G_IO_IN)
        iv_fd_set_handler_in(&self->fd_watch, log_reader_io_process_input);
      else
        iv_fd_set_handler_in(&self->fd_watch, NULL);

      if (cond & G_IO_OUT)
        iv_fd_set_handler_out(&self->fd_watch, log_reader_io_process_input);
      else
        iv_fd_set_handler_out(&self->fd_watch, NULL);

      if (cond & (G_IO_IN + G_IO_OUT))
        iv_fd_set_handler_err(&self->fd_watch, log_reader_io_process_input);
      else
        iv_fd_set_handler_err(&self->fd_watch, NULL);

    }
  else
    {
      if (self->options->follow_freq > 0)
        {
          if (iv_timer_registered(&self->follow_timer))
            iv_timer_unregister(&self->follow_timer);
          iv_validate_now();
          self->follow_timer.expires = iv_now;
          timespec_add_msec(&self->follow_timer.expires, self->options->follow_freq);
          iv_timer_register(&self->follow_timer);
        }
      else
        {
          /* NOTE: we don't need to unregister the timer here as follow_freq
           * never changes during runtime, thus if ever it was registered that
           * also means that we go into the if branch above. */
        }
    }
}