1179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Use of this source code is governed by a BSD-style license that can be
3179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors.
4179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
5179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <ctype.h>
6179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <stdio.h>
7179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/filename.h"
8179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/dbformat.h"
9fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/env.h"
10179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/logging.h"
11179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
12179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace leveldb {
13179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
14e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com// A utility routine: write "data" to the named file and Sync() it.
15e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.comextern Status WriteStringToFileSync(Env* env, const Slice& data,
16e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com                                    const std::string& fname);
17e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com
18179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic std::string MakeFileName(const std::string& name, uint64_t number,
19179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                                const char* suffix) {
20179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  char buf[100];
21179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  snprintf(buf, sizeof(buf), "/%06llu.%s",
22179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org           static_cast<unsigned long long>(number),
23179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org           suffix);
24179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return name + buf;
25179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
26179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
27179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstd::string LogFileName(const std::string& name, uint64_t number) {
28179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(number > 0);
29179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return MakeFileName(name, number, "log");
30179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
31179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
32179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstd::string TableFileName(const std::string& name, uint64_t number) {
33179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(number > 0);
342d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  return MakeFileName(name, number, "ldb");
352d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org}
362d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org
372d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.orgstd::string SSTTableFileName(const std::string& name, uint64_t number) {
382d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  assert(number > 0);
39179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return MakeFileName(name, number, "sst");
40179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
41179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
42179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstd::string DescriptorFileName(const std::string& dbname, uint64_t number) {
43179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(number > 0);
44179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  char buf[100];
45179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
46179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org           static_cast<unsigned long long>(number));
47179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return dbname + buf;
48179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
49179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
50179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstd::string CurrentFileName(const std::string& dbname) {
51179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return dbname + "/CURRENT";
52179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
53179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
54179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstd::string LockFileName(const std::string& dbname) {
55179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return dbname + "/LOCK";
56179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
57179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
58179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstd::string TempFileName(const std::string& dbname, uint64_t number) {
59179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(number > 0);
60179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return MakeFileName(dbname, number, "dbtmp");
61179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
62179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
63179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstd::string InfoLogFileName(const std::string& dbname) {
64179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return dbname + "/LOG";
65179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
66179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
67179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Return the name of the old info log file for "dbname".
68179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstd::string OldInfoLogFileName(const std::string& dbname) {
69179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return dbname + "/LOG.old";
70179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
71179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
72179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
73179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Owned filenames have the form:
74179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//    dbname/CURRENT
75179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//    dbname/LOCK
76179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//    dbname/LOG
77179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//    dbname/LOG.old
78179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//    dbname/MANIFEST-[0-9]+
792d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org//    dbname/[0-9]+.(log|sst|ldb)
80179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgbool ParseFileName(const std::string& fname,
81179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                   uint64_t* number,
82179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                   FileType* type) {
83179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Slice rest(fname);
84179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (rest == "CURRENT") {
85179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *number = 0;
86179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *type = kCurrentFile;
87179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  } else if (rest == "LOCK") {
88179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *number = 0;
89179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *type = kDBLockFile;
90179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  } else if (rest == "LOG" || rest == "LOG.old") {
91179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *number = 0;
92179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *type = kInfoLogFile;
93179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  } else if (rest.starts_with("MANIFEST-")) {
94179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    rest.remove_prefix(strlen("MANIFEST-"));
95179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    uint64_t num;
96179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (!ConsumeDecimalNumber(&rest, &num)) {
97179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      return false;
98179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
99179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (!rest.empty()) {
100179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      return false;
101179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
102179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *type = kDescriptorFile;
103179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *number = num;
104179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  } else {
105179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // Avoid strtoull() to keep filename format independent of the
106179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // current locale
107179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    uint64_t num;
108179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (!ConsumeDecimalNumber(&rest, &num)) {
109179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      return false;
110179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
111179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Slice suffix = rest;
112179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (suffix == Slice(".log")) {
113179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      *type = kLogFile;
1142d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) {
115179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      *type = kTableFile;
116179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else if (suffix == Slice(".dbtmp")) {
117179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      *type = kTempFile;
118179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else {
119179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      return false;
120179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
121179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    *number = num;
122179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
123179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return true;
124179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
125179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
126179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgStatus SetCurrentFile(Env* env, const std::string& dbname,
127179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                      uint64_t descriptor_number) {
128179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Remove leading "dbname/" and add newline to manifest file name
129179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string manifest = DescriptorFileName(dbname, descriptor_number);
130179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Slice contents = manifest;
131179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(contents.starts_with(dbname + "/"));
132179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  contents.remove_prefix(dbname.size() + 1);
133179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string tmp = TempFileName(dbname, descriptor_number);
134e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp);
135179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (s.ok()) {
136179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    s = env->RenameFile(tmp, CurrentFileName(dbname));
137179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
138179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (!s.ok()) {
139179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    env->DeleteFile(tmp);
140179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
141179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return s;
142179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
143179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
14445b9940be332834440bd5299419f396e38085ebehans@chromium.org}  // namespace leveldb
145