filename.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. extern Status WriteStringToFileSync(Env* env, const Slice& data,
  13. const std::string& fname);
  14. static std::string MakeFileName(const std::string& name, 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 name + buf;
  21. }
  22. std::string LogFileName(const std::string& name, uint64_t number) {
  23. assert(number > 0);
  24. return MakeFileName(name, number, "log");
  25. }
  26. std::string TableFileName(const std::string& name, uint64_t number) {
  27. assert(number > 0);
  28. return MakeFileName(name, number, "sst");
  29. }
  30. std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
  31. assert(number > 0);
  32. char buf[100];
  33. snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
  34. static_cast<unsigned long long>(number));
  35. return dbname + buf;
  36. }
  37. std::string CurrentFileName(const std::string& dbname) {
  38. return dbname + "/CURRENT";
  39. }
  40. std::string LockFileName(const std::string& dbname) {
  41. return dbname + "/LOCK";
  42. }
  43. std::string TempFileName(const std::string& dbname, uint64_t number) {
  44. assert(number > 0);
  45. return MakeFileName(dbname, number, "dbtmp");
  46. }
  47. std::string InfoLogFileName(const std::string& dbname) {
  48. return dbname + "/LOG";
  49. }
  50. // Return the name of the old info log file for "dbname".
  51. std::string OldInfoLogFileName(const std::string& dbname) {
  52. return dbname + "/LOG.old";
  53. }
  54. // Owned filenames have the form:
  55. // dbname/CURRENT
  56. // dbname/LOCK
  57. // dbname/LOG
  58. // dbname/LOG.old
  59. // dbname/MANIFEST-[0-9]+
  60. // dbname/[0-9]+.(log|sst)
  61. bool ParseFileName(const std::string& fname,
  62. uint64_t* number,
  63. FileType* type) {
  64. Slice rest(fname);
  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")) {
  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->DeleteFile(tmp);
  120. }
  121. return s;
  122. }
  123. } // namespace leveldb