rrdenginelib.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "rrdengine.h"
  3. int check_file_properties(uv_file file, uint64_t *file_size, size_t min_size)
  4. {
  5. int ret;
  6. uv_fs_t req;
  7. uv_stat_t* s;
  8. ret = uv_fs_fstat(NULL, &req, file, NULL);
  9. if (ret < 0) {
  10. fatal("uv_fs_fstat: %s\n", uv_strerror(ret));
  11. }
  12. fatal_assert(req.result == 0);
  13. s = req.ptr;
  14. if (!(s->st_mode & S_IFREG)) {
  15. error("Not a regular file.\n");
  16. uv_fs_req_cleanup(&req);
  17. return UV_EINVAL;
  18. }
  19. if (s->st_size < min_size) {
  20. error("File length is too short.\n");
  21. uv_fs_req_cleanup(&req);
  22. return UV_EINVAL;
  23. }
  24. *file_size = s->st_size;
  25. uv_fs_req_cleanup(&req);
  26. return 0;
  27. }
  28. /**
  29. * Open file for I/O.
  30. *
  31. * @param path The full path of the file.
  32. * @param flags Same flags as the open() system call uses.
  33. * @param file On success sets (*file) to be the uv_file that was opened.
  34. * @param direct Tries to open a file in direct I/O mode when direct=1, falls back to buffered mode if not possible.
  35. * @return Returns UV error number that is < 0 on failure. 0 on success.
  36. */
  37. int open_file_for_io(char *path, int flags, uv_file *file, int direct)
  38. {
  39. uv_fs_t req;
  40. int fd = -1, current_flags;
  41. fatal_assert(0 == direct || 1 == direct);
  42. for ( ; direct >= 0 ; --direct) {
  43. #ifdef __APPLE__
  44. /* Apple OS does not support O_DIRECT */
  45. direct = 0;
  46. #endif
  47. current_flags = flags;
  48. if (direct) {
  49. current_flags |= O_DIRECT;
  50. }
  51. fd = uv_fs_open(NULL, &req, path, current_flags, S_IRUSR | S_IWUSR, NULL);
  52. if (fd < 0) {
  53. if ((direct) && (UV_EINVAL == fd)) {
  54. error("File \"%s\" does not support direct I/O, falling back to buffered I/O.", path);
  55. } else {
  56. error("Failed to open file \"%s\".", path);
  57. --direct; /* break the loop */
  58. }
  59. } else {
  60. fatal_assert(req.result >= 0);
  61. *file = req.result;
  62. #ifdef __APPLE__
  63. info("Disabling OS X caching for file \"%s\".", path);
  64. fcntl(fd, F_NOCACHE, 1);
  65. #endif
  66. --direct; /* break the loop */
  67. }
  68. uv_fs_req_cleanup(&req);
  69. }
  70. return fd;
  71. }
  72. int is_legacy_child(const char *machine_guid)
  73. {
  74. uuid_t uuid;
  75. char dbengine_file[FILENAME_MAX+1];
  76. if (unlikely(!strcmp(machine_guid, "unittest-dbengine") || !strcmp(machine_guid, "dbengine-dataset") ||
  77. !strcmp(machine_guid, "dbengine-stress-test"))) {
  78. return 1;
  79. }
  80. if (!uuid_parse(machine_guid, uuid)) {
  81. uv_fs_t stat_req;
  82. snprintfz(dbengine_file, FILENAME_MAX, "%s/%s/dbengine", netdata_configured_cache_dir, machine_guid);
  83. int rc = uv_fs_stat(NULL, &stat_req, dbengine_file, NULL);
  84. if (likely(rc == 0 && ((stat_req.statbuf.st_mode & S_IFMT) == S_IFDIR))) {
  85. //info("Found legacy engine folder \"%s\"", dbengine_file);
  86. return 1;
  87. }
  88. }
  89. return 0;
  90. }
  91. int count_legacy_children(char *dbfiles_path)
  92. {
  93. int ret;
  94. uv_fs_t req;
  95. uv_dirent_t dent;
  96. int legacy_engines = 0;
  97. ret = uv_fs_scandir(NULL, &req, dbfiles_path, 0, NULL);
  98. if (ret < 0) {
  99. uv_fs_req_cleanup(&req);
  100. error("uv_fs_scandir(%s): %s", dbfiles_path, uv_strerror(ret));
  101. return ret;
  102. }
  103. while(UV_EOF != uv_fs_scandir_next(&req, &dent)) {
  104. if (dent.type == UV_DIRENT_DIR) {
  105. if (is_legacy_child(dent.name))
  106. legacy_engines++;
  107. }
  108. }
  109. uv_fs_req_cleanup(&req);
  110. return legacy_engines;
  111. }
  112. int compute_multidb_diskspace()
  113. {
  114. char multidb_disk_space_file[FILENAME_MAX + 1];
  115. FILE *fp;
  116. int computed_multidb_disk_quota_mb = -1;
  117. snprintfz(multidb_disk_space_file, FILENAME_MAX, "%s/dbengine_multihost_size", netdata_configured_varlib_dir);
  118. fp = fopen(multidb_disk_space_file, "r");
  119. if (likely(fp)) {
  120. int rc = fscanf(fp, "%d", &computed_multidb_disk_quota_mb);
  121. fclose(fp);
  122. if (unlikely(rc != 1 || computed_multidb_disk_quota_mb < RRDENG_MIN_DISK_SPACE_MB)) {
  123. errno = 0;
  124. error("File '%s' contains invalid input, it will be rebuild", multidb_disk_space_file);
  125. computed_multidb_disk_quota_mb = -1;
  126. }
  127. }
  128. if (computed_multidb_disk_quota_mb == -1) {
  129. int rc = count_legacy_children(netdata_configured_cache_dir);
  130. if (likely(rc >= 0)) {
  131. computed_multidb_disk_quota_mb = (rc + 1) * default_rrdeng_disk_quota_mb;
  132. info("Found %d legacy dbengines, setting multidb diskspace to %dMB", rc, computed_multidb_disk_quota_mb);
  133. fp = fopen(multidb_disk_space_file, "w");
  134. if (likely(fp)) {
  135. fprintf(fp, "%d", computed_multidb_disk_quota_mb);
  136. info("Created file '%s' to store the computed value", multidb_disk_space_file);
  137. fclose(fp);
  138. } else
  139. error("Failed to store the default multidb disk quota size on '%s'", multidb_disk_space_file);
  140. }
  141. else
  142. computed_multidb_disk_quota_mb = default_rrdeng_disk_quota_mb;
  143. }
  144. return computed_multidb_disk_quota_mb;
  145. }