From 38a2ce67bbeb7af6be716f1d46716fdbcf96e5bc Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 4 Nov 2016 11:23:10 -0700 Subject: [PATCH 1/6] Add tools/atp-extract.py Tool to list and extract files from the atp assets directory. --- tools/atp-extract.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tools/atp-extract.py diff --git a/tools/atp-extract.py b/tools/atp-extract.py new file mode 100644 index 0000000000..10c31ab0d3 --- /dev/null +++ b/tools/atp-extract.py @@ -0,0 +1,44 @@ +# +# Tool to extract atp files from the asset server cache. +# Usage: python2 atp-extract.py -[lxa] [filename] +# +# cd into the c:\Users\BettySpaghetti\AppData\Roaming\High Fidelity\assignment-client\assets dir +# run 'python2 atp-extract.py -l' to list all files +# run 'python2 atp-extract.py -x file' to extract that particular file to the current directory. +# run 'python2 atp-extract.py -a' to extract all files. +# + +import os, json, sys, shutil + +def loadMapFile(filename): + with open(filename, 'r') as f: + return json.load(f) + +def extractFile(assetMap, filename): + if filename != None: + assetFilename = assetMap.get("/" + filename) + if assetFilename != None: + dir = os.path.dirname(filename) + if dir != "" and not os.path.exists(dir): + os.makedirs(dir) + shutil.copy("files/" + assetFilename, filename) + return True + return False + +option = sys.argv[1] +if option == '-l': + assetMap = loadMapFile("map.json") + for key, value in assetMap.iteritems(): + print key[1:] +elif option == '-x': + assetMap = loadMapFile("map.json") + outputFilename = sys.argv[2] + if not extractFile(assetMap, outputFilename): + print("Error could not extract file: \"" + outputFilename + "\"") +elif option == '-a': + assetMap = loadMapFile("map.json") + for key, value in assetMap.iteritems(): + print("Extracting " + key[1:]) + extractFile(assetMap, key[1:]) +else: + print("unsuported option \"" + option + "\"") From 5287ec1eee45fadcfa523fd2b1710f565172c305 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Sat, 5 Nov 2016 10:15:56 -0700 Subject: [PATCH 2/6] Fix includes hitting max retries locking the script up --- libraries/script-engine/src/ScriptCache.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp index 96e3d7e914..025447a5b8 100644 --- a/libraries/script-engine/src/ScriptCache.cpp +++ b/libraries/script-engine/src/ScriptCache.cpp @@ -222,6 +222,9 @@ void ScriptCache::scriptContentAvailable() { }); } else { // Dubious, but retained here because it matches the behavior before fixing the threading + + allCallbacks = scriptRequest.scriptUsers; + scriptContent = _scriptCache[url]; finished = true; qCWarning(scriptengine) << "Error loading script from URL " << url; From 1a704f8d0a570870bf405bfc1b59ca68c3ffac38 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Sat, 5 Nov 2016 10:16:35 -0700 Subject: [PATCH 3/6] Fix ScriptCacheSignalProxy not being properly cleaned up --- libraries/script-engine/src/BatchLoader.cpp | 3 ++- libraries/script-engine/src/BatchLoader.h | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/script-engine/src/BatchLoader.cpp b/libraries/script-engine/src/BatchLoader.cpp index 964807894e..d191c89f09 100644 --- a/libraries/script-engine/src/BatchLoader.cpp +++ b/libraries/script-engine/src/BatchLoader.cpp @@ -55,7 +55,8 @@ void BatchLoader::start() { // Use a proxy callback to handle the call and emit the signal in a thread-safe way. // If BatchLoader is deleted before the callback is called, the subsequent "emit" call will not do // anything. - ScriptCacheSignalProxy* proxy = new ScriptCacheSignalProxy(scriptCache.data()); + ScriptCacheSignalProxy* proxy = new ScriptCacheSignalProxy(); + connect(scriptCache.data(), &ScriptCache::destroyed, proxy, &ScriptCacheSignalProxy::deleteLater); connect(proxy, &ScriptCacheSignalProxy::contentAvailable, this, [this](const QString& url, const QString& contents, bool isURL, bool success) { if (isURL && success) { diff --git a/libraries/script-engine/src/BatchLoader.h b/libraries/script-engine/src/BatchLoader.h index a03a8d80c6..046e17ff63 100644 --- a/libraries/script-engine/src/BatchLoader.h +++ b/libraries/script-engine/src/BatchLoader.h @@ -24,7 +24,6 @@ class ScriptCacheSignalProxy : public QObject { Q_OBJECT public: - ScriptCacheSignalProxy(QObject* parent) : QObject(parent) { } void receivedContent(const QString& url, const QString& contents, bool isURL, bool success); signals: From 2139e979da34c81b7c05bf90d6f4fe29a7001128 Mon Sep 17 00:00:00 2001 From: humbletim Date: Sun, 6 Nov 2016 09:33:16 -0500 Subject: [PATCH 4/6] map specific HTTP errors to corresponding ResourceRequest enums --- .../networking/src/HTTPResourceRequest.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/libraries/networking/src/HTTPResourceRequest.cpp b/libraries/networking/src/HTTPResourceRequest.cpp index 392654a419..64396ec62e 100644 --- a/libraries/networking/src/HTTPResourceRequest.cpp +++ b/libraries/networking/src/HTTPResourceRequest.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -78,10 +79,36 @@ void HTTPResourceRequest::onRequestFinished() { _loadedFromCache = _reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(); _result = Success; break; + case QNetworkReply::TimeoutError: _result = Timeout; break; + + case QNetworkReply::ContentNotFoundError: // Script.include('https://httpbin.org/status/404') + _result = NotFound; + break; + + case QNetworkReply::ProtocolInvalidOperationError: // Script.include('https://httpbin.org/status/400') + _result = InvalidURL; + break; + + case QNetworkReply::UnknownContentError: // Script.include('QUrl("https://httpbin.org/status/402")') + case QNetworkReply::ContentOperationNotPermittedError: //Script.include('https://httpbin.org/status/403') + case QNetworkReply::AuthenticationRequiredError: // Script.include('https://httpbin.org/basic-auth/user/passwd') + _result = AccessDenied; + break; + + case QNetworkReply::RemoteHostClosedError: // Script.include('http://127.0.0.1:22') + case QNetworkReply::ConnectionRefusedError: // Script.include(http://127.0.0.1:1') + case QNetworkReply::HostNotFoundError: // Script.include('http://foo.bar.highfidelity.io') + case QNetworkReply::ServiceUnavailableError: // Script.include('QUrl("https://httpbin.org/status/503")') + _result = ServerUnavailable; + break; + + case QNetworkReply::UnknownServerError: // Script.include('QUrl("https://httpbin.org/status/504")') + case QNetworkReply::InternalServerError: // Script.include('QUrl("https://httpbin.org/status/500")') default: + qDebug() << "HTTPResourceRequest error:" << QMetaEnum::fromType().valueToKey(_reply->error()); _result = Error; break; } From 61452c21a2d877a75be54686e91e15cec6abb9cc Mon Sep 17 00:00:00 2001 From: humbletim Date: Sun, 6 Nov 2016 09:40:28 -0500 Subject: [PATCH 5/6] bail early from irrecoverable retry situations --- libraries/script-engine/src/ScriptCache.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp index 96e3d7e914..941c0b6175 100644 --- a/libraries/script-engine/src/ScriptCache.cpp +++ b/libraries/script-engine/src/ScriptCache.cpp @@ -202,7 +202,14 @@ void ScriptCache::scriptContentAvailable() { finished = true; qCDebug(scriptengine) << "Done downloading script at:" << url.toString(); } else { - if (scriptRequest.numRetries < MAX_RETRIES) { + auto result = req->getResult(); + bool irrecoverable = + result == ResourceRequest::AccessDenied || + result == ResourceRequest::InvalidURL || + result == ResourceRequest::NotFound || + scriptRequest.numRetries >= MAX_RETRIES; + + if (!irrecoverable) { ++scriptRequest.numRetries; qDebug() << "Script request failed: " << url; From 852218815b63ae154108a77ffae0f272b13296b0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 7 Nov 2016 13:40:49 +1300 Subject: [PATCH 6/6] Display "content loading" while there are pending GPU texture transfers --- scripts/system/progress.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index 92853c9ada..81da38c8c2 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -248,7 +248,7 @@ } function update() { - var viewport, diff, x; + var viewport, diff, x, gpuTextures; initialDelayCooldown -= 30; @@ -261,26 +261,28 @@ } } + gpuTextures = Render.getConfig("Stats").textureGPUTransferCount; + // Update state if (!visible) { // Not visible because no recent downloads - if (displayProgress < 100) { // Have started downloading so fade in + if (displayProgress < 100 || gpuTextures > 0) { // Have started downloading so fade in visible = true; alphaDelta = ALPHA_DELTA_IN; fadeTimer = Script.setInterval(fade, FADE_INTERVAL); } } else if (alphaDelta !== 0.0) { // Fading in or out if (alphaDelta > 0) { - if (rawProgress === 100) { // Was downloading but now have finished so fade out + if (rawProgress === 100 && gpuTextures === 0) { // Was downloading but now have finished so fade out alphaDelta = ALPHA_DELTA_OUT; } } else { - if (displayProgress < 100) { // Was finished downloading but have resumed so fade in + if (displayProgress < 100 || gpuTextures > 0) { // Was finished downloading but have resumed so fade in alphaDelta = ALPHA_DELTA_IN; } } } else { // Fully visible because downloading or recently so if (fadeWaitTimer === null) { - if (rawProgress === 100) { // Was downloading but have finished so fade out soon + if (rawProgress === 100 && gpuTextures === 0) { // Was downloading but have finished so fade out soon fadeWaitTimer = Script.setTimeout(function () { alphaDelta = ALPHA_DELTA_OUT; fadeTimer = Script.setInterval(fade, FADE_INTERVAL); @@ -288,7 +290,8 @@ }, FADE_OUT_WAIT); } } else { - if (displayProgress < 100) { // Was finished and waiting to fade out but have resumed so don't fade out + if (displayProgress < 100 || gpuTextures > 0) { // Was finished and waiting to fade out but have resumed so + // don't fade out Script.clearInterval(fadeWaitTimer); fadeWaitTimer = null; }