1 /* Copyright (c) 2020, Samsung Electronics Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License. */
19 #include <logcommon.h>
21 bool qos_is_enabled(const struct qos_module *qos)
24 return qos->threshold > 0 && qos->max_throughput > 0 && qos->file_path && strlen(qos->file_path) > 0;
27 void qos_create_limits_file(struct qos_module *qos, bool is_limiting)
29 __attribute__((cleanup(close_fd))) int fd = creat(qos->file_path, 0644);
33 if (!is_limiting) // leave an empty file to reset limits.
37 __attribute__((cleanup(free_ptr))) struct metrics_info *const recv_infos = metrics_get_info(qos->log_metrics, &recv_count);
41 qsort(recv_infos, recv_count, sizeof(*recv_infos), metrics_sort_by_pid_first);
42 __attribute__((cleanup(free_ptr))) struct metrics_pid_aggr_info *const aggr_infos = calloc(recv_count, sizeof(*aggr_infos));
48 for (int i = 0; i < recv_count; ++i) {
49 if (recv_infos[i].pid != last) {
50 aggr_infos[aggr_count].pid = recv_infos[i].pid;
51 aggr_infos[aggr_count].count = 0;
52 for (int j = 0; j < DLOG_PRIO_MAX; ++j)
53 aggr_infos[aggr_count].count += recv_infos[i].count[j];
56 for (int j = 0; j < DLOG_PRIO_MAX; ++j)
57 aggr_infos[aggr_count - 1].count += recv_infos[i].count[j];
61 qos->distribution_func(qos, aggr_infos, aggr_count);
63 const int len = aggr_count * 32;
64 __attribute__((cleanup(free_ptr))) char *buf = malloc(len);
66 for (int i = 0; i < aggr_count; ++i)
67 if (aggr_infos[i].count >= 0) {
68 int w = snprintf(buf + pos, pos - len, "pidlimit|%d=%d\n", aggr_infos[i].pid, aggr_infos[i].count);
73 (void) full_write(fd, buf, pos); // can't do much about write errors; ignore
76 void qos_set_next_update_time(struct qos_module *qos, struct timespec now)
78 qos->cancel_limits_at = now;
79 qos->cancel_limits_at.tv_sec += qos->limit_duration;
82 void qos_apply_limits(struct qos_module *qos)
84 qos->currently_limiting = true;
85 qos_create_limits_file(qos, true);
88 void qos_relax_limits(struct qos_module *qos)
90 qos->currently_limiting = false;
91 qos_create_limits_file(qos, false);
94 void qos_add_log(struct qos_module *qos, const struct dlogutil_entry *due)
99 assert(qos->threshold > 0);
100 assert(qos->file_path);
102 if (!metrics_add_log(qos->log_metrics, due))
105 const int diff = metrics_get_total(qos->log_metrics) - qos->threshold;
109 if (diff == 0 || (qos->threshold_reapply && diff % qos->threshold_reapply == 0))
110 qos_apply_limits(qos); // the inQoSition declares Exterminatus
113 void qos_free(struct qos_module *qos)
115 metrics_destroy(qos->log_metrics);
116 free(qos->file_path);