Skip to content

Commit 403700b

Browse files
committed
RequiredDownloadManager
1 parent 96c8ab2 commit 403700b

9 files changed

Lines changed: 756 additions & 10 deletions

File tree

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/* DownloadThread
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include "CommonFramework/Tools/GlobalThreadPools.h"
8+
#include "CommonFramework/Globals.h"
9+
#include "CommonFramework/Exceptions/OperationFailedException.h"
10+
#include "Common/Cpp/Filesystem.h"
11+
#include "CommonFramework/Tools/FileDownloader.h"
12+
#include "CommonFramework/Tools/FileUnzip.h"
13+
#include "CommonFramework/Tools/FileHash.h"
14+
#include "CommonFramework/Logging/Logger.h"
15+
16+
#include "DownloadThread.h"
17+
18+
19+
#include <iostream>
20+
using std::cout;
21+
using std::endl;
22+
23+
namespace PokemonAutomation{
24+
25+
namespace fs = std::filesystem;
26+
27+
28+
29+
30+
DownloadThread::~DownloadThread(){
31+
// cout << "~DownloadThread" << endl;
32+
this->cancel();
33+
m_worker.wait_and_ignore_exceptions();
34+
}
35+
DownloadThread::DownloadThread(Hooks hooks, const DownloadedResourceMetadata& remote_metadata, Mutex& lock, ConditionVariable& cv)
36+
: m_hooks(std::move(hooks))
37+
, m_remote_metadata(remote_metadata)
38+
, m_download_lock(lock)
39+
, m_download_cv(cv)
40+
{}
41+
42+
void DownloadThread::start_download_thread(){
43+
m_worker = GlobalThreadPools::unlimited_normal().dispatch_now_blocking(
44+
[this]{
45+
46+
bool success = false;
47+
{
48+
std::unique_lock<Mutex> lock(m_download_lock);
49+
m_download_cv.wait(lock, [this] { return m_hooks.is_ready_to_start() || m_stopping; });
50+
51+
if (m_stopping) return;
52+
}
53+
54+
// runs when lambda is finished
55+
// updates action state, removes self from download queue
56+
struct ScopeGuard {
57+
DownloadThread* thread_ptr;
58+
bool& success_ref;
59+
~ScopeGuard() {
60+
thread_ptr->m_stopping = true;
61+
thread_ptr->m_hooks.on_finished(success_ref);
62+
}
63+
} guard{this, success};
64+
65+
try {
66+
// std::this_thread::sleep_for(std::chrono::seconds(7));
67+
68+
run_download(m_remote_metadata);
69+
70+
cout << "Done Download" << endl;
71+
success = true;
72+
73+
}catch(OperationCancelledException&){
74+
// user cancelled action
75+
success = false;
76+
77+
}catch(OperationFailedException&){
78+
success = false;
79+
m_hooks.report_failed();
80+
}catch (const std::exception& e) {
81+
std::cout << "Standard exception: " << e.what() << std::endl;
82+
success = false;
83+
m_hooks.report_exception_caught("ResourceDownloadButton::start_download");
84+
} catch(...){
85+
success = false;
86+
m_hooks.report_exception_caught("ResourceDownloadButton::start_download");
87+
}
88+
89+
}
90+
);
91+
92+
}
93+
94+
void DownloadThread::run_download(DownloadedResourceMetadata resource_metadata){
95+
Logger& logger = global_logger_tagged();
96+
// std::this_thread::sleep_for(std::chrono::seconds(5));
97+
98+
std::string url = resource_metadata.url;
99+
std::string resource_name = resource_metadata.resource_name;
100+
uint64_t expected_size = resource_metadata.size_compressed_bytes;
101+
102+
std::string resource_directory = DOWNLOADED_RESOURCE_PATH() + resource_name;
103+
try{
104+
105+
// delete directory and the old resource
106+
fs::remove_all(Filesystem::Path(resource_directory));
107+
108+
// download
109+
std::string zip_path = resource_directory + "/temp.zip";
110+
FileDownloader::download_file_to_disk(
111+
*this,
112+
logger,
113+
url,
114+
zip_path,
115+
expected_size,
116+
[this](uint64_t bytes_done, uint64_t total_bytes){
117+
m_hooks.report_download_progress(bytes_done, total_bytes);
118+
}
119+
);
120+
121+
// hash
122+
std::string hash =
123+
hash_file(
124+
*this,
125+
zip_path,
126+
[this](uint64_t bytes_done, uint64_t total_bytes){
127+
m_hooks.report_hash_progress(bytes_done, total_bytes);
128+
}
129+
);
130+
std::string expected_hash = resource_metadata.sha256;
131+
if (hash != expected_hash){
132+
std::cerr << "current hash: " << hash << endl;
133+
throw_and_log<OperationFailedException>(logger, ErrorReport::NO_ERROR_REPORT,
134+
"Downloaded file failed verification. SHA 256 hash did not match the expected value.");
135+
}
136+
137+
// Filesystem::Path p{zip_path};
138+
// cout << "File size: " << std::filesystem::file_size(p) << endl;
139+
140+
// unzip
141+
unzip_file(
142+
*this,
143+
zip_path.c_str(),
144+
resource_directory.c_str(),
145+
[this](uint64_t bytes_done, uint64_t total_bytes){
146+
m_hooks.report_unzip_progress(bytes_done, total_bytes);
147+
}
148+
);
149+
150+
// delete old zip file
151+
fs::remove(Filesystem::Path(zip_path));
152+
153+
throw_if_cancelled();
154+
155+
}catch(OperationCancelledException&){
156+
// delete directory and the resource
157+
fs::remove_all(Filesystem::Path(resource_directory));
158+
159+
throw;
160+
}catch(OperationFailedException&){
161+
// delete directory and the resource
162+
fs::remove_all(Filesystem::Path(resource_directory));
163+
164+
throw;
165+
}catch(...){
166+
// delete directory and the resource
167+
fs::remove_all(Filesystem::Path(resource_directory));
168+
169+
throw;
170+
}
171+
172+
}
173+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* DownloadThread
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_DownloadThread_H
8+
#define PokemonAutomation_DownloadThread_H
9+
10+
#include <functional>
11+
#include "Common/Cpp/CancellableScope.h"
12+
#include "Common/Cpp/Concurrency/AsyncTask.h"
13+
#include "Common/Cpp/Concurrency/ConditionVariable.h"
14+
#include "Common/Cpp/Concurrency/Mutex.h"
15+
#include "ResourceDownloadHelpers.h"
16+
17+
18+
namespace PokemonAutomation{
19+
20+
class DownloadThread : public CancellableScope{
21+
22+
public:
23+
struct Hooks {
24+
std::function<bool()> is_ready_to_start;
25+
std::function<void(bool success)> on_finished;
26+
// std::function<void(const DownloadedResourceMetadata&)> run_download;
27+
// std::function<void(bool success)> update_label;
28+
std::function<void()> report_failed;
29+
std::function<void(const char*)> report_exception_caught;
30+
std::function<void(uint64_t bytes_done, uint64_t total_bytes)> report_download_progress;
31+
std::function<void(uint64_t bytes_done, uint64_t total_bytes)> report_hash_progress;
32+
std::function<void(uint64_t bytes_done, uint64_t total_bytes)> report_unzip_progress;
33+
};
34+
35+
public:
36+
~DownloadThread();
37+
DownloadThread(Hooks hooks, const DownloadedResourceMetadata& remote_metadata, Mutex& lock, ConditionVariable& cv);
38+
39+
public:
40+
void start_download_thread();
41+
42+
// throws OperationCancelledException if the user cancels the action
43+
void run_download(DownloadedResourceMetadata resource_metadata);
44+
45+
46+
47+
private:
48+
Hooks m_hooks;
49+
DownloadedResourceMetadata m_remote_metadata;
50+
AsyncTask m_worker;
51+
52+
std::atomic<bool> m_stopping{false};
53+
Mutex& m_download_lock;
54+
ConditionVariable& m_download_cv;
55+
};
56+
}
57+
#endif
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* Required Download
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
8+
#include "CommonFramework/GlobalSettingsPanel.h"
9+
#include "RequiredDownloadManager.h"
10+
#include "RequiredDownload.h"
11+
12+
#include <iostream>
13+
using std::cout;
14+
using std::endl;
15+
16+
namespace PokemonAutomation{
17+
18+
19+
RequiredDownload::RequiredDownload(RequiredDownloadManager& download_manager, DownloadedResourceMetadata resource_metadata, uint16_t index, Mutex& lock, ConditionVariable& cv)
20+
: m_download_manager(download_manager)
21+
, m_resource_metadata(resource_metadata)
22+
, m_index(index)
23+
, m_name(resource_metadata.resource_name)
24+
, m_lock(lock)
25+
, m_cv(cv)
26+
, m_download_thread(initialize_download_thread())
27+
{}
28+
29+
DownloadThread RequiredDownload::initialize_download_thread(){
30+
31+
DownloadThread::Hooks generic_row_hooks{
32+
.is_ready_to_start = [this] { return m_download_manager.is_download_ready_to_start(m_index); },
33+
.on_finished = [this](bool success) {
34+
// GlobalSettings::instance().update_resource_download_row_status(m_index, success);
35+
on_download_finished();
36+
},
37+
.report_failed = [this] { report_download_failed(); },
38+
.report_exception_caught = [this](const char* context) { report_unexpected_exception_caught(context); },
39+
.report_download_progress = [this](uint64_t bytes_done, uint64_t total_bytes) { report_download_progress(bytes_done, total_bytes); },
40+
.report_hash_progress = [this](uint64_t bytes_done, uint64_t total_bytes) { report_hash_progress(bytes_done, total_bytes); },
41+
.report_unzip_progress = [this](uint64_t bytes_done, uint64_t total_bytes) { report_unzip_progress(bytes_done, total_bytes); }
42+
};
43+
44+
return DownloadThread{generic_row_hooks, m_resource_metadata, m_lock, m_cv};
45+
46+
}
47+
48+
49+
50+
void RequiredDownload::start_download(){
51+
m_download_thread.start_download_thread();
52+
}
53+
54+
void RequiredDownload::cancel_download(){
55+
m_download_thread.cancel();
56+
// m_parent_session.remove_from_download_list(m_index);
57+
}
58+
59+
60+
void RequiredDownload::on_download_finished(){
61+
m_download_manager.remove_from_download_list(m_index);
62+
m_download_manager.check_if_all_downloads_done();
63+
}
64+
65+
void RequiredDownload::report_download_failed(){
66+
m_download_manager.report_download_failed();
67+
// m_listeners.run_method(&Listener::on_download_failed);
68+
}
69+
70+
71+
void RequiredDownload::report_unexpected_exception_caught(const std::string& function_name){
72+
m_download_manager.report_unexpected_exception_caught(function_name);
73+
}
74+
75+
//////////////////////////
76+
// Listeners
77+
//////////////////////////
78+
void RequiredDownload::add_listener(Listener& listener){
79+
m_listeners.add(listener);
80+
}
81+
void RequiredDownload::remove_listener(Listener& listener){
82+
m_listeners.remove(listener);
83+
}
84+
85+
86+
void RequiredDownload::report_download_progress(uint64_t bytes_done, uint64_t total_bytes){
87+
m_listeners.run_method(&Listener::on_download_progress, bytes_done, total_bytes);
88+
}
89+
void RequiredDownload::report_unzip_progress(uint64_t bytes_done, uint64_t total_bytes){
90+
m_listeners.run_method(&Listener::on_unzip_progress, bytes_done, total_bytes);
91+
}
92+
void RequiredDownload::report_hash_progress(uint64_t bytes_done, uint64_t total_bytes){
93+
m_listeners.run_method(&Listener::on_hash_progress, bytes_done, total_bytes);
94+
}
95+
96+
}

0 commit comments

Comments
 (0)