Success/Failure return from Asyn Task, Prompt to visit website upon update failure

This commit is contained in:
Simon Robertshaw 2012-06-22 19:04:38 +01:00
parent 55d90a44a8
commit eb52f759de
11 changed files with 172 additions and 82 deletions

View File

@ -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

View File

@ -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<ClientListener*>::iterator iterator = listeners.begin(), end = listeners.end(); iterator != end; ++iterator)

View File

@ -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<Client> {
private:
void * versionCheckRequest;
bool updateAvailable;
UpdateInfo updateInfo;
std::string lastError;
@ -59,6 +73,8 @@ private:
public:
vector<ClientListener*> listeners;
UpdateInfo GetUpdateInfo();
Client();
~Client();

View File

@ -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;

View File

@ -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;

View File

@ -67,7 +67,7 @@ void LocalBrowserController::removeSelectedC()
std::vector<std::string> saves;
public:
RemoveSavesTask(std::vector<std::string> 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;
}
};

View File

@ -198,7 +198,7 @@ void SearchController::removeSelectedC()
std::vector<int> saves;
public:
RemoveSavesTask(std::vector<int> 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<int> saves;
public:
UnpublishSavesTask(std::vector<int> 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<int> saves;
public:
FavouriteSavesTask(std::vector<int> 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;
}
};

View File

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

View File

@ -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_ */

View File

@ -7,12 +7,14 @@
#include <bzlib.h>
#include <sstream>
#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
}

View File

@ -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_ */