From d997dae36cec19efbb7d6f56306895e2b9ea19f9 Mon Sep 17 00:00:00 2001 From: Vladimir Gorshenkov Date: Sat, 22 Jan 2022 20:04:48 +0300 Subject: [PATCH] [Network] and [Kernel] add Cancel for downloader (windows) --- .../src/FileTransporter_private.h | 13 +-- .../src/FileTransporter_win.cpp | 29 ++++--- .../FileTransporter/src/transport_external.h | 12 ++- DesktopEditor/graphics/BaseThread.cpp | 18 ++--- DesktopEditor/graphics/BaseThread.h | 2 +- .../TestDownloader/TestDownloader.pro | 23 ------ .../{TestDownloader.pri => downloader.pro} | 37 ++++++--- Test/Applications/TestDownloader/main.cpp | 22 ++---- .../TestDownloader/mainwindow.cpp | 79 +++++++++++++++++++ Test/Applications/TestDownloader/mainwindow.h | 46 +++++++++++ .../Applications/TestDownloader/mainwindow.ui | 62 +++++++++++++++ 11 files changed, 261 insertions(+), 82 deletions(-) delete mode 100644 Test/Applications/TestDownloader/TestDownloader.pro rename Test/Applications/TestDownloader/{TestDownloader.pri => downloader.pro} (58%) create mode 100644 Test/Applications/TestDownloader/mainwindow.cpp create mode 100644 Test/Applications/TestDownloader/mainwindow.h create mode 100644 Test/Applications/TestDownloader/mainwindow.ui diff --git a/Common/Network/FileTransporter/src/FileTransporter_private.h b/Common/Network/FileTransporter/src/FileTransporter_private.h index c70edba4b0..a6f70fd89a 100644 --- a/Common/Network/FileTransporter/src/FileTransporter_private.h +++ b/Common/Network/FileTransporter/src/FileTransporter_private.h @@ -59,8 +59,8 @@ namespace NSNetwork m_sResponse = L""; - m_func_onComplete = NULL; - m_func_onProgress = NULL; + m_func_onComplete = nullptr; + m_func_onProgress = nullptr; m_bIsExit = nullptr; } @@ -82,8 +82,8 @@ namespace NSNetwork m_sResponse = L""; - m_func_onComplete = NULL; - m_func_onProgress = NULL; + m_func_onComplete = nullptr; + m_func_onProgress = nullptr; m_bIsExit = nullptr; } @@ -105,8 +105,8 @@ namespace NSNetwork m_sResponse = L""; - m_func_onComplete = NULL; - m_func_onProgress = NULL; + m_func_onComplete = nullptr; + m_func_onProgress = nullptr; m_bIsExit = nullptr; } @@ -118,6 +118,7 @@ namespace NSNetwork NSFile::CFileBinary::Remove(m_sDownloadFilePath); m_sDownloadFilePath = L""; } + m_bIsExit = nullptr; } virtual int DownloadFile() = 0; diff --git a/Common/Network/FileTransporter/src/FileTransporter_win.cpp b/Common/Network/FileTransporter/src/FileTransporter_win.cpp index af71ff7882..eb97904d36 100644 --- a/Common/Network/FileTransporter/src/FileTransporter_win.cpp +++ b/Common/Network/FileTransporter/src/FileTransporter_win.cpp @@ -32,7 +32,6 @@ #include "FileTransporter_private.h" - #include #pragma comment(lib, "Wininet") #pragma comment(lib, "Ole32.lib") @@ -90,8 +89,15 @@ namespace NSNetwork CoInitialize ( NULL ); if ( /*S_OK != _DownloadFile ( m_sFileUrl )*/TRUE ) { + DeleteUrlCacheEntry(m_sDownloadFileUrl.c_str()); HRESULT hrResultAll = DownloadFileAll(m_sDownloadFileUrl, m_sDownloadFilePath); + if(E_ABORT == hrResultAll && m_bIsExit->load()) + { + //DeleteUrlCacheEntry(m_sDownloadFileUrl.c_str()); + CoUninitialize (); + return hrResultAll; + } if (S_OK != hrResultAll) { hrResultAll = (true == DownloadFilePS(m_sDownloadFileUrl, m_sDownloadFilePath)) ? S_OK : S_FALSE; @@ -369,15 +375,11 @@ namespace NSNetwork m_pFile = NULL; } - if(m_func_onProgress) - { - DownloadProgress progress; - progress.func_onProgress = m_func_onProgress; - // Скачиваем файл с возвратом процентов состояния - return URLDownloadToFileW (NULL, sFileURL.c_str(), strFileOutput.c_str(), NULL, static_cast(&progress)); - } - else - return URLDownloadToFileW (NULL, sFileURL.c_str(), strFileOutput.c_str(), NULL, NULL); + DownloadProgress progress; + progress.bIsExit = m_bIsExit; + progress.func_onProgress = m_func_onProgress; + // Скачиваем файл с возвратом процентов состояния + return URLDownloadToFileW (NULL, sFileURL.c_str(), strFileOutput.c_str(), NULL, static_cast(&progress)); } class DownloadProgress : public IBindStatusCallback { @@ -415,6 +417,10 @@ namespace NSNetwork virtual HRESULT __stdcall OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) { + if(bIsExit && bIsExit->load()) + { + return E_ABORT; + } if(ulProgressMax != 0) { int percent = static_cast((100.0 * ulProgress) / ulProgressMax); @@ -424,7 +430,8 @@ namespace NSNetwork return S_OK; } - std::function func_onProgress; + std::atomic* bIsExit = nullptr; + std::function func_onProgress = nullptr; }; bool DownloadFilePS(const std::wstring& sFileURL, const std::wstring& strFileOutput) diff --git a/Common/Network/FileTransporter/src/transport_external.h b/Common/Network/FileTransporter/src/transport_external.h index 6cbecd6172..6658a8925a 100644 --- a/Common/Network/FileTransporter/src/transport_external.h +++ b/Common/Network/FileTransporter/src/transport_external.h @@ -46,9 +46,7 @@ namespace NSNetwork { namespace NSFileTransport - { - pid_t pid; - std::atomic* m_isExit; + { std::string wget_url_validate(const std::string& url) { std::string::size_type pos = 0; @@ -63,8 +61,8 @@ namespace NSNetwork int download_external(const std::wstring& sUrl, const std::wstring& sOutput, std::function func_onProgress, std::atomic* isExit) { + pid_t pid; int nReturnCode = -1; - m_isExit = isExit; std::string sUrlA = U_TO_UTF8(sUrl); //sUrlA =("\"" + sUrlA + "\""); std::string sOutputA = U_TO_UTF8(sOutput); @@ -134,7 +132,7 @@ namespace NSNetwork while (1) { - if(m_isExit->load()) + if(isExit && isExit->load()) { kill(pid, SIGTERM); //while (-1 == waitpid(pid, &status, 0)); // wait for child to complete @@ -168,7 +166,7 @@ namespace NSNetwork int waitres; while (1) // wait for child to complete { - if(m_isExit->load()) + if(isExit && isExit->load()) { kill(pid, SIGTERM); return nReturnCode; @@ -222,7 +220,7 @@ namespace NSNetwork int waitres; while (1) // wait for child to complete { - if(m_isExit->load()) + if(isExit && isExit->load()) { kill(pid, SIGTERM); return nReturnCode; diff --git a/DesktopEditor/graphics/BaseThread.cpp b/DesktopEditor/graphics/BaseThread.cpp index 917b80a948..d525af42dd 100644 --- a/DesktopEditor/graphics/BaseThread.cpp +++ b/DesktopEditor/graphics/BaseThread.cpp @@ -155,7 +155,7 @@ namespace NSThreads m_lThreadPriority = 0; m_bIsNeedDestroy = false; - m_bIsExit = new std::atomic(false); + m_bIsExit = nullptr; } CBaseThread::~CBaseThread() { @@ -172,7 +172,7 @@ namespace NSThreads m_bRunThread = TRUE; - m_bIsExit->exchange(false); + m_bIsExit = new std::atomic(false); #if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE) DWORD dwTemp; ((__native_thread*)m_hThread)->m_thread = CreateThread(NULL, 0, &__ThreadProc, (void*)this, 0, &dwTemp); @@ -197,11 +197,13 @@ namespace NSThreads m_bRunThread = FALSE; Join(); + RELEASEOBJECT(m_bIsExit); RELEASEOBJECT(m_hThread); } void CBaseThread::StopNoJoin() { m_bRunThread = FALSE; + RELEASEOBJECT(m_bIsExit); RELEASEOBJECT(m_hThread); } void CBaseThread::DestroyOnFinish() @@ -241,12 +243,10 @@ namespace NSThreads m_bIsExit->exchange(true); -#if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE) - //WaitForSingleObject(((__native_thread*)m_hThread)->m_thread, INFINITE); -#else - //pthread_cancel(((__native_thread*)m_hThread)->m_thread); - //pthread_kill(((__native_thread*)m_hThread)->m_thread, SIGUSR1); - pthread_join(((__native_thread*)m_hThread)->m_thread, 0); -#endif + m_bRunThread = FALSE; + + Join(); + RELEASEOBJECT(m_bIsExit); + RELEASEOBJECT(m_hThread); } } diff --git a/DesktopEditor/graphics/BaseThread.h b/DesktopEditor/graphics/BaseThread.h index cd1bfd98a1..16ae50c563 100644 --- a/DesktopEditor/graphics/BaseThread.h +++ b/DesktopEditor/graphics/BaseThread.h @@ -59,7 +59,7 @@ namespace NSThreads class KERNEL_DECL CBaseThread { protected: - CThreadDescriptor* m_hThread; + CThreadDescriptor* m_hThread; INT m_bRunThread; INT m_bSuspend; diff --git a/Test/Applications/TestDownloader/TestDownloader.pro b/Test/Applications/TestDownloader/TestDownloader.pro deleted file mode 100644 index 3297ad4c85..0000000000 --- a/Test/Applications/TestDownloader/TestDownloader.pro +++ /dev/null @@ -1,23 +0,0 @@ -QT -= gui - -TEMPLATE = app - -CONFIG += c++11 console -CONFIG -= app_bundle - - -# You can make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -include(TestDownloader.pri) - -SOURCES += \ - main.cpp - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - - diff --git a/Test/Applications/TestDownloader/TestDownloader.pri b/Test/Applications/TestDownloader/downloader.pro similarity index 58% rename from Test/Applications/TestDownloader/TestDownloader.pri rename to Test/Applications/TestDownloader/downloader.pro index c11872a1c4..7a695a7944 100644 --- a/Test/Applications/TestDownloader/TestDownloader.pri +++ b/Test/Applications/TestDownloader/downloader.pro @@ -1,16 +1,14 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2014-10-03T18:30:31 -# -#------------------------------------------------- +QT += core gui -QT -= core -QT -= gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -CORE_ROOT_DIR = $$PWD/../../.. +CONFIG += c++11 +#CONFIG += console + +CORE_ROOT_DIR = $$PWD/../../../../core PWD_ROOT_DIR = $$PWD -include(../../../Common/base.pri) +include($$CORE_ROOT_DIR/Common/base.pri) core_windows { QMAKE_LFLAGS += /INCREMENTAL:NO @@ -21,8 +19,9 @@ core_windows { DEFINES += KERNEL_USE_DYNAMIC_LIBRARY core_windows { - DEFINES += _RWSTD_NO_SETRLIMIT + DEFINES += _RWSTD_NO_SETRLIMIT } + #CORE_BUILDS_LIBRARIES_PATH = $$CORE_ROOT_DIR/build/lib/linux_64/debug #linux CORE_BUILDS_LIBRARIES_PATH = $$CORE_ROOT_DIR/build/lib/win_64/debug #windows #kernel @@ -36,10 +35,26 @@ LIBS += -L$$CORE_BUILDS_LIBRARIES_PATH -lkernel_network #BOOST CONFIG += core_boost_regex -include($$PWD/../../../Common/3dParty/boost/boost.pri) +include($$CORE_ROOT_DIR/Common/3dParty/boost/boost.pri) core_windows { LIBS += -lAdvapi32 } ######################################################## + + +SOURCES += \ + main.cpp \ + mainwindow.cpp + +HEADERS += \ + mainwindow.h + +FORMS += \ + mainwindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/Test/Applications/TestDownloader/main.cpp b/Test/Applications/TestDownloader/main.cpp index 6f6fc10fb7..fd3e533415 100644 --- a/Test/Applications/TestDownloader/main.cpp +++ b/Test/Applications/TestDownloader/main.cpp @@ -1,17 +1,11 @@ -#include "../../../Common/Network/FileTransporter/include/FileTransporter.h" -#define CHECK_URL L"http://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/updates/editors_update_x64.exe" -typedef NSNetwork::NSFileTransport::CFileDownloader Downloader; -#include -//int wmain(int argc, wchar_t *argv[]) windows +#include "mainwindow.h" + +#include + int main(int argc, char *argv[]) { - auto check_url = CHECK_URL; - auto downloader = new Downloader(check_url, false); - std::vector vec; - downloader->SetEvent_OnProgress([&](int percent) { - vec.push_back(percent); - }); - downloader->SetFilePath(L"/mnt/HDD_DATA/Work/core/Test/Applications/TestDownloader/tmp.exe"); - //downloader->SetFilePath(L"C:\\Users\\Vladimir.Gorshenkov\\Downloads\\tmp.exe"); windows - downloader->DownloadSync(); + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); } diff --git a/Test/Applications/TestDownloader/mainwindow.cpp b/Test/Applications/TestDownloader/mainwindow.cpp new file mode 100644 index 0000000000..3b191e7b75 --- /dev/null +++ b/Test/Applications/TestDownloader/mainwindow.cpp @@ -0,0 +1,79 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include +#include + +#define URL L"http://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/updates/editors_update_x64.exe" + +MainWindow::MainWindow(QWidget *parent): + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + downloader = new Downloader(URL, false); + downloader->SetEvent_OnComplete(std::bind(&MainWindow::onLoadUpdateFinished, this, std::placeholders::_1)); + downloader->SetEvent_OnProgress(std::bind(&MainWindow::onProgress, this, std::placeholders::_1)); +} + +MainWindow::~MainWindow() +{ + delete downloader; + delete ui; +} + +void MainWindow::onProgress(const int percent) +{ + qDebug() << "Precent... " << percent; + QMetaObject::invokeMethod(this, "onProgressSlot", Qt::QueuedConnection, Q_ARG(int, percent)); +} + +void MainWindow::onProgressSlot(int percent) +{ + ui->textEdit->setText(QString::number(percent)); + ui->progressBar->setValue(percent); +} + +void MainWindow::onLoadUpdateFinished(int error) +{ + qDebug() << "Loading finished..."; + QMetaObject::invokeMethod(this, "onLoadFinishedSlot", Qt::QueuedConnection, Q_ARG(int, error)); +} + +void MainWindow::onLoadFinishedSlot(int error) +{ + if (error == 0) { + ui->textEdit->setText("Loading finished..."); + } else { + qDebug() << "Download error: " << error; + ui->textEdit->setText("Download error"); + } + + const QString path = QString::fromStdWString(downloader->GetFilePath()); + if (QDir().exists(path)) QDir().remove(path); +} + +void MainWindow::on_buttonStart_clicked() +{ + qDebug() << "Start loading..."; + ui->progressBar->setValue(0); +// const QString tmp_file = QDir::tempPath() + QDir::separator() + QString("temp.tmp"); + const QString tmp_file = QString("C:\\Users\\Vladimir.Gorshenkov\\NewControl\\core\\Test\\Applications\\TestDownloader\\temp.tmp"); + ui->textEdit->setText(QString("Start loading: %1 to %2").arg(QString::fromStdWString(URL), tmp_file)); + downloader->SetFilePath(tmp_file.toStdWString()); + downloader->Start(0); +} + +void MainWindow::on_buttonCancel_clicked() +{ + qDebug() << "Loading cancel..."; + ui->progressBar->setValue(0); + ui->textEdit->setText("Loading cancel..."); + const QString path = QString::fromStdWString(downloader->GetFilePath()); + downloader->Cancel(); +// if (QDir().exists(path)) QDir().remove(path); + + qDebug() << "Stop finished"; +} + + diff --git a/Test/Applications/TestDownloader/mainwindow.h b/Test/Applications/TestDownloader/mainwindow.h new file mode 100644 index 0000000000..6690e24d3f --- /dev/null +++ b/Test/Applications/TestDownloader/mainwindow.h @@ -0,0 +1,46 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include "../../../../core/Common/Network/FileTransporter/include/FileTransporter.h" + + +//#define URL L"http://nct.onlyoffice.com/sh/XHh" +typedef std::wstring WString; +typedef NSNetwork::NSFileTransport::CFileDownloader Downloader; + + +QT_BEGIN_NAMESPACE + namespace Ui {class MainWindow;} +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + + MainWindow(QWidget *parent = nullptr); + + ~MainWindow(); + +private slots: + + void on_buttonStart_clicked(); + void on_buttonCancel_clicked(); + + void onProgressSlot(int percent); + void onLoadFinishedSlot(int error); + +private: + + void onProgress(const int percent); + void onLoadUpdateFinished(int error); + + Downloader *downloader; + + Ui::MainWindow *ui; +}; +#endif // MAINWINDOW_H diff --git a/Test/Applications/TestDownloader/mainwindow.ui b/Test/Applications/TestDownloader/mainwindow.ui new file mode 100644 index 0000000000..4a7c74b2e3 --- /dev/null +++ b/Test/Applications/TestDownloader/mainwindow.ui @@ -0,0 +1,62 @@ + + + MainWindow + + + + 0 + 0 + 616 + 479 + + + + MainWindow + + + + + + + 0 + + + + + + + Start + + + + + + + Cancel + + + + + + + true + + + + + + + + + 0 + 0 + 616 + 19 + + + + + + + +