Status FsManager::Open()

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();
}