選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

154 行
4.2 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 LargeValueFileName(const std::string& name,
  28. const LargeValueRef& large_ref) {
  29. std::string result = name + "/";
  30. result += LargeValueRefToFilenameString(large_ref);
  31. result += ".val";
  32. return result;
  33. }
  34. std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
  35. assert(number > 0);
  36. char buf[100];
  37. snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
  38. static_cast<unsigned long long>(number));
  39. return dbname + buf;
  40. }
  41. std::string CurrentFileName(const std::string& dbname) {
  42. return dbname + "/CURRENT";
  43. }
  44. std::string LockFileName(const std::string& dbname) {
  45. return dbname + "/LOCK";
  46. }
  47. std::string TempFileName(const std::string& dbname, uint64_t number) {
  48. assert(number > 0);
  49. return MakeFileName(dbname, number, "dbtmp");
  50. }
  51. std::string InfoLogFileName(const std::string& dbname) {
  52. return dbname + "/LOG";
  53. }
  54. // Return the name of the old info log file for "dbname".
  55. std::string OldInfoLogFileName(const std::string& dbname) {
  56. return dbname + "/LOG.old";
  57. }
  58. // Owned filenames have the form:
  59. // dbname/CURRENT
  60. // dbname/LOCK
  61. // dbname/LOG
  62. // dbname/LOG.old
  63. // dbname/MANIFEST-[0-9]+
  64. // dbname/[0-9a-f]{20}-[0-9]+-[0-9]+.val
  65. // dbname/[0-9]+.(log|sst)
  66. bool ParseFileName(const std::string& fname,
  67. uint64_t* number,
  68. LargeValueRef* large_ref,
  69. FileType* type) {
  70. Slice rest(fname);
  71. if (rest == "CURRENT") {
  72. *number = 0;
  73. *type = kCurrentFile;
  74. } else if (rest == "LOCK") {
  75. *number = 0;
  76. *type = kDBLockFile;
  77. } else if (rest == "LOG" || rest == "LOG.old") {
  78. *number = 0;
  79. *type = kInfoLogFile;
  80. } else if (rest.size() >= 4 &&
  81. Slice(rest.data() + rest.size() - 4, 4) == ".val") {
  82. LargeValueRef h;
  83. if (!FilenameStringToLargeValueRef(Slice(rest.data(), rest.size() - 4),
  84. &h)) {
  85. return false;
  86. }
  87. *large_ref = h;
  88. *type = kLargeValueFile;
  89. } else if (rest.starts_with("MANIFEST-")) {
  90. rest.remove_prefix(strlen("MANIFEST-"));
  91. uint64_t num;
  92. if (!ConsumeDecimalNumber(&rest, &num)) {
  93. return false;
  94. }
  95. if (!rest.empty()) {
  96. return false;
  97. }
  98. *type = kDescriptorFile;
  99. *number = num;
  100. } else {
  101. // Avoid strtoull() to keep filename format independent of the
  102. // current locale
  103. uint64_t num;
  104. if (!ConsumeDecimalNumber(&rest, &num)) {
  105. return false;
  106. }
  107. Slice suffix = rest;
  108. if (suffix == Slice(".log")) {
  109. *type = kLogFile;
  110. } else if (suffix == Slice(".sst")) {
  111. *type = kTableFile;
  112. } else if (suffix == Slice(".dbtmp")) {
  113. *type = kTempFile;
  114. } else {
  115. return false;
  116. }
  117. *number = num;
  118. }
  119. return true;
  120. }
  121. Status SetCurrentFile(Env* env, const std::string& dbname,
  122. uint64_t descriptor_number) {
  123. // Remove leading "dbname/" and add newline to manifest file name
  124. std::string manifest = DescriptorFileName(dbname, descriptor_number);
  125. Slice contents = manifest;
  126. assert(contents.starts_with(dbname + "/"));
  127. contents.remove_prefix(dbname.size() + 1);
  128. std::string tmp = TempFileName(dbname, descriptor_number);
  129. Status s = WriteStringToFile(env, contents.ToString() + "\n", tmp);
  130. if (s.ok()) {
  131. s = env->RenameFile(tmp, CurrentFileName(dbname));
  132. }
  133. if (!s.ok()) {
  134. env->DeleteFile(tmp);
  135. }
  136. return s;
  137. }
  138. }