Branch data Line data Source code
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 : 14769 : static std::string MakeFileName(const std::string& dbname, uint64_t number,
21 : : const char* suffix) {
22 : 14769 : char buf[100];
23 : 14769 : snprintf(buf, sizeof(buf), "/%06llu.%s",
24 : : static_cast<unsigned long long>(number), suffix);
25 : 14769 : return dbname + buf;
26 : : }
27 : :
28 : 4652 : std::string LogFileName(const std::string& dbname, uint64_t number) {
29 [ - + ]: 4652 : assert(number > 0);
30 : 4652 : return MakeFileName(dbname, number, "log");
31 : : }
32 : :
33 : 6176 : std::string TableFileName(const std::string& dbname, uint64_t number) {
34 [ - + ]: 6176 : assert(number > 0);
35 : 6176 : return MakeFileName(dbname, number, "ldb");
36 : : }
37 : :
38 : 0 : std::string SSTTableFileName(const std::string& dbname, uint64_t number) {
39 [ # # ]: 0 : assert(number > 0);
40 : 0 : return MakeFileName(dbname, number, "sst");
41 : : }
42 : :
43 : 7882 : std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
44 [ - + ]: 7882 : assert(number > 0);
45 : 7882 : char buf[100];
46 : 7882 : snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
47 : : static_cast<unsigned long long>(number));
48 : 7882 : return dbname + buf;
49 : : }
50 : :
51 : 9649 : std::string CurrentFileName(const std::string& dbname) {
52 : 9649 : return dbname + "/CURRENT";
53 : : }
54 : :
55 : 2943 : std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; }
56 : :
57 : 3941 : std::string TempFileName(const std::string& dbname, uint64_t number) {
58 [ - + ]: 3941 : assert(number > 0);
59 : 3941 : return MakeFileName(dbname, number, "dbtmp");
60 : : }
61 : :
62 : 0 : std::string InfoLogFileName(const std::string& dbname) {
63 : 0 : return dbname + "/LOG";
64 : : }
65 : :
66 : : // Return the name of the old info log file for "dbname".
67 : 0 : std::string OldInfoLogFileName(const std::string& dbname) {
68 : 0 : 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 : 45987 : bool ParseFileName(const std::string& filename, uint64_t* number,
79 : : FileType* type) {
80 [ - + ]: 45987 : Slice rest(filename);
81 [ + + ]: 45987 : if (rest == "CURRENT") {
82 : 6122 : *number = 0;
83 : 6122 : *type = kCurrentFile;
84 [ + + ]: 39865 : } else if (rest == "LOCK") {
85 : 5373 : *number = 0;
86 : 5373 : *type = kDBLockFile;
87 [ + + - + ]: 34492 : } else if (rest == "LOG" || rest == "LOG.old") {
88 : 7 : *number = 0;
89 : 7 : *type = kInfoLogFile;
90 [ + + ]: 34485 : } else if (rest.starts_with("MANIFEST-")) {
91 : 8969 : rest.remove_prefix(strlen("MANIFEST-"));
92 : 8969 : uint64_t num;
93 [ + - ]: 8969 : if (!ConsumeDecimalNumber(&rest, &num)) {
94 : : return false;
95 : : }
96 [ + - ]: 8969 : if (!rest.empty()) {
97 : : return false;
98 : : }
99 : 8969 : *type = kDescriptorFile;
100 : 8969 : *number = num;
101 : : } else {
102 : : // Avoid strtoull() to keep filename format independent of the
103 : : // current locale
104 : 25516 : uint64_t num;
105 [ + + ]: 25516 : if (!ConsumeDecimalNumber(&rest, &num)) {
106 : : return false;
107 : : }
108 : 14650 : Slice suffix = rest;
109 [ + + ]: 14650 : if (suffix == Slice(".log")) {
110 : 6825 : *type = kLogFile;
111 [ + - + + ]: 7825 : } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) {
112 : 7822 : *type = kTableFile;
113 [ - + ]: 3 : } else if (suffix == Slice(".dbtmp")) {
114 : 0 : *type = kTempFile;
115 : : } else {
116 : : return false;
117 : : }
118 : 14647 : *number = num;
119 : : }
120 : : return true;
121 : : }
122 : :
123 : 3941 : 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 : 3941 : std::string manifest = DescriptorFileName(dbname, descriptor_number);
127 [ - + ]: 3941 : Slice contents = manifest;
128 [ + - - + ]: 7882 : assert(contents.starts_with(dbname + "/"));
129 [ - + ]: 3941 : contents.remove_prefix(dbname.size() + 1);
130 [ + - ]: 3941 : std::string tmp = TempFileName(dbname, descriptor_number);
131 [ + - + - : 11823 : Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp);
- + + - ]
132 [ + - ]: 3941 : if (s.ok()) {
133 [ + - + - : 3941 : s = env->RenameFile(tmp, CurrentFileName(dbname));
- + ]
134 : : }
135 [ - + ]: 3941 : if (!s.ok()) {
136 [ # # ]: 0 : env->DeleteFile(tmp);
137 : : }
138 : 3941 : return s;
139 : 3941 : }
140 : :
141 : : } // namespace leveldb
|