master
c 137 lines 4.54 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "database/rrd.h"
4 #include "registry_internals.h"
5
6 void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, STRING *u, const char *name) {
7 if(likely(registry.log_fp)) {
8 if(unlikely(fprintf(registry.log_fp, "%c\t%08x\t%s\t%s\t%s\t%s\n",
9 action,
10 p->last_t,
11 p->guid,
12 m->guid,
13 name,
14 string2str(u)) < 0))
15 netdata_log_error("Registry: failed to save log. Registry data may be lost in case of abnormal restart.");
16
17 // we increase the counter even on failures
18 // so that the registry will be saved periodically
19 registry.log_count++;
20
21 // this must be outside the log_lock(), or a deadlock will happen.
22 // registry_db_save() checks the same inside the log_lock, so only
23 // one thread will save the db
24 if(unlikely(registry_db_should_be_saved()))
25 registry_db_save();
26 }
27 }
28
29 int registry_log_open(void) {
30 if(registry.log_fp)
31 fclose(registry.log_fp);
32
33 registry.log_fp = fopen(registry.log_filename, "a");
34 if(registry.log_fp) {
35 if (setvbuf(registry.log_fp, NULL, _IOLBF, 0) != 0)
36 netdata_log_error("Cannot set line buffering on registry log file.");
37 return 0;
38 }
39
40 netdata_log_error("Cannot open registry log file '%s'. Registry data will be lost in case of netdata or server crash.", registry.log_filename);
41 return -1;
42 }
43
44 void registry_log_close(void) {
45 if(registry.log_fp) {
46 fclose(registry.log_fp);
47 registry.log_fp = NULL;
48 }
49 }
50
51 void registry_log_recreate(void) {
52 if(registry.log_fp != NULL) {
53 registry_log_close();
54
55 // open it with truncate
56 registry.log_fp = fopen(registry.log_filename, "w");
57 if(registry.log_fp) fclose(registry.log_fp);
58 else
59 netdata_log_error("Cannot truncate registry log '%s'", registry.log_filename);
60
61 registry.log_fp = NULL;
62 registry_log_open();
63 }
64 }
65
66 ssize_t registry_log_load(void) {
67 ssize_t line = -1;
68
69 // closing the log is required here
70 // otherwise we will append to it the values we read
71 registry_log_close();
72
73 netdata_log_debug(D_REGISTRY, "Registry: loading active db from: %s", registry.log_filename);
74 FILE *fp = fopen(registry.log_filename, "r");
75 if(!fp)
76 netdata_log_error("Registry: cannot open registry file: %s", registry.log_filename);
77 else {
78 char *s, buf[4096 + 1];
79 line = 0;
80 size_t len = 0;
81
82 while ((s = fgets_trim_len(buf, 4096, fp, &len))) {
83 line++;
84
85 switch (s[0]) {
86 case 'A': // accesses
87 case 'D': // deletes
88
89 // verify it is valid
90 if (unlikely(len < 85 || s[1] != '\t' || s[10] != '\t' || s[47] != '\t' || s[84] != '\t')) {
91 netdata_log_error("Registry: log line %zd is wrong (len = %zu).", line, len);
92 continue;
93 }
94 s[1] = s[10] = s[47] = s[84] = '\0';
95
96 // get the variables
97 time_t when = (time_t)strtoul(&s[2], NULL, 16);
98 char *person_guid = &s[11];
99 char *machine_guid = &s[48];
100 char *name = &s[85];
101
102 // skip the name to find the url
103 char *url = name;
104 while(*url && *url != '\t') url++;
105 if(!*url) {
106 netdata_log_error("Registry: log line %zd does not have a url.", line);
107 continue;
108 }
109 *url++ = '\0';
110
111 // make sure the person exists
112 // without this, a new person guid will be created
113 REGISTRY_PERSON *p = registry_person_find(person_guid);
114 if(!p) p = registry_person_allocate(person_guid, when);
115
116 if(s[0] == 'A')
117 registry_request_access(p->guid, machine_guid, url, name, when);
118 else
119 registry_request_delete(p->guid, machine_guid, url, name, when);
120
121 registry.log_count++;
122 break;
123
124 default:
125 netdata_log_error("Registry: ignoring line %zd of filename '%s': %s.", line, registry.log_filename, s);
126 break;
127 }
128 }
129
130 fclose(fp);
131 }
132
133 // open the log again
134 registry_log_open();
135
136 return line;
137 }