diff options
author | lonkaars <loek@pipeframe.xyz> | 2022-12-25 14:16:55 +0100 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2022-12-25 14:16:55 +0100 |
commit | 9205f93bda48ffdc080d40140511b68b88c46fd7 (patch) | |
tree | 9de14ae45b18125c563eb01595238128453604b4 | |
parent | 2b1145fb0aec3feb9cbab2df9be57ab43fc7f975 (diff) |
cache working with asynchronous image downloads
-rw-r--r-- | oop2eindopdr/CacheManager.cpp | 41 | ||||
-rw-r--r-- | oop2eindopdr/CacheManager.h | 5 | ||||
-rw-r--r-- | oop2eindopdr/DownloadManager.cpp | 14 | ||||
-rw-r--r-- | oop2eindopdr/PokemonCard.cpp | 9 |
4 files changed, 58 insertions, 11 deletions
diff --git a/oop2eindopdr/CacheManager.cpp b/oop2eindopdr/CacheManager.cpp index b8c368e..9324b81 100644 --- a/oop2eindopdr/CacheManager.cpp +++ b/oop2eindopdr/CacheManager.cpp @@ -5,6 +5,9 @@ #include <iostream> #include <ctime> +#include <thread> +#include <chrono> + CacheManager::CacheManager(const char* cache_path) : CacheManager(std::string(cache_path)) { } CacheManager::CacheManager(std::string cache_path) { this->cache_path = cache_path; @@ -41,10 +44,42 @@ void CacheManager::update_cache() { std::fstream* CacheManager::cache_get(std::string filename) { return cache_get(filename.c_str()); } std::fstream* CacheManager::cache_get(const char* filename) { std::filesystem::path fixed_path = prefix_cache_path(filename); // fix duplicate slashes and add prefix - std::filesystem::create_directories(fixed_path.parent_path()); // make sure folder exists - if (!std::filesystem::exists(fixed_path)) + unsigned int i = 0; + + i = 0; + while (!std::filesystem::exists(fixed_path.parent_path())) { + std::filesystem::create_directories(fixed_path.parent_path()); // make sure folder exists + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + i++; + if (i > 100) { + std::cout << "folder touch doesn't succeed after 100 tries on file " << fixed_path << std::endl; + exit(1); + } + } + + i = 0; + while (!std::filesystem::exists(fixed_path)) { std::fstream(fixed_path, std::ios::trunc | std::ios::out).close(); // touch file - std::fstream* file = new std::fstream(fixed_path.c_str(), std::ios::out | std::ios::in); // open file + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + i++; + if (i > 100) { + std::cout << "file touch doesn't succeed after 100 tries on file " << fixed_path << std::endl; + exit(1); + } + } + + i = 0; + std::fstream* file = nullptr; + do { + delete file; + file = new std::fstream(fixed_path.c_str(), std::ios::out | std::ios::in); // open file + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + i++; + if (i > 100) { + std::cout << "file open doesn't succeed after 100 tries on file " << fixed_path << std::endl; + exit(1); + } + } while (!file->is_open()); this->files.push_back(file); // add file pointer (for closing all files on exit) return file; } diff --git a/oop2eindopdr/CacheManager.h b/oop2eindopdr/CacheManager.h index e441b1b..0b15cfa 100644 --- a/oop2eindopdr/CacheManager.h +++ b/oop2eindopdr/CacheManager.h @@ -10,8 +10,6 @@ private: std::string cache_path; /** @brief pointers to open file handles */ std::vector<std::fstream*> files; - /** @brief add cache path before filename */ - virtual std::string prefix_cache_path(const char* filename); public: /** @brief initialize CacheManager class at `cache_path` */ CacheManager(const char* cache_path); @@ -36,6 +34,9 @@ public: virtual bool cache_exists(const char* filename); virtual bool cache_exists(std::string filename); + /** @brief add cache path before filename */ + virtual std::string prefix_cache_path(const char* filename); + /** @brief currently opened cache update unix timestamp */ uint64_t age; }; diff --git a/oop2eindopdr/DownloadManager.cpp b/oop2eindopdr/DownloadManager.cpp index ff24613..dacc04a 100644 --- a/oop2eindopdr/DownloadManager.cpp +++ b/oop2eindopdr/DownloadManager.cpp @@ -1,3 +1,4 @@ +#include <iostream> #include <fstream> #include <cpr/cpr.h> @@ -15,7 +16,11 @@ DownloadManager::~DownloadManager() { std::fstream* DownloadManager::open_file(std::string filename) { while (this->file_queue.size() > this->max_files); - std::fstream* out = new std::fstream(filename); + std::fstream* out = nullptr; + do { + delete out; + out = new std::fstream(filename, std::ios::out | std::ios::binary); + } while (!out->is_open()); this->file_queue.push_back(out); return out; } @@ -28,9 +33,12 @@ void DownloadManager::close_file(std::fstream* file_ptr) { std::thread* DownloadManager::wget(std::string url, std::string filename) { std::thread* download = new std::thread([url, filename, this] { - cpr::Response res = cpr::Get(cpr::Url{url}); + cpr::Response res; + do res = cpr::Get(cpr::Url{url}); + while (res.status_code != 200); + std::fstream* file = this->open_file(filename); - *file << res.text; + file->write(res.text.data(), res.downloaded_bytes); // can't use << for binary data this->close_file(file); }); download_queue.push_back(download); diff --git a/oop2eindopdr/PokemonCard.cpp b/oop2eindopdr/PokemonCard.cpp index c7e4ea3..eb6a6e5 100644 --- a/oop2eindopdr/PokemonCard.cpp +++ b/oop2eindopdr/PokemonCard.cpp @@ -31,7 +31,7 @@ PokemonCard::PokemonCard(Pokedex* pokedex) { } PokemonCard::~PokemonCard() { - + if (this->image_download_thread != nullptr) delete this->image_download_thread; } void PokemonCard::fetch_market_value() { @@ -62,8 +62,11 @@ void PokemonCard::verify_files() { } void PokemonCard::download_files() { - std::thread* card_normal_dl = this->pokedex->download_manager->wget(this->url_card_normal, prefix_cache_path("card.png")); - std::thread* card_hires_dl = this->pokedex->download_manager->wget(this->url_card_hires, prefix_cache_path("card_hires.png")); + const std::string card_normal_path = this->pokedex->cache->prefix_cache_path(prefix_cache_path("card.png").c_str()); + const std::string card_hires_path = this->pokedex->cache->prefix_cache_path(prefix_cache_path("card_hires.png").c_str()); + + std::thread* card_normal_dl = this->pokedex->download_manager->wget(this->url_card_normal, card_normal_path); + std::thread* card_hires_dl = this->pokedex->download_manager->wget(this->url_card_hires, card_hires_path); this->image_download_thread = new std::thread([card_hires_dl, card_normal_dl, this] { card_normal_dl->join(); |