Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Media/Filesystem Mounting frontend and Archive mouting backend #18

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@
[submodule "third-party/kissnet"]
path = third-party/kissnet
url = https://github.com/Ybalrid/kissnet
[submodule "third-party/bit7z"]
path = third-party/bit7z
url = https://github.com/rikyoz/bit7z.git
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ set(SRC_FILES
src/asset/AssetLibrary.cpp
src/asset/Asset.cpp
src/asset/AssetCache.cpp
src/asset/MediaManager.cpp
src/asset/MountManager.cpp
src/asset/MountArchive.cpp
src/asset/ImageAsset.cpp
src/net/WebSocket.cpp
src/net/NetworkThread.cpp
Expand All @@ -48,6 +51,7 @@ set(INCLUDE_DIRS
third-party/stb
third-party/glm
third-party/SDL/include
third-party/bit7z
)

# Add executable
Expand Down Expand Up @@ -119,6 +123,11 @@ target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE imgui)
# Kissnet
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third-party/kissnet)

#bit7z
set(BIT7Z_AUTO_FORMAT ON CACHE BOOL "enable auto format support" FORCE)
add_subdirectory(${CMAKE_SOURCE_DIR}/third-party/bit7z)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE bit7z)


find_program(CLANG_TIDY_EXE NAMES clang-tidy)

Expand Down
11 changes: 11 additions & 0 deletions src/asset/MediaManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "MediaManager.h"

#include "MountManager.h"

MediaManager::MediaManager() : mount_manager(std::make_unique<MountManager>()) {
}

MediaManager& MediaManager::instance() {
static MediaManager instance;
return instance;
}
20 changes: 20 additions & 0 deletions src/asset/MediaManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <memory>

class MountManager;

class MediaManager {
public:
static MediaManager& instance();

private:
MediaManager();

// Delete copy and move semantics
MediaManager(MediaManager&) = delete;
void operator=(MediaManager const&) = delete;

// Access to the underlying storage system
std::unique_ptr<MountManager> mount_manager;
};
22 changes: 22 additions & 0 deletions src/asset/Mount.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include <filesystem>

class Mount {
public:
Mount(const std::filesystem::path& target_path) : path{target_path} {};

std::filesystem::path get_path() const {
return path;
};

virtual void load() = 0;

virtual bool seek_file(const std::string& path) const = 0;
virtual std::vector<uint8_t> fetch_data(const std::string& path) = 0;

protected:
const std::filesystem::path path;
virtual void load_cache() = 0;
virtual void save_cache() = 0;
};
70 changes: 70 additions & 0 deletions src/asset/MountArchive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "MountArchive.h"

#include "bit7z/bitarchivereader.hpp"
#include "utils/Log.h"

MountArchive::MountArchive(const std::filesystem::path& archive_path)
: Mount(archive_path), reader(std::make_unique<bit7z::BitArchiveReader>(library, path.string())) {
}

void MountArchive::load() {
reset_reader();

try {
reader = std::make_unique<bit7z::BitArchiveReader>(library, get_path().string());
reader->test();
}
catch (const std::exception& exception) {
throw exception;
}

load_cache();
}

bool MountArchive::seek_file(const std::string& path) const {
return static_cache.contains(path);
}

std::vector<uint8_t> MountArchive::fetch_data(const std::string& path) {
uint32_t index = static_cache.at(path);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can throw std::out_of_range, is that acceptable?

std::vector<uint8_t> buffer;

try {
reader->extractTo(buffer, index);
}
catch (const std::exception& exception) {
throw exception;
}

return buffer;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are the contents of buffer if we caught an exception? does the caller have a way of knowing that this data is bad?

}

void MountArchive::load_cache() {
const std::filesystem::path cache_file_path = get_path().replace_filename("cache");

if (std::filesystem::exists(cache_file_path)) {
return;
}

const auto items = reader->items();
for (const auto& item : items) {
// 7zip returns files with a double-backslash prefix
// These are stripped to be consistent with filesystem relative paths
static_cache.at(item.path().replace(0, 2, "/")) = item.index();
}
}

void MountArchive::save_cache() {
// TODO: Implement writing cache to disk
}

void MountArchive::reset_reader() {
try {
if (reader) {
reader.reset();
}
}
catch (const std::exception& e) {
Log::log_print(ERR, e.what());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we rethrow?

}
}
30 changes: 30 additions & 0 deletions src/asset/MountArchive.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef MOUNTARCHIVE_H
#define MOUNTARCHIVE_H

#include "Mount.h"

#include <include/bit7z/bit7zlibrary.hpp>
#include <include/bit7z/bitarchivereader.hpp>

class MountArchive : public Mount {
public:
explicit MountArchive(const std::filesystem::path& archive_path);
~MountArchive() = default;

void load() override;

bool seek_file(const std::string& path) const override;
std::vector<uint8_t> fetch_data(const std::string& path) override;

private:
void load_cache() override;
void save_cache() override;

void reset_reader();

std::unordered_map<std::string, uint32_t> static_cache;
const bit7z::Bit7zLibrary library;
std::unique_ptr<bit7z::BitArchiveReader> reader;
};

#endif // MOUNTARCHIVE_H
50 changes: 50 additions & 0 deletions src/asset/MountManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "MountManager.h"

#include "MountArchive.h"
#include "utils/Log.h"

#include <format>
#include <shared_mutex>

MountManager::MountManager() {
}

void MountManager::load_mounts(const std::vector<std::filesystem::path>& target_mount_path) {
std::unique_lock<std::shared_mutex> locker(lock);

if (!loaded_mounts.empty()) {
loaded_mounts.clear();
}

for (const std::filesystem::path& mount_path : target_mount_path) {

try {
std::unique_ptr<MountArchive> archive = std::make_unique<MountArchive>(mount_path);
archive->load();
loaded_mounts.push_back(std::move(archive));
}
catch (std::exception exception) {
Log::log_print(
WARNING,
std::format("Failed to create mount at {}: {}", mount_path.string(), exception.what()).c_str());
continue;
}
}
}

std::optional<std::vector<uint8_t>> MountManager::fetch_data(const std::string& relative_path) {
std::shared_lock<std::shared_mutex> locker(lock);
Log::log_print(INFO, std::format("Loading file at {}", relative_path).c_str());
for (auto& mount : loaded_mounts) {
if (mount->seek_file(relative_path)) {
try {
return std::make_optional<std::vector<uint8_t>>(mount->fetch_data(relative_path));
}
catch (std::exception exception) {
Log::log_print(
ERR, std::format("Failed to load data due to the following errror {}", exception.what()).c_str());
}
}
}
return std::nullopt;
}
19 changes: 19 additions & 0 deletions src/asset/MountManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <filesystem>
#include <shared_mutex>
#include <vector>

#include "Mount.h"

class MountManager {
public:
MountManager();

void load_mounts(const std::vector<std::filesystem::path>& target_mount_path);
std::optional<std::vector<uint8_t>> fetch_data(const std::string& relative_path);

private:
std::shared_mutex lock;
std::vector<std::unique_ptr<Mount>> loaded_mounts;
};
1 change: 1 addition & 0 deletions third-party/bit7z
Submodule bit7z added at 386e00