From fc20591921a409c33fb35df18dcc5593d7f13c6e Mon Sep 17 00:00:00 2001 From: qgh <> Date: Wed, 11 Sep 2024 08:02:29 +0800 Subject: [PATCH 1/5] Fixed the issue of the main page getting stuck due to the long execution time required for updates --- .../assets-manager/AssetsManagerEx.cpp | 183 ++++++++++-------- .../assets-manager/AssetsManagerEx.h | 10 + 2 files changed, 116 insertions(+), 77 deletions(-) diff --git a/native/extensions/assets-manager/AssetsManagerEx.cpp b/native/extensions/assets-manager/AssetsManagerEx.cpp index 8c3e90d107b..0827fa66934 100644 --- a/native/extensions/assets-manager/AssetsManagerEx.cpp +++ b/native/extensions/assets-manager/AssetsManagerEx.cpp @@ -57,6 +57,8 @@ NS_CC_EXT_BEGIN const std::string AssetsManagerEx::VERSION_ID = "@version"; const std::string AssetsManagerEx::MANIFEST_ID = "@manifest"; +AssetsManagerEx* AssetsManagerEx::_assetsManager = nullptr; + // Implementation of AssetsManagerEx AssetsManagerEx::AssetsManagerEx(const std::string &manifestUrl, const std::string &storagePath) { @@ -69,6 +71,8 @@ AssetsManagerEx::AssetsManagerEx(const std::string &manifestUrl, const std::stri } void AssetsManagerEx::init(const std::string &manifestUrl, const std::string &storagePath) { + _assetsManager = this; + // Init variables std::string pointer = StringUtils::format("%p", this); _eventName = "__cc_assets_manager_" + pointer; @@ -110,6 +114,7 @@ AssetsManagerEx::~AssetsManagerEx() { CC_SAFE_RELEASE(_tempManifest); } CC_SAFE_RELEASE(_remoteManifest); + _assetsManager = nullptr; } AssetsManagerEx *AssetsManagerEx::create(const std::string &manifestUrl, const std::string &storagePath) { @@ -421,8 +426,8 @@ bool AssetsManagerEx::decompress(const std::string &filename) { // Check if this entry is a directory or a file. const size_t filenameLength = strlen(fileName); if (fileName[filenameLength - 1] == '/') { - //There are not directory entry in some case. - //So we need to create directory when decompressing file entry + // There are not directory entry in some case. + // So we need to create directory when decompressing file entry if (!_fileUtils->createDirectory(basename(fullPath))) { // Failed to create directory CC_LOG_DEBUG("AssetsManagerEx : can not create directory %s\n", fullPath.c_str()); @@ -552,7 +557,8 @@ void AssetsManagerEx::dispatchUpdateEvent(EventAssetsManagerEx::EventCode code, break; } - if (_eventCallback != nullptr) { + // If more than one instance is spawned, then the event callback will fail, so a judgment call needs to be made. + if (_eventCallback != nullptr && _assetsManager == this) { auto *event = ccnew EventAssetsManagerEx(_eventName, this, code, assetId, message, curleCode, curlmCode); event->addRef(); _eventCallback(event); @@ -648,20 +654,27 @@ void AssetsManagerEx::parseManifest() { if (_updateEntry == UpdateEntry::DO_UPDATE) { startUpdate(); + dispatchUpdateEvent(EventAssetsManagerEx::EventCode::NEW_VERSION_FOUND); } else if (_updateEntry == UpdateEntry::CHECK_UPDATE) { - prepareUpdate(); + auto cb = [this]() { + dispatchUpdateEvent(EventAssetsManagerEx::EventCode::NEW_VERSION_FOUND); + }; + prepareUpdateAsync(cb); } - - dispatchUpdateEvent(EventAssetsManagerEx::EventCode::NEW_VERSION_FOUND); } } } void AssetsManagerEx::prepareUpdate() { - if (_updateState != State::NEED_UPDATE) { + prepareUpdateAsync(); +} + +void AssetsManagerEx::prepareUpdateAsync(const PrepareUpdateFinishedCallback &cb) { + // Avoiding multiple function calls. + if (_updateState != State::NEED_UPDATE || _updateState == State::PARPER_UPDATING) { return; } - + _updateState = State::PARPER_UPDATING; // Clean up before update _failedUnits.clear(); _downloadUnits.clear(); @@ -673,83 +686,99 @@ void AssetsManagerEx::prepareUpdate() { _downloadResumed = false; _downloadedSize.clear(); _totalEnabled = false; - - // Temporary manifest exists, previously updating and equals to the remote version, resuming previous download - if (_tempManifest && _tempManifest->isLoaded() && _tempManifest->isUpdating() && _tempManifest->versionEquals(_remoteManifest)) { - _tempManifest->saveToFile(_tempManifestPath); - _tempManifest->genResumeAssetsList(&_downloadUnits); - _totalWaitToDownload = _totalToDownload = static_cast(_downloadUnits.size()); - _downloadResumed = true; - - // Collect total size - for (const auto &iter : _downloadUnits) { - const DownloadUnit &unit = iter.second; - if (unit.size > 0) { - _totalSize += unit.size; - } - } - } else { - // Temporary manifest exists, but can't be parsed or version doesn't equals remote manifest (out of date) - if (_tempManifest) { - // Remove all temp files - _fileUtils->removeDirectory(_tempStoragePath); - CC_SAFE_RELEASE(_tempManifest); - // Recreate temp storage path and save remote manifest - _fileUtils->createDirectory(_tempStoragePath); - _remoteManifest->saveToFile(_tempManifestPath); + std::function prepareFinished = [this, cb](void *) { + _updateState = State::READY_TO_UPDATE; + if (cb) { + cb(); } + this->release(); + }; + this->addRef(); + // If there are many diffMap, it will lead to a very time-consuming run. So here it needs to be executed in a thread. + AsyncTaskPool::getInstance()->enqueue(AsyncTaskPool::TaskType::TASK_OTHER, prepareFinished, nullptr, [this]() { + // Temporary manifest exists, previously updating and equals to the remote version, resuming previous download + if (_tempManifest && _tempManifest->isLoaded() && _tempManifest->isUpdating() && _tempManifest->versionEquals(_remoteManifest)) { + _tempManifest->saveToFile(_tempManifestPath); + _tempManifest->genResumeAssetsList(&_downloadUnits); + _totalWaitToDownload = _totalToDownload = static_cast(_downloadUnits.size()); + _downloadResumed = true; + + // Collect total size + for (const auto &iter : _downloadUnits) { + const DownloadUnit &unit = iter.second; + if (unit.size > 0) { + _totalSize += unit.size; + } + } + } else { + // Temporary manifest exists, but can't be parsed or version doesn't equals remote manifest (out of date) + if (_tempManifest) { + // Remove all temp files + _fileUtils->removeDirectory(_tempStoragePath); + CC_SAFE_RELEASE(_tempManifest); + // Recreate temp storage path and save remote manifest + _fileUtils->createDirectory(_tempStoragePath); + _remoteManifest->saveToFile(_tempManifestPath); + } - // Temporary manifest will be used to register the download states of each asset, - // in this case, it equals remote manifest. - _tempManifest = _remoteManifest; - - // Check difference between local manifest and remote manifest - std::unordered_map diffMap = _localManifest->genDiff(_remoteManifest); - if (diffMap.empty()) { - updateSucceed(); - return; - } // Generate download units for all assets that need to be updated or added - std::string packageUrl = _remoteManifest->getPackageUrl(); - // Preprocessing local files in previous version and creating download folders - for (auto &it : diffMap) { - Manifest::AssetDiff diff = it.second; - if (diff.type != Manifest::DiffType::DELETED) { - std::string path = diff.asset.path; - DownloadUnit unit; - unit.customId = it.first; - unit.srcUrl = packageUrl + path + "?md5=" + diff.asset.md5; - unit.storagePath = _tempStoragePath + path; - unit.size = diff.asset.size; - _downloadUnits.emplace(unit.customId, unit); - _tempManifest->setAssetDownloadState(it.first, Manifest::DownloadState::UNSTARTED); - _totalSize += unit.size; + // Temporary manifest will be used to register the download states of each asset, + // in this case, it equals remote manifest. + _tempManifest = _remoteManifest; + + // Check difference between local manifest and remote manifest + std::unordered_map diffMap = _localManifest->genDiff(_remoteManifest); + if (diffMap.empty()) { + updateSucceed(); + return; + } // Generate download units for all assets that need to be updated or added + std::string packageUrl = _remoteManifest->getPackageUrl(); + // Preprocessing local files in previous version and creating download folders + auto prevTime = std::chrono::steady_clock::now(); + DownloadUnit unit; + for (auto &it : diffMap) { + Manifest::AssetDiff diff = it.second; + if (diff.type != Manifest::DiffType::DELETED) { + const std::string &path = diff.asset.path; + unit.customId = it.first; + unit.srcUrl = packageUrl + path + "?md5=" + diff.asset.md5; + unit.storagePath = _tempStoragePath + path; + unit.size = diff.asset.size; + _downloadUnits.emplace(unit.customId, unit); + _tempManifest->setAssetDownloadState(it.first, Manifest::DownloadState::UNSTARTED); + _totalSize += unit.size; + } } - } - // Start updating the temp manifest - _tempManifest->setUpdating(true); - // Save current download manifest information for resuming - _tempManifest->saveToFile(_tempManifestPath); + // Start updating the temp manifest + _tempManifest->setUpdating(true); + // Save current download manifest information for resuming + _tempManifest->saveToFile(_tempManifestPath); - _totalWaitToDownload = _totalToDownload = static_cast(_downloadUnits.size()); - } - _updateState = State::READY_TO_UPDATE; + _totalWaitToDownload = _totalToDownload = static_cast(_downloadUnits.size()); + } + }); } void AssetsManagerEx::startUpdate() { - if (_updateState == State::NEED_UPDATE) { - prepareUpdate(); - } - if (_updateState == State::READY_TO_UPDATE) { - _totalSize = 0; - _updateState = State::UPDATING; - std::string msg; - if (_downloadResumed) { - msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload); - } else { - msg = StringUtils::format("Start to update %d files from remote package.", _totalToDownload); + auto cb = [this]() { + if (_updateState == State::READY_TO_UPDATE) { + _totalSize = 0; + _updateState = State::UPDATING; + std::string msg; + if (_downloadResumed) { + msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload); + } else { + msg = StringUtils::format("Start to update %d files from remote package.", _totalToDownload); + } + if (this == _assetsManager) { + dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg); + batchDownload(); + } } - dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg); - batchDownload(); + }; + if (_updateState == State::NEED_UPDATE) { + prepareUpdateAsync(cb); + } else { + cb(); } } diff --git a/native/extensions/assets-manager/AssetsManagerEx.h b/native/extensions/assets-manager/AssetsManagerEx.h index d3b2622de7d..44ac8da0dea 100644 --- a/native/extensions/assets-manager/AssetsManagerEx.h +++ b/native/extensions/assets-manager/AssetsManagerEx.h @@ -58,6 +58,7 @@ class CC_EX_DLL AssetsManagerEx : public RefCounted { DOWNLOADING_MANIFEST, MANIFEST_LOADED, NEED_UPDATE, + PARPER_UPDATING, READY_TO_UPDATE, UPDATING, UNZIPPING, @@ -292,6 +293,14 @@ class CC_EX_DLL AssetsManagerEx : public RefCounted { */ virtual void onSuccess(const std::string &srcUrl, const std::string &storagePath, const std::string &customId); + /** @brief prepareUpdate may take a long time to execute, so we need to do it asynchronously. + @param cb Function that are called at the end of the prepareUpdate execution and are running callbacks in the main thread. + * @js NA + * @lua NA + */ + using PrepareUpdateFinishedCallback = std::function; + void prepareUpdateAsync(const PrepareUpdateFinishedCallback &cb = PrepareUpdateFinishedCallback()); + private: void batchDownload(); @@ -405,6 +414,7 @@ class CC_EX_DLL AssetsManagerEx : public RefCounted { //! Callback function to dispatch events EventCallback _eventCallback = nullptr; + static AssetsManagerEx *_assetsManager; //! Marker for whether the assets manager is inited bool _inited = false; }; From 7379867b2bc5b668b4872da4cfc20858be55a7f4 Mon Sep 17 00:00:00 2001 From: qgh <> Date: Wed, 11 Sep 2024 10:37:10 +0800 Subject: [PATCH 2/5] Fix errors in CI prompts --- native/extensions/assets-manager/AssetsManagerEx.cpp | 2 +- native/extensions/assets-manager/AssetsManagerEx.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native/extensions/assets-manager/AssetsManagerEx.cpp b/native/extensions/assets-manager/AssetsManagerEx.cpp index 0827fa66934..a7eb9bf2fc8 100644 --- a/native/extensions/assets-manager/AssetsManagerEx.cpp +++ b/native/extensions/assets-manager/AssetsManagerEx.cpp @@ -686,7 +686,7 @@ void AssetsManagerEx::prepareUpdateAsync(const PrepareUpdateFinishedCallback &cb _downloadResumed = false; _downloadedSize.clear(); _totalEnabled = false; - std::function prepareFinished = [this, cb](void *) { + std::function prepareFinished = [this, cb](void * param) { _updateState = State::READY_TO_UPDATE; if (cb) { cb(); diff --git a/native/extensions/assets-manager/AssetsManagerEx.h b/native/extensions/assets-manager/AssetsManagerEx.h index 44ac8da0dea..735e0ae6c22 100644 --- a/native/extensions/assets-manager/AssetsManagerEx.h +++ b/native/extensions/assets-manager/AssetsManagerEx.h @@ -414,7 +414,7 @@ class CC_EX_DLL AssetsManagerEx : public RefCounted { //! Callback function to dispatch events EventCallback _eventCallback = nullptr; - static AssetsManagerEx *_assetsManager; + static AssetsManagerEx *assetsManager; //! Marker for whether the assets manager is inited bool _inited = false; }; From fb4e7134abe85f56f9cce97c5a8b2cd0e85461ea Mon Sep 17 00:00:00 2001 From: qgh <> Date: Thu, 12 Sep 2024 09:43:05 +0800 Subject: [PATCH 3/5] Change variable name --- native/extensions/assets-manager/AssetsManagerEx.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/native/extensions/assets-manager/AssetsManagerEx.cpp b/native/extensions/assets-manager/AssetsManagerEx.cpp index a7eb9bf2fc8..2a8168ff741 100644 --- a/native/extensions/assets-manager/AssetsManagerEx.cpp +++ b/native/extensions/assets-manager/AssetsManagerEx.cpp @@ -57,7 +57,7 @@ NS_CC_EXT_BEGIN const std::string AssetsManagerEx::VERSION_ID = "@version"; const std::string AssetsManagerEx::MANIFEST_ID = "@manifest"; -AssetsManagerEx* AssetsManagerEx::_assetsManager = nullptr; +AssetsManagerEx* AssetsManagerEx::assetsManager = nullptr; // Implementation of AssetsManagerEx @@ -71,7 +71,7 @@ AssetsManagerEx::AssetsManagerEx(const std::string &manifestUrl, const std::stri } void AssetsManagerEx::init(const std::string &manifestUrl, const std::string &storagePath) { - _assetsManager = this; + assetsManager = this; // Init variables std::string pointer = StringUtils::format("%p", this); @@ -114,7 +114,7 @@ AssetsManagerEx::~AssetsManagerEx() { CC_SAFE_RELEASE(_tempManifest); } CC_SAFE_RELEASE(_remoteManifest); - _assetsManager = nullptr; + assetsManager = nullptr; } AssetsManagerEx *AssetsManagerEx::create(const std::string &manifestUrl, const std::string &storagePath) { @@ -558,7 +558,7 @@ void AssetsManagerEx::dispatchUpdateEvent(EventAssetsManagerEx::EventCode code, } // If more than one instance is spawned, then the event callback will fail, so a judgment call needs to be made. - if (_eventCallback != nullptr && _assetsManager == this) { + if (_eventCallback != nullptr && assetsManager == this) { auto *event = ccnew EventAssetsManagerEx(_eventName, this, code, assetId, message, curleCode, curlmCode); event->addRef(); _eventCallback(event); @@ -769,7 +769,7 @@ void AssetsManagerEx::startUpdate() { } else { msg = StringUtils::format("Start to update %d files from remote package.", _totalToDownload); } - if (this == _assetsManager) { + if (this == assetsManager) { dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg); batchDownload(); } From 99458b697794e6d526a37577c3028ece83cbf6c0 Mon Sep 17 00:00:00 2001 From: qgh <> Date: Thu, 12 Sep 2024 10:25:23 +0800 Subject: [PATCH 4/5] Fixed typos --- native/extensions/assets-manager/AssetsManagerEx.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/native/extensions/assets-manager/AssetsManagerEx.cpp b/native/extensions/assets-manager/AssetsManagerEx.cpp index 2a8168ff741..611cd14cba2 100644 --- a/native/extensions/assets-manager/AssetsManagerEx.cpp +++ b/native/extensions/assets-manager/AssetsManagerEx.cpp @@ -671,10 +671,10 @@ void AssetsManagerEx::prepareUpdate() { void AssetsManagerEx::prepareUpdateAsync(const PrepareUpdateFinishedCallback &cb) { // Avoiding multiple function calls. - if (_updateState != State::NEED_UPDATE || _updateState == State::PARPER_UPDATING) { + if (_updateState != State::NEED_UPDATE || _updateState == State::PREPARE_UPDATING) { return; } - _updateState = State::PARPER_UPDATING; + _updateState = State::PREPARE_UPDATING; // Clean up before update _failedUnits.clear(); _downloadUnits.clear(); @@ -687,6 +687,7 @@ void AssetsManagerEx::prepareUpdateAsync(const PrepareUpdateFinishedCallback &cb _downloadedSize.clear(); _totalEnabled = false; std::function prepareFinished = [this, cb](void * param) { + CC_UNUSED_PARAM(param); _updateState = State::READY_TO_UPDATE; if (cb) { cb(); From 95e936cdc7f6617cd1b125fb90b3654db6bf71d4 Mon Sep 17 00:00:00 2001 From: qgh <> Date: Thu, 12 Sep 2024 10:54:59 +0800 Subject: [PATCH 5/5] Add warning --- native/extensions/assets-manager/AssetsManagerEx.cpp | 1 + native/extensions/assets-manager/AssetsManagerEx.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/native/extensions/assets-manager/AssetsManagerEx.cpp b/native/extensions/assets-manager/AssetsManagerEx.cpp index 611cd14cba2..9693b03dd10 100644 --- a/native/extensions/assets-manager/AssetsManagerEx.cpp +++ b/native/extensions/assets-manager/AssetsManagerEx.cpp @@ -672,6 +672,7 @@ void AssetsManagerEx::prepareUpdate() { void AssetsManagerEx::prepareUpdateAsync(const PrepareUpdateFinishedCallback &cb) { // Avoiding multiple function calls. if (_updateState != State::NEED_UPDATE || _updateState == State::PREPARE_UPDATING) { + CC_LOG_WARNING("The current state does not need to be updated or is being executed."); return; } _updateState = State::PREPARE_UPDATING; diff --git a/native/extensions/assets-manager/AssetsManagerEx.h b/native/extensions/assets-manager/AssetsManagerEx.h index 735e0ae6c22..c8c2bc85513 100644 --- a/native/extensions/assets-manager/AssetsManagerEx.h +++ b/native/extensions/assets-manager/AssetsManagerEx.h @@ -58,7 +58,7 @@ class CC_EX_DLL AssetsManagerEx : public RefCounted { DOWNLOADING_MANIFEST, MANIFEST_LOADED, NEED_UPDATE, - PARPER_UPDATING, + PREPARE_UPDATING, READY_TO_UPDATE, UPDATING, UNZIPPING,