From eb52f759de6f0805865fb7f31444f2b1421b4d25 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Fri, 22 Jun 2012 19:04:38 +0100 Subject: [PATCH] Success/Failure return from Asyn Task, Prompt to visit website upon update failure --- src/Config.h | 17 ++++- src/client/Client.cpp | 39 ++++++++--- src/client/Client.h | 16 +++++ src/client/HTTP.cpp | 19 ++---- src/dialogues/ConfirmPrompt.cpp | 2 +- src/localbrowser/LocalBrowserController.cpp | 3 +- src/search/SearchController.cpp | 9 ++- src/tasks/Task.cpp | 62 ++++++++++++----- src/tasks/Task.h | 11 ++- src/update/UpdateActivity.cpp | 74 ++++++++++++--------- src/update/UpdateActivity.h | 2 + 11 files changed, 172 insertions(+), 82 deletions(-) diff --git a/src/Config.h b/src/Config.h index fdc34d769..5bf10cc56 100644 --- a/src/Config.h +++ b/src/Config.h @@ -19,13 +19,16 @@ #define SAVE_VERSION 80 #define MINOR_VERSION 3 #define BETA +#define SNAPSHOT #define BUILD_NUM 155 //VersionInfoEnd -#ifdef BETA +#if defined(SNAPSHOT) +#define IDENT_RELTYPE "S" +#elif defined(BETA) #define IDENT_RELTYPE "B" #else -#define IDENT_RELTYPE "S" +#define IDENT_RELTYPE "R" #endif #ifdef WIN32 @@ -40,6 +43,16 @@ #define IDENT_PLATFORM "UNKNOWN" #endif +#if defined(X86_SSE3) +#define IDENT_BUILD "SSE3" +#elif defined(X86_SSE2) +#define IDENT_BUILD "SSE2" +#elif defined(X86_SSE) +#define IDENT_BUILD "SSE" +#else +#define IDENT_BUILD "NO" +#endif + #define IDENT_VERSION "G" //Change this if you're not Simon! It should be a single letter #define MTOS_EXPAND(str) #str diff --git a/src/client/Client.cpp b/src/client/Client.cpp index ec8892784..d0a7bee2a 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -114,7 +114,7 @@ Client::Client(): stampsLib.close(); //Begin version check - versionCheckRequest = http_async_req_start(NULL, SERVER "/Version.json", NULL, 0, 1); + versionCheckRequest = http_async_req_start(NULL, SERVER "/Download/Version.json", NULL, 0, 1); } void Client::Tick() @@ -127,7 +127,6 @@ void Client::Tick() char * data = http_async_req_stop(versionCheckRequest, &status, &dataLength); versionCheckRequest = NULL; - notifyUpdateAvailable(); if(status != 200) { if(data) @@ -144,25 +143,42 @@ void Client::Tick() json::Object stableVersion = objDocument["Stable"]; json::Object betaVersion = objDocument["Beta"]; + json::Object snapshotVersion = objDocument["Snapshot"]; json::Number stableMajor = stableVersion["Major"]; json::Number stableMinor = stableVersion["Minor"]; json::Number stableBuild = stableVersion["Build"]; + json::String stableFile = stableVersion["File"]; json::Number betaMajor = betaVersion["Major"]; json::Number betaMinor = betaVersion["Minor"]; json::Number betaBuild = betaVersion["Build"]; + json::String betaFile = betaVersion["File"]; + + json::Number snapshotMajor = snapshotVersion["Major"]; + json::Number snapshotMinor = snapshotVersion["Minor"]; + json::Number snapshotBuild = snapshotVersion["Build"]; + json::String snapshotFile = snapshotVersion["File"]; -#ifdef BETA - if( (betaMajor.Value()>SAVE_VERSION || (betaMinor.Value()>MINOR_VERSION && betaMajor.Value()==SAVE_VERSION) || betaBuild.Value()>BUILD_NUM) || - (stableMajor.Value()>SAVE_VERSION || (stableMinor.Value()>MINOR_VERSION && stableMajor.Value()==SAVE_VERSION) || stableBuild.Value()>BUILD_NUM)) - { - updateAvailable = true; - } -#else if(stableMajor.Value()>SAVE_VERSION || (stableMinor.Value()>MINOR_VERSION && stableMajor.Value()==SAVE_VERSION) || stableBuild.Value()>BUILD_NUM) { updateAvailable = true; + updateInfo = UpdateInfo(stableMajor.Value(), stableMinor.Value(), stableBuild.Value(), stableFile.Value(), UpdateInfo::Stable); + } + +#ifdef BETA + if(betaMajor.Value()>SAVE_VERSION || (betaMinor.Value()>MINOR_VERSION && betaMajor.Value()==SAVE_VERSION) || betaBuild.Value()>BUILD_NUM) + { + updateAvailable = true; + updateInfo = UpdateInfo(betaMajor.Value(), betaMinor.Value(), betaBuild.Value(), betaFile.Value(), UpdateInfo::Beta); + } +#endif + +#ifdef SNAPSHOT + if(snapshotMajor.Value()>SAVE_VERSION || (snapshotMinor.Value()>MINOR_VERSION && snapshotMajor.Value()==SAVE_VERSION) || snapshotBuild.Value()>BUILD_NUM) + { + updateAvailable = true; + updateInfo = UpdateInfo(snapshotMajor.Value(), snapshotMinor.Value(), snapshotBuild.Value(), snapshotFile.Value(), UpdateInfo::Snapshot); } #endif @@ -182,6 +198,11 @@ void Client::Tick() } } +UpdateInfo Client::GetUpdateInfo() +{ + return updateInfo; +} + void Client::notifyUpdateAvailable() { for (std::vector::iterator iterator = listeners.begin(), end = listeners.end(); iterator != end; ++iterator) diff --git a/src/client/Client.h b/src/client/Client.h index 8c1fae7b5..b2822d4d7 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -27,11 +27,25 @@ enum RequestStatus { RequestOkay, RequestFailure }; +class UpdateInfo +{ +public: + enum BuildType { Stable, Beta, Snapshot }; + std::string File; + int Major; + int Minor; + int Build; + BuildType Type; + UpdateInfo() : Major(0), Minor(0), Build(0), File(""), Type(Stable) {} + UpdateInfo(int major, int minor, int build, std::string file, BuildType type) : Major(major), Minor(minor), Build(build), File(file), Type(type) {} +}; + class ClientListener; class Client: public Singleton { private: void * versionCheckRequest; bool updateAvailable; + UpdateInfo updateInfo; std::string lastError; @@ -59,6 +73,8 @@ private: public: vector listeners; + UpdateInfo GetUpdateInfo(); + Client(); ~Client(); diff --git a/src/client/HTTP.cpp b/src/client/HTTP.cpp index a8e576448..d622a81ff 100644 --- a/src/client/HTTP.cpp +++ b/src/client/HTTP.cpp @@ -468,7 +468,7 @@ int http_async_req_status(void *ctx) if (cx->txdl) { // generate POST - cx->tbuf = (char *)malloc(strlen(cx->host) + strlen(cx->path) + 121 + 128 + cx->txdl + cx->thlen); + cx->tbuf = (char *)malloc(strlen(cx->host) + strlen(cx->path) + 141 + 128 + cx->txdl + cx->thlen); cx->tptr = 0; cx->tlen = 0; cx->tlen += sprintf(cx->tbuf+cx->tlen, "POST %s HTTP/1.1\n", cx->path); @@ -484,12 +484,7 @@ int http_async_req_status(void *ctx) cx->thlen = 0; } cx->tlen += sprintf(cx->tbuf+cx->tlen, "Content-Length: %d\n", cx->txdl); - cx->tlen += sprintf(cx->tbuf+cx->tlen, "User-Agent: PowderToy/%d.%d (%s; M%d) TPTPP/%s%d.%d.%d%s\n", SAVE_VERSION, MINOR_VERSION, IDENT_PLATFORM, 0, IDENT_VERSION, SAVE_VERSION, MINOR_VERSION, BUILD_NUM, IDENT_RELTYPE); -//#ifdef BETA -// cx->tlen += sprintf(cx->tbuf+cx->tlen, "X-Powder-Version: %s%dB%d\n", IDENT_VERSION, SAVE_VERSION, MINOR_VERSION); -//#else -// cx->tlen += sprintf(cx->tbuf+cx->tlen, "X-Powder-Version: %s%dS%d\n", IDENT_VERSION, SAVE_VERSION, MINOR_VERSION); -//#endif + cx->tlen += sprintf(cx->tbuf+cx->tlen, "User-Agent: PowderToy/%d.%d (%s; %s; M%d) TPTPP/%d.%d.%d%s\n", SAVE_VERSION, MINOR_VERSION, IDENT_PLATFORM, IDENT_BUILD, 0, SAVE_VERSION, MINOR_VERSION, BUILD_NUM, IDENT_RELTYPE); cx->tlen += sprintf(cx->tbuf+cx->tlen, "\n"); memcpy(cx->tbuf+cx->tlen, cx->txd, cx->txdl); cx->tlen += cx->txdl; @@ -500,7 +495,7 @@ int http_async_req_status(void *ctx) else { // generate GET - cx->tbuf = (char *)malloc(strlen(cx->host) + strlen(cx->path) + 89 + 128 + cx->thlen); + cx->tbuf = (char *)malloc(strlen(cx->host) + strlen(cx->path) + 100 + 128 + cx->thlen); cx->tptr = 0; cx->tlen = 0; cx->tlen += sprintf(cx->tbuf+cx->tlen, "GET %s HTTP/1.1\n", cx->path); @@ -515,13 +510,7 @@ int http_async_req_status(void *ctx) } if (!cx->keep) cx->tlen += sprintf(cx->tbuf+cx->tlen, "Connection: close\n"); - cx->tlen += sprintf(cx->tbuf+cx->tlen, "User-Agent: PowderToy/%d.%d (%s; M%d) TPTPP/%s%d.%d.%d%s\n", SAVE_VERSION, MINOR_VERSION, IDENT_PLATFORM, 0, IDENT_VERSION, SAVE_VERSION, MINOR_VERSION, BUILD_NUM, IDENT_RELTYPE); - -/*#ifdef BETA - cx->tlen += sprintf(cx->tbuf+cx->tlen, "X-Powder-Version: %s%dB%d\n", IDENT_VERSION, SAVE_VERSION, MINOR_VERSION); -#else - cx->tlen += sprintf(cx->tbuf+cx->tlen, "X-Powder-Version: %s%dS%d\n", IDENT_VERSION, SAVE_VERSION, MINOR_VERSION); -#endif*/ + cx->tlen += sprintf(cx->tbuf+cx->tlen, "User-Agent: PowderToy/%d.%d (%s; %s; M%d) TPTPP/%d.%d.%d%s\n", SAVE_VERSION, MINOR_VERSION, IDENT_PLATFORM, IDENT_BUILD, 0, SAVE_VERSION, MINOR_VERSION, BUILD_NUM, IDENT_RELTYPE); cx->tlen += sprintf(cx->tbuf+cx->tlen, "\n"); } cx->state = HTS_XMIT; diff --git a/src/dialogues/ConfirmPrompt.cpp b/src/dialogues/ConfirmPrompt.cpp index 91a13267e..d9cf94542 100644 --- a/src/dialogues/ConfirmPrompt.cpp +++ b/src/dialogues/ConfirmPrompt.cpp @@ -11,7 +11,7 @@ #include "interface/Button.h" ConfirmPrompt::ConfirmPrompt(std::string title, std::string message, ConfirmDialogueCallback * callback_): - ui::Window(ui::Point(-1, -1), ui::Point(200, 50)), + ui::Window(ui::Point(-1, -1), ui::Point(250, 50)), callback(callback_) { int width, height; diff --git a/src/localbrowser/LocalBrowserController.cpp b/src/localbrowser/LocalBrowserController.cpp index 644266f8f..47f02bb12 100644 --- a/src/localbrowser/LocalBrowserController.cpp +++ b/src/localbrowser/LocalBrowserController.cpp @@ -67,7 +67,7 @@ void LocalBrowserController::removeSelectedC() std::vector saves; public: RemoveSavesTask(std::vector saves_) { saves = saves_; } - virtual void doWork() + virtual bool doWork() { for(int i = 0; i < saves.size(); i++) { @@ -78,6 +78,7 @@ void LocalBrowserController::removeSelectedC() usleep(100*1000); notifyProgress((float(i+1)/float(saves.size())*100)); } + return true; } }; diff --git a/src/search/SearchController.cpp b/src/search/SearchController.cpp index 68fe978a5..5e592aed6 100644 --- a/src/search/SearchController.cpp +++ b/src/search/SearchController.cpp @@ -198,7 +198,7 @@ void SearchController::removeSelectedC() std::vector saves; public: RemoveSavesTask(std::vector saves_) { saves = saves_; } - virtual void doWork() + virtual bool doWork() { for(int i = 0; i < saves.size(); i++) { @@ -215,6 +215,7 @@ void SearchController::removeSelectedC() usleep(100*1000); notifyProgress((float(i+1)/float(saves.size())*100)); } + return true; } }; @@ -251,7 +252,7 @@ void SearchController::unpublishSelectedC() std::vector saves; public: UnpublishSavesTask(std::vector saves_) { saves = saves_; } - virtual void doWork() + virtual bool doWork() { for(int i = 0; i < saves.size(); i++) { @@ -268,6 +269,7 @@ void SearchController::unpublishSelectedC() usleep(100*1000); notifyProgress((float(i+1)/float(saves.size())*100)); } + return true; } }; @@ -284,7 +286,7 @@ void SearchController::FavouriteSelected() std::vector saves; public: FavouriteSavesTask(std::vector saves_) { saves = saves_; } - virtual void doWork() + virtual bool doWork() { for(int i = 0; i < saves.size(); i++) { @@ -301,6 +303,7 @@ void SearchController::FavouriteSelected() usleep(100*1000); notifyProgress((float(i+1)/float(saves.size())*100)); } + return true; } }; diff --git a/src/tasks/Task.cpp b/src/tasks/Task.cpp index 7be013e4e..b2ded163c 100644 --- a/src/tasks/Task.cpp +++ b/src/tasks/Task.cpp @@ -47,37 +47,43 @@ bool Task::GetDone() return done; } +bool Task::GetSuccess() +{ + return success; +} + void Task::Poll() { if(!done) { int newProgress; bool newDone = false; + bool newSuccess = false; std::string newStatus; std::string newError; pthread_mutex_lock(&taskMutex); newProgress = thProgress; newDone = thDone; + newSuccess = thSuccess; newStatus = std::string(thStatus); newError = std::string(thError); pthread_mutex_unlock(&taskMutex); + success = newSuccess; + if(newProgress!=progress) { progress = newProgress; - if(listener) - listener->NotifyProgress(this); + notifyProgressMain(); } if(newError!=error) { error = std::string(newError); - if(listener) - listener->NotifyError(this); + notifyErrorMain(); } if(newStatus!=status) { status = std::string(newStatus); - if(listener) - listener->NotifyStatus(this); + notifyStatusMain(); } if(done) @@ -90,8 +96,7 @@ void Task::Poll() if(newDone!=done) { done = newDone; - if(listener) - listener->NotifyDone(this); + notifyDoneMain(); } } } @@ -106,7 +111,7 @@ void Task::before() } -void Task::doWork() +bool Task::doWork() { notifyStatus("Fake progress"); for(int i = 0; i < 100; i++) @@ -114,6 +119,7 @@ void Task::doWork() notifyProgress(i); usleep((100)*1000); } + return true; } void Task::after() @@ -123,8 +129,11 @@ void Task::after() void * Task::doWork_helper(void * ref) { - ((Task*)ref)->doWork(); - ((Task*)ref)->notifyDone(); + bool newSuccess = ((Task*)ref)->doWork(); + pthread_mutex_lock(&((Task*)ref)->taskMutex); + ((Task*)ref)->thSuccess = newSuccess; + ((Task*)ref)->thDone = true; + pthread_mutex_unlock(&((Task*)ref)->taskMutex); return NULL; } @@ -142,16 +151,33 @@ void Task::notifyStatus(std::string status) pthread_mutex_unlock(&taskMutex); } -void Task::notifyDone() -{ - pthread_mutex_lock(&taskMutex); - thDone = true; - pthread_mutex_unlock(&taskMutex); -} - void Task::notifyError(std::string error) { pthread_mutex_lock(&taskMutex); thError = std::string(error); pthread_mutex_unlock(&taskMutex); } + +void Task::notifyProgressMain() +{ + if(listener) + listener->NotifyProgress(this); +} + +void Task::notifyStatusMain() +{ + if(listener) + listener->NotifyStatus(this); +} + +void Task::notifyDoneMain() +{ + if(listener) + listener->NotifyDone(this); +} + +void Task::notifyErrorMain() +{ + if(listener) + listener->NotifyError(this); +} diff --git a/src/tasks/Task.h b/src/tasks/Task.h index ae83e1ddb..76284ac1c 100644 --- a/src/tasks/Task.h +++ b/src/tasks/Task.h @@ -19,6 +19,7 @@ public: void Start(); int GetProgress(); bool GetDone(); + bool GetSuccess(); std::string GetError(); std::string GetStatus(); void Poll(); @@ -27,11 +28,13 @@ public: protected: int progress; bool done; + bool success; std::string status; std::string error; int thProgress; bool thDone; + bool thSuccess; std::string thStatus; std::string thError; @@ -43,13 +46,17 @@ protected: virtual void before(); virtual void after(); - virtual void doWork(); + virtual bool doWork(); static void * doWork_helper(void * ref); virtual void notifyProgress(int progress); virtual void notifyError(std::string error); virtual void notifyStatus(std::string status); - virtual void notifyDone(); + + virtual void notifyProgressMain(); + virtual void notifyErrorMain(); + virtual void notifyStatusMain(); + virtual void notifyDoneMain(); }; #endif /* TASK_H_ */ diff --git a/src/update/UpdateActivity.cpp b/src/update/UpdateActivity.cpp index 74343c10f..1f07373a6 100644 --- a/src/update/UpdateActivity.cpp +++ b/src/update/UpdateActivity.cpp @@ -7,12 +7,14 @@ #include #include +#include "dialogues/ConfirmPrompt.h" #include "interface/Engine.h" #include "UpdateActivity.h" #include "tasks/Task.h" #include "client/HTTP.h" #include "client/Client.h" #include "Update.h" +#include "Misc.h" class UpdateDownloadTask : public Task @@ -22,11 +24,14 @@ public: private: UpdateActivity * a; std::string updateName; - virtual void notifyDone() - { + virtual void notifyDoneMain(){ a->NotifyDone(this); } - virtual void doWork() + virtual void notifyErrorMain() + { + a->NotifyError(this); + } + virtual bool doWork() { std::stringstream errorStream; void * request = http_async_req_start(NULL, (char*)updateName.c_str(), NULL, 0, 0); @@ -48,13 +53,13 @@ private: free(data); errorStream << "Server responded with Status " << status; notifyError("Could not download update"); - return; + return false; } if (!data) { errorStream << "Server responded with nothing"; notifyError("Server did not return any data"); - return; + return false; } notifyStatus("Unpacking update"); @@ -107,50 +112,57 @@ private: } Client::Ref().SetPref("version.update", true); - return; + return true; corrupt: notifyError("Downloaded update is corrupted\n" + errorStream.str()); free(data); - return; + return false; } }; UpdateActivity::UpdateActivity() { - char my_uri[] = "http://" SERVER "/Update.api?Action=Download&Architecture=" - #if defined WIN32 - "Windows32" - #elif defined LIN32 - "Linux32" - #elif defined LIN64 - "Linux64" - #elif defined MACOSX - "MacOSX" - #else - "Unknown" - #endif - "&InstructionSet=" - #if defined X86_SSE3 - "SSE3" - #elif defined X86_SSE2 - "SSE2" - #elif defined X86_SSE - "SSE" - #else - "SSE" - #endif - ; - updateDownloadTask = new UpdateDownloadTask(my_uri, this); + std::stringstream file; + file << "http://" << SERVER << Client::Ref().GetUpdateInfo().File; + updateDownloadTask = new UpdateDownloadTask(file.str(), this); updateWindow = new TaskWindow("Downloading update...", updateDownloadTask, true); } void UpdateActivity::NotifyDone(Task * sender) +{ + if(sender->GetSuccess()) + { + Exit(); + } +} + +void UpdateActivity::Exit() { updateWindow->Exit(); ui::Engine::Ref().Exit(); delete this; } +void UpdateActivity::NotifyError(Task * sender) +{ + class ErrorMessageCallback: public ConfirmDialogueCallback + { + UpdateActivity * a; + public: + ErrorMessageCallback(UpdateActivity * a_) { a = a_; } + virtual void ConfirmCallback(ConfirmPrompt::DialogueResult result) { + if (result == ConfirmPrompt::ResultOkay) + { + OpenURI("http://powdertoy.co.uk/Download.html"); + } + a->Exit(); + } + virtual ~ErrorMessageCallback() { } + }; + new ConfirmPrompt("Autoupdate failed", "Please visit the website to download a newer version.\nError: " + sender->GetError(), new ErrorMessageCallback(this)); +} + + UpdateActivity::~UpdateActivity() { // TODO Auto-generated destructor stub } diff --git a/src/update/UpdateActivity.h b/src/update/UpdateActivity.h index 1f3da7375..f92368484 100644 --- a/src/update/UpdateActivity.h +++ b/src/update/UpdateActivity.h @@ -17,7 +17,9 @@ class UpdateActivity { public: UpdateActivity(); virtual ~UpdateActivity(); + void Exit(); virtual void NotifyDone(Task * sender); + virtual void NotifyError(Task * sender); }; #endif /* UPDATEACTIVITY_H_ */