Skip to content

Commit

Permalink
Merge pull request cocos2d#9039 from pandamicro/v3_origin
Browse files Browse the repository at this point in the history
cocos2d#9061: Polish AssetsManagerEx, bug fixes and feature added
  • Loading branch information
minggo committed Nov 27, 2014
2 parents cc1a19e + ef76724 commit 6db7cfb
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 90 deletions.
131 changes: 97 additions & 34 deletions extensions/assets-manager/AssetsManagerEx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ AssetsManagerEx::AssetsManagerEx(const std::string& manifestUrl, const std::stri
, _percentByFile(0)
, _totalToDownload(0)
, _totalWaitToDownload(0)
, _inited(false)
{
// Init variables
_eventDispatcher = Director::getInstance()->getEventDispatcher();
Expand All @@ -95,18 +96,7 @@ AssetsManagerEx::AssetsManagerEx(const std::string& manifestUrl, const std::stri
_cacheManifestPath = _storagePath + MANIFEST_FILENAME;
_tempManifestPath = _storagePath + TEMP_MANIFEST_FILENAME;

// Init and load local manifest
_localManifest = new Manifest();
loadLocalManifest(manifestUrl);

// Init and load temporary manifest
_tempManifest = new Manifest();
_tempManifest->parse(_tempManifestPath);
if (!_tempManifest->isLoaded())
_fileUtils->removeFile(_tempManifestPath);

// Init remote manifest for future usage
_remoteManifest = new Manifest();
initManifests(manifestUrl);
}

AssetsManagerEx::~AssetsManagerEx()
Expand All @@ -123,7 +113,7 @@ AssetsManagerEx::~AssetsManagerEx()

AssetsManagerEx* AssetsManagerEx::create(const std::string& manifestUrl, const std::string& storagePath)
{
AssetsManagerEx* ret = new AssetsManagerEx(manifestUrl, storagePath);
AssetsManagerEx* ret = new (std::nothrow) AssetsManagerEx(manifestUrl, storagePath);
if (ret)
{
ret->autorelease();
Expand All @@ -135,6 +125,48 @@ AssetsManagerEx* AssetsManagerEx::create(const std::string& manifestUrl, const s
return ret;
}

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->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);
}
}

void AssetsManagerEx::prepareLocalManifest()
{
// An alias to assets
Expand All @@ -146,22 +178,42 @@ void AssetsManagerEx::prepareLocalManifest()

void AssetsManagerEx::loadLocalManifest(const std::string& manifestUrl)
{
// Prefer to use the cached manifest file, if not found use user configured manifest file
Manifest *cachedManifest = nullptr;
// Find the cached manifest file
if (_fileUtils->isFileExist(_cacheManifestPath))
{
_localManifest->parse(_cacheManifestPath);
if (_localManifest->isLoaded())
prepareLocalManifest();
else
_fileUtils->removeFile(_cacheManifestPath);
cachedManifest = new (std::nothrow) Manifest();
if (cachedManifest) {
cachedManifest->parse(_cacheManifestPath);
if (!cachedManifest->isLoaded())
{
_fileUtils->removeFile(_cacheManifestPath);
CC_SAFE_RELEASE(cachedManifest);
cachedManifest = nullptr;
}
}
}

// Fail to found or load cached manifest file
if (!_localManifest->isLoaded())
// Load local manifest in app package
_localManifest->parse(_manifestUrl);
if (_localManifest->isLoaded())
{
_localManifest->parse(_manifestUrl);
if (_localManifest->isLoaded())
prepareLocalManifest();
// Compare with cached manifest to determine which one to use
if (cachedManifest) {
if (strcmp(_localManifest->getVersion().c_str(), cachedManifest->getVersion().c_str()) > 0)
{
// Recreate storage, to empty the content
_fileUtils->removeDirectory(_storagePath);
_fileUtils->createDirectory(_storagePath);
CC_SAFE_RELEASE(cachedManifest);
}
else
{
CC_SAFE_RELEASE(_localManifest);
_localManifest = cachedManifest;
}
}
prepareLocalManifest();
}

// Fail to load local manifest
Expand Down Expand Up @@ -408,7 +460,7 @@ void AssetsManagerEx::parseVersion()
if (_updateState != State::VERSION_LOADED)
return;

_remoteManifest->parse(_cacheVersionPath);
_remoteManifest->parseVersion(_cacheVersionPath);

if (!_remoteManifest->isVersionLoaded())
{
Expand Down Expand Up @@ -521,21 +573,16 @@ void AssetsManagerEx::startUpdate()
// Check difference
else
{
// Temporary manifest not exists,
// 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.
if(!_tempManifest->isLoaded()) {
_tempManifest->release();
_tempManifest = _remoteManifest;
}
_tempManifest->release();
_tempManifest = _remoteManifest;

std::unordered_map<std::string, Manifest::AssetDiff> diff_map = _localManifest->genDiff(_remoteManifest);
if (diff_map.size() == 0)
{
_updateState = State::UP_TO_DATE;
// Rename temporary manifest to valid manifest
_fileUtils->renameFile(_storagePath, TEMP_MANIFEST_FILENAME, MANIFEST_FILENAME);
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ALREADY_UP_TO_DATE);
updateSucceed();
}
else
{
Expand Down Expand Up @@ -608,6 +655,11 @@ void AssetsManagerEx::updateSucceed()

void AssetsManagerEx::checkUpdate()
{
if (!_inited){
CCLOG("AssetsManagerEx : Manifests uninited.\n");
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_NO_LOCAL_MANIFEST);
return;
}
if (!_localManifest->isLoaded())
{
CCLOG("AssetsManagerEx : No local manifest file found error.\n");
Expand Down Expand Up @@ -640,6 +692,11 @@ void AssetsManagerEx::checkUpdate()

void AssetsManagerEx::update()
{
if (!_inited){
CCLOG("AssetsManagerEx : Manifests uninited.\n");
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_NO_LOCAL_MANIFEST);
return;
}
if (!_localManifest->isLoaded())
{
CCLOG("AssetsManagerEx : No local manifest file found error.\n");
Expand Down Expand Up @@ -701,6 +758,12 @@ void AssetsManagerEx::update()

void AssetsManagerEx::updateAssets(const Downloader::DownloadUnits& assets)
{
if (!_inited){
CCLOG("AssetsManagerEx : Manifests uninited.\n");
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_NO_LOCAL_MANIFEST);
return;
}

if (_updateState != State::UPDATING && _localManifest->isLoaded() && _remoteManifest->isLoaded())
{
int size = (int)(assets.size());
Expand Down
5 changes: 5 additions & 0 deletions extensions/assets-manager/AssetsManagerEx.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ class CC_EX_DLL AssetsManagerEx : public Ref

std::string get(const std::string& key) const;

void initManifests(const std::string& manifestUrl);

void loadLocalManifest(const std::string& manifestUrl);

void prepareLocalManifest();
Expand Down Expand Up @@ -259,6 +261,9 @@ class CC_EX_DLL AssetsManagerEx : public Ref
int _totalToDownload;
//! Total number of assets still waiting to be downloaded
int _totalWaitToDownload;

//! Marker for whether the assets manager is inited
bool _inited;
};

NS_CC_EXT_END
Expand Down
61 changes: 30 additions & 31 deletions extensions/assets-manager/Downloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,46 +471,45 @@ void Downloader::batchDownloadAsync(const DownloadUnits &units, const std::strin

void Downloader::batchDownloadSync(const DownloadUnits &units, const std::string &batchId/* = ""*/)
{
if (units.size() == 0)
{
return;
}
// Make sure downloader won't be released
std::weak_ptr<Downloader> ptr = shared_from_this();

// Test server download resuming support with the first unit
_supportResuming = false;
CURL *header = curl_easy_init();
// Make a resume request
curl_easy_setopt(header, CURLOPT_RESUME_FROM_LARGE, 0);
if (prepareHeader(header, units.begin()->second.srcUrl))
if (units.size() != 0)
{
long responseCode;
curl_easy_getinfo(header, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode == HTTP_CODE_SUPPORT_RESUME)
// Test server download resuming support with the first unit
_supportResuming = false;
CURL *header = curl_easy_init();
// Make a resume request
curl_easy_setopt(header, CURLOPT_RESUME_FROM_LARGE, 0);
if (prepareHeader(header, units.begin()->second.srcUrl))
{
_supportResuming = true;
long responseCode;
curl_easy_getinfo(header, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode == HTTP_CODE_SUPPORT_RESUME)
{
_supportResuming = true;
}
}
}
curl_easy_cleanup(header);

int count = 0;
DownloadUnits group;
for (auto it = units.cbegin(); it != units.cend(); ++it, ++count)
{
if (count == FOPEN_MAX)
curl_easy_cleanup(header);

int count = 0;
DownloadUnits group;
for (auto it = units.cbegin(); it != units.cend(); ++it, ++count)
{
if (count == FOPEN_MAX)
{
groupBatchDownload(group);
group.clear();
count = 0;
}
const std::string &key = it->first;
const DownloadUnit &unit = it->second;
group.emplace(key, unit);
}
if (group.size() > 0)
{
groupBatchDownload(group);
group.clear();
count = 0;
}
const std::string &key = it->first;
const DownloadUnit &unit = it->second;
group.emplace(key, unit);
}
if (group.size() > 0)
{
groupBatchDownload(group);
}

Director::getInstance()->getScheduler()->performFunctionInCocosThread([ptr, batchId]{
Expand Down
63 changes: 39 additions & 24 deletions extensions/assets-manager/Manifest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,33 +63,48 @@ Manifest::Manifest(const std::string& manifestUrl/* = ""*/)
parse(manifestUrl);
}

void Manifest::parse(const std::string& manifestUrl)
void Manifest::loadJson(const std::string& url)
{
clear();
std::string content;
if (_fileUtils->isFileExist(manifestUrl))
{
// Load file content
content = _fileUtils->getStringFromFile(manifestUrl);
std::string content;
if (_fileUtils->isFileExist(url))
{
// Load file content
content = _fileUtils->getStringFromFile(url);

if (content.size() == 0)
{
CCLOG("Fail to retrieve local file content: %s\n", url.c_str());
}
else
{
// Parse file with rapid json
_json.Parse<0>(content.c_str());
// Print error
if (_json.HasParseError()) {
size_t offset = _json.GetErrorOffset();
if (offset > 0)
offset--;
std::string errorSnippet = content.substr(offset, 10);
CCLOG("File parse error %s at <%s>\n", _json.GetParseError(), errorSnippet.c_str());
}
}
}
}

if (content.size() == 0)
{
CCLOG("Fail to retrieve local file content: %s\n", manifestUrl.c_str());
}
else
{
// Parse file with rapid json
_json.Parse<0>(content.c_str());
// Print error
if (_json.HasParseError()) {
size_t offset = _json.GetErrorOffset();
if (offset > 0)
offset--;
std::string errorSnippet = content.substr(offset, 10);
CCLOG("File parse error %s at <%s>\n", _json.GetParseError(), errorSnippet.c_str());
}
}
}
void Manifest::parseVersion(const std::string& versionUrl)
{
loadJson(versionUrl);

if (_json.IsObject())
{
loadVersion(_json);
}
}

void Manifest::parse(const std::string& manifestUrl)
{
loadJson(manifestUrl);

if (_json.IsObject())
{
Expand Down
Loading

0 comments on commit 6db7cfb

Please sign in to comment.