// 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.
//
// File names used by DB code
#ifndef STORAGE_LEVELDB_DB_FILENAME_H_
#define STORAGE_LEVELDB_DB_FILENAME_H_
#include <stdint.h>
#include <string>
#include "leveldb/slice.h"
#include "leveldb/status.h"
#include "port/port.h"
namespace leveldb
{
class Env;
enum FileType
{
kLogFile,
kDBLockFile,
kTableFile,
kDescriptorFile,
kCurrentFile,
kTempFile,
kInfoLogFile // Either the current one, or an old one
};
// Return the name of the log file with the specified number
// in the db named by "dbname". The result will be prefixed with
// "dbname".
extern std::string LogFileName(const std::string& dbname, uint64_t number);
// Return the name of the sstable with the specified number
// in the db named by "dbname". The result will be prefixed with
// "dbname".
extern std::string TableFileName(const std::string& dbname, uint64_t number);
// Return the legacy file name for an sstable with the specified number
// in the db named by "dbname". The result will be prefixed with
// "dbname".
extern std::string SSTTableFileName(const std::string& dbname, uint64_t number);
// Return the name of the descriptor file for the db named by
// "dbname" and the specified incarnation number. The result will be
// prefixed with "dbname".
extern std::string DescriptorFileName(const std::string& dbname,
uint64_t number);
// Return the name of the current file. This file contains the name
// of the current manifest file. The result will be prefixed with
// "dbname".
extern std::string CurrentFileName(const std::string& dbname);
// Return the name of the lock file for the db named by
// "dbname". The result will be prefixed with "dbname".
extern std::string LockFileName(const std::string& dbname);
// Return the name of a temporary file owned by the db named "dbname".
// The result will be prefixed with "dbname".
extern std::string TempFileName(const std::string& dbname, uint64_t number);
// Return the name of the info log file for "dbname".
extern std::string InfoLogFileName(const std::string& dbname);
// Return the name of the old info log file for "dbname".
extern std::string OldInfoLogFileName(const std::string& dbname);
// If filename is a leveldb file, store the type of the file in *type.
// The number encoded in the filename is stored in *number. If the
// filename was successfully parsed, returns true. Else return false.
extern bool ParseFileName(const std::string& filename,
uint64_t* number,
FileType* type);
// Make the CURRENT file point to the descriptor file with the
// specified number.
extern Status SetCurrentFile(Env* env, const std::string& dbname,
uint64_t descriptor_number);
} // namespace leveldb
#endif // STORAGE_LEVELDB_DB_FILENAME_H_
// 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, "ldb");
}
std::string SSTTableFileName(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|ldb)
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") || suffix == Slice(".ldb"))
{
*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