@cryptotaxi247 / netdata-1 / commits / 83df0e794

simple_pattern now also supports asterisks in the middle; cgroups cleanup;

Costa Tsaousis (ktsaou) committed Jan 15, 2017 at 06:03 UTC 83df0e7941994cb3a081af565f4b11f3c436bfe0
7 files changed +283 -212
CMakeLists.txt
+1 -1
@@ -101,7 +101,7 @@ set(NETDATA_SOURCE_FILES
101 src/registry_person.c
102 src/registry_person.h
103 src/registry_machine.c
104 - src/registry_machine.h src/registry_internals.c src/registry_init.c src/registry_db.c src/registry_log.c src/proc_uptime.c src/sys_devices_system_edac_mc.c src/plugin_proc_diskspace.c src/plugin_proc_diskspace.h)
104 + src/registry_machine.h src/registry_internals.c src/registry_init.c src/registry_db.c src/registry_log.c src/proc_uptime.c src/sys_devices_system_edac_mc.c src/plugin_proc_diskspace.c src/plugin_proc_diskspace.h src/simple_pattern.c src/simple_pattern.h)
105
106 set(APPS_PLUGIN_SOURCE_FILES
107 src/appconfig.c
src/Makefile.am
+1
@@ -46,6 +46,7 @@ netdata_SOURCES = \
46 plugins_d.c plugins_d.h \
47 popen.c popen.h \
48 socket.c socket.h \
49 + simple_pattern.c simple_pattern.h \
50 sys_fs_cgroup.c \
51 sys_devices_system_edac_mc.c \
52 procfile.c procfile.h \
src/common.c
-126
@@ -1187,129 +1187,3 @@ int read_single_number_file(const char *filename, unsigned long long *result) {
1187 *result = strtoull(buffer, NULL, 0);
1188 return 0;
1189 }
1190 -
1191 -// ----------------------------------------------------------------------------
1192 -// simple_pattern_match
1193 -
1194 -struct simple_pattern {
1195 - const char *match;
1196 - size_t len;
1197 - NETDATA_SIMPLE_PREFIX_MODE mode;
1198 - struct simple_pattern *next;
1199 -};
1200 -
1201 -NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
1202 - struct simple_pattern *root = NULL, *last = NULL;
1203 -
1204 - if(unlikely(!list || !*list)) return root;
1205 -
1206 - char *a = strdupz(list);
1207 - if(a && *a) {
1208 - char *s = a;
1209 -
1210 - while(s && *s) {
1211 - // skip all spaces
1212 - while(isspace(*s)) s++;
1213 -
1214 - // empty string
1215 - if(unlikely(!*s)) break;
1216 -
1217 - // find the next space
1218 - char *c = s;
1219 - while(*c && !isspace(*c)) c++;
1220 -
1221 - // find the next word
1222 - char *n;
1223 - if(likely(*c)) n = c + 1;
1224 - else n = NULL;
1225 -
1226 - // terminate our string
1227 - *c = '\0';
1228 -
1229 - char buf[100 + 1];
1230 - strncpy(buf, s, 100);
1231 - buf[100] = '\0';
1232 - if(likely(n)) *c = ' ';
1233 - s = buf;
1234 -
1235 - NETDATA_SIMPLE_PREFIX_MODE mode;
1236 - size_t len = strlen(s);
1237 - if(len >= 2 && *s == '*' && s[len - 1] == '*') {
1238 - s[len - 1] = '\0';
1239 - s++;
1240 - mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
1241 - }
1242 - else if(len >= 1 && *s == '*') {
1243 - s++;
1244 - mode = NETDATA_SIMPLE_PATTERN_MODE_SUFFIX;
1245 - }
1246 - else if(len >= 1 && s[len - 1] == '*') {
1247 - s[len - 1] = '\0';
1248 - mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
1249 - }
1250 - else
1251 - mode = default_mode;
1252 -
1253 - // allocate the structure
1254 - struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
1255 - if(*s) {
1256 - m->match = strdup(s);
1257 - m->len = strlen(m->match);
1258 - m->mode = mode;
1259 - }
1260 - else {
1261 - m->mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
1262 - }
1263 -
1264 - // link it at the end
1265 - if(unlikely(!root))
1266 - root = last = m;
1267 - else {
1268 - last->next = m;
1269 - last = m;
1270 - }
1271 -
1272 - // prepare for next loop
1273 - s = n;
1274 - }
1275 - }
1276 -
1277 - free(a);
1278 - return (NETDATA_SIMPLE_PATTERN *)root;
1279 -}
1280 -
1281 -int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str) {
1282 - struct simple_pattern *m, *root = (struct simple_pattern *)list;
1283 -
1284 - if(unlikely(!root)) return 0;
1285 -
1286 - size_t len = strlen(str);
1287 - for(m = root; m ; m = m->next) {
1288 - if(m->len <= len) {
1289 - switch(m->mode) {
1290 - case NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING:
1291 - if(unlikely(!m->len || strstr(str, m->match)))
1292 - return 1;
1293 - break;
1294 -
1295 - case NETDATA_SIMPLE_PATTERN_MODE_PREFIX:
1296 - if(unlikely(strncmp(str, m->match, m->len) == 0))
1297 - return 1;
1298 - break;
1299 -
1300 - case NETDATA_SIMPLE_PATTERN_MODE_SUFFIX:
1301 - if(unlikely(strcmp(&str[len - m->len], m->match) == 0))
1302 - return 1;
1303 - break;
1304 -
1305 - case NETDATA_SIMPLE_PATTERN_MODE_EXACT:
1306 - default:
1307 - if(unlikely(strcmp(str, m->match) == 0))
1308 - return 1;
1309 - break;
1310 - }
1311 - }
1312 - }
1313 -
1314 - return 0;
1315 -}
src/common.h
+1 -10
@@ -164,6 +164,7 @@
164 // ----------------------------------------------------------------------------
165 // netdata include files
166
167 +#include "simple_pattern.h"
168 #include "avl.h"
169 #include "clocks.h"
170 #include "log.h"
@@ -278,14 +279,4 @@ extern void get_system_HZ(void);
279
280 extern int read_single_number_file(const char *filename, unsigned long long *result);
281
281 -typedef enum {
282 - NETDATA_SIMPLE_PATTERN_MODE_EXACT,
283 - NETDATA_SIMPLE_PATTERN_MODE_PREFIX,
284 - NETDATA_SIMPLE_PATTERN_MODE_SUFFIX,
285 - NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING
286 -} NETDATA_SIMPLE_PREFIX_MODE;
287 -typedef void NETDATA_SIMPLE_PATTERN;
288 -extern NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode);
289 -extern int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str);
290 -
282 #endif /* NETDATA_COMMON_H */
src/simple_pattern.c new
+204
@@ -0,0 +1,204 @@
1 +#include "common.h"
2 +
3 +struct simple_pattern {
4 + const char *match;
5 + size_t len;
6 + NETDATA_SIMPLE_PREFIX_MODE mode;
7 +
8 + struct simple_pattern *child;
9 +
10 + struct simple_pattern *next;
11 +};
12 +
13 +static inline struct simple_pattern *parse_pattern(const char *str, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
14 + info(">>>> PARSE: '%s'", str);
15 +
16 + NETDATA_SIMPLE_PREFIX_MODE mode;
17 + struct simple_pattern *child = NULL;
18 +
19 + char *buf = strdupz(str);
20 + char *s = buf, *c = buf;
21 +
22 + // skip asterisks in front
23 + while(*c == '*') c++;
24 +
25 + // find the next asterisk
26 + while(*c && *c != '*') c++ ;
27 +
28 + // do we have an asterisk in the middle?
29 + if(*c == '*' && c[1] != '\0') {
30 + // yes, we have
31 + child = parse_pattern(c, default_mode);
32 + c[1] = '\0';
33 + }
34 +
35 + // check what this one matches
36 +
37 + size_t len = strlen(s);
38 + if(len >= 2 && *s == '*' && s[len - 1] == '*') {
39 + s[len - 1] = '\0';
40 + s++;
41 + mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
42 + }
43 + else if(len >= 1 && *s == '*') {
44 + s++;
45 + mode = NETDATA_SIMPLE_PATTERN_MODE_SUFFIX;
46 + }
47 + else if(len >= 1 && s[len - 1] == '*') {
48 + s[len - 1] = '\0';
49 + mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
50 + }
51 + else
52 + mode = default_mode;
53 +
54 + // allocate the structure
55 + struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
56 + if(*s) {
57 + m->match = strdup(s);
58 + m->len = strlen(m->match);
59 + m->mode = mode;
60 + }
61 + else {
62 + m->mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
63 + }
64 +
65 + m->child = child;
66 +
67 + free(buf);
68 +
69 + info("PATTERN '%s' is composed by", str);
70 + struct simple_pattern *p;
71 + for(p = m; p ; p = p->child)
72 + info(">>>> COMPONENT: '%s%s%s' (len %zu type %u)",
73 + (p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
74 + p->match,
75 + (p->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
76 + p->len,
77 + p->mode);
78 +
79 + return m;
80 +}
81 +
82 +NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
83 + struct simple_pattern *root = NULL, *last = NULL;
84 +
85 + if(unlikely(!list || !*list)) return root;
86 +
87 + char *buf = strdupz(list);
88 + if(buf && *buf) {
89 + char *s = buf;
90 +
91 + while(s && *s) {
92 + // skip all spaces
93 + while(isspace(*s)) s++;
94 +
95 + // empty string
96 + if(unlikely(!*s)) break;
97 +
98 + // find the next space
99 + char *c = s;
100 + while(*c && !isspace(*c)) c++;
101 +
102 + // find the next word
103 + char *n;
104 + if(likely(*c)) n = c + 1;
105 + else n = NULL;
106 +
107 + // terminate our string
108 + *c = '\0';
109 +
110 + struct simple_pattern *m = parse_pattern(s, default_mode);
111 +
112 + if(likely(n)) *c = ' ';
113 +
114 + // link it at the end
115 + if(unlikely(!root))
116 + root = last = m;
117 + else {
118 + last->next = m;
119 + last = m;
120 + }
121 +
122 + // prepare for next loop
123 + s = n;
124 + }
125 + }
126 +
127 + free(buf);
128 + return (NETDATA_SIMPLE_PATTERN *)root;
129 +}
130 +
131 +static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len) {
132 + info("CHECK string '%s' (len %zu) with pattern '%s%s%s' (len %zu type %u)", str, len,
133 + (m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
134 + m->match,
135 + (m->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
136 + m->len, m->mode);
137 +
138 + char *s;
139 +
140 + if(m->len <= len) {
141 + switch(m->mode) {
142 + case NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING:
143 + if(!m->len) return 1;
144 + if((s = strstr(str, m->match))) {
145 + if(!m->child) return 1;
146 + return match_pattern(m->child, &s[m->len], len - (s - str) - m->len);
147 + }
148 + break;
149 +
150 + case NETDATA_SIMPLE_PATTERN_MODE_PREFIX:
151 + if(unlikely(strncmp(str, m->match, m->len) == 0)) {
152 + if(!m->child) return 1;
153 + return match_pattern(m->child, &str[m->len], len - m->len);
154 + }
155 + break;
156 +
157 + case NETDATA_SIMPLE_PATTERN_MODE_SUFFIX:
158 + if(unlikely(strcmp(&str[len - m->len], m->match) == 0)) {
159 + if(!m->child) return 1;
160 + return 0;
161 + }
162 + break;
163 +
164 + case NETDATA_SIMPLE_PATTERN_MODE_EXACT:
165 + default:
166 + if(unlikely(strcmp(str, m->match) == 0)) {
167 + if(!m->child) return 1;
168 + return 0;
169 + }
170 + break;
171 + }
172 + }
173 +
174 + return 0;
175 +}
176 +
177 +int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str) {
178 + struct simple_pattern *m, *root = (struct simple_pattern *)list;
179 +
180 + if(unlikely(!root)) return 0;
181 +
182 + size_t len = strlen(str);
183 + for(m = root; m ; m = m->next)
184 + if(match_pattern(m, str, len)) {
185 + info("MATCHED string '%s' (len %zu) with pattern '%s%s%s' (len %zu type %u)", str, len,
186 + (m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
187 + m->match,
188 + (m->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
189 + m->len, m->mode);
190 +
191 + struct simple_pattern *p;
192 + for(p = m; p ; p = p->child)
193 + info(">>>> MATCHED COMPONENT: '%s%s%s' (len %zu type %u)",
194 + (p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
195 + p->match,
196 + (p->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
197 + p->len,
198 + p->mode);
199 +
200 + return 1;
201 + }
202 +
203 + return 0;
204 +}
src/simple_pattern.h new
+15
@@ -0,0 +1,15 @@
1 +#ifndef NETDATA_SIMPLE_PATTERN_H
2 +#define NETDATA_SIMPLE_PATTERN_H
3 +
4 +typedef enum {
5 + NETDATA_SIMPLE_PATTERN_MODE_EXACT,
6 + NETDATA_SIMPLE_PATTERN_MODE_PREFIX,
7 + NETDATA_SIMPLE_PATTERN_MODE_SUFFIX,
8 + NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING
9 +} NETDATA_SIMPLE_PREFIX_MODE;
10 +
11 +typedef void NETDATA_SIMPLE_PATTERN;
12 +extern NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode);
13 +extern int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str);
14 +
15 +#endif //NETDATA_SIMPLE_PATTERN_H
src/sys_fs_cgroup.c
+61 -75
@@ -8,8 +8,10 @@ static int cgroup_enable_cpuacct_usage = CONFIG_ONDEMAND_ONDEMAND;
8 static int cgroup_enable_memory = CONFIG_ONDEMAND_ONDEMAND;
9 static int cgroup_enable_devices = CONFIG_ONDEMAND_ONDEMAND;
10 static int cgroup_enable_blkio = CONFIG_ONDEMAND_ONDEMAND;
11 +static int cgroup_enable_systemd_services = CONFIG_ONDEMAND_NO;
12 static int cgroup_enable_new_cgroups_detected_at_runtime = 1;
13 static int cgroup_check_for_new_every = 10;
14 +static int cgroup_update_every = 1;
15 static char *cgroup_cpuacct_base = NULL;
16 static char *cgroup_blkio_base = NULL;
17 static char *cgroup_memory_base = NULL;
@@ -27,13 +29,21 @@ static NETDATA_SIMPLE_PATTERN *systemd_services_cgroups = NULL;
29 static char *cgroups_rename_script = PLUGINS_DIR "/cgroup-name.sh";
30
31 void read_cgroup_plugin_configuration() {
30 - cgroup_check_for_new_every = (int)config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every);
32 + cgroup_update_every = (int)config_get_number("plugin:cgroups", "update every", rrd_update_every);
33 + if(cgroup_update_every < rrd_update_every)
34 + cgroup_update_every = rrd_update_every;
35 +
36 + cgroup_check_for_new_every = (int)config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every * cgroup_update_every);
37 + if(cgroup_check_for_new_every < cgroup_update_every)
38 + cgroup_check_for_new_every = cgroup_update_every;
39
40 cgroup_enable_cpuacct_stat = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct stat", cgroup_enable_cpuacct_stat);
41 cgroup_enable_cpuacct_usage = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct usage", cgroup_enable_cpuacct_usage);
42 cgroup_enable_memory = config_get_boolean_ondemand("plugin:cgroups", "enable memory", cgroup_enable_memory);
43 cgroup_enable_blkio = config_get_boolean_ondemand("plugin:cgroups", "enable blkio", cgroup_enable_blkio);
44
45 + cgroup_enable_systemd_services = config_get_boolean_ondemand("plugin:cgroups", "enable systemd services", cgroup_enable_systemd_services);
46 +
47 char filename[FILENAME_MAX + 1], *s;
48 struct mountinfo *mi, *root = mountinfo_read(0);
49
@@ -94,6 +104,7 @@ void read_cgroup_plugin_configuration() {
104 " *.user "
105 " *.mount "
106 " *.partition "
107 + " *.service "
108 " */ns " // /lxc/*/ns #1397
109 ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
110
@@ -121,10 +132,11 @@ void read_cgroup_plugin_configuration() {
132 " *.user "
133 ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
134
124 - systemd_services_cgroups = netdata_simple_pattern_list_create(
125 - config_get("plugin:cgroups", "cgroups to match as systemd services",
126 - " *.service "
127 - ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
135 + if(cgroup_enable_systemd_services)
136 + systemd_services_cgroups = netdata_simple_pattern_list_create(
137 + config_get("plugin:cgroups", "cgroups to match as systemd services",
138 + " /system.slice/*.service "
139 + ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
140
141 mountinfo_free(root);
142 }
@@ -749,37 +761,40 @@ void cgroup_get_chart_name(struct cgroup *cg) {
761 debug(D_CGROUP, "cgroup '%s' will not be renamed - it matches the list of disabled cgroup renames (will be shown as '%s')", cg->id, cg->chart_id);
762
763
752 - if(netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->id) ||
753 - netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->chart_id)) {
754 - debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') matches systemd services cgroups", cg->id, cg->chart_id, cg->chart_title);
764 + if(cgroup_enable_systemd_services) {
765 + if(netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->id) ||
766 + netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->chart_id)) {
767 + debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') matches systemd services cgroups", cg->id, cg->chart_id, cg->chart_title);
768
756 - char buffer[CGROUP_CHARTID_LINE_MAX + 1];
757 - cg->options |= CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE;
769 + char buffer[CGROUP_CHARTID_LINE_MAX + 1];
770 + cg->options |= CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE;
771
759 - strncpy(buffer, cg->id, CGROUP_CHARTID_LINE_MAX);
760 - char *s = buffer;
772 + strncpy(buffer, cg->id, CGROUP_CHARTID_LINE_MAX);
773 + char *s = buffer;
774
762 - // skip to the last slash
763 - size_t len = strlen(s);
764 - while(len--) if(unlikely(s[len] == '/')) break;
765 - if(len) s = &s[len+1];
775 + // skip to the last slash
776 + size_t len = strlen(s);
777 + while(len--) if(unlikely(s[len] == '/')) break;
778 + if(len) s = &s[len + 1];
779
767 - // remove extension
768 - //len = strlen(s);
769 - //while(len--) if(unlikely(s[len] == '.')) break;
770 - //if(len) s[len] = '\0';
780 + // remove extension
781 + //len = strlen(s);
782 + //while(len--) if(unlikely(s[len] == '.')) break;
783 + //if(len) s[len] = '\0';
784
772 - freez(cg->chart_title);
773 - cg->chart_title = cgroup_title_strdupz(s);
785 + freez(cg->chart_title);
786 + cg->chart_title = cgroup_title_strdupz(s);
787
775 - freez(cg->chart_id);
776 - cg->chart_id = cgroup_chart_id_strdupz(s);
777 - cg->hash_chart = simple_hash(cg->chart_id);
788 + freez(cg->chart_id);
789 + cg->chart_id = cgroup_chart_id_strdupz(s);
790 + cg->hash_chart = simple_hash(cg->chart_id);
791 + cg->enabled = 1;
792
779 - debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
793 + debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
794 + }
795 + else
796 + debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') does not match systemd services groups", cg->id, cg->chart_id, cg->chart_title);
797 }
781 - else
782 - debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') does not match systemd services groups", cg->id, cg->chart_id, cg->chart_title);
798 }
799
800 struct cgroup *cgroup_add(const char *id) {
@@ -1509,29 +1524,6 @@ void update_cgroup_charts(int update_every) {
1524 // ----------------------------------------------------------------------------
1525 // cgroups main
1526
1512 -int do_sys_fs_cgroup(int update_every, usec_t dt) {
1513 - (void)dt;
1514 -
1515 - static int cgroup_global_config_read = 0;
1516 - static time_t last_run = 0;
1517 - time_t now = now_realtime_sec();
1518 -
1519 - if(unlikely(!cgroup_global_config_read)) {
1520 - read_cgroup_plugin_configuration();
1521 - cgroup_global_config_read = 1;
1522 - }
1523 -
1524 - if(unlikely(cgroup_enable_new_cgroups_detected_at_runtime && now - last_run > cgroup_check_for_new_every)) {
1525 - find_all_cgroups();
1526 - last_run = now;
1527 - }
1528 -
1529 - read_all_cgroups(cgroup_root);
1530 - update_cgroup_charts(update_every);
1531 -
1532 - return 0;
1533 -}
1534 -
1527 void *cgroups_main(void *ptr) {
1528 struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
1529
@@ -1546,51 +1538,45 @@ void *cgroups_main(void *ptr) {
1538 struct rusage thread;
1539
1540 // when ZERO, attempt to do it
1549 - int vdo_sys_fs_cgroup = 0;
1550 - int vdo_cpu_netdata = !config_get_boolean("plugin:cgroups", "cgroups plugin resources", 1);
1541 + int vdo_cpu_netdata = config_get_boolean("plugin:cgroups", "cgroups plugin resources", 1);
1542
1552 - // keep track of the time each module was called
1553 - usec_t sutime_sys_fs_cgroup = 0ULL;
1554 -
1555 - // the next time we will run - aligned properly
1556 - usec_t sunext = (now_realtime_sec() - (now_realtime_sec() % rrd_update_every) + rrd_update_every) * USEC_PER_SEC;
1543 + read_cgroup_plugin_configuration();
1544
1545 RRDSET *stcpu_thread = NULL;
1546
1547 + usec_t step = cgroup_update_every * USEC_PER_SEC;
1548 + usec_t find_every = cgroup_check_for_new_every * USEC_PER_SEC, find_next = 0;
1549 for(;;) {
1561 - usec_t sunow;
1562 - if(unlikely(netdata_exit)) break;
1563 -
1564 - // delay until it is our time to run
1565 - while((sunow = now_realtime_usec()) < sunext)
1566 - sleep_usec(sunext - sunow);
1550 + usec_t now = now_monotonic_usec();
1551 + usec_t next = now - (now % step) + step;
1552
1568 - // find the next time we need to run
1569 - while(now_realtime_usec() > sunext)
1570 - sunext += rrd_update_every * USEC_PER_SEC;
1553 + while(now < next) {
1554 + sleep_usec(next - now);
1555 + now = now_monotonic_usec();
1556 + }
1557
1558 if(unlikely(netdata_exit)) break;
1559
1560 // BEGIN -- the job to be done
1561
1576 - if(!vdo_sys_fs_cgroup) {
1577 - debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_fs_cgroup().");
1578 - sunow = now_realtime_usec();
1579 - vdo_sys_fs_cgroup = do_sys_fs_cgroup(rrd_update_every, (sutime_sys_fs_cgroup > 0)?sunow - sutime_sys_fs_cgroup:0ULL);
1580 - sutime_sys_fs_cgroup = sunow;
1562 + if(unlikely(now >= find_next)) {
1563 + find_all_cgroups();
1564 + find_next = now + find_every;
1565 }
1582 - if(unlikely(netdata_exit)) break;
1566 +
1567 + read_all_cgroups(cgroup_root);
1568 + update_cgroup_charts(cgroup_update_every);
1569
1570 // END -- the job is done
1571
1572 // --------------------------------------------------------------------
1573
1588 - if(!vdo_cpu_netdata) {
1574 + if(vdo_cpu_netdata) {
1575 getrusage(RUSAGE_THREAD, &thread);
1576
1577 if(!stcpu_thread) stcpu_thread = rrdset_find("netdata.plugin_cgroups_cpu");
1578 if(!stcpu_thread) {
1593 - stcpu_thread = rrdset_create("netdata", "plugin_cgroups_cpu", NULL, "cgroups", NULL, "NetData CGroups Plugin CPU usage", "milliseconds/s", 132000, rrd_update_every, RRDSET_TYPE_STACKED);
1579 + stcpu_thread = rrdset_create("netdata", "plugin_cgroups_cpu", NULL, "cgroups", NULL, "NetData CGroups Plugin CPU usage", "milliseconds/s", 132000, cgroup_update_every, RRDSET_TYPE_STACKED);
1580
1581 rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL);
1582 rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);