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); }
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; } }
static void _update_watches(JournalReader *self) { gboolean free_to_send; main_loop_assert_main_thread(); _start_watches_if_stopped(self); free_to_send = log_source_free_to_send(&self->super); if (!free_to_send) { _suspend_until_awoken(self); return; } if (self->immediate_check) { _force_check_in_next_poll(self); return; } poll_events_update_watches(self->poll_events, G_IO_IN); }
/* follow timer callback. Check if the file has new content, or deleted or * moved. Ran every follow_freq seconds. */ static void poll_file_changes_check_file(gpointer s) { PollFileChanges *self = (PollFileChanges *) s; struct stat st, followed_st; off_t pos = -1; gint fd = self->fd; msg_trace("Checking if the followed file has new lines", evt_tag_str("follow_filename", self->follow_filename)); if (fd >= 0) { pos = lseek(fd, 0, SEEK_CUR); if (pos == (off_t) -1) { msg_error("Error invoking seek on followed file", evt_tag_errno("error", errno)); goto reschedule; } if (fstat(fd, &st) < 0) { if (errno == ESTALE) { msg_trace("log_reader_fd_check file moved ESTALE", evt_tag_str("follow_filename", self->follow_filename)); log_pipe_notify(self->control, NC_FILE_MOVED, self); return; } else { msg_error("Error invoking fstat() on followed file", evt_tag_errno("error", errno)); goto reschedule; } } msg_trace("log_reader_fd_check", evt_tag_int("pos", pos), evt_tag_int("size", st.st_size)); if (pos < st.st_size || !S_ISREG(st.st_mode)) { /* we have data to read */ poll_events_invoke_callback(s); return; } else if (pos == st.st_size) { /* we are at EOF */ log_pipe_notify(self->control, NC_FILE_EOF, self); } else if (pos > st.st_size) { /* the last known position is larger than the current size of the file. it got truncated. Restart from the beginning. */ log_pipe_notify(self->control, NC_FILE_MOVED, self); /* we may be freed by the time the notification above returns */ return; } } if (self->follow_filename) { if (stat(self->follow_filename, &followed_st) != -1) { if (fd < 0 || (st.st_ino != followed_st.st_ino && followed_st.st_size > 0)) { msg_trace("log_reader_fd_check file moved eof", evt_tag_int("pos", pos), evt_tag_int("size", followed_st.st_size), evt_tag_str("follow_filename", self->follow_filename)); /* file was moved and we are at EOF, follow the new file */ log_pipe_notify(self->control, NC_FILE_MOVED, self); /* we may be freed by the time the notification above returns */ return; } } else { msg_verbose("Follow mode file still does not exist", evt_tag_str("filename", self->follow_filename)); } } reschedule: poll_events_update_watches(s, G_IO_IN); }