120 lines
3.6 KiB
C++
120 lines
3.6 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),
|
|
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) {
|
|
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) {
|
|
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) {
|
|
Components::iterator itr = readingSources.find(source);
|
|
if (err.has_value()) {
|
|
error("Coundn't read " + source + ": " + err.value()->what());
|
|
readingSources.erase(itr);
|
|
return;
|
|
}
|
|
|
|
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) {
|
|
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) {
|
|
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) {
|
|
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 {
|
|
return knownSources.count(source) > 0;
|
|
}
|