* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef OMNISTREAM_SNAPSHOTDIRECTORY_H
#define OMNISTREAM_SNAPSHOTDIRECTORY_H
#include <filesystem>
#include <atomic>
#include <memory>
#include <stdexcept>
#include <vector>
#include "DirectoryStateHandle.h"
#include "core/utils/FileUtils.h"
namespace fs = std::filesystem;
class TemporarySnapshotDirectory;
class PermanentSnapshotDirectory;
class SnapshotDirectory {
public:
enum class State {
ONGOING,
COMPLETED,
DELETED
};
SnapshotDirectory(const SnapshotDirectory&) = delete;
SnapshotDirectory& operator=(const SnapshotDirectory&) = delete;
const fs::path& getDirectory() const
{
return directory_;
}
void mkdirs() const
{
fs::create_directories(directory_);
}
bool exists() const
{
return fs::exists(directory_);
}
std::vector<fs::path> listDirectory() const
{
return FileUtils::listDirectory(directory_);
}
void cleanup()
{
if (state_.compare_exchange_strong(ongoingState_, State::DELETED)) {
FileUtils::deleteDirectory(directory_);
}
}
bool isSnapshotCompleted() const
{
return state_.load() == State::COMPLETED;
}
virtual std::unique_ptr<DirectoryStateHandle> completeSnapshotAndGetHandle() = 0;
virtual ~SnapshotDirectory() = default;
protected:
explicit SnapshotDirectory(const fs::path& directory)
: directory_(directory), state_(State::ONGOING), ongoingState_(State::ONGOING) {}
fs::path directory_;
std::atomic<State> state_;
State ongoingState_ = State::ONGOING;
};
class TemporarySnapshotDirectory : public SnapshotDirectory {
public:
explicit TemporarySnapshotDirectory(const fs::path& directory)
: SnapshotDirectory(directory) {}
std::unique_ptr<DirectoryStateHandle> completeSnapshotAndGetHandle() override
{
return nullptr;
}
};
class PermanentSnapshotDirectory : public SnapshotDirectory {
public:
explicit PermanentSnapshotDirectory(const fs::path& directory)
: SnapshotDirectory(directory) {}
std::unique_ptr<DirectoryStateHandle> completeSnapshotAndGetHandle() override
{
State current = state_.load();
if (current == State::COMPLETED) {
return DirectoryStateHandle::forPathWithSizePtr(Path(directory_.string()));
}
State expected = State::ONGOING;
if (state_.compare_exchange_strong(expected, State::COMPLETED)) {
return DirectoryStateHandle::forPathWithSizePtr(Path(directory_.string()));
} else {
if (expected == State::COMPLETED) {
return DirectoryStateHandle::forPathWithSizePtr(Path(directory_.string()));
} else {
throw std::runtime_error("Snapshot state is invalid");
}
}
}
};
#endif