1 /* 2 * This program source code file is part of KiCad, a free EDA CAD application. 3 * 4 * Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com 5 * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. 6 * 7 * This program is free software: you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation, either version 3 of the License, or (at your 10 * option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef PCM_TASK_MANAGER_H_ 22 #define PCM_TASK_MANAGER_H_ 23 24 #include "dialogs/dialog_pcm_progress.h" 25 #include "pcm.h" 26 #include "pcm_data.h" 27 #include "sync_queue.h" 28 #include <atomic> 29 #include <condition_variable> 30 #include <functional> 31 #include <memory> 32 #include <mutex> 33 #include <nlohmann/json-schema.hpp> 34 #include <widgets/wx_progress_reporters.h> 35 #include <wx/string.h> 36 37 38 typedef std::function<void()> PCM_TASK; 39 40 41 /** 42 * @brief Helper class that handles package (un)installation 43 * 44 * Package state changes are first enqueued using DownloadAndInstall/Uninstall methods 45 * and then applied using RunQueue(). 46 * 47 * RunQueue() is multithreaded for better experience. 48 */ 49 class PCM_TASK_MANAGER 50 { 51 public: PCM_TASK_MANAGER(std::shared_ptr<PLUGIN_CONTENT_MANAGER> pcm)52 PCM_TASK_MANAGER( std::shared_ptr<PLUGIN_CONTENT_MANAGER> pcm ) : m_pcm( pcm ){}; 53 54 /** 55 * @brief Enqueue package download and installation 56 * 57 * Enqueues a download task for a given package version. 58 * 59 * Download task fetches the package archive and if successful enqueues an installation task. 60 * Installation task verifies sha256 hash if specified, extracts the package, removes the 61 * downloaded archive and marks package as installed. 62 * 63 * Both tasks report their state independently to a progress dialog. 64 * 65 * @param aPackage package metadata 66 * @param aVersion version to be installed 67 * @param aRepositoryId id of the source repository 68 */ 69 void DownloadAndInstall( const PCM_PACKAGE& aPackage, const wxString& aVersion, 70 const wxString& aRepositoryId ); 71 72 /** 73 * @brief Enqueue package uninstallation 74 * 75 * Enqueues uninstallation task that removes all package files and marks package 76 * as uninstalled. 77 * 78 * @param aPackage package metadata 79 */ 80 void Uninstall( const PCM_PACKAGE& aPackage ); 81 82 /** 83 * @brief Run queue of pending actions 84 * 85 * This method spawns 2 threads to concurrently run tasks in download and install 86 * queues until they are drained. 87 * 88 * Download queue feeds into install queue so the install thread keeps running until 89 * download thread indicated that it's finished AND all installs are processed. 90 * 91 * @param aParent parent dialog for progress window 92 */ 93 void RunQueue( wxWindow* aParent ); 94 95 /** 96 * @brief Installs package from an archive file on disk 97 * 98 * Unlike DownloadAndInstall/Uninstall methods this one immediately extracts the package 99 * and marks it as installed. 100 * 101 * @param aParent parent dialog for progress window 102 * @param aFilePath path to the archive file 103 */ 104 void InstallFromFile( wxWindow* aParent, const wxString& aFilePath ); 105 106 private: 107 /** 108 * @brief Download URL to a file 109 * 110 * @param aFilePath path to file 111 * @param aUrl URL to download 112 * @return int CURLE error code 113 */ 114 int downloadFile( const wxString& aFilePath, const wxString& aUrl ); 115 116 /** 117 * @brief Extract package archive 118 * 119 * @param aFilePath path to the archive 120 * @param aPackageId id of the package 121 * @param isMultiThreaded MUST be set to true if the caller is not running in the main thread 122 * @return true if archive was extracted successfuly 123 */ 124 bool extract( const wxString& aFilePath, const wxString& aPackageId, bool isMultiThreaded ); 125 126 /** 127 * @brief Delete all package files 128 * 129 * @param aPackageId id of the package 130 */ 131 void deletePackageDirectories( const wxString& aPackageId ); 132 133 std::unique_ptr<DIALOG_PCM_PROGRESS> m_reporter; 134 SYNC_QUEUE<PCM_TASK> m_download_queue; 135 SYNC_QUEUE<PCM_TASK> m_install_queue; 136 std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm; 137 }; 138 139 140 #endif // PCM_TASK_MANAGER_H_ 141