filename.cc 4.0 KB

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