filename.cc 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. // 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. snprintf(buf, sizeof(buf), "/%06llu.%s",
  18. static_cast<unsigned long long>(number),
  19. suffix);
  20. return dbname + buf;
  21. }
  22. std::string LogFileName(const std::string& dbname, uint64_t number) {
  23. assert(number > 0);
  24. return MakeFileName(dbname, number, "log");
  25. }
  26. std::string TableFileName(const std::string& dbname, uint64_t number) {
  27. assert(number > 0);
  28. return MakeFileName(dbname, number, "ldb");
  29. }
  30. std::string SSTTableFileName(const std::string& dbname, uint64_t number) {
  31. assert(number > 0);
  32. return MakeFileName(dbname, number, "sst");
  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-9]+.(log|sst|ldb)
  65. bool ParseFileName(const std::string& filename,
  66. uint64_t* number,
  67. FileType* type) {
  68. Slice rest(filename);
  69. if (rest == "CURRENT") {
  70. *number = 0;
  71. *type = kCurrentFile;
  72. } else if (rest == "LOCK") {
  73. *number = 0;
  74. *type = kDBLockFile;
  75. } else if (rest == "LOG" || rest == "LOG.old") {
  76. *number = 0;
  77. *type = kInfoLogFile;
  78. } else if (rest.starts_with("MANIFEST-")) {
  79. rest.remove_prefix(strlen("MANIFEST-"));
  80. uint64_t num;
  81. if (!ConsumeDecimalNumber(&rest, &num)) {
  82. return false;
  83. }
  84. if (!rest.empty()) {
  85. return false;
  86. }
  87. *type = kDescriptorFile;
  88. *number = num;
  89. } else {
  90. // Avoid strtoull() to keep filename format independent of the
  91. // current locale
  92. uint64_t num;
  93. if (!ConsumeDecimalNumber(&rest, &num)) {
  94. return false;
  95. }
  96. Slice suffix = rest;
  97. if (suffix == Slice(".log")) {
  98. *type = kLogFile;
  99. } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) {
  100. *type = kTableFile;
  101. } else if (suffix == Slice(".dbtmp")) {
  102. *type = kTempFile;
  103. } else {
  104. return false;
  105. }
  106. *number = num;
  107. }
  108. return true;
  109. }
  110. Status SetCurrentFile(Env* env, const std::string& dbname,
  111. uint64_t descriptor_number) {
  112. // Remove leading "dbname/" and add newline to manifest file name
  113. std::string manifest = DescriptorFileName(dbname, descriptor_number);
  114. Slice contents = manifest;
  115. assert(contents.starts_with(dbname + "/"));
  116. contents.remove_prefix(dbname.size() + 1);
  117. std::string tmp = TempFileName(dbname, descriptor_number);
  118. Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp);
  119. if (s.ok()) {
  120. s = env->RenameFile(tmp, CurrentFileName(dbname));
  121. }
  122. if (!s.ok()) {
  123. env->DeleteFile(tmp);
  124. }
  125. return s;
  126. }
  127. } // namespace leveldb