135 linhas
3.6 KiB

  1. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. #include "db/filename.h"
  7. #include "db/dbformat.h"
  8. #include "leveldb/env.h"
  9. #include "util/logging.h"
  10. namespace leveldb {
  11. static std::string MakeFileName(const std::string& name, uint64_t number,
  12. const char* suffix) {
  13. char buf[100];
  14. snprintf(buf, sizeof(buf), "/%06llu.%s",
  15. static_cast<unsigned long long>(number),
  16. suffix);
  17. return name + buf;
  18. }
  19. std::string LogFileName(const std::string& name, uint64_t number) {
  20. assert(number > 0);
  21. return MakeFileName(name, number, "log");
  22. }
  23. std::string TableFileName(const std::string& name, uint64_t number) {
  24. assert(number > 0);
  25. return MakeFileName(name, number, "sst");
  26. }
  27. std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
  28. assert(number > 0);
  29. char buf[100];
  30. snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
  31. static_cast<unsigned long long>(number));
  32. return dbname + buf;
  33. }
  34. std::string CurrentFileName(const std::string& dbname) {
  35. return dbname + "/CURRENT";
  36. }
  37. std::string LockFileName(const std::string& dbname) {
  38. return dbname + "/LOCK";
  39. }
  40. std::string TempFileName(const std::string& dbname, uint64_t number) {
  41. assert(number > 0);
  42. return MakeFileName(dbname, number, "dbtmp");
  43. }
  44. std::string InfoLogFileName(const std::string& dbname) {
  45. return dbname + "/LOG";
  46. }
  47. // Return the name of the old info log file for "dbname".
  48. std::string OldInfoLogFileName(const std::string& dbname) {
  49. return dbname + "/LOG.old";
  50. }
  51. // Owned filenames have the form:
  52. // dbname/CURRENT
  53. // dbname/LOCK
  54. // dbname/LOG
  55. // dbname/LOG.old
  56. // dbname/MANIFEST-[0-9]+
  57. // dbname/[0-9]+.(log|sst)
  58. bool ParseFileName(const std::string& fname,
  59. uint64_t* number,
  60. FileType* type) {
  61. Slice rest(fname);
  62. if (rest == "CURRENT") {
  63. *number = 0;
  64. *type = kCurrentFile;
  65. } else if (rest == "LOCK") {
  66. *number = 0;
  67. *type = kDBLockFile;
  68. } else if (rest == "LOG" || rest == "LOG.old") {
  69. *number = 0;
  70. *type = kInfoLogFile;
  71. } else if (rest.starts_with("MANIFEST-")) {
  72. rest.remove_prefix(strlen("MANIFEST-"));
  73. uint64_t num;
  74. if (!ConsumeDecimalNumber(&rest, &num)) {
  75. return false;
  76. }
  77. if (!rest.empty()) {
  78. return false;
  79. }
  80. *type = kDescriptorFile;
  81. *number = num;
  82. } else {
  83. // Avoid strtoull() to keep filename format independent of the
  84. // current locale
  85. uint64_t num;
  86. if (!ConsumeDecimalNumber(&rest, &num)) {
  87. return false;
  88. }
  89. Slice suffix = rest;
  90. if (suffix == Slice(".log")) {
  91. *type = kLogFile;
  92. } else if (suffix == Slice(".sst")) {
  93. *type = kTableFile;
  94. } else if (suffix == Slice(".dbtmp")) {
  95. *type = kTempFile;
  96. } else {
  97. return false;
  98. }
  99. *number = num;
  100. }
  101. return true;
  102. }
  103. Status SetCurrentFile(Env* env, const std::string& dbname,
  104. uint64_t descriptor_number) {
  105. // Remove leading "dbname/" and add newline to manifest file name
  106. std::string manifest = DescriptorFileName(dbname, descriptor_number);
  107. Slice contents = manifest;
  108. assert(contents.starts_with(dbname + "/"));
  109. contents.remove_prefix(dbname.size() + 1);
  110. std::string tmp = TempFileName(dbname, descriptor_number);
  111. Status s = WriteStringToFile(env, contents.ToString() + "\n", tmp);
  112. if (s.ok()) {
  113. s = env->RenameFile(tmp, CurrentFileName(dbname));
  114. }
  115. if (!s.ok()) {
  116. env->DeleteFile(tmp);
  117. }
  118. return s;
  119. }
  120. }