compaction.c 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #define NETDATA_RRD_INTERNALS
  3. #include "metadatalog.h"
  4. /* Return 0 on success. */
  5. int compaction_failure_recovery(struct metalog_instance *ctx, struct metadata_logfile **metalogfiles,
  6. unsigned *matched_files)
  7. {
  8. int ret;
  9. unsigned starting_fileno, fileno, i, j, recovered_files;
  10. struct metadata_logfile *metalogfile = NULL, *compactionfile = NULL, **tmp_metalogfiles;
  11. char *dbfiles_path = ctx->rrdeng_ctx->dbfiles_path;
  12. for (i = 0 ; i < *matched_files ; ++i) {
  13. metalogfile = metalogfiles[i];
  14. if (0 == metalogfile->starting_fileno)
  15. continue; /* skip standard metadata log files */
  16. break; /* this is a compaction temporary file */
  17. }
  18. if (i == *matched_files) /* no recovery needed */
  19. return 0;
  20. info("Starting metadata log file failure recovery procedure in \"%s\".", dbfiles_path);
  21. if (*matched_files - i > 1) { /* Can't have more than 1 temporary compaction files */
  22. error("Metadata log files are in an invalid state. Cannot proceed.");
  23. return 1;
  24. }
  25. compactionfile = metalogfile;
  26. starting_fileno = compactionfile->starting_fileno;
  27. fileno = compactionfile->fileno;
  28. /* scratchpad space to move file pointers around */
  29. tmp_metalogfiles = callocz(*matched_files, sizeof(*tmp_metalogfiles));
  30. for (j = 0, recovered_files = 0 ; j < i ; ++j) {
  31. metalogfile = metalogfiles[j];
  32. fatal_assert(0 == metalogfile->starting_fileno);
  33. if (metalogfile->fileno < starting_fileno) {
  34. tmp_metalogfiles[recovered_files++] = metalogfile;
  35. continue;
  36. }
  37. break; /* reached compaction file serial number */
  38. }
  39. if ((j == i) /* Shouldn't be possible, invalid compaction temporary file */ ||
  40. (metalogfile->fileno == starting_fileno && metalogfile->fileno == fileno)) {
  41. error("Deleting invalid compaction temporary file \"%s/"METALOG_PREFIX METALOG_FILE_NUMBER_PRINT_TMPL
  42. METALOG_EXTENSION"\"", dbfiles_path, starting_fileno, fileno);
  43. unlink_metadata_logfile(compactionfile);
  44. freez(compactionfile);
  45. freez(tmp_metalogfiles);
  46. --*matched_files; /* delete the last one */
  47. info("Finished metadata log file failure recovery procedure in \"%s\".", dbfiles_path);
  48. return 0;
  49. }
  50. for ( ; j < i ; ++j) { /* continue iterating through normal metadata log files */
  51. metalogfile = metalogfiles[j];
  52. fatal_assert(0 == metalogfile->starting_fileno);
  53. if (metalogfile->fileno < fileno) { /* It has already been compacted */
  54. error("Deleting invalid metadata log file \"%s/"METALOG_PREFIX METALOG_FILE_NUMBER_PRINT_TMPL
  55. METALOG_EXTENSION"\"", dbfiles_path, 0U, metalogfile->fileno);
  56. unlink_metadata_logfile(metalogfile);
  57. freez(metalogfile);
  58. continue;
  59. }
  60. tmp_metalogfiles[recovered_files++] = metalogfile;
  61. }
  62. /* compaction temporary file is valid */
  63. tmp_metalogfiles[recovered_files++] = compactionfile;
  64. ret = rename_metadata_logfile(compactionfile, 0, starting_fileno);
  65. if (ret < 0) {
  66. error("Cannot rename temporary compaction files. Cannot proceed.");
  67. freez(tmp_metalogfiles);
  68. return 1;
  69. }
  70. memcpy(metalogfiles, tmp_metalogfiles, recovered_files * sizeof(*metalogfiles));
  71. *matched_files = recovered_files;
  72. freez(tmp_metalogfiles);
  73. info("Finished metadata log file failure recovery procedure in \"%s\".", dbfiles_path);
  74. return 0;
  75. }