add_recv_timestamp(&lem.header, now);
fixup_pipe_msg(&lem, payload_size);
- if (qos_is_enabled(&server->qos))
- qos_add_log(&server->qos, &lem.header);
+ if (server->qos)
+ qos_add_log(server->qos, &lem.header);
r = buffer_append(&lem.header, wr->buf_ptr);
wr->readed -= ple->len;
memmove(wr->buffer, wr->buffer + ple->len, sizeof wr->buffer - ple->len);
assert(lem.header.len <= sizeof(lem));
assert(((char *)&lem)[lem.header.len - 1] == '\0');
- if (qos_is_enabled(&server->qos))
- qos_add_log(&server->qos, &lem.header);
+ if (server->qos)
+ qos_add_log(server->qos, &lem.header);
r = buffer_append(&lem.header, wr->buf_ptr);
if (r != 0)
return 0;
}
-void qos_periodic_check(struct logger *server)
-{
- struct qos_module *const qos = &server->qos;
- struct timespec ts_mono;
- if (clock_gettime(CLOCK_MONOTONIC, &ts_mono))
- return;
-
- if (ts_mono.tv_sec < qos->cancel_limits_at.tv_sec)
- return;
- if (ts_mono.tv_sec == qos->cancel_limits_at.tv_sec
- && ts_mono.tv_nsec < qos->cancel_limits_at.tv_nsec)
- return;
-
- if (metrics_get_total(qos->log_metrics) >= qos->threshold)
- qos_apply_limits(qos);
- else
- qos_relax_limits(qos);
-
- qos_set_next_update_time(qos, ts_mono);
- metrics_clear(qos->log_metrics);
-}
-
/**
* @brief FD limit handler
* @details Checks whether the FD limit was reached and leaves logs about it if so
l->buf_params = data->buf_params;
- l->qos.log_metrics = metrics_create();
- if (!l->qos.log_metrics)
- return -ENOMEM;
+ if (data->qos) {
+ l->qos = data->qos;
+ data->qos = NULL;
- l->qos.max_throughput = data->qos_max_throughput;
- l->qos.threshold = data->qos_threshold;
- l->qos.threshold_reapply = data->qos_threshold_reapply;
- l->qos.limit_duration = data->qos_limit_duration;
- l->qos.file_path = data->qos_file_path;
- l->qos.distribution_func = data->distribution_func;
- data->qos_file_path = NULL;
+ l->qos->log_metrics = metrics_create();
+ if (!l->qos->log_metrics)
+ return -ENOMEM;
+ }
// Check if the daemon is being launched for the first time since reboot
bool first_time;
if (!g_backend.logger_readers[id])
continue;
- if (qos_is_enabled(&l->qos)) {
- r = reader_add_subreader_metrics(&g_backend.logger_readers[id]->common, &l->qos);
+ if (l->qos) {
+ r = reader_add_subreader_metrics(&g_backend.logger_readers[id]->common, l->qos);
if (r < 0) {
reader_free(&g_backend.logger_readers[id]->common);
g_backend.logger_readers[id] = NULL;
epoll_metadata_destroy(&l->epoll_common);
epoll_metadata_destroy(&l->epoll_socket);
- qos_free(&l->qos);
+ qos_free(l->qos);
}
/**
return false;
service_all_readers(server);
- qos_periodic_check(server);
+
+ if (server->qos)
+ qos_periodic_check(server->qos);
+
return true;
}
data->epoll_time = log_config_get_int(&conf, "epoll_time_ms", DEFAULT_EPOLL_TIME_MS);
g_backend.lazy_polling_total = 0; // Android Logger backend only, read below
- const char *const qos_file_path = log_config_get(&conf, "qos_file_path");
- data->qos_file_path = qos_file_path ? strdup(qos_file_path) : NULL;
+ struct qos_module qos = {0, };
+
+ qos.file_path = (char *) log_config_get(&conf, "qos_file_path");
+ qos.limit_duration = log_config_get_int(&conf, "qos_refresh_rate_s", DEFAULT_QOS_LIMIT_DURATION_S);
+ qos.max_throughput = log_config_get_int(&conf, "qos_max_throughput_logs", DEFAULT_QOS_THROUGHPUT_LOGS);
+ qos.threshold = log_config_get_int(&conf, "qos_threshold_logs", DEFAULT_QOS_THRESHOLD_LOGS);
+ qos.threshold_reapply = log_config_get_int(&conf, "qos_threshold_reapply_logs", DEFAULT_QOS_THRESHOLD_REAPPLY_LOGS);
+ qos.distribution_func = qos_get_distribution_func_by_name(log_config_get(&conf, "qos_method"));
- data->qos_limit_duration = log_config_get_int(&conf, "qos_refresh_rate_s", DEFAULT_QOS_LIMIT_DURATION_S);
- data->qos_max_throughput = log_config_get_int(&conf, "qos_max_throughput_logs", DEFAULT_QOS_THROUGHPUT_LOGS);
- data->qos_threshold = log_config_get_int(&conf, "qos_threshold_logs", DEFAULT_QOS_THRESHOLD_LOGS);
- data->qos_threshold_reapply = log_config_get_int(&conf, "qos_threshold_reapply_logs", DEFAULT_QOS_THRESHOLD_REAPPLY_LOGS);
- data->distribution_func = qos_get_distribution_func_by_name(log_config_get(&conf, "qos_method"));
+ if (qos.threshold > 0
+ && qos.max_throughput > 0
+ && qos.file_path && strlen(qos.file_path) > 0) {
+ data->qos = malloc(sizeof *data->qos);
+ if (!data->qos) {
+ ret = -ENOMEM;
+ goto end;
+ }
+ *data->qos = qos;
+ data->qos->file_path = strdup(qos.file_path);
+ if (!data->qos->file_path) {
+ ret = -ENOMEM;
+ goto end;
+ }
+ }
const char *const first_time_file_path = log_config_get(&conf, "first_time_file_path");
data->first_time_file_path = first_time_file_path ? strdup(first_time_file_path) : NULL;
{
list_remove_if(&data->logfile_configs, NULL, cond_string_free);
free(data->dynamic_config_dir);
- free(data->qos_file_path);
+ qos_free(data->qos);
free(data->first_time_file_path);
}
#include <stdlib.h>
#include <logcommon.h>
-bool qos_is_enabled(const struct qos_module *qos)
-{
- assert(qos);
- return qos->threshold > 0 && qos->max_throughput > 0 && qos->file_path && strlen(qos->file_path) > 0;
-}
-
void qos_create_limits_file(struct qos_module *qos, bool is_limiting)
{
__attribute__((cleanup(close_fd))) int fd = creat(qos->file_path, 0644);
qos_create_limits_file(qos, false);
}
+void qos_periodic_check(struct qos_module *qos)
+{
+ struct timespec ts_mono;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts_mono))
+ return;
+
+ if (ts_mono.tv_sec < qos->cancel_limits_at.tv_sec)
+ return;
+ if (ts_mono.tv_sec == qos->cancel_limits_at.tv_sec
+ && ts_mono.tv_nsec < qos->cancel_limits_at.tv_nsec)
+ return;
+
+ if (metrics_get_total(qos->log_metrics) >= qos->threshold)
+ qos_apply_limits(qos);
+ else
+ qos_relax_limits(qos);
+
+ qos_set_next_update_time(qos, ts_mono);
+ metrics_clear(qos->log_metrics);
+}
+
void qos_add_log(struct qos_module *qos, const struct dlogutil_entry *due)
{
assert(qos);
void qos_free(struct qos_module *qos)
{
+ if (!qos)
+ return;
+
metrics_destroy(qos->log_metrics);
free(qos->file_path);
+ free(qos);
}