Merge branch 'MSVC' of https://github.com/fsb4000/novacoin into fsb4000-MSVC
[novacoin.git] / src / leveldb / db / 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 <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 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   return name + buf;
25 }
26
27 std::string LogFileName(const std::string& name, uint64_t number) {
28   assert(number > 0);
29   return MakeFileName(name, number, "log");
30 }
31 // TableFileName returns the filenames we usually write to, while
32 // SSTTableFileName returns the alternative filenames we also try to read from
33 // for backward compatibility. For now, swap them around.
34 // TODO: when compatibility is no longer necessary, swap them back
35 // (TableFileName to use "ldb" and SSTTableFileName to use "sst").
36 std::string TableFileName(const std::string& name, uint64_t number) {
37   assert(number > 0);
38   return MakeFileName(name, number, "sst");
39 }
40
41 std::string SSTTableFileName(const std::string& name, uint64_t number) {
42   assert(number > 0);
43   return MakeFileName(name, number, "ldb");
44 }
45
46 std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
47   assert(number > 0);
48   char buf[100];
49   snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
50            static_cast<unsigned long long>(number));
51   return dbname + buf;
52 }
53
54 std::string CurrentFileName(const std::string& dbname) {
55   return dbname + "/CURRENT";
56 }
57
58 std::string LockFileName(const std::string& dbname) {
59   return dbname + "/LOCK";
60 }
61
62 std::string TempFileName(const std::string& dbname, uint64_t number) {
63   assert(number > 0);
64   return MakeFileName(dbname, number, "dbtmp");
65 }
66
67 std::string InfoLogFileName(const std::string& dbname) {
68   return dbname + "/LOG";
69 }
70
71 // Return the name of the old info log file for "dbname".
72 std::string OldInfoLogFileName(const std::string& dbname) {
73   return dbname + "/LOG.old";
74 }
75
76
77 // Owned filenames have the form:
78 //    dbname/CURRENT
79 //    dbname/LOCK
80 //    dbname/LOG
81 //    dbname/LOG.old
82 //    dbname/MANIFEST-[0-9]+
83 //    dbname/[0-9]+.(log|sst|ldb)
84 bool ParseFileName(const std::string& fname,
85                    uint64_t* number,
86                    FileType* type) {
87   Slice rest(fname);
88   if (rest == "CURRENT") {
89     *number = 0;
90     *type = kCurrentFile;
91   } else if (rest == "LOCK") {
92     *number = 0;
93     *type = kDBLockFile;
94   } else if (rest == "LOG" || rest == "LOG.old") {
95     *number = 0;
96     *type = kInfoLogFile;
97   } else if (rest.starts_with("MANIFEST-")) {
98     rest.remove_prefix(strlen("MANIFEST-"));
99     uint64_t num;
100     if (!ConsumeDecimalNumber(&rest, &num)) {
101       return false;
102     }
103     if (!rest.empty()) {
104       return false;
105     }
106     *type = kDescriptorFile;
107     *number = num;
108   } else {
109     // Avoid strtoull() to keep filename format independent of the
110     // current locale
111     uint64_t num;
112     if (!ConsumeDecimalNumber(&rest, &num)) {
113       return false;
114     }
115     Slice suffix = rest;
116     if (suffix == Slice(".log")) {
117       *type = kLogFile;
118     } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) {
119       *type = kTableFile;
120     } else if (suffix == Slice(".dbtmp")) {
121       *type = kTempFile;
122     } else {
123       return false;
124     }
125     *number = num;
126   }
127   return true;
128 }
129
130 Status SetCurrentFile(Env* env, const std::string& dbname,
131                       uint64_t descriptor_number) {
132   // Remove leading "dbname/" and add newline to manifest file name
133   std::string manifest = DescriptorFileName(dbname, descriptor_number);
134   Slice contents = manifest;
135   assert(contents.starts_with(dbname + "/"));
136   contents.remove_prefix(dbname.size() + 1);
137   std::string tmp = TempFileName(dbname, descriptor_number);
138   Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp);
139   if (s.ok()) {
140     s = env->RenameFile(tmp, CurrentFileName(dbname));
141   }
142   if (!s.ok()) {
143     env->DeleteFile(tmp);
144   }
145   return s;
146 }
147
148 }  // namespace leveldb