diff options
author | Aaron Brashears <aaronb@lindenlab.com> | 2009-05-18 23:38:35 +0000 |
---|---|---|
committer | Aaron Brashears <aaronb@lindenlab.com> | 2009-05-18 23:38:35 +0000 |
commit | 6df2755ba6b24d0cefd52ce175b0212dd46c9b10 (patch) | |
tree | 833bc29e7bd5438eb89f34119ae157efe6258b2c /indra/llcommon | |
parent | 0257214763203708e8e29d09346e777b95cdfce6 (diff) |
Result of svn merge -r119432:120464 svn+ssh://svn/svn/linden/branches/http_database/merge-03 into trunk. QAR-1462
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/llcommon/llapp.cpp | 32 | ||||
-rw-r--r-- | indra/llcommon/llapp.h | 45 | ||||
-rw-r--r-- | indra/llcommon/llerror.cpp | 7 | ||||
-rw-r--r-- | indra/llcommon/llliveappconfig.cpp | 32 | ||||
-rw-r--r-- | indra/llcommon/llliveappconfig.h | 34 | ||||
-rw-r--r-- | indra/llcommon/lllivefile.cpp | 35 | ||||
-rw-r--r-- | indra/llcommon/lllivefile.h | 50 | ||||
-rw-r--r-- | indra/llcommon/llstat.cpp | 11 | ||||
-rw-r--r-- | indra/llcommon/llstring.h | 46 | ||||
-rw-r--r-- | indra/llcommon/lluri.cpp | 5 | ||||
-rw-r--r-- | indra/llcommon/lluri.h | 17 |
12 files changed, 240 insertions, 76 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 3f14be6e18..d6a9e10707 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -32,7 +32,6 @@ set(llcommon_SOURCE_FILES llformat.cpp llframetimer.cpp llheartbeat.cpp - llindraconfigfile.cpp llliveappconfig.cpp lllivefile.cpp lllog.cpp @@ -118,7 +117,6 @@ set(llcommon_HEADER_FILES llheartbeat.h llhttpstatuscodes.h llindexedqueue.h - llindraconfigfile.h llkeythrottle.h lllinkedqueue.h llliveappconfig.h diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 199315f34e..968b92d1e7 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -38,7 +38,9 @@ #include "llerrorcontrol.h" #include "llerrorthread.h" #include "llframetimer.h" +#include "lllivefile.h" #include "llmemory.h" +#include "llstl.h" // for DeletePointer() #include "lltimer.h" // @@ -91,7 +93,6 @@ LLAppChildCallback LLApp::sDefaultChildCallback = NULL; LLApp::LLApp() : mThreadErrorp(NULL) { commonCtor(); - startErrorThread(); } void LLApp::commonCtor() @@ -106,9 +107,6 @@ void LLApp::commonCtor() sSigChildCount = new LLAtomicU32(0); #endif - // Setup error handling - setupErrorHandling(); - // initialize the options structure. We need to make this an array // because the structured data will not auto-allocate if we // reference an invalid location with the [] operator. @@ -141,6 +139,11 @@ LLApp::~LLApp() delete sSigChildCount; sSigChildCount = NULL; #endif + + // reclaim live file memory + std::for_each(mLiveFiles.begin(), mLiveFiles.end(), DeletePointer()); + mLiveFiles.clear(); + setStopped(); // HACK: wait for the error thread to clean itself ms_sleep(20); @@ -214,6 +217,15 @@ bool LLApp::parseCommandOptions(int argc, char** argv) return true; } + +void LLApp::manageLiveFile(LLLiveFile* livefile) +{ + if(!livefile) return; + livefile->checkAndReload(); + livefile->addToEventTimer(); + mLiveFiles.push_back(livefile); +} + bool LLApp::setOptionData(OptionPriority level, LLSD data) { if((level < 0) @@ -275,6 +287,7 @@ void LLApp::setupErrorHandling() #endif + startErrorThread(); } void LLApp::startErrorThread() @@ -283,10 +296,13 @@ void LLApp::startErrorThread() // Start the error handling thread, which is responsible for taking action // when the app goes into the APP_STATUS_ERROR state // - llinfos << "Starting error thread" << llendl; - mThreadErrorp = new LLErrorThread(); - mThreadErrorp->setUserData((void *) this); - mThreadErrorp->start(); + if(!mThreadErrorp) + { + llinfos << "Starting error thread" << llendl; + mThreadErrorp = new LLErrorThread(); + mThreadErrorp->setUserData((void *) this); + mThreadErrorp->start(); + } } void LLApp::setErrorHandler(LLAppErrorHandler handler) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index f8a593c33d..cc60ba0b80 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -40,8 +40,7 @@ // Forward declarations class LLErrorThread; -class LLApp; - +class LLLiveFile; typedef void (*LLAppErrorHandler)(); typedef void (*LLAppChildCallback)(int pid, bool exited, int status); @@ -128,6 +127,19 @@ public: bool parseCommandOptions(int argc, char** argv); /** + * @brief Keep track of live files automatically. + * + * *TODO: it currently uses the <code>addToEventTimer()</code> API + * instead of the runner. I should probalby use the runner. + * + * *NOTE: DO NOT add the livefile instance to any kind of check loop. + * + * @param livefile A valid instance of an LLLiveFile. This LLApp + * instance will delete the livefile instance. + */ + void manageLiveFile(LLLiveFile* livefile); + + /** * @brief Set the options at the specified priority. * * This function completely replaces the options at the priority @@ -194,11 +206,26 @@ public: #endif static int getPid(); - // - // Error handling methods - // + /** @name Error handling methods */ + //@{ + /** + * @brief Do our generic platform-specific error-handling setup -- + * signals on unix, structured exceptions on windows. + * + * DO call this method if your app will either spawn children or be + * spawned by a launcher. + * Call just after app object construction. + * (Otherwise your app will crash when getting signals, + * and will not core dump.) + * + * DO NOT call this method if your application has specialized + * error handling code. + */ + void setupErrorHandling(); + void setErrorHandler(LLAppErrorHandler handler); void setSyncErrorHandler(LLAppErrorHandler handler); + //@} #if !LL_WINDOWS // @@ -214,8 +241,9 @@ public: void setDefaultChildCallback(LLAppChildCallback callback); // Fork and do the proper signal handling/error handling mojo - // WARNING: You need to make sure your signal handling callback is correct after - // you fork, because not all threads are duplicated when you fork! + // *NOTE: You need to make sure your signal handling callback is + // correct after you fork, because not all threads are duplicated + // when you fork! pid_t fork(); #endif @@ -255,7 +283,6 @@ protected: private: void startErrorThread(); - void setupErrorHandling(); // Do platform-specific error-handling setup (signals, structured exceptions) static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. @@ -278,6 +305,8 @@ private: // The application options. LLSD mOptions; + // The live files for this application + std::vector<LLLiveFile*> mLiveFiles; //@} private: diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index e8c95d0a76..d671decccb 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -289,7 +289,7 @@ namespace public: static LogControlFile& fromDirectory(const std::string& dir); - virtual void loadFile(); + virtual bool loadFile(); private: LogControlFile(const std::string &filename) @@ -317,7 +317,7 @@ namespace // NB: This instance is never freed } - void LogControlFile::loadFile() + bool LogControlFile::loadFile() { LLSD configuration; @@ -333,12 +333,13 @@ namespace llwarns << filename() << " missing, ill-formed," " or simply undefined; not changing configuration" << llendl; - return; + return false; } } LLError::configure(configuration); llinfos << "logging reconfigured from " << filename() << llendl; + return true; } diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp index e1bfc11a03..75bdfee8b7 100644 --- a/indra/llcommon/llliveappconfig.cpp +++ b/indra/llcommon/llliveappconfig.cpp @@ -38,9 +38,12 @@ #include "llsd.h" #include "llsdserialize.h" -LLLiveAppConfig::LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period) -: LLLiveFile(filename, refresh_period), - mApp(app) +LLLiveAppConfig::LLLiveAppConfig( + const std::string& filename, + F32 refresh_period, + LLApp::OptionPriority priority) : + LLLiveFile(filename, refresh_period), + mPriority(priority) { } @@ -48,7 +51,7 @@ LLLiveAppConfig::~LLLiveAppConfig() { } // virtual -void LLLiveAppConfig::loadFile() +bool LLLiveAppConfig::loadFile() { llinfos << "LLLiveAppConfig::loadFile(): reading from " << filename() << llendl; @@ -59,12 +62,25 @@ void LLLiveAppConfig::loadFile() LLSDSerialize::fromXML(config, file); if(!config.isMap()) { - llinfos << "LLDataserverConfig::loadFile(): not an map!" + llwarns << "Live app config not an map in " << filename() << " Ignoring the data." << llendl; - return; + return false; } file.close(); } - mApp->setOptionData( - LLApp::PRIORITY_SPECIFIC_CONFIGURATION, config); + else + { + llinfos << "Live file " << filename() << " does not exit." << llendl; + } + // *NOTE: we do not handle the else case here because we would not + // have attempted to load the file unless LLLiveFile had + // determined there was a reason to load it. This only happens + // when either the file has been updated or it is either suddenly + // in existence or has passed out of existence. Therefore, we want + // to set the config to an empty config, and return that it + // changed. + + LLApp* app = LLApp::instance(); + if(app) app->setOptionData(mPriority, config); + return true; } diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h index 55d84a4778..a6ece6e8b3 100644 --- a/indra/llcommon/llliveappconfig.h +++ b/indra/llcommon/llliveappconfig.h @@ -33,25 +33,43 @@ #ifndef LLLIVEAPPCONFIG_H #define LLLIVEAPPCONFIG_H +#include "llapp.h" #include "lllivefile.h" -class LLApp; +/** + * @class LLLiveAppConfig + * @see LLLiveFile + * + * To use this, instantiate a LLLiveAppConfig object inside your main + * loop. The traditional name for it is live_config. Be sure to call + * <code>live_config.checkAndReload()</code> periodically. + */ class LLLiveAppConfig : public LLLiveFile { public: - // To use this, instantiate a LLLiveAppConfig object inside your main loop. - // The traditional name for it is live_config. - // Be sure to call live_config.checkAndReload() periodically. - LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period); - ~LLLiveAppConfig(); + /** + * @brief Constructor + * + * @param filename. The name of the file for periodically checking + * configuration. + * @param refresh_period How often the internal timer should + * bother checking the filesystem. + * @param The application priority level of that configuration file. + */ + LLLiveAppConfig( + const std::string& filename, + F32 refresh_period, + LLApp::OptionPriority priority); + + ~LLLiveAppConfig(); ///< Destructor protected: - /*virtual*/ void loadFile(); + /*virtual*/ bool loadFile(); private: - LLApp* mApp; + LLApp::OptionPriority mPriority; }; #endif diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index b6f458cb3e..effda6c49c 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -35,14 +35,17 @@ #include "llframetimer.h" #include "lltimer.h" +const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f; + + class LLLiveFile::Impl { public: - Impl(const std::string &filename, const F32 refresh_period); + Impl(const std::string& filename, const F32 refresh_period); ~Impl(); bool check(); - + void changed(); bool mForceCheck; F32 mRefreshPeriod; @@ -50,16 +53,19 @@ public: std::string mFilename; time_t mLastModTime; + time_t mLastStatTime; bool mLastExists; LLEventTimer* mEventTimer; }; -LLLiveFile::Impl::Impl(const std::string &filename, const F32 refresh_period) - : mForceCheck(true), +LLLiveFile::Impl::Impl(const std::string& filename, const F32 refresh_period) + : + mForceCheck(true), mRefreshPeriod(refresh_period), mFilename(filename), mLastModTime(0), + mLastStatTime(0), mLastExists(false), mEventTimer(NULL) { @@ -70,7 +76,7 @@ LLLiveFile::Impl::~Impl() delete mEventTimer; } -LLLiveFile::LLLiveFile(const std::string &filename, const F32 refresh_period) +LLLiveFile::LLLiveFile(const std::string& filename, const F32 refresh_period) : impl(* new Impl(filename, refresh_period)) { } @@ -121,17 +127,30 @@ bool LLLiveFile::Impl::check() // We want to read the file. Update status info for the file. mLastExists = true; - mLastModTime = stat_data.st_mtime; - + mLastStatTime = stat_data.st_mtime; return true; } +void LLLiveFile::Impl::changed() +{ + // we wanted to read this file, and we were successful. + mLastModTime = mLastStatTime; +} + bool LLLiveFile::checkAndReload() { bool changed = impl.check(); if (changed) { - loadFile(); + if(loadFile()) + { + impl.changed(); + this->changed(); + } + else + { + changed = false; + } } return changed; } diff --git a/indra/llcommon/lllivefile.h b/indra/llcommon/lllivefile.h index a3a9cf49ab..89b5d95e44 100644 --- a/indra/llcommon/lllivefile.h +++ b/indra/llcommon/lllivefile.h @@ -33,29 +33,65 @@ #ifndef LL_LLLIVEFILE_H #define LL_LLLIVEFILE_H -const F32 configFileRefreshRate = 5.0; // seconds +extern const F32 DEFAULT_CONFIG_FILE_REFRESH; class LLLiveFile { public: - LLLiveFile(const std::string &filename, const F32 refresh_period = 5.f); + LLLiveFile(const std::string& filename, const F32 refresh_period = 5.f); virtual ~LLLiveFile(); + /** + * @brief Check to see if this live file should reload. + * + * Call this before using anything that was read & cached + * from the file. + * + * This method calls the <code>loadFile()</code> method if + * any of: + * file has a new modify time since the last check + * file used to exist and now does not + * file used to not exist but now does + * @return Returns true if the file was reloaded. + */ bool checkAndReload(); - // Returns true if the file changed in any way - // Call this before using anything that was read & cached from the file + std::string filename() const; + /** + * @brief Add this live file to an automated recheck. + * + * Normally, just calling checkAndReload() is enough. In some + * cases though, you may need to let the live file periodically + * check itself. + */ void addToEventTimer(); - // Normally, just calling checkAndReload() is enough. In some cases - // though, you may need to let the live file periodically check itself. void setRefreshPeriod(F32 seconds); protected: - virtual void loadFile() = 0; // Implement this to load your file if it changed + /** + * @breif Implement this to load your file if it changed. + * + * This method is called automatically by <code>checkAndReload()</code>, + * so though you must implement this in derived classes, you do + * not need to call it manually. + * @return Returns true if the file was successfully loaded. + */ + virtual bool loadFile() = 0; + + /** + * @brief Implement this method if you want to get a change callback. + * + * This virtual function will be called automatically at the end + * of <code>checkAndReload()</code> if a new configuration was + * loaded. This does not track differences between the current and + * newly loaded file, so any successful load event will trigger a + * <code>changed()</code> callback. Default is to do nothing. + */ + virtual void changed() {} private: class Impl; diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index e411a1c798..291b019616 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -62,7 +62,7 @@ public: static std::string filename(); protected: - /* virtual */ void loadFile(); + /* virtual */ bool loadFile(); public: void init(LLPerfStats* statsp); @@ -94,12 +94,12 @@ LLStatsConfigFile& LLStatsConfigFile::instance() /* virtual */ // Load and parse the stats configuration file -void LLStatsConfigFile::loadFile() +bool LLStatsConfigFile::loadFile() { if (!mStatsp) { llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl; - return; + return false; } mChanged = true; @@ -113,7 +113,7 @@ void LLStatsConfigFile::loadFile() { llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl; mStatsp->setReportPerformanceDuration( 0.f ); - return; + return false; } } else @@ -123,7 +123,7 @@ void LLStatsConfigFile::loadFile() llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl; mStatsp->setReportPerformanceDuration( 0.f ); } - return; + return true; } } @@ -159,6 +159,7 @@ void LLStatsConfigFile::loadFile() { llinfos << "Performance stats recording turned off" << llendl; } + return true; } diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 99a9b9e269..6ba665b8d2 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -228,7 +228,25 @@ public: // True if this is the head of s. static BOOL isHead( const std::basic_string<T>& string, const T* s ); - + + /** + * @brief Returns true if string starts with substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool startsWith( + const std::basic_string<T>& string, + const std::basic_string<T>& substr); + + /** + * @brief Returns true if string ends in substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool endsWith( + const std::basic_string<T>& string, + const std::basic_string<T>& substr); + static void addCRLF(std::basic_string<T>& string); static void removeCRLF(std::basic_string<T>& string); @@ -335,7 +353,7 @@ public: * This function works on bytes rather than glyphs, so this will * incorrectly truncate non-single byte strings. * Use utf8str_truncate() for utf8 strings - * @return a copy of in string minus the trailing count characters. + * @return a copy of in string minus the trailing count bytes. */ inline std::string chop_tail_copy( const std::string& in, @@ -1065,6 +1083,30 @@ BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s } } +// static +template<class T> +bool LLStringUtilBase<T>::startsWith( + const std::basic_string<T>& string, + const std::basic_string<T>& substr) +{ + if(string.empty() || (substr.empty())) return false; + if(0 == string.find(substr)) return true; + return false; +} + +// static +template<class T> +bool LLStringUtilBase<T>::endsWith( + const std::basic_string<T>& string, + const std::basic_string<T>& substr) +{ + if(string.empty() || (substr.empty())) return false; + std::string::size_type idx = string.rfind(substr); + if(std::string::npos == idx) return false; + return (idx == (string.size() - substr.size())); +} + + template<class T> BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value) { diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 3dbc837875..f6e8f01f0e 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -162,11 +162,10 @@ namespace { return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@" } -// *TODO: Consider using curl. After http textures gets merged everywhere. -// static +//static std::string LLURI::escape(const std::string& str) { - static std::string default_allowed(unreserved() + ":@!$'()*+,=/?&#;"); + static std::string default_allowed = unreserved(); static bool initialized = false; if(!initialized) { diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index 156d80b97e..8e46e2e89e 100644 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h @@ -127,27 +127,16 @@ public: /** @name Escaping Utilities */ //@{ /** - * @brief Escape a raw url with a reasonable set of allowed characters. - * - * The default set was chosen to match HTTP urls and general - * guidelines for naming resources. Passing in a raw url does not - * produce well defined results because you really need to know - * which segments are path parts because path parts are supposed - * to be escaped individually. The default set chosen is: + * @brief Escape the string passed except for unreserved * * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz * 0123456789 * -._~ - * :@!$'()*+,=/?&#; * - * *NOTE: This API is basically broken because it does not - * allow you to specify significant path characters. For example, - * if the filename actually contained a /, then you cannot use - * this function to generate the serialized url for that - * resource. + * @see http://www.ietf.org/rfc/rfc1738.txt * * @param str The raw URI to escape. - * @return Returns the escaped uri or an empty string. + * @return Returns the rfc 1738 escaped uri or an empty string. */ static std::string escape(const std::string& str); |