/ src / leveldb / db / filename.cc
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 "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  static std::string MakeFileName(const std::string& dbname, uint64_t number,
 21                                  const char* suffix) {
 22    char buf[100];
 23    snprintf(buf, sizeof(buf), "/%06llu.%s",
 24             static_cast<unsigned long long>(number), suffix);
 25    return dbname + buf;
 26  }
 27  
 28  std::string LogFileName(const std::string& dbname, uint64_t number) {
 29    assert(number > 0);
 30    return MakeFileName(dbname, number, "log");
 31  }
 32  
 33  std::string TableFileName(const std::string& dbname, uint64_t number) {
 34    assert(number > 0);
 35    return MakeFileName(dbname, number, "ldb");
 36  }
 37  
 38  std::string SSTTableFileName(const std::string& dbname, uint64_t number) {
 39    assert(number > 0);
 40    return MakeFileName(dbname, number, "sst");
 41  }
 42  
 43  std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
 44    assert(number > 0);
 45    char buf[100];
 46    snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
 47             static_cast<unsigned long long>(number));
 48    return dbname + buf;
 49  }
 50  
 51  std::string CurrentFileName(const std::string& dbname) {
 52    return dbname + "/CURRENT";
 53  }
 54  
 55  std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; }
 56  
 57  std::string TempFileName(const std::string& dbname, uint64_t number) {
 58    assert(number > 0);
 59    return MakeFileName(dbname, number, "dbtmp");
 60  }
 61  
 62  std::string InfoLogFileName(const std::string& dbname) {
 63    return dbname + "/LOG";
 64  }
 65  
 66  // Return the name of the old info log file for "dbname".
 67  std::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)
 78  bool 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  
123  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    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->DeleteFile(tmp);
137    }
138    return s;
139  }
140  
141  }  // namespace leveldb