You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.8 KiB
139 lines
3.8 KiB
// Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
|
// Use of this source code is governed by a BSD-style license that can be |
|
// found in the LICENSE file. See the AUTHORS file for names of contributors. |
|
|
|
#include <ctype.h> |
|
#include <stdio.h> |
|
#include "db/filename.h" |
|
#include "db/dbformat.h" |
|
#include "leveldb/env.h" |
|
#include "util/logging.h" |
|
|
|
namespace leveldb { |
|
|
|
// A utility routine: write "data" to the named file and Sync() it. |
|
extern Status WriteStringToFileSync(Env* env, const Slice& data, |
|
const std::string& fname); |
|
|
|
static std::string MakeFileName(const std::string& name, uint64_t number, |
|
const char* suffix) { |
|
char buf[100]; |
|
snprintf(buf, sizeof(buf), "/%06llu.%s", |
|
static_cast<unsigned long long>(number), |
|
suffix); |
|
return name + buf; |
|
} |
|
|
|
std::string LogFileName(const std::string& name, uint64_t number) { |
|
assert(number > 0); |
|
return MakeFileName(name, number, "log"); |
|
} |
|
|
|
std::string TableFileName(const std::string& name, uint64_t number) { |
|
assert(number > 0); |
|
return MakeFileName(name, number, "sst"); |
|
} |
|
|
|
std::string DescriptorFileName(const std::string& dbname, uint64_t number) { |
|
assert(number > 0); |
|
char buf[100]; |
|
snprintf(buf, sizeof(buf), "/MANIFEST-%06llu", |
|
static_cast<unsigned long long>(number)); |
|
return dbname + buf; |
|
} |
|
|
|
std::string CurrentFileName(const std::string& dbname) { |
|
return dbname + "/CURRENT"; |
|
} |
|
|
|
std::string LockFileName(const std::string& dbname) { |
|
return dbname + "/LOCK"; |
|
} |
|
|
|
std::string TempFileName(const std::string& dbname, uint64_t number) { |
|
assert(number > 0); |
|
return MakeFileName(dbname, number, "dbtmp"); |
|
} |
|
|
|
std::string InfoLogFileName(const std::string& dbname) { |
|
return dbname + "/LOG"; |
|
} |
|
|
|
// Return the name of the old info log file for "dbname". |
|
std::string OldInfoLogFileName(const std::string& dbname) { |
|
return dbname + "/LOG.old"; |
|
} |
|
|
|
|
|
// Owned filenames have the form: |
|
// dbname/CURRENT |
|
// dbname/LOCK |
|
// dbname/LOG |
|
// dbname/LOG.old |
|
// dbname/MANIFEST-[0-9]+ |
|
// dbname/[0-9]+.(log|sst) |
|
bool ParseFileName(const std::string& fname, |
|
uint64_t* number, |
|
FileType* type) { |
|
Slice rest(fname); |
|
if (rest == "CURRENT") { |
|
*number = 0; |
|
*type = kCurrentFile; |
|
} else if (rest == "LOCK") { |
|
*number = 0; |
|
*type = kDBLockFile; |
|
} else if (rest == "LOG" || rest == "LOG.old") { |
|
*number = 0; |
|
*type = kInfoLogFile; |
|
} else if (rest.starts_with("MANIFEST-")) { |
|
rest.remove_prefix(strlen("MANIFEST-")); |
|
uint64_t num; |
|
if (!ConsumeDecimalNumber(&rest, &num)) { |
|
return false; |
|
} |
|
if (!rest.empty()) { |
|
return false; |
|
} |
|
*type = kDescriptorFile; |
|
*number = num; |
|
} else { |
|
// Avoid strtoull() to keep filename format independent of the |
|
// current locale |
|
uint64_t num; |
|
if (!ConsumeDecimalNumber(&rest, &num)) { |
|
return false; |
|
} |
|
Slice suffix = rest; |
|
if (suffix == Slice(".log")) { |
|
*type = kLogFile; |
|
} else if (suffix == Slice(".sst")) { |
|
*type = kTableFile; |
|
} else if (suffix == Slice(".dbtmp")) { |
|
*type = kTempFile; |
|
} else { |
|
return false; |
|
} |
|
*number = num; |
|
} |
|
return true; |
|
} |
|
|
|
Status SetCurrentFile(Env* env, const std::string& dbname, |
|
uint64_t descriptor_number) { |
|
// Remove leading "dbname/" and add newline to manifest file name |
|
std::string manifest = DescriptorFileName(dbname, descriptor_number); |
|
Slice contents = manifest; |
|
assert(contents.starts_with(dbname + "/")); |
|
contents.remove_prefix(dbname.size() + 1); |
|
std::string tmp = TempFileName(dbname, descriptor_number); |
|
Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp); |
|
if (s.ok()) { |
|
s = env->RenameFile(tmp, CurrentFileName(dbname)); |
|
} |
|
if (!s.ok()) { |
|
env->DeleteFile(tmp); |
|
} |
|
return s; |
|
} |
|
|
|
} // namespace leveldb
|
|
|