Skip to content

Commit

Permalink
local: http asset manifest with only manual asset adding, ref #62
Browse files Browse the repository at this point in the history
only rudimentary coherency checks are present, ref #96
  • Loading branch information
iboB committed Sep 11, 2024
1 parent f8e8ca5 commit 11bae0e
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 6 deletions.
1 change: 1 addition & 0 deletions local-provider/code/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ target_link_libraries(ac-local
xec::xec
jalog::jalog
ac::xxhash-cpp
ac::http
PUBLIC
ac::api
)
Expand Down
83 changes: 79 additions & 4 deletions local-provider/code/ac/AssetSourceHttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,93 @@
// SPDX-License-Identifier: MIT
//
#include "AssetSourceHttp.hpp"
#include <stdexcept>
#include "FsUtil.hpp"
#include <ahttp/ahttp.hpp>
#include <xxhash/hash.hpp>
#include <astl/move.hpp>
#include <astl/throw_ex.hpp>
#include <fstream>

namespace ac {

//AssetSourceHttp::AssetSourceHttp() {}
AssetSourceHttp::AssetSourceHttp(std::string id, std::string edownloadDir)
: m_id(astl::move(id))
, m_downloadDir(astl::move(edownloadDir))
{
fs::expandPathInPlace(m_downloadDir);
}

void AssetSourceHttp::addAsset(std::string id, ManifestEntry entry) {
AssetManifestEntry ame;
(ManifestEntry&)ame = astl::move(entry);
ame.targetPath = m_downloadDir + "/" + id;

auto st = fs::basicStat(ame.targetPath);
if (st.file()) {
ame.info.size = st.size;
ame.info.path = ame.targetPath;
}
else if (st.exists()) {
throw_ex{} << "Target path is not a file: " << ame.targetPath;
}

m_assetManifest.emplace(std::move(id), std::move(ame));
}

std::optional<AssetSource::BasicAssetInfo> AssetSourceHttp::checkAssetSync(std::string_view id) noexcept {
return {};
auto it = m_assetManifest.find(std::string(id));
if (it == m_assetManifest.end()) {
return std::nullopt;
}
return it->second.info;
}

AssetSource::BasicAssetInfo AssetSourceHttp::fetchAssetSync(std::string_view id, ProgressCb pcb) {
throw std::runtime_error("Not implemented");
auto it = m_assetManifest.find(std::string(id));
if (it == m_assetManifest.end()) {
throw_ex{} << "Asset not found: " << id;
}

auto& ame = it->second;

if (ame.info.path) {
// already downloaded
return ame.info;
}

auto g = ahttp::get_sync(ame.url);
auto fout = std::ofstream(ame.targetPath, std::ios::binary);
if (!fout) {
throw_ex{} << "Failed to open file for writing: " << ame.targetPath;
}

pcb(0);

static constexpr size_t chunkSize = 1024 * 1024; // 1mb chunks
std::vector<uint8_t> buf(chunkSize);
size_t totalDownloaded = 0;
xxhash::h64 hasher;
while (!g.done()) {
auto chunk = g.get_next_chunk(buf);
fout.write((const char*)chunk.data(), chunk.size());
hasher.update(chunk);
totalDownloaded += chunk.size();

if (g.size()) {
// if we have a size, we can report meaningful progress
// otherwise only leave the 0 above
pcb(float(totalDownloaded) / *g.size());
}
}
fout.close();

if (ame.xxhash && *ame.xxhash != hasher.digest()) {
throw_ex{} << "Hash mismatch for asset: " << id;
}

ame.info.size = totalDownloaded;
ame.info.path = ame.targetPath;
return ame.info;
}

} // namespace ac
12 changes: 10 additions & 2 deletions local-provider/code/ac/AssetSourceHttp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@ class AC_LOCAL_EXPORT AssetSourceHttp final : public AssetSource {
std::optional<uint64_t> xxhash; // expected xxhash of the asset (if available in the manifest)
};

//AssetSourceHttp(std::string id, std::string elocalDir, );
AssetSourceHttp(std::string id, std::string edownloadDir);

void addAsset(std::string id, ManifestEntry entry);

virtual std::string_view id() const noexcept override { return m_id; }

virtual std::optional<BasicAssetInfo> checkAssetSync(std::string_view id) noexcept override;
virtual BasicAssetInfo fetchAssetSync(std::string_view id, ProgressCb) override;
virtual BasicAssetInfo fetchAssetSync(std::string_view id, ProgressCb pcb) override;
private:
std::string m_id;

std::string m_downloadDir;

struct AssetManifestEntry : public ManifestEntry {
std::string targetPath; // where the asset should be stored

Expand Down

0 comments on commit 11bae0e

Please sign in to comment.