Better destroydb

Summary:
Delete archive directory before WAL folder
  since archive may be contained as a subfolder.
  Also improve loop readability.
Closes https://github.com/facebook/rocksdb/pull/3797

Differential Revision: D7866378

Pulled By: riversand963

fbshipit-source-id: 0c45d97677ce6fbefa3f8d602ef5e2a2a925e6f5
This commit is contained in:
Dmitri Smirnov 2018-05-03 16:07:41 -07:00 committed by Facebook Github Bot
parent a8d77ca381
commit 934f96de27
2 changed files with 53 additions and 41 deletions

View File

@ -2088,6 +2088,7 @@ void DBImpl::ReleaseFileNumberFromPendingOutputs(
Status DBImpl::GetUpdatesSince( Status DBImpl::GetUpdatesSince(
SequenceNumber seq, unique_ptr<TransactionLogIterator>* iter, SequenceNumber seq, unique_ptr<TransactionLogIterator>* iter,
const TransactionLogIterator::ReadOptions& read_options) { const TransactionLogIterator::ReadOptions& read_options) {
RecordTick(stats_, GET_UPDATES_SINCE_CALLS); RecordTick(stats_, GET_UPDATES_SINCE_CALLS);
if (seq > versions_->LastSequence()) { if (seq > versions_->LastSequence()) {
return Status::NotFound("Requested sequence not yet written in the db"); return Status::NotFound("Requested sequence not yet written in the db");
@ -2436,11 +2437,11 @@ Status DestroyDB(const std::string& dbname, const Options& options,
uint64_t number; uint64_t number;
FileType type; FileType type;
InfoLogPrefix info_log_prefix(!soptions.db_log_dir.empty(), dbname); InfoLogPrefix info_log_prefix(!soptions.db_log_dir.empty(), dbname);
for (size_t i = 0; i < filenames.size(); i++) { for (const auto& fname : filenames) {
if (ParseFileName(filenames[i], &number, info_log_prefix.prefix, &type) && if (ParseFileName(fname, &number, info_log_prefix.prefix, &type) &&
type != kDBLockFile) { // Lock file will be deleted at end type != kDBLockFile) { // Lock file will be deleted at end
Status del; Status del;
std::string path_to_delete = dbname + "/" + filenames[i]; std::string path_to_delete = dbname + "/" + fname;
if (type == kMetaDatabase) { if (type == kMetaDatabase) {
del = DestroyDB(path_to_delete, options); del = DestroyDB(path_to_delete, options);
} else if (type == kTableFile) { } else if (type == kTableFile) {
@ -2456,13 +2457,12 @@ Status DestroyDB(const std::string& dbname, const Options& options,
std::vector<std::string> paths; std::vector<std::string> paths;
for (size_t path_id = 0; path_id < options.db_paths.size(); path_id++) { for (const auto& path : options.db_paths) {
paths.emplace_back(options.db_paths[path_id].path); paths.emplace_back(path.path);
} }
for (auto& cf : column_families) { for (const auto& cf : column_families) {
for (size_t path_id = 0; path_id < cf.options.cf_paths.size(); for (const auto& path : cf.options.cf_paths) {
path_id++) { paths.emplace_back(path.path);
paths.emplace_back(cf.options.cf_paths[path_id].path);
} }
} }
@ -2473,56 +2473,64 @@ Status DestroyDB(const std::string& dbname, const Options& options,
std::sort(paths.begin(), paths.end()); std::sort(paths.begin(), paths.end());
paths.erase(std::unique(paths.begin(), paths.end()), paths.end()); paths.erase(std::unique(paths.begin(), paths.end()), paths.end());
for (auto& path : paths) { for (const auto& path : paths) {
env->GetChildren(path, &filenames); if (env->GetChildren(path, &filenames).ok()) {
for (size_t i = 0; i < filenames.size(); i++) { for (const auto& fname : filenames) {
if (ParseFileName(filenames[i], &number, &type) && if (ParseFileName(fname, &number, &type) &&
type == kTableFile) { // Lock file will be deleted at end type == kTableFile) { // Lock file will be deleted at end
std::string table_path = path + "/" + filenames[i]; std::string table_path = path + "/" + fname;
Status del = DeleteSSTFile(&soptions, table_path, path); Status del = DeleteSSTFile(&soptions, table_path, dbname);
if (result.ok() && !del.ok()) { if (result.ok() && !del.ok()) {
result = del; result = del;
}
} }
} }
env->DeleteDir(path);
} }
} }
std::vector<std::string> walDirFiles; std::vector<std::string> walDirFiles;
std::string archivedir = ArchivalDirectory(dbname); std::string archivedir = ArchivalDirectory(dbname);
bool wal_dir_exists = false;
if (dbname != soptions.wal_dir) { if (dbname != soptions.wal_dir) {
env->GetChildren(soptions.wal_dir, &walDirFiles); wal_dir_exists = env->GetChildren(soptions.wal_dir, &walDirFiles).ok();
archivedir = ArchivalDirectory(soptions.wal_dir); archivedir = ArchivalDirectory(soptions.wal_dir);
} }
// Delete log files in the WAL dir // Archive dir may be inside wal dir or dbname and should be
for (const auto& file : walDirFiles) { // processed and removed before those otherwise we have issues
if (ParseFileName(file, &number, &type) && type == kLogFile) { // removing them
Status del = env->DeleteFile(LogFileName(soptions.wal_dir, number));
if (result.ok() && !del.ok()) {
result = del;
}
}
}
std::vector<std::string> archiveFiles; std::vector<std::string> archiveFiles;
env->GetChildren(archivedir, &archiveFiles); if (env->GetChildren(archivedir, &archiveFiles).ok()) {
// Delete archival files. // Delete archival files.
for (size_t i = 0; i < archiveFiles.size(); ++i) { for (const auto& file : archiveFiles) {
if (ParseFileName(archiveFiles[i], &number, &type) && type == kLogFile) { if (ParseFileName(file, &number, &type) &&
Status del = env->DeleteFile(archivedir + "/" + archiveFiles[i]); type == kLogFile) {
if (result.ok() && !del.ok()) { Status del = env->DeleteFile(archivedir + "/" + file);
result = del; if (result.ok() && !del.ok()) {
result = del;
}
} }
} }
env->DeleteDir(archivedir);
} }
// ignore case where no archival directory is present // Delete log files in the WAL dir
env->DeleteDir(archivedir); if (wal_dir_exists) {
for (const auto& file : walDirFiles) {
if (ParseFileName(file, &number, &type) && type == kLogFile) {
Status del = env->DeleteFile(LogFileName(soptions.wal_dir, number));
if (result.ok() && !del.ok()) {
result = del;
}
}
}
env->DeleteDir(soptions.wal_dir);
}
env->UnlockFile(lock); // Ignore error since state is already gone env->UnlockFile(lock); // Ignore error since state is already gone
env->DeleteFile(lockname); env->DeleteFile(lockname);
env->DeleteDir(dbname); // Ignore error in case dir contains other files env->DeleteDir(dbname); // Ignore error in case dir contains other files
env->DeleteDir(soptions.wal_dir);
} }
return result; return result;
} }

View File

@ -515,15 +515,19 @@ Status WinEnvIO::CreateDir(const std::string& name) {
Status WinEnvIO::CreateDirIfMissing(const std::string& name) { Status WinEnvIO::CreateDirIfMissing(const std::string& name) {
Status result; Status result;
if (DirExists(name)) {
return result;
}
BOOL ret = CreateDirectoryA(name.c_str(), NULL); BOOL ret = CreateDirectoryA(name.c_str(), NULL);
if (!ret) { if (!ret) {
auto lastError = GetLastError(); auto lastError = GetLastError();
if (lastError != ERROR_ALREADY_EXISTS) { if (lastError != ERROR_ALREADY_EXISTS) {
result = IOErrorFromWindowsError( result = IOErrorFromWindowsError(
"Failed to create a directory: " + name, lastError); "Failed to create a directory: " + name, lastError);
} else if (!DirExists(name)) { } else {
result = result =
Status::IOError("`" + name + "' exists but is not a directory"); Status::IOError(name + ": exists but is not a directory");
} }
} }
return result; return result;