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