diff options
| -rw-r--r-- | indra/llcorehttp/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llcorehttp/_httplibcurl.cpp | 51 | ||||
| -rw-r--r-- | indra/llcorehttp/_httplibcurl.h | 7 | ||||
| -rw-r--r-- | indra/llcorehttp/_httppolicy.cpp | 69 | ||||
| -rw-r--r-- | indra/llcorehttp/_httppolicy.h | 22 | ||||
| -rw-r--r-- | indra/llcorehttp/_httppolicyclass.cpp | 125 | ||||
| -rw-r--r-- | indra/llcorehttp/_httppolicyclass.h | 59 | ||||
| -rw-r--r-- | indra/llcorehttp/_httpservice.cpp | 21 | ||||
| -rw-r--r-- | indra/llcorehttp/_httpservice.h | 28 | ||||
| -rw-r--r-- | indra/llcorehttp/httprequest.cpp | 29 | 
10 files changed, 351 insertions, 62 deletions
| diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 4c00cc04e9..f3df9bb94f 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -37,6 +37,7 @@ set(llcorehttp_SOURCE_FILES      _httpopsetget.cpp      _httpopsetpriority.cpp      _httppolicy.cpp +    _httppolicyclass.cpp      _httppolicyglobal.cpp      _httpreplyqueue.cpp      _httprequestqueue.cpp @@ -63,6 +64,7 @@ set(llcorehttp_HEADER_FILES      _httpopsetget.h      _httpopsetpriority.h      _httppolicy.h +    _httppolicyclass.h      _httppolicyglobal.h      _httpreadyqueue.h      _httpreplyqueue.h diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index 65eb642056..45e16d420e 100644 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -39,17 +39,10 @@ namespace LLCore  HttpLibcurl::HttpLibcurl(HttpService * service) -	: mService(service) -{ -	// *FIXME:  Use active policy class count later -	for (int policy_class(0); policy_class < LL_ARRAY_SIZE(mMultiHandles); ++policy_class) -	{ -		mMultiHandles[policy_class] = 0; -	} - -	// Create multi handle for default class -	mMultiHandles[0] = curl_multi_init(); -} +	: mService(service), +	  mPolicyCount(0), +	  mMultiHandles(NULL) +{}  HttpLibcurl::~HttpLibcurl() @@ -64,17 +57,23 @@ HttpLibcurl::~HttpLibcurl()  		mActiveOps.erase(item);  	} -	for (int policy_class(0); policy_class < LL_ARRAY_SIZE(mMultiHandles); ++policy_class) +	if (mMultiHandles)  	{ -		if (mMultiHandles[policy_class]) +		for (int policy_class(0); policy_class < mPolicyCount; ++policy_class)  		{ -			// *FIXME:  Do some multi cleanup here first +			if (mMultiHandles[policy_class]) +			{ +				// *FIXME:  Do some multi cleanup here first -			curl_multi_cleanup(mMultiHandles[policy_class]); -			mMultiHandles[policy_class] = 0; +				curl_multi_cleanup(mMultiHandles[policy_class]); +				mMultiHandles[policy_class] = 0; +			}  		} -	} +		delete [] mMultiHandles; +		mMultiHandles = NULL; +	} +	  	mService = NULL;  } @@ -87,12 +86,26 @@ void HttpLibcurl::term()  {} +void HttpLibcurl::setPolicyCount(int policy_count) +{ +	llassert_always(policy_count <= POLICY_CLASS_LIMIT); +	llassert_always(! mMultiHandles);					// One-time call only +	 +	mPolicyCount = policy_count; +	mMultiHandles = new CURLM * [mPolicyCount]; +	for (int policy_class(0); policy_class < mPolicyCount; ++policy_class) +	{ +		mMultiHandles[policy_class] = curl_multi_init(); +	} +} + +  HttpService::ELoopSpeed HttpLibcurl::processTransport()  {  	HttpService::ELoopSpeed	ret(HttpService::REQUEST_SLEEP);  	// Give libcurl some cycles to do I/O & callbacks -	for (int policy_class(0); policy_class < LL_ARRAY_SIZE(mMultiHandles); ++policy_class) +	for (int policy_class(0); policy_class < mPolicyCount; ++policy_class)  	{  		if (! mMultiHandles[policy_class])  			continue; @@ -147,7 +160,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()  void HttpLibcurl::addOp(HttpOpRequest * op)  { -	llassert_always(op->mReqPolicy < POLICY_CLASS_LIMIT); +	llassert_always(op->mReqPolicy < mPolicyCount);  	llassert_always(mMultiHandles[op->mReqPolicy] != NULL);  	// Create standard handle diff --git a/indra/llcorehttp/_httplibcurl.h b/indra/llcorehttp/_httplibcurl.h index 0d0c4cad6d..5e1dd1bfbf 100644 --- a/indra/llcorehttp/_httplibcurl.h +++ b/indra/llcorehttp/_httplibcurl.h @@ -78,6 +78,10 @@ public:  	/// additional references will be added.)  	void addOp(HttpOpRequest * op); +	/// One-time call to set the number of policy classes to be +	/// serviced and to create the resources for each. +	void setPolicyCount(int policy_count); +	  	int getActiveCount() const;  	int getActiveCountInClass(int policy_class) const; @@ -92,7 +96,8 @@ protected:  protected:  	HttpService *		mService;				// Simple reference, not owner  	active_set_t		mActiveOps; -	CURLM *				mMultiHandles[POLICY_CLASS_LIMIT]; +	int					mPolicyCount; +	CURLM **			mMultiHandles;  }; // end class HttpLibcurl  }  // end namespace LLCore diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp index 4be9f1d45f..1dae20add6 100644 --- a/indra/llcorehttp/_httppolicy.cpp +++ b/indra/llcorehttp/_httppolicy.cpp @@ -31,6 +31,7 @@  #include "_httpoprequest.h"  #include "_httpservice.h"  #include "_httplibcurl.h" +#include "_httppolicyclass.h"  #include "lltimer.h" @@ -38,14 +39,44 @@  namespace LLCore  { + +struct HttpPolicy::State +{ +public: +	State() +		: mConnMax(DEFAULT_CONNECTIONS), +		  mConnAt(DEFAULT_CONNECTIONS), +		  mConnMin(2), +		  mNextSample(0), +		  mErrorCount(0), +		  mErrorFactor(0) +		{} +	 +	HttpReadyQueue		mReadyQueue; +	HttpRetryQueue		mRetryQueue; + +	HttpPolicyClass		mOptions; + +	long				mConnMax; +	long				mConnAt; +	long				mConnMin; + +	HttpTime			mNextSample; +	unsigned long		mErrorCount; +	unsigned long		mErrorFactor; +}; + +  HttpPolicy::HttpPolicy(HttpService * service) -	: mService(service) +	: mActiveClasses(0), +	  mState(NULL), +	  mService(service)  {}  HttpPolicy::~HttpPolicy()  { -	for (int policy_class(0); policy_class < LL_ARRAY_SIZE(mState); ++policy_class) +	for (int policy_class(0); policy_class < mActiveClasses; ++policy_class)  	{  		HttpRetryQueue & retryq(mState[policy_class].mRetryQueue);  		while (! retryq.empty()) @@ -67,13 +98,27 @@ HttpPolicy::~HttpPolicy()  			readyq.pop();  		}  	} +	delete [] mState; +	mState = NULL;  	mService = NULL;  } -void HttpPolicy::setPolicies(const HttpPolicyGlobal & global) +void HttpPolicy::setPolicies(const HttpPolicyGlobal & global, +							 const std::vector<HttpPolicyClass> & classes)  { +	llassert_always(! mState); +  	mGlobalOptions = global; +	mActiveClasses = classes.size(); +	mState = new State [mActiveClasses]; +	for (int i(0); i < mActiveClasses; ++i) +	{ +		mState[i].mOptions = classes[i]; +		mState[i].mConnMax = classes[i].mConnectionLimit; +		mState[i].mConnAt = mState[i].mConnMax; +		mState[i].mConnMin = 2; +	}  } @@ -123,13 +168,14 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue()  	HttpService::ELoopSpeed result(HttpService::REQUEST_SLEEP);  	HttpLibcurl & transport(mService->getTransport()); -	for (int policy_class(0); policy_class < LL_ARRAY_SIZE(mState); ++policy_class) +	for (int policy_class(0); policy_class < mActiveClasses; ++policy_class)  	{ +		State & state(mState[policy_class]);  		int active(transport.getActiveCountInClass(policy_class)); -		int needed(DEFAULT_CONNECTIONS - active);				// *FIXME:  move to policy class +		int needed(state.mConnAt - active);		// Expect negatives here -		HttpRetryQueue & retryq(mState[policy_class].mRetryQueue); -		HttpReadyQueue & readyq(mState[policy_class].mReadyQueue); +		HttpRetryQueue & retryq(state.mRetryQueue); +		HttpReadyQueue & readyq(state.mReadyQueue);  		if (needed > 0)  		{ @@ -174,9 +220,10 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue()  bool HttpPolicy::changePriority(HttpHandle handle, HttpRequest::priority_t priority)  { -	for (int policy_class(0); policy_class < LL_ARRAY_SIZE(mState); ++policy_class) +	for (int policy_class(0); policy_class < mActiveClasses; ++policy_class)  	{ -		HttpReadyQueue::container_type & c(mState[policy_class].mReadyQueue.get_container()); +		State & state(mState[policy_class]); +		HttpReadyQueue::container_type & c(state.mReadyQueue.get_container());  		// Scan ready queue for requests that match policy  		for (HttpReadyQueue::container_type::iterator iter(c.begin()); c.end() != iter;) @@ -188,7 +235,7 @@ bool HttpPolicy::changePriority(HttpHandle handle, HttpRequest::priority_t prior  				HttpOpRequest * op(*cur);  				c.erase(cur);									// All iterators are now invalidated  				op->mReqPriority = priority; -				mState[policy_class].mReadyQueue.push(op);		// Re-insert using adapter class +				state.mReadyQueue.push(op);						// Re-insert using adapter class  				return true;  			}  		} @@ -242,7 +289,7 @@ bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)  int HttpPolicy::getReadyCount(HttpRequest::policy_t policy_class)  { -	if (policy_class < POLICY_CLASS_LIMIT)				// *FIXME:  use actual active class count +	if (policy_class < mActiveClasses)  	{  		return (mState[policy_class].mReadyQueue.size()  				+ mState[policy_class].mRetryQueue.size()); diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h index 05de9303b5..c93279bc83 100644 --- a/indra/llcorehttp/_httppolicy.h +++ b/indra/llcorehttp/_httppolicy.h @@ -33,6 +33,7 @@  #include "_httpreadyqueue.h"  #include "_httpretryqueue.h"  #include "_httppolicyglobal.h" +#include "_httppolicyclass.h"  #include "_httpinternal.h" @@ -92,26 +93,25 @@ public:  	// Get pointer to global policy options.  Caller is expected  	// to do context checks like no setting once running. -	HttpPolicyGlobal &	getGlobalOptions() +	HttpPolicyGlobal & getGlobalOptions()  		{  			return mGlobalOptions;  		} -	void setPolicies(const HttpPolicyGlobal & global); +	void setPolicies(const HttpPolicyGlobal & global, +					 const std::vector<HttpPolicyClass> & classes); +  	// Get ready counts for a particular class  	int getReadyCount(HttpRequest::policy_t policy_class);  protected: -	struct State -	{ -		HttpReadyQueue		mReadyQueue; -		HttpRetryQueue		mRetryQueue; -	}; - -	State				mState[POLICY_CLASS_LIMIT]; -	HttpService *		mService;				// Naked pointer, not refcounted, not owner -	HttpPolicyGlobal	mGlobalOptions; +	struct State; + +	int									mActiveClasses; +	State *								mState; +	HttpService *						mService;				// Naked pointer, not refcounted, not owner +	HttpPolicyGlobal					mGlobalOptions;  };  // end class HttpPolicy diff --git a/indra/llcorehttp/_httppolicyclass.cpp b/indra/llcorehttp/_httppolicyclass.cpp new file mode 100644 index 0000000000..8007468d3c --- /dev/null +++ b/indra/llcorehttp/_httppolicyclass.cpp @@ -0,0 +1,125 @@ +/** + * @file _httppolicyclass.cpp + * @brief Definitions for internal class defining class policy option. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "_httppolicyclass.h" + +#include "_httpinternal.h" + + +namespace LLCore +{ + + +HttpPolicyClass::HttpPolicyClass() +	: mSetMask(0UL), +	  mConnectionLimit(DEFAULT_CONNECTIONS), +	  mPerHostConnectionLimit(DEFAULT_CONNECTIONS), +	  mPipelining(0) +{} + + +HttpPolicyClass::~HttpPolicyClass() +{} + + +HttpPolicyClass & HttpPolicyClass::operator=(const HttpPolicyClass & other) +{ +	if (this != &other) +	{ +		mSetMask = other.mSetMask; +		mConnectionLimit = other.mConnectionLimit; +		mPerHostConnectionLimit = other.mPerHostConnectionLimit; +		mPipelining = other.mPipelining; +	} +	return *this; +} + + +HttpPolicyClass::HttpPolicyClass(const HttpPolicyClass & other) +	: mSetMask(other.mSetMask), +	  mConnectionLimit(other.mConnectionLimit), +	  mPerHostConnectionLimit(other.mPerHostConnectionLimit), +	  mPipelining(other.mPipelining) +{} + + +HttpStatus HttpPolicyClass::set(HttpRequest::EClassPolicy opt, long value) +{ +	switch (opt) +	{ +	case HttpRequest::CP_CONNECTION_LIMIT: +		mConnectionLimit = llclamp(value, long(LIMIT_CONNECTIONS_MIN), long(LIMIT_CONNECTIONS_MAX)); +		break; + +	case HttpRequest::CP_PER_HOST_CONNECTION_LIMIT: +		mPerHostConnectionLimit = llclamp(value, long(LIMIT_CONNECTIONS_MIN), mConnectionLimit); +		break; + +	case HttpRequest::CP_ENABLE_PIPELINING: +		mPipelining = llclamp(value, 0L, 1L); +		break; + +	default: +		return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG); +	} + +	mSetMask |= 1UL << int(opt); +	return HttpStatus(); +} + + +HttpStatus HttpPolicyClass::get(HttpRequest::EClassPolicy opt, long * value) +{ +	static const HttpStatus not_set(HttpStatus::LLCORE, HE_OPT_NOT_SET); +	long * src(NULL); +	 +	switch (opt) +	{ +	case HttpRequest::CP_CONNECTION_LIMIT: +		src = &mConnectionLimit; +		break; + +	case HttpRequest::CP_PER_HOST_CONNECTION_LIMIT: +		src = &mPerHostConnectionLimit; +		break; + +	case HttpRequest::CP_ENABLE_PIPELINING: +		src = &mPipelining; +		break; + +	default: +		return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG); +	} + +	if (! (mSetMask & (1UL << int(opt)))) +		return not_set; + +	*value = *src; +	return HttpStatus(); +} + + +}  // end namespace LLCore diff --git a/indra/llcorehttp/_httppolicyclass.h b/indra/llcorehttp/_httppolicyclass.h new file mode 100644 index 0000000000..d175413cbd --- /dev/null +++ b/indra/llcorehttp/_httppolicyclass.h @@ -0,0 +1,59 @@ +/** + * @file _httppolicyclass.h + * @brief Declarations for internal class defining policy class options. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef	_LLCORE_HTTP_POLICY_CLASS_H_ +#define	_LLCORE_HTTP_POLICY_CLASS_H_ + + +#include "httprequest.h" + + +namespace LLCore +{ + +class HttpPolicyClass +{ +public: +	HttpPolicyClass(); +	~HttpPolicyClass(); + +	HttpPolicyClass & operator=(const HttpPolicyClass &); +	HttpPolicyClass(const HttpPolicyClass &);			// Not defined + +public: +	HttpStatus set(HttpRequest::EClassPolicy opt, long value); +	HttpStatus get(HttpRequest::EClassPolicy opt, long * value); +	 +public: +	unsigned long				mSetMask; +	long						mConnectionLimit; +	long						mPerHostConnectionLimit; +	long						mPipelining; +};  // end class HttpPolicyClass + +}  // end namespace LLCore + +#endif // _LLCORE_HTTP_POLICY_CLASS_H_ diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index faafd9a6c7..9c5c7bf9b4 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -53,6 +53,12 @@ HttpService::HttpService()  	  mPolicy(NULL),  	  mTransport(NULL)  { +	HttpPolicyClass pol_class; +	pol_class.set(HttpRequest::CP_CONNECTION_LIMIT, DEFAULT_CONNECTIONS); +	pol_class.set(HttpRequest::CP_PER_HOST_CONNECTION_LIMIT, DEFAULT_CONNECTIONS); +	pol_class.set(HttpRequest::CP_ENABLE_PIPELINING, 0L); + +	mPolicyClasses.push_back(pol_class);  } @@ -114,6 +120,18 @@ void HttpService::term()  } +HttpRequest::policy_t HttpService::createPolicyClass() +{ +	const HttpRequest::policy_t policy_class(mPolicyClasses.size()); +	if (policy_class >= POLICY_CLASS_LIMIT) +	{ +		return 0; +	} +	mPolicyClasses.push_back(HttpPolicyClass()); +	return policy_class; +} + +  bool HttpService::isStopped()  {  	// What is really wanted here is something like: @@ -142,7 +160,8 @@ void HttpService::startThread()  	}  	// Push current policy definitions -	mPolicy->setPolicies(mPolicyGlobal); +	mPolicy->setPolicies(mPolicyGlobal, mPolicyClasses); +	mTransport->setPolicyCount(mPolicyClasses.size());  	mThread = new LLCoreInt::HttpThread(boost::bind(&HttpService::threadRun, this, _1));  	mThread->addRef();		// Need an explicit reference, implicit one is used internally diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h index 3f953ec1a7..43044d97c0 100644 --- a/indra/llcorehttp/_httpservice.h +++ b/indra/llcorehttp/_httpservice.h @@ -28,9 +28,12 @@  #define	_LLCORE_HTTP_SERVICE_H_ +#include <vector> +  #include "httpcommon.h"  #include "httprequest.h"  #include "_httppolicyglobal.h" +#include "_httppolicyclass.h"  namespace LLCoreInt @@ -163,6 +166,14 @@ public:  		{  			return mPolicyGlobal;  		} + +	HttpRequest::policy_t createPolicyClass(); +	 +	HttpPolicyClass & getClassOptions(HttpRequest::policy_t policy_class) +		{ +			llassert(policy_class >= 0 && policy_class < mPolicyClasses.size()); +			return mPolicyClasses[policy_class]; +		}  protected:  	void threadRun(LLCoreInt::HttpThread * thread); @@ -170,20 +181,21 @@ protected:  	ELoopSpeed processRequestQueue(ELoopSpeed loop);  protected: -	static HttpService *		sInstance; +	static HttpService *				sInstance;  	// === shared data === -	static volatile EState		sState; -	HttpRequestQueue *			mRequestQueue; -	volatile bool				mExitRequested; +	static volatile EState				sState; +	HttpRequestQueue *					mRequestQueue; +	volatile bool						mExitRequested;  	// === calling-thread-only data === -	LLCoreInt::HttpThread *		mThread; -	HttpPolicyGlobal			mPolicyGlobal; +	LLCoreInt::HttpThread *				mThread; +	HttpPolicyGlobal					mPolicyGlobal; +	std::vector<HttpPolicyClass>		mPolicyClasses;  	// === working-thread-only data === -	HttpPolicy *				mPolicy;		// Simple pointer, has ownership -	HttpLibcurl *				mTransport;		// Simple pointer, has ownership +	HttpPolicy *						mPolicy;		// Simple pointer, has ownership +	HttpLibcurl *						mTransport;		// Simple pointer, has ownership  };  // end class HttpService  }  // end namespace LLCore diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp index 6d13a213f5..a525d8f9ea 100644 --- a/indra/llcorehttp/httprequest.cpp +++ b/indra/llcorehttp/httprequest.cpp @@ -92,26 +92,31 @@ HttpRequest::~HttpRequest()  HttpStatus HttpRequest::setPolicyGlobalOption(EGlobalPolicy opt, long value)  { -	// *FIXME:  Fail if thread is running. - +	if (HttpService::RUNNING == HttpService::instanceOf()->getState()) +	{ +		return HttpStatus(HttpStatus::LLCORE, HE_OPT_NOT_DYNAMIC); +	}  	return HttpService::instanceOf()->getGlobalOptions().set(opt, value);  }  HttpStatus HttpRequest::setPolicyGlobalOption(EGlobalPolicy opt, const std::string & value)  { -	// *FIXME:  Fail if thread is running. - +	if (HttpService::RUNNING == HttpService::instanceOf()->getState()) +	{ +		return HttpStatus(HttpStatus::LLCORE, HE_OPT_NOT_DYNAMIC); +	}  	return HttpService::instanceOf()->getGlobalOptions().set(opt, value);  }  HttpRequest::policy_t HttpRequest::createPolicyClass()  { -	// *FIXME:  Implement classes -	policy_t policy_id = 1; -	 -	return policy_id; +	if (HttpService::RUNNING == HttpService::instanceOf()->getState()) +	{ +		return 0; +	} +	return HttpService::instanceOf()->createPolicyClass();  } @@ -119,9 +124,11 @@ HttpStatus HttpRequest::setPolicyClassOption(policy_t policy_id,  											 EClassPolicy opt,  											 long value)  { -	HttpStatus status; - -	return status; +	if (HttpService::RUNNING == HttpService::instanceOf()->getState()) +	{ +		return HttpStatus(HttpStatus::LLCORE, HE_OPT_NOT_DYNAMIC); +	} +	return HttpService::instanceOf()->getClassOptions(policy_id).set(opt, value);  } | 
