mason/src/collection.cpp

138 lines
4.2 KiB
C++

#include "collection.h"
constexpr std::string_view downloads("downloads");
static const std::regex remote("(^https?):\\/\\/");
Collection::Collection(
const std::filesystem::path& destination,
const std::string& target,
const std::shared_ptr<Logger>& logger,
const std::shared_ptr<TaskManager>& taskManager
):
Loggable(logger),
std::enable_shared_from_this<Collection>(),
mutex(),
destination(destination),
target(target),
taskManager(taskManager),
knownSources(),
successSources(),
downloadingSources(),
readingSources(),
buildingSources()
{
try {
std::filesystem::create_directories(destination);
} catch (const std::exception& e) {
fatal(e.what());
throw e;
}
}
void Collection::addSource(const std::string& source) {
std::lock_guard lock(mutex);
if (_hasSource(source)) {
major("Source " + source + " is already present, skipping as duplicate");
return;
}
debug("Adding source " + source);
if (isRemote(source))
queueDownload(source);
else
queueRead(source, source);
}
void Collection::sourceDownaloded(const std::string& source, TaskManager::Error err) {
std::lock_guard lock(mutex);
Downloads::const_iterator itr = downloadingSources.find(source);
std::optional<std::filesystem::path> location = itr->second->getLocation();
downloadingSources.erase(itr);
if (err.has_value() || !location.has_value()) {
error("Coundn't download " + source + ": " + err.value()->what());
return;
}
queueRead(source, location.value());
}
void Collection::sourceRead(const std::string& source, TaskManager::Error err) {
std::lock_guard lock(mutex);
debug("Source " + source + " has been read");
Components::iterator itr = readingSources.find(source);
if (err.has_value()) {
error("Coundn't read " + source + ": " + err.value()->what());
readingSources.erase(itr);
return;
}
debug("Queuing build of " + source);
std::pair<Components::iterator, bool> res = buildingSources.emplace(source, std::move(itr->second));
readingSources.erase(itr);
taskManager->queue(
std::bind(&Component::build, res.first->second.get(), destination, target),
std::bind(&Collection::sourceBuilt, this, source, std::placeholders::_1)
);
}
void Collection::sourceBuilt(const std::string& source, TaskManager::Error err) {
std::lock_guard lock(mutex);
debug("Source " + source + " has been built");
Components::iterator itr = buildingSources.find(source);
buildingSources.erase(itr);
if (err.has_value()) {
error("Coundn't read " + source + ": " + err.value()->what());
return;
}
successSources.emplace(source);
}
bool Collection::isRemote(const std::string& source) {
return std::regex_search(source, remote);
}
void Collection::queueDownload(const std::string& source) {
debug("Queuing download of " + source);
std::pair<Downloads::iterator, bool> res = downloadingSources.emplace(std::piecewise_construct,
std::forward_as_tuple(source),
std::forward_as_tuple(
std::make_unique<Download>(source, destination/downloads, logger)
)
);
taskManager->queue(
std::bind(&Download::proceed, res.first->second.get()),
std::bind(&Collection::sourceDownaloded, this, source, std::placeholders::_1)
);
}
void Collection::queueRead(const std::string& source, const std::filesystem::path& location) {
debug("Queuing read of " + source);
std::pair<Components::iterator, bool> res = readingSources.emplace(std::piecewise_construct,
std::forward_as_tuple(source),
std::forward_as_tuple(
std::make_unique<Component>(location, shared_from_this(), logger)
)
);
taskManager->queue(
std::bind(&Component::read, res.first->second.get()),
std::bind(&Collection::sourceRead, this, source, std::placeholders::_1)
);
}
bool Collection::hasSource(const std::string& source) const {
std::lock_guard lock(mutex);
return _hasSource(source);
}
bool Collection::_hasSource(const std::string& source) const {
return knownSources.count(source) > 0;
}