in src/kudu/fs/fs_manager.cc [491:663]
Status FsManager::Open(FsReport* report, Timer* read_instance_metadata_files,
Timer* read_data_directories,
std::atomic<int>* containers_processed,
std::atomic<int>* containers_total) {
if (read_instance_metadata_files) {
read_instance_metadata_files->Start();
}
// Load and verify the instance metadata files.
//
// Done first to minimize side effects in the case that the configured roots
// are not yet initialized on disk.
CanonicalizedRootsList missing_roots;
RETURN_NOT_OK(PartialOpen(&missing_roots));
// Ensure all of the ancillary directories exist.
vector<string> ancillary_dirs = { GetWalsRootDir(),
GetTabletMetadataDir(),
GetConsensusMetadataDir() };
for (const auto& d : ancillary_dirs) {
bool is_dir;
RETURN_NOT_OK_PREPEND(GetEnv()->IsDirectory(d, &is_dir),
Substitute("could not verify required directory $0", d));
if (!is_dir) {
return Status::Corruption(
Substitute("Required directory $0 exists but is not a directory", d));
}
}
// In the event of failure, delete everything we created.
vector<string> created_dirs;
vector<string> created_files;
auto deleter = MakeScopedCleanup([&]() {
// Delete files first so that the directories will be empty when deleted.
for (const auto& f : created_files) {
WARN_NOT_OK(GetEnv()->DeleteFile(f), "Could not delete file " + f);
}
// Delete directories in reverse order since parent directories will have
// been added before child directories.
for (auto it = created_dirs.rbegin(); it != created_dirs.rend(); it++) {
WARN_NOT_OK(GetEnv()->DeleteDir(*it), "Could not delete dir " + *it);
}
});
// Create any missing roots, if desired.
if (!opts_.read_only &&
opts_.update_instances != UpdateInstanceBehavior::DONT_UPDATE) {
Status s = CreateFileSystemRoots(
missing_roots, *metadata_, &created_dirs, &created_files);
static const string kUnableToCreateMsg = "unable to create missing filesystem roots";
if (opts_.update_instances == UpdateInstanceBehavior::UPDATE_AND_IGNORE_FAILURES) {
// We only warn on error here -- regardless of errors, we might be in
// good enough shape to open the DataDirManager.
WARN_NOT_OK(s, kUnableToCreateMsg);
} else if (opts_.update_instances == UpdateInstanceBehavior::UPDATE_AND_ERROR_ON_FAILURE) {
RETURN_NOT_OK_PREPEND(s, kUnableToCreateMsg);
}
}
if (read_instance_metadata_files) {
read_instance_metadata_files->Stop();
}
string decrypted_key;
bool tenants_exist = is_tenants_exist();
if (tenants_exist && key_provider_) {
if (!FLAGS_enable_multi_tenancy) {
return Status::IllegalState(
"The '--enable_multi_tenancy' should set for the existed tenants.");
}
if (FLAGS_encrypt_data_at_rest && tenant_key(fs::kDefaultTenantID).empty()) {
return Status::IllegalState(
"Data at rest encryption is enabled and tenants exist, but no tenant key found");
}
// TODO(kedeng) :
// After implementing tenant management, different tenants need to be handled here.
//
// The priority of tenant key is higher than that of server key.
RETURN_NOT_OK(
key_provider_->DecryptEncryptionKey(this->tenant_key(fs::kDefaultTenantID),
this->tenant_key_iv(fs::kDefaultTenantID),
this->tenant_key_version(fs::kDefaultTenantID),
&decrypted_key));
} else if (!server_key().empty() && key_provider_) {
// Just check whether the upgrade operation is needed for '--enable_multi_tenancy'.
if (FLAGS_enable_multi_tenancy) {
return Status::IllegalState(
"--enable_multi_tenancy is set, but no tenants exist.");
}
string server_key;
RETURN_NOT_OK(key_provider_->DecryptEncryptionKey(this->server_key(),
this->server_key_iv(),
this->server_key_version(),
&decrypted_key));
} else if (server_key().empty() && FLAGS_encrypt_data_at_rest) {
return Status::IllegalState(
"--encrypt_data_at_rest is set, but no server key found.");
}
if (!decrypted_key.empty()) {
// 'decrypted_key' is a hexadecimal string and SetEncryptionKey expects bits
// (hex / 2 = bytes * 8 = bits).
GetEnv()->SetEncryptionKey(reinterpret_cast<const uint8_t*>(
a2b_hex(decrypted_key).c_str()),
decrypted_key.length() * 4);
}
// Open the directory manager if it has not been opened already.
RETURN_NOT_OK(OpenDataDirManager());
// Only clean temporary files after the data dir manager successfully opened.
// This ensures that we were able to obtain the exclusive directory locks
// on the data directories before we start deleting files.
if (!opts_.read_only) {
CleanTmpFiles();
CheckAndFixPermissions();
}
// Set an initial error handler to mark data directories as failed.
error_manager_->SetErrorNotificationCb(
ErrorHandlerType::DISK_ERROR, [this](const string& uuid, const string& tenant_id) {
this->dd_manager(tenant_id)->MarkDirFailedByUuid(uuid);
});
// Finally, initialize and open the block manager if needed.
if (!opts_.skip_block_manager) {
if (read_data_directories) {
read_data_directories->Start();
}
RETURN_NOT_OK(InitAndOpenBlockManager(report,
containers_processed,
containers_total,
fs::kDefaultTenantID,
BlockManager::MergeReport::REQUIRED));
if (read_data_directories) {
read_data_directories->Stop();
if (opts_.metric_entity && FsManager::IsLogType(opts_.block_manager_type)) {
METRIC_log_block_manager_containers_processing_time_startup.Instantiate(opts_.metric_entity,
(read_data_directories->TimeElapsed()).ToMilliseconds());
}
}
}
// Report wal and metadata directories.
if (report) {
report->wal_dir = canonicalized_wal_fs_root_.path;
report->metadata_dir = canonicalized_metadata_fs_root_.path;
}
if (FLAGS_enable_data_block_fsync) {
// Files/directories created by the directory manager in the fs roots have
// been synchronized, so now is a good time to sync the roots themselves.
WARN_NOT_OK(env_util::SyncAllParentDirs(GetEnv(), created_dirs, created_files),
"could not sync newly created fs roots");
}
LOG(INFO) << "Opened local filesystem: " <<
JoinStrings(DataDirManager::GetRootNames(canonicalized_all_fs_roots_), ",")
<< std::endl << SecureDebugString(*metadata_);
if (!created_dirs.empty()) {
LOG(INFO) << "New directories created while opening local filesystem: " <<
JoinStrings(created_dirs, ", ");
}
if (!created_files.empty()) {
LOG(INFO) << "New files created while opening local filesystem: " <<
JoinStrings(created_files, ", ");
}
// Success: do not delete any missing roots created.
deleter.cancel();
return Status::OK();
}