github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb.chai2010/src/filename.cc (about)

     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  
    32  std::string TableFileName(const std::string& name, uint64_t number) {
    33    assert(number > 0);
    34    return MakeFileName(name, number, "ldb");
    35  }
    36  
    37  std::string SSTTableFileName(const std::string& name, uint64_t number) {
    38    assert(number > 0);
    39    return MakeFileName(name, number, "sst");
    40  }
    41  
    42  std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
    43    assert(number > 0);
    44    char buf[100];
    45    snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
    46             static_cast<unsigned long long>(number));
    47    return dbname + buf;
    48  }
    49  
    50  std::string CurrentFileName(const std::string& dbname) {
    51    return dbname + "/CURRENT";
    52  }
    53  
    54  std::string LockFileName(const std::string& dbname) {
    55    return dbname + "/LOCK";
    56  }
    57  
    58  std::string TempFileName(const std::string& dbname, uint64_t number) {
    59    assert(number > 0);
    60    return MakeFileName(dbname, number, "dbtmp");
    61  }
    62  
    63  std::string InfoLogFileName(const std::string& dbname) {
    64    return dbname + "/LOG";
    65  }
    66  
    67  // Return the name of the old info log file for "dbname".
    68  std::string OldInfoLogFileName(const std::string& dbname) {
    69    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  bool ParseFileName(const std::string& fname,
    81                     uint64_t* number,
    82                     FileType* type) {
    83    Slice rest(fname);
    84    if (rest == "CURRENT") {
    85      *number = 0;
    86      *type = kCurrentFile;
    87    } else if (rest == "LOCK") {
    88      *number = 0;
    89      *type = kDBLockFile;
    90    } else if (rest == "LOG" || rest == "LOG.old") {
    91      *number = 0;
    92      *type = kInfoLogFile;
    93    } else if (rest.starts_with("MANIFEST-")) {
    94      rest.remove_prefix(strlen("MANIFEST-"));
    95      uint64_t num;
    96      if (!ConsumeDecimalNumber(&rest, &num)) {
    97        return false;
    98      }
    99      if (!rest.empty()) {
   100        return false;
   101      }
   102      *type = kDescriptorFile;
   103      *number = num;
   104    } else {
   105      // Avoid strtoull() to keep filename format independent of the
   106      // current locale
   107      uint64_t num;
   108      if (!ConsumeDecimalNumber(&rest, &num)) {
   109        return false;
   110      }
   111      Slice suffix = rest;
   112      if (suffix == Slice(".log")) {
   113        *type = kLogFile;
   114      } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) {
   115        *type = kTableFile;
   116      } else if (suffix == Slice(".dbtmp")) {
   117        *type = kTempFile;
   118      } else {
   119        return false;
   120      }
   121      *number = num;
   122    }
   123    return true;
   124  }
   125  
   126  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    std::string manifest = DescriptorFileName(dbname, descriptor_number);
   130    Slice contents = manifest;
   131    assert(contents.starts_with(dbname + "/"));
   132    contents.remove_prefix(dbname.size() + 1);
   133    std::string tmp = TempFileName(dbname, descriptor_number);
   134    Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp);
   135    if (s.ok()) {
   136      s = env->RenameFile(tmp, CurrentFileName(dbname));
   137    }
   138    if (!s.ok()) {
   139      env->DeleteFile(tmp);
   140    }
   141    return s;
   142  }
   143  
   144  }  // namespace leveldb