registry_log.c 4.4 KB

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