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