* @brief Process log
* @details Processes a raw log and, if it's old enough, prints it
* @param[in] e The entry to process
- * @param[in] last Last entry in the buffer
+ * @param[in] ts Reference timestamp
* @param[in] l_file Output file metadata
* @param[in] timeout Sort timeout in ms
- * @param[in] ignore_timeout Whether to print regardless of timeout
* @return 1 if the log was old enough, else 0
*/
-static int process_log(struct logger_entry *e, struct logger_entry *last, struct log_file *l_file, long timeout, int ignore_timeout)
+static int process_log(struct logger_entry *e, struct timespec ts, struct log_file *l_file, long timeout)
{
assert(e);
- assert(last);
assert(l_file);
- long s = last->sec_recv_mono - e->sec_recv_mono;
- long ns = last->nsec_recv_mono - e->nsec_recv_mono;
+ long s = ts.tv_sec - e->sec_recv_mono;
+ long ns = ts.tv_nsec - e->nsec_recv_mono;
if (ns < 0) {
ns += 1000000000;
--s;
}
- if (ignore_timeout || timeout <= (s*1000 + ns/1000000)) {
+ if (timeout <= (s*1000 + ns/1000000)) {
logfile_write_with_rotation(e, l_file);
return 1;
} else
return 0;
}
+void flush_logs(struct sort_vector *logs, struct log_file *l_file)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ while (!sort_vector_empty(logs) && process_log(sort_vector_back(logs), ts, l_file, logs->timeout))
+ sort_vector_pop(logs);
+}
+
/**
* @brief Handle input
* @details The main loop reading log data
assert(l_file);
int nfds;
- int filled = 1;
int r;
- int accepting_logs = 1;
- struct fd_info * fdi;
+ struct fd_info *fdi = NULL;
int pipes = 0;
- int looping = 1;
- int timeout = dump ? 5 : 100;
- int resttime = 0;
- int force_flush = 0;
int epollfd;
struct epoll_event ev = { .events = EPOLLIN };
struct fd_info *swap_tmp = data_fds[nfds];
data_fds[nfds--] = data_fds[--fd_count];
data_fds[fd_count] = swap_tmp; // swap non-destructively lest memory leak
- if (!dump)
- accepting_logs = -1;
}
}
- while (looping) {
- if (dump > 0) {
- if (!accepting_logs) {
- while (sort_vector_used_size(logs) > dump)
- sort_vector_pop(logs);
- dump = 0;
- filled = 0;
- }
- } else {
- int last_printed = logs->begin;
- while (!filled && !sort_vector_empty(logs))
- if (process_log(logs->data[logs->begin],
- logs->data[(logs->end ?: logs->size) - 1],
- l_file, logs->timeout, force_flush))
- sort_vector_pop(logs);
- else
- break;
- if (last_printed == logs->begin && !sort_vector_empty(logs)) {
- resttime += timeout;
- if (resttime >= logs->timeout)
- force_flush = 1;
- } else {
- resttime = 0;
- force_flush = 0;
- }
- }
+ while (true) {
+ if (!fdi && !dump)
+ flush_logs(logs, l_file);
- if (!accepting_logs) {
- if (sort_vector_empty(logs))
- break;
- else
- continue;
- }
-
- filled = 1;
- nfds = epoll_wait(epollfd, &ev, 1, timeout);
+ nfds = epoll_wait(epollfd, &ev, 1, 100);
if (nfds > 0)
fdi = (struct fd_info*) ev.data.ptr;
else if (nfds == 0 && fd_count > 0)
fdi = data_fds[fd_count - 1];
+ else if (dump)
+ break;
else {
- filled = 0;
- if (dump && !pipes) {
- force_flush = 1;
- accepting_logs = 0;
- }
+ fdi = NULL;
continue;
}
break;
}
+ while (fdi->ops->has_log(fdi))
+ if (fdi_push_log(fdi, logs, l_file))
+ break;
+
if (r == 0 || (dump && fdi->log_len <= 0 && fdi->log_len != UNLIMITED_LOG_LEN)) {
if (fdi->ops != &ops_binfile) // HACK
epoll_ctl(epollfd, EPOLL_CTL_DEL, fdi->fd, NULL);
if (fdi->ops == &ops_pipe && dump) // HACK
--pipes;
- else if (--fd_count <= 0) {
- accepting_logs = 0;
- filled = 0;
- }
- }
-
- while (fdi->ops->has_log(fdi))
- if (fdi_push_log(fdi, logs, l_file)) {
- looping = 0;
+ else if (--fd_count <= 0)
break;
- }
+ }
}
+
+ if (dump > 0)
+ while (sort_vector_used_size(logs) > dump)
+ sort_vector_pop(logs);
+
+ logs->timeout = 0;
+ flush_logs(logs, l_file);
}
int parse_options(int argc, char **argv, struct log_file *l_file, struct sort_vector *logs, int *enabled_buffers, list_head *file_input_names, action_e *action, int *dump, list_head *filters)