예제 #1
0
LLCurl::Multi::~Multi()
{
	llassert(isStopped());

	if (LLCurl::sMultiThreaded)
	{
		LLCurl::Easy::sMultiMutex->lock();
	}

	delete mSignal;
	mSignal = NULL;

	// Clean up active
	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
		iter != mEasyActiveList.end(); ++iter)
	{
		Easy* easy = *iter;
		check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
		delete easy;
	}
	mEasyActiveList.clear();
	mEasyActiveMap.clear();
	
	// Clean up freed
	for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer());	
	mEasyFreeList.clear();

	check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle));
	--gCurlMultiCount;

	if (LLCurl::sMultiThreaded)
	{
		LLCurl::Easy::sMultiMutex->unlock();
	}
}
예제 #2
0
파일: llcurl.cpp 프로젝트: HizWylder/GIS
void LLCurl::Multi::removeEasy(Easy* easy)
{
	{
		LLMutexLock lock(mMutexp) ;
		check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
	}
	easyFree(easy);
}
예제 #3
0
void LLCurl::Multi::cleanup(bool deleted)
{
	if(!mCurlMultiHandle)
	{
		return ; //nothing to clean.
	}
	llassert_always(deleted || !mValid) ;

	LLMutexLock lock(mDeletionMutexp);
	
	// Clean up active
	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
		iter != mEasyActiveList.end(); ++iter)
	{
		Easy* easy = *iter;
		check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));

		if(deleted)
		{
			easy->mResponder = NULL ; //avoid triggering mResponder.
		}
		delete easy;
	}
	mEasyActiveList.clear();
	mEasyActiveMap.clear();
	
	// Clean up freed
	for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer());	
	mEasyFreeList.clear();

	check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle));
	mCurlMultiHandle = NULL ;
	
	delete mMutexp ;
	mMutexp = NULL ;
	delete mEasyMutexp ;
	mEasyMutexp = NULL ;

	mQueued = 0 ;
	mState = STATE_COMPLETED;
	
	--gCurlMultiCount;

	return ;
}
예제 #4
0
bool LLCurl::Multi::addEasy(Easy* easy)
{
	CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle());
	check_curl_multi_code(mcode);
	//if (mcode != CURLM_OK)
	//{
	//	llwarns << "Curl Error: " << curl_multi_strerror(mcode) << llendl;
	//	return false;
	//}
	return true;
}
예제 #5
0
파일: llcurl.cpp 프로젝트: HizWylder/GIS
void LLCurl::Multi::cleanup()
{
	if(!mCurlMultiHandle)
	{
		return ; //nothing to clean.
	}

	// Clean up active
	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
		iter != mEasyActiveList.end(); ++iter)
	{
		Easy* easy = *iter;
		check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
		delete easy;
	}
	mEasyActiveList.clear();
	mEasyActiveMap.clear();
	
	// Clean up freed
	for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer());	
	mEasyFreeList.clear();

	check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle));
	mCurlMultiHandle = NULL ;

	delete mMutexp ;
	mMutexp = NULL ;
	delete mDeletionMutexp ;
	mDeletionMutexp = NULL ;
	delete mEasyMutexp ;
	mEasyMutexp = NULL ;
	
	mQueued = 0 ;
	mState = STATE_COMPLETED;
	
	--gCurlMultiCount;

	return ;
}
예제 #6
0
//return true if dead
bool LLCurl::Multi::doPerform()
{
	LLMutexLock lock(mDeletionMutexp) ;
	
	bool dead = mDead ;

	if(mDead)
	{
		setState(STATE_COMPLETED);
		mQueued = 0 ;
	}
	else if(getState() != STATE_COMPLETED)
	{		
		setState(STATE_PERFORMING);

		S32 q = 0;
		for (S32 call_count = 0;
				call_count < MULTI_PERFORM_CALL_REPEAT;
				call_count++)
		{
			LLMutexLock lock(mMutexp) ;

			//WARNING: curl_multi_perform will block for many hundreds of milliseconds
			// NEVER call this from the main thread, and NEVER allow the main thread to 
			// wait on a mutex held by this thread while curl_multi_perform is executing
			CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
			if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
			{
				check_curl_multi_code(code);
			
				break;
			}
		}

		mQueued = q;	
		setState(STATE_COMPLETED) ;
		mIdleTimer.reset() ;
	}
	else if(!mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it.
	{
		dead = true ;
	}
	else if(mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut - 1.f) //idle for too long, mark it invalid.
	{
		mValid = FALSE ;
	}

	return dead ;
}
예제 #7
0
void LLCurl::Multi::doPerform()
{
	S32 q = 0;
	if (mThreaded)
		mSignal->unlock();
	for (S32 call_count = 0;
			call_count < MULTI_PERFORM_CALL_REPEAT;
			call_count += 1)
	{
		CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
		if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
		{
			check_curl_multi_code(code);
			break;
		}
	
	}
	if (mThreaded)
		mSignal->lock();
	mQueued = q;
	mPerformState = PERFORM_STATE_COMPLETED;
}
예제 #8
0
// Caller has provided us with a ref count on op.
void HttpLibcurl::addOp(HttpOpRequest * op)
{
	llassert_always(op->mReqPolicy < mPolicyCount);
	llassert_always(mMultiHandles[op->mReqPolicy] != NULL);
	
	// Create standard handle
	if (! op->prepareRequest(mService))
	{
		// Couldn't issue request, fail with notification
		// *TODO:  Need failure path
		return;
	}

	// Make the request live
	CURLMcode code;
	code = curl_multi_add_handle(mMultiHandles[op->mReqPolicy], op->mCurlHandle);
	if (CURLM_OK != code)
	{
		// *TODO:  Better cleanup and recovery but not much we can do here.
		check_curl_multi_code(code);
		return;
	}
	op->mCurlActive = true;
	mActiveOps.insert(op);
	++mActiveHandles[op->mReqPolicy];
	
	if (op->mTracing > HTTP_TRACE_OFF)
	{
		HttpPolicy & policy(mService->getPolicy());
		
		LL_INFOS(LOG_CORE) << "TRACE, ToActiveQueue, Handle:  "
						   << static_cast<HttpHandle>(op)
						   << ", Actives:  " << mActiveOps.size()
						   << ", Readies:  " << policy.getReadyCount(op->mReqPolicy)
						   << LL_ENDL;
	}
}
예제 #9
0
파일: llcurl.cpp 프로젝트: HizWylder/GIS
void LLCurlFF::check_multi_code(CURLMcode code)
{
	check_curl_multi_code(code);
}
예제 #10
0
void HttpLibcurl::policyUpdated(int policy_class)
{
	if (policy_class < 0 || policy_class >= mPolicyCount || ! mMultiHandles)
	{
		return;
	}
	
	HttpPolicy & policy(mService->getPolicy());
	
	if (! mActiveHandles[policy_class])
	{
		// Clear to set options.  As of libcurl 7.37.0, if a pipelining
		// multi handle has active requests and you try to set the
		// multi handle to non-pipelining, the library gets very angry
		// and goes off the rails corrupting memory.  A clue that you're
		// about to crash is that you'll get a missing server response
		// error (curl code 9).  So, if options are to be set, we let
		// the multi handle run out of requests, then set options, and
		// re-enable request processing.
		//
		// All of this stall mechanism exists for this reason.  If
		// libcurl becomes more resilient later, it should be possible
		// to remove all of this.  The connection limit settings are fine,
		// it's just that pipelined-to-non-pipelined transition that
		// is fatal at the moment.
		
		HttpPolicyClass & options(policy.getClassOptions(policy_class));
		CURLM * multi_handle(mMultiHandles[policy_class]);
		CURLMcode code;

		// Enable policy if stalled
		policy.stallPolicy(policy_class, false);
		mDirtyPolicy[policy_class] = false;
		
		if (options.mPipelining > 1)
		{
			// We'll try to do pipelining on this multihandle
			code = curl_multi_setopt(multi_handle,
									 CURLMOPT_PIPELINING,
									 1L);
			check_curl_multi_code(code, CURLMOPT_PIPELINING);
			code = curl_multi_setopt(multi_handle,
									 CURLMOPT_MAX_PIPELINE_LENGTH,
									 long(options.mPipelining));
			check_curl_multi_code(code, CURLMOPT_MAX_PIPELINE_LENGTH);
			code = curl_multi_setopt(multi_handle,
									 CURLMOPT_MAX_HOST_CONNECTIONS,
									 long(options.mPerHostConnectionLimit));
			check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS);
			code = curl_multi_setopt(multi_handle,
									 CURLMOPT_MAX_TOTAL_CONNECTIONS,
									 long(options.mConnectionLimit));
			check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS);
		}
		else
		{
			code = curl_multi_setopt(multi_handle,
									 CURLMOPT_PIPELINING,
									 0L);
			check_curl_multi_code(code, CURLMOPT_PIPELINING);
			code = curl_multi_setopt(multi_handle,
									 CURLMOPT_MAX_HOST_CONNECTIONS,
									 0L);
			check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS);
			code = curl_multi_setopt(multi_handle,
									 CURLMOPT_MAX_TOTAL_CONNECTIONS,
									 long(options.mConnectionLimit));
			check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS);
		}
	}
	else if (! mDirtyPolicy[policy_class])
	{
		// Mark policy dirty and request a stall in the policy.
		// When policy goes idle, we'll re-invoke this method
		// and perform the change.  Don't allow this thread to
		// sleep while we're waiting for quiescence, we'll just
		// stop processing.
		mDirtyPolicy[policy_class] = true;
		policy.stallPolicy(policy_class, true);
	}
}
예제 #11
0
void LLCurl::Multi::removeEasy(Easy* easy)
{
	check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
	easyFree(easy);
}