博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Cocos 更新时反复杀进程,导致差异更新失效的Bug
阅读量:6941 次
发布时间:2019-06-27

本文共 6219 字,大约阅读时间需要 20 分钟。

Cocos 更新时反复杀进程时,差异更新失效的问题:

问题复现步骤:

1、在project.manifest.temp 文件下载成功后,下载Assets资源的时候杀掉进程
2、重启游戏,继续更新时会使用上次下载成功的project.manifest.temp文件,这个时候因为没有将文件下载状态保存,而更新的时候又判断没有下再成功就去下载,就导致将所有文件都下载了。

下载流程分析

1、 project.manifest.temp 文件下载成功之前如果kill进程,下次进入就会删除这个文件,重新下载;PS:调用update

接口开始更新时kill进程,再次启动都会引起project.manifest.temp的重新下载,这也是导致bug的原因之一。

// 这个方法会在更新之前调用void AssetsManagerEx::initManifests(const std::string& manifestUrl){    _inited = true;    // Init and load local manifest    _localManifest = new (std::nothrow) Manifest();    if (_localManifest)    {        loadLocalManifest(manifestUrl);        // Init and load temporary manifest        _tempManifest = new (std::nothrow) Manifest();        if (_tempManifest)        {            _tempManifest->parse(_tempManifestPath);            // 这里判断如果文件不是完整的,并且存在就删除它;            if (!_tempManifest->isLoaded() && _fileUtils->isFileExist(_tempManifestPath))                _fileUtils->removeFile(_tempManifestPath);        }        else        {            _inited = false;        }        // Init remote manifest for future usage        _remoteManifest = new (std::nothrow) Manifest();        if (!_remoteManifest)        {            _inited = false;        }    }    else    {        _inited = false;    }    if (!_inited)    {        CC_SAFE_DELETE(_localManifest);        CC_SAFE_DELETE(_tempManifest);        CC_SAFE_DELETE(_remoteManifest);    }}

2、开始下载根据project.manifest.temp 临时文件是否完整存在来决定是恢复之前的下载状态,还是根据重新下载回来的manifest文件与本地文件对比差异度,决定下载那些。

void AssetsManagerEx::startUpdate(){    if (_updateState != State::NEED_UPDATE)        return;    _updateState = State::UPDATING;    // Clean up before update    _failedUnits.clear();    _downloadUnits.clear();    _compressedFiles.clear();    _totalWaitToDownload = _totalToDownload = 0;    _percent = _percentByFile = _sizeCollected = _totalSize = 0;    _downloadedSize.clear();    _totalEnabled = false;    // Temporary manifest exists, resuming previous download    if (_tempManifest->isLoaded() && _tempManifest->versionEquals(_remoteManifest))    {        // 文件是完整的,直接从文件恢复下载,并且从文件中读取下载状态,来判断是否需要下载        // 更新完成之前kill进程和每次启动程序下载project.manifest.temp文件都会导致下载状态被清空        // 恢复下载是根据manifest临时文件中保存的下载状态来决定,详细见3        _tempManifest->genResumeAssetsList(&_downloadUnits);        _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size();        this->batchDownload();        std::string msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload);        CCLOG(msg);        // this time , the remoteManifest(has no DownloadState) file overwrite tempManifest file. when we kill process, and restart, it will uses error file.      // 为了避免被重新下载的manifest文件覆盖掉下载状态,我们这里需要将当前状态再次写入文件备份        _tempManifest->saveToFile(_tempManifestPath);        dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg);    }    // Check difference    else    {        // Temporary manifest not exists or out of date,        // it will be used to register the download states of each asset,        // in this case, it equals remote manifest.        _tempManifest->release();        _tempManifest = _remoteManifest;        std::unordered_map
diff_map = _localManifest->genDiff(_remoteManifest); std::string log = StringUtils::format("AssetsManagerEx : Diff file size %d", diff_map.size()); CCLOG(log); if (diff_map.size() == 0) { CCLOG("AssetsManagerEx updateSucceed"); updateSucceed(); } else { // Generate download units for all assets that need to be updated or added std::string packageUrl = _remoteManifest->getPackageUrl(); for (auto it = diff_map.begin(); it != diff_map.end(); ++it) { Manifest::AssetDiff diff = it->second; if (diff.type == Manifest::DiffType::DELETED) { CCLOG("AssetsManagerEx DELETED " + diff.asset.path); _fileUtils->removeFile(_storagePath + diff.asset.path); } else { std::string path = diff.asset.path; CCLOG("AssetsManagerEx " + diff.asset.path + " type "+ diff.type); // Create path _fileUtils->createDirectory(basename(_storagePath + path)); DownloadUnit unit; unit.customId = it->first; unit.srcUrl = packageUrl + path; unit.storagePath = _storagePath + path; _downloadUnits.emplace(unit.customId, unit); } } // Set other assets' downloadState to SUCCESSED auto &assets = _remoteManifest->getAssets(); for (auto it = assets.cbegin(); it != assets.cend(); ++it) { const std::string &key = it->first; auto diffIt = diff_map.find(key); if (diffIt == diff_map.end()) { // 根据文件对比,将不需要下载的文件的状态设置为下载成功 _tempManifest->setAssetDownloadState(key, Manifest::DownloadState::SUCCESSED); } } _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size(); this->batchDownload(); std::string msg = StringUtils::format("Start to update %d files from remote package.", _totalToDownload); // 为了避免进程在更新完成之前被kill导致下载状态丢失,这里先保存文件,备份一次 _tempManifest->saveToFile(_tempManifestPath); dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg); } }}

3、恢复下载是,需要根据之前保存在临时文件中的下载状态来决定下载那些文件

void Manifest::genResumeAssetsList(DownloadUnits *units) const{    for (auto it = _assets.begin(); it != _assets.end(); ++it)    {        Asset asset = it->second;        if (asset.downloadState != DownloadState::SUCCESSED)        {            DownloadUnit unit;            unit.customId = it->first;            unit.srcUrl = _packageUrl + asset.path;            unit.storagePath = _manifestRoot + asset.path;            units->emplace(unit.customId, unit);        }    }}

转载于:https://www.cnblogs.com/lipeil/p/7360243.html

你可能感兴趣的文章
铜陵市云计算数据中心入选省“示范工程”
查看>>
Facebook新算法:360度摄影不再感觉头晕
查看>>
Opera反驳微软:我们才是最节能浏览器
查看>>
启用WCF NetTcpBinding的共享端口
查看>>
签约百度推进互联网+交通 西安打造智慧城市
查看>>
大数据全面应用打击线下线上假冒伪劣
查看>>
伊顿助力阿里打造世界级顶尖数据中心
查看>>
可穿戴式设备的安全水平究竟如何?
查看>>
无限城市助力智慧城市 挥毫创新3.0时代
查看>>
德司法部长:Facebook应被视为媒体公司 需打击仇视言论
查看>>
[知识图谱] 1.1-知识图谱是什么?
查看>>
Git 入门级命令锦集
查看>>
parcel初体验
查看>>
JavaScript中的错误类型
查看>>
创建型设计模式——抽象工厂模式
查看>>
用react+redux实现微信PC客户端UI交互界面
查看>>
Dijkstra算法及正确性分析
查看>>
Python自动化邮件添加HTML表格图像和Excel附件
查看>>
Flutter BottomAppBar插入FAB
查看>>
vue 动态加载组件
查看>>