示例#1
0
void CArchonProcess::CollectGarbage (void)

//	CollectGarbage
//
//	Collects garbage

	{
	CString sTask;

	try 
		{
		int i;

		//	Compute how long it's been since we last collected garbage

		DWORD dwStart = sysGetTickCount();
		DWORD dwTimeSinceLastCollection = dwStart - m_dwLastGarbageCollect;

		//	If it has been less than a certain time, then only collect garbage if
		//	all engines are idle.

		if (dwTimeSinceLastCollection < MAX_GARBAGE_COLLECT_WAIT)
			{
			//	Check to see if engines are idle

			bool bEnginesIdle = true;
			for (i = 0; i < m_Engines.GetCount(); i++)
				if (!m_Engines[i].pEngine->IsIdle())
					{
					bEnginesIdle = false;
					break;
					}

			//	If the engines are busy, then check to see if we have enough
			//	memory to wait some more.

			if (!bEnginesIdle)
				{
				CProcess CurrentProc;
				CurrentProc.CreateCurrentProcess();
				CProcess::SMemoryInfo MemoryInfo;
				if (!CurrentProc.GetMemoryInfo(&MemoryInfo))
					{
					LogBlackBox(ERR_CANT_GET_MEMORY_INFO);
					return;
					}

				//	If we have enough memory, then wait to collect garbage

				if (MemoryInfo.dwCurrentAlloc < MAX_GARBAGE_COLLECT_MEMORY)
					return;

				//	Warning that we're running out of memory

				LogBlackBox(ERR_MEMORY_WARNING);
				}
			}

		//	Collect

	#ifdef DEBUG_GARBAGE_COLLECTION
		printf("[%s] Collecting garbage.\n", (LPSTR)m_sName);
	#endif

		m_dwLastGarbageCollect = dwStart;

		m_RunEvent.Reset();
		m_PauseEvent.Set();

		//	Keep track of how long each engine takes to pause (for diagnostic
		//	purposes).

		TArray<DWORD> PauseTime;
		PauseTime.InsertEmpty(m_Engines.GetCount());

		//	Some engines still need an explicit call (because they don't have
		//	their own main thread).

		for (i = 0; i < m_Engines.GetCount(); i++)
			m_Engines[i].pEngine->SignalPause();

		//	Wait for the engines to stop

		for (i = 0; i < m_Engines.GetCount(); i++)
			{
			DWORD dwStart = sysGetTickCount();

			m_Engines[i].pEngine->WaitForPause();

			PauseTime[i] = sysGetTicksElapsed(dwStart);
			}

		//	Wait for our threads to stop

		m_EventThread.WaitForPause();
		m_ImportThread.WaitForPause();

		//	Now we ask all engines to mark their data in use

		for (i = 0; i < m_Engines.GetCount(); i++)
			{
			sTask = strPattern("Marking data: %s engine.", m_Engines[i].pEngine->GetName());
			m_Engines[i].pEngine->Mark();
			}

		//	Now we mark our own structures

		sTask = STR_MARKING_MNEMOSYNTH;
		m_MnemosynthDb.Mark();

		sTask = STR_MARKING_EVENT_THREAD;
		m_EventThread.Mark();

		sTask = STR_MARKING_IMPORT_THREAD;
		m_ImportThread.Mark();

		//	Now we sweep all unused

		sTask = STR_MARK_AND_SWEEP;

		DWORD dwSweepStart = sysGetTickCount();
		CDatum::MarkAndSweep();
		DWORD dwSweepTime = sysGetTickCount() - dwSweepStart;

		sTask = NULL_STR;

		//	Now we start all engines up again

		m_PauseEvent.Reset();
		m_RunEvent.Set();

		//	If garbage collection took too long, then we need to log it.

		DWORD dwTime = sysGetTickCount() - dwStart;
		if (dwTime >= 500)
			{
			//	Log each engine that took too long

			for (i = 0; i < m_Engines.GetCount(); i++)
				if (PauseTime[i] >= 500)
					Log(MSG_LOG_INFO, strPattern(STR_ENGINE_PAUSE_TIME, m_Engines[i].pEngine->GetName(), PauseTime[i] / 1000, (PauseTime[i] % 1000) / 10));

			//	Log overall time

			Log(MSG_LOG_INFO, strPattern(STR_GARBAGE_COLLECTION, 
					dwTime / 1000, (dwTime % 1000) / 10,
					dwSweepTime / 1000, (dwSweepTime % 1000) / 10));
			}
		}
	catch (...)
		{
		if (sTask.IsEmpty())
			CriticalError(ERR_CRASH_IN_COLLECT_GARBAGE);
		else
			CriticalError(strPattern("CRASH: %s", sTask));
		}
	}
示例#2
0
void CEsperEngine::ProcessMessage (const SArchonMessage &Msg, CHexeSecurityCtx *pSecurityCtx)

//	ProcessMessage
//
//	Processes messages

	{
	try
		{
		DWORD dwStartTime = sysGetTickCount();

		//	Arc.fileMsg

		if (strEquals(Msg.sMsg, MSG_ARC_FILE_MSG))
			{
			SArchonMessage NewMsg;
			CInterprocessMessageQueue::DecodeFileMsg(Msg, &NewMsg);
			SendMessage(NewMsg);
			}

		//	Arc.getStatus

		else if (strEquals(Msg.sMsg, MSG_ARC_GET_STATUS))
			MsgGetStatus(Msg, pSecurityCtx);

		//	Arc.housekeeping

		else if (strEquals(Msg.sMsg, MSG_ARC_HOUSEKEEPING))
			MsgHousekeeping(Msg, pSecurityCtx);

		//	Arc.sandboxMsg

		else if (strEquals(Msg.sMsg, MSG_ARC_SANDBOX_MSG))
			{
			SArchonMessage SandboxMsg;
			CHexeSecurityCtx SecurityCtx;

			SandboxMsg.sMsg = Msg.dPayload.GetElement(0);
			SandboxMsg.sReplyAddr = Msg.sReplyAddr;
			SandboxMsg.dwTicket = Msg.dwTicket;
			SandboxMsg.dPayload = Msg.dPayload.GetElement(1);

			SecurityCtx.Init(Msg.dPayload.GetElement(2));

			return ProcessMessage(SandboxMsg, &SecurityCtx);
			}

		//	Esper messages

		else if (strEquals(Msg.sMsg, MSG_ESPER_HTTP))
			MsgEsperHTTP(Msg);

		else if (strEquals(Msg.sMsg, MSG_ESPER_GET_USAGE_HISTORY))
			MsgEsperGetUsageHistory(Msg, pSecurityCtx);

		//	Else, unhandled message

		else
			{
			CString sError = strPattern(ERR_INVALID_MSG, Msg.sMsg);
			SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, sError, Msg);
			m_pProcess->Log(MSG_LOG_ERROR, sError);
			}

		DWORD dwTime = sysGetTicksElapsed(dwStartTime);
		if (dwTime >= 1000)
			Log(MSG_LOG_INFO, strPattern(ERR_MSG_TIMING, Msg.sMsg, dwTime));
		}
	catch (...)
		{
		m_pProcess->Log(MSG_LOG_ERROR, strPattern(ERR_CRASH_MSG, Msg.sMsg));
		SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, ERR_INTERNAL_SERVER_ERROR, Msg);
		}
	}