static void log_reader_idle_timeout(void *cookie) { LogReader *self = (LogReader *) cookie; msg_notice("Source timeout has elapsed, closing connection", evt_tag_int("fd", log_proto_server_get_fd(self->proto))); log_pipe_notify(self->control, NC_CLOSE, self); }
void _handle_file_deleted(WildcardSourceDriver *self, const DirectoryMonitorEvent *event) { FileReader *reader = g_hash_table_lookup(self->file_readers, event->full_path); if (reader) { msg_debug("Monitored file is deleted", evt_tag_str("filename", event->full_path)); log_pipe_notify(&reader->super, NC_FILE_DELETED, NULL); } if (pending_file_list_remove(self->waiting_list, event->full_path)) { msg_warning("Waiting file was deleted, it wasn't read at all", evt_tag_str("filename", event->full_path)); } }
static void _work_finished(gpointer s) { JournalReader *self = (JournalReader *) s; if (self->notify_code) { gint notify_code = self->notify_code; self->notify_code = 0; log_pipe_notify(self->control, notify_code, self); } if (self->super.super.flags & PIF_INITIALIZED) { _update_watches(self); } log_pipe_unref(&self->super.super); }
static void log_reader_work_finished(void *s) { LogReader *self = (LogReader *) s; if (self->pending_proto_present) { /* pending proto is only set in the main thread, so no need to * lock it before coming here. After we're syncing with the * log_writer_reopen() call, quite possibly coming from a * non-main thread. */ g_static_mutex_lock(&self->pending_proto_lock); if (self->proto) log_proto_free(self->proto); self->proto = self->pending_proto; self->pending_proto = NULL; self->pending_proto_present = FALSE; g_cond_signal(self->pending_proto_cond); g_static_mutex_unlock(&self->pending_proto_lock); } if (self->notify_code) { gint notify_code = self->notify_code; self->notify_code = 0; log_pipe_notify(self->control, &self->super.super, notify_code, self); } if (self->super.super.flags & PIF_INITIALIZED) { /* reenable polling the source assuming that we're still in * business (e.g. the reader hasn't been uninitialized) */ log_proto_reset_error(self->proto); log_reader_start_watches(self); } log_pipe_unref(&self->super.super); }
void log_pipe_forward_notify(LogPipe *self, LogPipe *sender, gint notify_code, gpointer user_data) { log_pipe_notify(self->pipe_next, self, notify_code, user_data); }
/* returns: notify_code (NC_XXXX) or 0 for success */ static gint log_reader_fetch_log(LogReader *self) { GSockAddr *sa; gint msg_count = 0; gboolean may_read = TRUE; if (self->waiting_for_preemption) may_read = FALSE; /* NOTE: this loop is here to decrease the load on the main loop, we try * to fetch a couple of messages in a single run (but only up to * fetch_limit). */ while (msg_count < self->options->fetch_limit && !main_loop_io_worker_job_quit()) { const guchar *msg; gsize msg_len; LogProtoStatus status; msg = NULL; sa = NULL; /* NOTE: may_read is used to implement multi-read checking. It * is initialized to TRUE to indicate that the protocol is * allowed to issue a read(). If multi-read is disallowed in the * protocol, it resets may_read to FALSE after the first read was issued. */ status = log_proto_fetch(self->proto, &msg, &msg_len, &sa, &may_read); switch (status) { case LPS_EOF: case LPS_ERROR: g_sockaddr_unref(sa); return status == LPS_ERROR ? NC_READ_ERROR : NC_CLOSE; case LPS_SUCCESS: break; default: g_assert_not_reached(); break; } if (!msg) { /* no more messages for now */ break; } if (msg_len > 0 || (self->options->flags & LR_EMPTY_LINES)) { msg_count++; if (!log_reader_handle_line(self, msg, msg_len, sa)) { /* window is full, don't generate further messages */ log_proto_queued(self->proto); g_sockaddr_unref(sa); break; } } log_proto_queued(self->proto); g_sockaddr_unref(sa); } if (self->options->flags & LR_PREEMPT) { if (log_proto_is_preemptable(self->proto)) { self->waiting_for_preemption = FALSE; log_pipe_notify(self->control, &self->super.super, NC_FILE_SKIP, self); } else { self->waiting_for_preemption = TRUE; } } if (msg_count == self->options->fetch_limit) self->immediate_check = TRUE; return 0; }
/* follow timer callback. Check if the file has new content, or deleted or * moved. Ran every follow_freq seconds. */ static void log_reader_io_follow_file(gpointer s) { LogReader *self = (LogReader *) s; struct stat st, followed_st; off_t pos = -1; gint fd = log_proto_get_fd(self->proto); msg_trace("Checking if the followed file has new lines", evt_tag_str("follow_filename", self->follow_filename), NULL); 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), NULL); 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), NULL); log_pipe_notify(self->control, &self->super.super, NC_FILE_MOVED, self); return; } else { msg_error("Error invoking fstat() on followed file", evt_tag_errno("error", errno), NULL); goto reschedule; } } msg_trace("log_reader_fd_check", evt_tag_int("pos", pos), evt_tag_int("size", st.st_size), NULL); if (pos < st.st_size) { /* we have data to read */ log_reader_io_process_input(s); return; } else if (pos == st.st_size) { /* we are at EOF */ log_pipe_notify(self->control, &self->super.super, 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, &self->super.super, 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), NULL); /* file was moved and we are at EOF, follow the new file */ log_pipe_notify(self->control, &self->super.super, 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), NULL); } } reschedule: log_reader_update_watches(self); }
static gboolean log_reader_fd_check(GSource *source) { LogReaderWatch *self = (LogReaderWatch *) source; if (!log_source_free_to_send(&self->reader->super)) return FALSE; if (self->reader->options->follow_freq > 0) { struct stat st, followed_st; off_t pos = -1; gint fd = log_proto_get_fd(self->reader->proto); /* FIXME: this is a _HUGE_ layering violation... */ 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), NULL); return FALSE; } if (fstat(fd, &st) < 0) { if (errno == ESTALE) { msg_trace("log_reader_fd_check file moved ESTALE", evt_tag_str("follow_filename",self->reader->follow_filename), NULL); log_pipe_notify(self->reader->control, &self->reader->super.super, NC_FILE_MOVED, self); return FALSE; } else { msg_error("Error invoking fstat() on followed file", evt_tag_errno("error", errno), NULL); return FALSE; } } msg_trace("log_reader_fd_check", evt_tag_int("pos", pos), evt_tag_int("size", st.st_size), NULL); if (pos < st.st_size) { return TRUE; } else if (pos == st.st_size) { log_pipe_notify(self->reader->control, &self->reader->super.super, NC_FILE_EOF, self); } else if (pos > st.st_size) { /* reopen the file */ log_pipe_notify(self->reader->control, &self->reader->super.super, NC_FILE_MOVED, self); } } if (self->reader->follow_filename && stat(self->reader->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->reader->follow_filename), NULL); /* file was moved and we are at EOF, follow the new file */ log_pipe_notify(self->reader->control, &self->reader->super.super, NC_FILE_MOVED, self); } } else if (self->reader->follow_filename) { GTimeVal now; g_source_get_current_time(source, &now); if (g_time_val_diff(&now, &self->last_follow_freq_check) > self->reader->options->follow_freq * 1000) { msg_verbose("Follow mode file still does not exist", evt_tag_str("filename", self->reader->follow_filename), NULL); self->last_follow_freq_check = now; } } return FALSE; } return !!(self->pollfd.revents & (G_IO_IN | G_IO_OUT | G_IO_ERR | G_IO_HUP)); }
static void _last_msg_sent(gpointer s) { LogReader *self = (LogReader *) s; log_pipe_notify(self->control, NC_LAST_MSG_SENT, self); }