From 9880ba39a76cef03eb14ac3d93449bc6037610cc Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Tue, 10 Jun 2014 23:46:14 +0200 Subject: [PATCH] pkg: Support for install callbacks and fix memory corruption. --- simgear/package/Delegate.hxx | 1 + simgear/package/Install.cxx | 61 +++++++++++++++++++++++++--- simgear/package/Install.hxx | 78 +++++++++++++++++++++++++++++++++--- 3 files changed, 130 insertions(+), 10 deletions(-) diff --git a/simgear/package/Delegate.hxx b/simgear/package/Delegate.hxx index a1b0f147..8bb23a33 100644 --- a/simgear/package/Delegate.hxx +++ b/simgear/package/Delegate.hxx @@ -37,6 +37,7 @@ public: typedef enum { FAIL_SUCCESS = 0, ///< not a failure :) FAIL_UNKNOWN = 1, + FAIL_IN_PROGRESS, ///< downloading/installation in progress (not a failure :P) FAIL_CHECKSUM, ///< package MD5 verificstion failed FAIL_DOWNLOAD, ///< network issue FAIL_EXTRACT, ///< package archive failed to extract cleanly diff --git a/simgear/package/Install.cxx b/simgear/package/Install.cxx index ba612d6a..3d516299 100644 --- a/simgear/package/Install.cxx +++ b/simgear/package/Install.cxx @@ -255,11 +255,11 @@ private: }; //////////////////////////////////////////////////////////////////// - Install::Install(PackageRef aPkg, const SGPath& aPath) : m_package(aPkg), m_path(aPath), - m_download(NULL) + m_download(NULL), + _status(Delegate::FAIL_IN_PROGRESS) { parseRevision(); } @@ -315,24 +315,75 @@ void Install::uninstall() { Dir d(m_path); d.remove(true); - delete this; } +//------------------------------------------------------------------------------ +Install* Install::done(const Callback& cb) +{ + if( _status == Delegate::FAIL_SUCCESS ) + cb(this); + else + _cb_done = cb; + + return this; +} + +//------------------------------------------------------------------------------ +Install* Install::fail(const Callback& cb) +{ + if( _status != Delegate::FAIL_SUCCESS + && _status != Delegate::FAIL_IN_PROGRESS ) + cb(this); + else + _cb_fail = cb; + + return this; +} + +//------------------------------------------------------------------------------ +Install* Install::always(const Callback& cb) +{ + if( _status != Delegate::FAIL_IN_PROGRESS ) + cb(this); + else + _cb_always = cb; + + return this; +} + +//------------------------------------------------------------------------------ +Install* Install::progress(const ProgressCallback& cb) +{ + _cb_progress = cb; + return this; +} + +//------------------------------------------------------------------------------ void Install::installResult(Delegate::FailureCode aReason) { if (aReason == Delegate::FAIL_SUCCESS) { m_package->catalog()->root()->finishInstall(this); + if( _cb_done ) + _cb_done(this); } else { m_package->catalog()->root()->failedInstall(this, aReason); + if( _cb_fail ) + _cb_fail(this); } + + if( _cb_always ) + _cb_always(this); } - + +//------------------------------------------------------------------------------ void Install::installProgress(unsigned int aBytes, unsigned int aTotal) { m_package->catalog()->root()->installProgress(this, aBytes, aTotal); + if( _cb_progress ) + _cb_progress(this, aBytes, aTotal); } - + } // of namespace pkg } // of namespace simgear diff --git a/simgear/package/Install.hxx b/simgear/package/Install.hxx index dd676b88..f5458d69 100644 --- a/simgear/package/Install.hxx +++ b/simgear/package/Install.hxx @@ -26,6 +26,9 @@ #include #include +#include +#include + namespace simgear { @@ -47,6 +50,10 @@ typedef SGSharedPtr InstallRef; class Install : public SGReferenced { public: + typedef boost::function Callback; + typedef boost::function + ProgressCallback; + /** * create from a directory on disk, or fail. */ @@ -66,12 +73,65 @@ public: void startUpdate(); void uninstall(); + + /** + * Set the handler to be called when the installation successfully + * completes. + * + * @note If the installation is already complete, the handler is called + * immediately. + */ + Install* done(const Callback& cb); + + template + Install* done(C* instance, void (C::*mem_func)(Install*)) + { + return done(boost::bind(mem_func, instance, _1)); + } + + /** + * Set the handler to be called when the installation fails or is aborted. + * + * @note If the installation has already failed, the handler is called + * immediately. + */ + Install* fail(const Callback& cb); + + template + Install* fail(C* instance, void (C::*mem_func)(Install*)) + { + return fail(boost::bind(mem_func, instance, _1)); + } + + /** + * Set the handler to be called when the installation either successfully + * completes or fails. + * + * @note If the installation is already complete or has already failed, the + * handler is called immediately. + */ + Install* always(const Callback& cb); + + template + Install* always(C* instance, void (C::*mem_func)(Install*)) + { + return always(boost::bind(mem_func, instance, _1)); + } -// boost signals time? - // failure - // progress - // completed - + /** + * Set the handler to be called during downloading the installation file + * indicating the progress of the download. + * + */ + Install* progress(const ProgressCallback& cb); + + template + Install* progress(C* instance, + void (C::*mem_func)(Install*, unsigned int, unsigned int)) + { + return progress(boost::bind(mem_func, instance, _1, _2, _3)); + } + private: friend class Package; @@ -91,6 +151,14 @@ private: SGPath m_path; ///< installation point on disk PackageArchiveDownloader* m_download; + + Delegate::FailureCode _status; + + Callback _cb_done, + _cb_fail, + _cb_always; + ProgressCallback _cb_progress; + }; -- 2.39.5