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 <cassert>
8#include <cstdio>
9
10#include "db/dbformat.h"
11#include "leveldb/env.h"
12#include "util/logging.h"
13
14namespace leveldb {
15
16// A utility routine: write "data" to the named file and Sync() it.
17Status WriteStringToFileSync(Env* env, const Slice& data,
18 const std::string& fname);
19
20static std::string MakeFileName(const std::string& dbname, uint64_t number,
21 const char* suffix) {
22 char buf[100];
23 std::snprintf(buf, sizeof(buf), "/%06llu.%s",
24 static_cast<unsigned long long>(number), suffix);
25 return dbname + buf;
26}
27
28std::string LogFileName(const std::string& dbname, uint64_t number) {
29 assert(number > 0);
30 return MakeFileName(dbname, number, "log");
31}
32
33std::string TableFileName(const std::string& dbname, uint64_t number) {
34 assert(number > 0);
35 return MakeFileName(dbname, number, "ldb");
36}
37
38std::string SSTTableFileName(const std::string& dbname, uint64_t number) {
39 assert(number > 0);
40 return MakeFileName(dbname, number, "sst");
41}
42
43std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
44 assert(number > 0);
45 char buf[100];
46 std::snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
47 static_cast<unsigned long long>(number));
48 return dbname + buf;
49}
50
51std::string CurrentFileName(const std::string& dbname) {
52 return dbname + "/CURRENT";
53}
54
55std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; }
56
57std::string TempFileName(const std::string& dbname, uint64_t number) {
58 assert(number > 0);
59 return MakeFileName(dbname, number, "dbtmp");
60}
61
62std::string InfoLogFileName(const std::string& dbname) {
63 return dbname + "/LOG";
64}
65
66// Return the name of the old info log file for "dbname".
67std::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)
78bool 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
123Status 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->RemoveFile(tmp);
137 }
138 return s;
139}
140
141} // namespace leveldb
142