diff options
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); | 
