Exemple #1
0
/*
 * Saves VMEM usage of all the sessions into log
 */
void
RedZoneHandler_LogVmemUsageOfAllSessions()
{
	if (!vmemTrackerInited)
	{
		return;
	}

	Assert(NULL != MySessionState);

	/*
	 * Grabbing a shared lock ensures that the data structure is not
	 * modified while we are reading. Shared lock is enough as we
	 * are only reading and not modifying the SessionState data structure
	 */
	LWLockAcquire(SessionStateLock, LW_SHARED);

	SessionState *curSessionState = AllSessionStateEntries->usedList;

	PG_TRY();
	{
		/* Write the header for the subsequent lines of memory usage information */
		write_stderr("session_state: session_id, is_runaway, qe_count, active_qe_count, dirty_qe_count, vmem_mb, runaway_vmem_mb, runaway_command_cnt\n");

		while (curSessionState != NULL)
		{
			Assert(INVALID_SESSION_ID != curSessionState->sessionId);

			write_stderr("session_state: %d, %d, %d, %d, %d, %d, %d, %d\n", curSessionState->sessionId,
					curSessionState->runawayStatus != RunawayStatus_NotRunaway, curSessionState->pinCount,
					curSessionState->activeProcessCount, curSessionState->cleanupCountdown, VmemTracker_ConvertVmemChunksToMB(curSessionState->sessionVmem),
					VmemTracker_ConvertVmemChunksToMB(curSessionState->sessionVmemRunaway), curSessionState->commandCountRunaway);

			curSessionState = curSessionState->next;
		}
	}
	PG_CATCH();
	{
		LWLockRelease(SessionStateLock);
		PG_RE_THROW();
	}
	PG_END_TRY();

	LWLockRelease(SessionStateLock);
}
/*
 * Starts a runaway cleanup by triggering an ERROR if the VMEM tracker is active
 * and a commit is not already in progress. Otherwise, it marks the process as clean
 */
void
RunawayCleaner_StartCleanup()
{
	/*
	 * Cleanup can be attempted from multiple places, such as before deactivating
	 * a process (if a pending runaway event) or periodically from CHECK_FOR_INTERRUPTS
	 * (indirectly via RedZoneHandler_DetectRunaway). We don't carry multiple cleanup
	 * for a single runaway event. Every time we *start* a cleanup process, we set the
	 * beginCleanupRunawayVersion to the runaway version for which we started cleaning
	 * up. Later on, if we reenter this method (e.g., another CHECK_FOR_INTERRUPTS()
	 * during cleanup), we can observe that the cleanup already started from this runaway
	 * event, and therefore we skip duplicate cleanup
	 */
	if (RunawayCleaner_ShouldStartRunawayCleanup())
	{
		Assert(beginCleanupRunawayVersion < *latestRunawayVersion);
		Assert(endCleanupRunawayVersion < *latestRunawayVersion);
		/* We don't want to cleanup multiple times for same runaway event */
		beginCleanupRunawayVersion = *latestRunawayVersion;

		if (CritSectionCount == 0 && InterruptHoldoffCount == 0 && vmemTrackerInited &&
			gp_command_count > 0 /* Cleaning up QEs that are not executing a valid command
			may cause the QD to get stuck [MPP-24950] */ &&
			/* Super user is terminated only when it's the primary runaway consumer (i.e., the top consumer) */
			(!superuser() || MySessionState->runawayStatus == RunawayStatus_PrimaryRunawaySession))
		{
#ifdef FAULT_INJECTOR
	FaultInjector_InjectFaultIfSet(
			RunawayCleanup,
			DDLNotSpecified,
			"",  // databaseName
			""); // tableName
#endif

			ereport(ERROR, (errmsg("Canceling query because of high VMEM usage. Used: %dMB, available %dMB, red zone: %dMB",
					VmemTracker_ConvertVmemChunksToMB(MySessionState->sessionVmem), VmemTracker_GetAvailableVmemMB(),
					RedZoneHandler_GetRedZoneLimitMB()), errprintstack(true)));
		}

		/*
		 * If we cannot error out because of a critical section or because we are a super user
		 * or for some other reason (such as the QE is not running any valid command, i.e.,
		 * gp_command_count is not positive) simply declare this process as clean
		 */
		RunawayCleaner_RunawayCleanupDoneForProcess(true /* ignoredCleanup */);
	}
}
Exemple #3
0
/*
 * Returns the red-zone cut-off in "MB" unit
 */
int32
RedZoneHandler_GetRedZoneLimitMB()
{
	return VmemTracker_ConvertVmemChunksToMB(redZoneChunks);
}