コード例 #1
0
	FINLINE void FTKAPI setThreadAppId(
		FLMUINT		uiAppId)
	{
		f_mutexLock( m_hMutex);
		m_uiAppId = uiAppId;
		f_mutexUnlock( m_hMutex);
	}
コード例 #2
0
/****************************************************************************
Desc:
****************************************************************************/
void flmDbgLogWrite(
	F_Database *	pDatabase,
	FLMUINT			uiBlkAddress,
	FLMUINT			uiWriteAddress,
	FLMUINT64		ui64TransId,
	char *			pszEvent)
{
	char		pszTmpBuf[ 256];
	
	if( !g_bDbgLogEnabled)
		return;

	if( !uiWriteAddress)
	{
		f_sprintf( (char *)pszTmpBuf, "d%X b=%X t%I64u %s",
			(unsigned)((FLMUINT)pDatabase),
			(unsigned)uiBlkAddress, ui64TransId, pszEvent);
	}
	else
	{
		f_sprintf( (char *)pszTmpBuf, "d%X b=%X a=%X t%I64u %s",
				(unsigned)((FLMUINT)pDatabase),
    			(unsigned)uiBlkAddress, (unsigned)uiWriteAddress,
				ui64TransId, pszEvent);
	}
	f_mutexLock( g_hDbgLogMutex);
	_flmDbgOutputMsg( pszTmpBuf);
	f_mutexUnlock( g_hDbgLogMutex);
}
コード例 #3
0
/****************************************************************************
Desc:
****************************************************************************/
void flmDbgLogExit( void)
{
	if( g_bDbgLogEnabled)
	{
		// Output "Log End" message
		f_mutexLock( g_hDbgLogMutex);
		_flmDbgOutputMsg( "--- LOG END ---");
		f_mutexUnlock( g_hDbgLogMutex);
		
		// Flush the log
		flmDbgLogFlush();
	}

	// Free all resources

	if( g_hDbgLogMutex != F_MUTEX_NULL)
	{
		f_mutexDestroy( &g_hDbgLogMutex);
	}

	if( g_pszLogBuf)
	{
		f_free( &g_pszLogBuf);
	}

	if( g_pLogFile)
	{
		g_pLogFile->Truncate( g_uiLogFileOffset + g_uiLogBufOffset);
		g_pLogFile->Close();
		g_pLogFile->Release();
		g_pLogFile = NULL;
	}

	g_bDbgLogEnabled = FALSE;
}
コード例 #4
0
/********************************************************************
Desc: Output a label in the LABEL_COLUMN
*********************************************************************/
void gigaOutputLabel(
	FLMUINT			uiRow,
	const char *	pszLabel,
	FLMBOOL			bMutexLocked)
{
	char			szLabel [DATA_COLUMN - LABEL_COLUMN];
	char *		pszTmp;
	FLMUINT		uiNumDots = sizeof( szLabel) - 1;

	f_memset( szLabel, '.', uiNumDots);
	szLabel [uiNumDots] = 0;

	pszTmp = &szLabel [0];
	uiNumDots -= 2;
	
	while( *pszLabel && uiNumDots)
	{
		*pszTmp++ = (FLMBYTE)(*pszLabel++);
		uiNumDots--;
	}
	
	if( !bMutexLocked && gv_hWindowMutex != F_MUTEX_NULL)
	{
		f_mutexLock( gv_hWindowMutex);
	}
	
	FTXWinPrintStrXY( gv_pWindow, szLabel, LABEL_COLUMN, uiRow);
	
	if( !bMutexLocked && gv_hWindowMutex != F_MUTEX_NULL)
	{
		f_mutexUnlock( gv_hWindowMutex);
	}

}
コード例 #5
0
/****************************************************************************
Desc:	Event callback
*****************************************************************************/
void  IX_Event::catchEvent(
	eEventType	eEvent,
	IF_Db *		pDb,
	FLMUINT,		// uiThreadId,
	FLMUINT64,	// ui64TransID,
	FLMUINT		uiIndexOrCollection,
	FLMUINT64	ui64NodeId,
	RCODE			// rc
	)
{
	XFLM_INDEX_STATUS	ixStatus;
	FLMUINT				uiGMT;

	if (eEvent == XFLM_EVENT_INDEXING_PROGRESS && !ui64NodeId && pDb)
	{
		if (RC_OK( ((F_Db *)pDb)->indexStatus( uiIndexOrCollection, &ixStatus)))
		{
			f_timeGetSeconds( &uiGMT );

			f_mutexLock( m_pDispInfo->hScreenMutex);
			FTXWinPrintf( m_pDispInfo->pLogWin,
				"Index %u came on-line.  Elapsed time = %u second(s)\n",
				uiIndexOrCollection, uiGMT - (FLMUINT)ixStatus.ui32StartTime);
			f_mutexUnlock( m_pDispInfo->hScreenMutex);
		}
	}
}
コード例 #6
0
/****************************************************************************
Desc:
****************************************************************************/
void F_IOBuffer::notifyComplete(
	RCODE					completionRc)
{
	f_assert( m_bPending);
	
	m_bPending = FALSE;
	m_bCompleted = TRUE;
	m_completionRc = completionRc;
	m_uiEndTime = FLM_GET_TIMER();
	m_uiElapsedTime = FLM_TIMER_UNITS_TO_MILLI( 
		FLM_ELAPSED_TIME( m_uiEndTime, m_uiStartTime));

	if( m_fnCompletion)
	{
		m_fnCompletion( this, m_pvData);
		m_fnCompletion = NULL;
		m_pvData = NULL;
	}

	if( m_pBufferMgr)
	{
		f_assert( m_eList == MGR_LIST_PENDING);
		f_mutexLock( m_pBufferMgr->m_hMutex);
		
		m_pBufferMgr->unlinkFromList( this);
		m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstUsed, this);
		
		if( RC_OK( m_pBufferMgr->m_completionRc) && RC_BAD( completionRc))
		{
			m_pBufferMgr->m_completionRc = completionRc;
		}
		
		f_mutexUnlock( m_pBufferMgr->m_hMutex);		
	}
}
コード例 #7
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE FTKAPI F_IOBufferMgr::waitForAllPendingIO( void)
{
	RCODE				rc = NE_FLM_OK;
	RCODE				tmpRc;
	F_IOBuffer *	pBuf;
	FLMBOOL			bMutexLocked = FALSE;

	f_mutexLock( m_hMutex);
	bMutexLocked = TRUE;
	
	while( (pBuf = m_pFirstPending) != NULL)
	{
		pBuf->AddRef();
		
		f_mutexUnlock( m_hMutex);
		bMutexLocked = FALSE;
		
		if( RC_BAD( tmpRc = pBuf->waitToComplete()))
		{
			if( RC_OK( m_completionRc))
			{
				f_mutexLock( m_hMutex);
				bMutexLocked = TRUE;
				m_completionRc = tmpRc;
			}
		}
		
		if( !bMutexLocked)
		{
			f_mutexLock( m_hMutex);
			bMutexLocked = TRUE;
		}

		pBuf->Release( TRUE);
		pBuf = NULL;
	}
	
	rc = m_completionRc;
	m_completionRc = NE_FLM_OK;
	
	if( bMutexLocked)
	{
		f_mutexUnlock( m_hMutex);
	}
	
	return( rc);
}
コード例 #8
0
/****************************************************************************
Desc:
****************************************************************************/
void flmDbgLogMsg(
	char *		pszMsg)
{
	if (!g_bDbgLogEnabled)
		return;
	f_mutexLock( g_hDbgLogMutex);
	_flmDbgOutputMsg( pszMsg);
	f_mutexUnlock( g_hDbgLogMutex);
}
コード例 #9
0
/********************************************************************
Desc:	Show help for the gigaloader.
*********************************************************************/
void gigaShowHelp( void)
{
#ifdef FLM_NLM
	if (!gv_bSynchronized)
	{
		SynchronizeStart();
		gv_bSynchronized = TRUE;
	}
#endif
	f_mutexLock( gv_hWindowMutex);
	FTXWinClear( gv_pWindow);
	FTXWinPrintStr( gv_pWindow, "\n");
	FTXWinPrintStr( gv_pWindow, 
"Parameters: [Number To Create] [Options]\n\n");
	FTXWinPrintStr( gv_pWindow, 
"\nNumber To Create\n");
	FTXWinPrintStr( gv_pWindow, 
"   Number of object to create (default = 100,000)\n");
	FTXWinPrintStr( gv_pWindow, 
"\nOptions (may be specified anywhere on command line):\n");
	FTXWinPrintStr( gv_pWindow, 
"   -b         = Run in batch mode.\n");
	FTXWinPrintStr( gv_pWindow, 
"   -c<n>      = Cache (bytes) to use, 0=Use default mode\n");
	FTXWinPrintStr( gv_pWindow, 
"   -p<n>      = Block cache percentage (0-100) to use (default 50)\n");
	FTXWinPrintStr( gv_pWindow, 
"   -i<n>      = Checkpoint interval (seconds) to use.\n");
#ifdef FLM_NLM
	FTXWinPrintStr( gv_pWindow, 
"   -n<DbName> = Database name (default = sys:\\_netware\\gigatest.db).\n");
#else
	FTXWinPrintStr( gv_pWindow, 
"   -n<DbName> = Database name (default = gigatest.db).\n");
#endif
	FTXWinPrintStr( gv_pWindow, 
"   -dr<Dir>   = Directory where rfl files are located (default=same as db)\n");
	FTXWinPrintStr( gv_pWindow, 
"   -dd<Dir>   = Directory where data files are located (default=same as db)\n");
	FTXWinPrintStr( gv_pWindow, 
"   -t<n>      = Transaction Size (objects per transaction, default=100).\n");
#ifdef FLM_NLM
	FTXWinPrintStr( gv_pWindow, 
"   -w         = Wait to end to synchronize\n");
#endif
	FTXWinPrintStr( gv_pWindow, 
"   -md<n>     = Set maximum dirty cache (bytes), 0=Use default mode\n");
	FTXWinPrintStr( gv_pWindow, 
"   -ld<n>     = Set low dirty cache (bytes), default=0\n");
	FTXWinPrintStr( gv_pWindow, 
"   -?         = A '?' anywhere in the command line will cause this help\n");
	FTXWinPrintStr( gv_pWindow, 
"                screen to be displayed, with or without the leading '-'.\n");
	f_mutexUnlock( gv_hWindowMutex);
	gigaOutputErrMsg( "");
}
コード例 #10
0
ファイル: flmimon.cpp プロジェクト: ajumi2/libflaim
/******************************************************************
Desc:	Implements the addChar function of the DynamicBuffer class
*******************************************************************/
RCODE F_DynamicBuffer::addChar(
	char			ucCharacter)
{
	RCODE			rc = FERR_OK;

	if (!m_bSetup)
	{
		flmAssert( 0);
		rc = RC_SET( FERR_FAILURE);
		goto Exit;

	}

	f_mutexLock( m_hMutex);

	// Is there room for just one more character plus a terminator?
	if ((m_uiBuffSize - m_uiUsedChars) > 1)
	{
		m_pucBuffer[ m_uiUsedChars++] = ucCharacter;
		m_pucBuffer[ m_uiUsedChars] = 0;
	}
	else
	{
		// Allocate a new buffer or increase the size of the existing one.
		if( !m_uiBuffSize)
		{
			if( RC_BAD( rc = f_alloc( 50, &m_pucBuffer)))
			{
				goto Exit;
			}
			m_uiBuffSize = 50;
		}
		else
		{
			if( RC_BAD( rc = f_realloc( m_uiBuffSize + 50,  &m_pucBuffer)))
			{
				goto Exit;
			}
			m_uiBuffSize += 50;
		}


		m_pucBuffer[ m_uiUsedChars++] = ucCharacter;
		m_pucBuffer[ m_uiUsedChars] = 0;
	}

Exit:

	if ( m_bSetup)
	{
		f_mutexUnlock( m_hMutex);
	}

	return( rc);
}
コード例 #11
0
/********************************************************************
Desc: Checks to see if the user pressed ESCAPE to exit the loader.
		Also updates the total loaded counter on the screen.
*********************************************************************/
FLMUINT gigaSeeIfQuit( void)
{
	FLMUINT	uiChar = 0;;

	f_mutexLock( gv_hWindowMutex);
	gigaOutputUINT( TOTAL_LOADED_ROW, gv_uiTotalLoaded, TRUE);
	if (RC_OK( FTXWinTestKB( gv_pWindow)))
	{
		FTXWinInputChar( gv_pWindow, &uiChar);
		if (uiChar == FKB_ESCAPE)
		{
			uiChar = gigaGetInput(
							"ESCAPE pressed, quit? (ESC,Q,Y=Quit, other=continue): ",
							NULL, TRUE);
			switch (uiChar)
			{
				case 'Q':
				case 'q':
				case 'y':
				case 'Y':
					uiChar = FKB_ESCAPE;
					break;
				case FKB_ESCAPE:
					break;
				default:
					uiChar = 0;
					break;
			}
		}
		else if( uiChar == 'i' || uiChar == 'I')
		{
			HFDB			hDb;

			f_threadDestroy( &gv_pIxManagerThrd);
			if (RC_OK( FlmDbOpen( gv_szDibName, gv_szDataDir,
										gv_szRflDir, 0, NULL, &hDb)))
			{
				f_threadCreate( &gv_pIxManagerThrd,
					flstIndexManagerThread, "index_manager",
					F_DEFAULT_THREAD_GROUP, 0, (void *)hDb);
			}
		}
	}

	if (gv_bShutdown)
	{
		uiChar = FKB_ESCAPE;
	}
	
	f_mutexUnlock( gv_hWindowMutex);
	return( uiChar);
}
コード例 #12
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE FLMAPI f_rwlockAcquire(
	F_RWLOCK				hReadWriteLock,
	F_SEM					hSem,
	FLMBOOL				bWriter)
{
	RCODE					rc = NE_FLM_OK;
	F_RWLOCK_IMP *		pReadWriteLock = (F_RWLOCK_IMP *)hReadWriteLock;
	FLMBOOL				bMutexLocked = FALSE;
	
	f_mutexLock( pReadWriteLock->hMutex);
	bMutexLocked = TRUE;
	
	if( bWriter)
	{
		if( pReadWriteLock->iRefCnt != 0)
		{
			rc = f_notifyWait( pReadWriteLock->hMutex, hSem, (void *)((FLMINT)bWriter),
				&pReadWriteLock->pNotifyList); 
		}
		
		if( RC_OK( rc))
		{
			f_assert( !pReadWriteLock->iRefCnt);
			pReadWriteLock->iRefCnt = -1;
			pReadWriteLock->uiWriteThread = f_threadId();
		}
	}
	else
	{	 
		if( pReadWriteLock->iRefCnt < 0 || pReadWriteLock->pNotifyList)
		{
			rc = f_notifyWait( pReadWriteLock->hMutex, hSem, (void *)((FLMINT)bWriter), 
				&pReadWriteLock->pNotifyList); 
		}
		
		if( RC_OK( rc))
		{
			pReadWriteLock->iRefCnt++;
		}
	}
	
	f_assert( RC_BAD( rc) || pReadWriteLock->iRefCnt);
	
	if( bMutexLocked)
	{
		f_mutexUnlock( pReadWriteLock->hMutex);
	}
	
	return( rc);
}
コード例 #13
0
ファイル: flog.cpp プロジェクト: Tyrion-Lannister-274AL/flaim
/****************************************************************************
Desc:	Ends a logging message
****************************************************************************/
void flmEndLogMessage(
	IF_LogMessageClient **		ppLogMessage)
{
	if( *ppLogMessage)
	{
		f_mutexLock( gv_XFlmSysData.hLoggerMutex);
		flmAssert( gv_XFlmSysData.uiPendingLogMessages);
		
		(*ppLogMessage)->endMessage();
		(*ppLogMessage)->Release();
		*ppLogMessage = NULL;
		
		gv_XFlmSysData.uiPendingLogMessages--;
		f_mutexUnlock( gv_XFlmSysData.hLoggerMutex);
	}
}
コード例 #14
0
/****************************************************************************
Desc:
****************************************************************************/
void FTKAPI F_IOBuffer::clearPending( void)
{
	f_assert( m_bPending);
	
	if( m_pBufferMgr)
	{
		f_assert( m_eList == MGR_LIST_PENDING);
		
		f_mutexLock( m_pBufferMgr->m_hMutex);
		m_pBufferMgr->unlinkFromList( this);
		m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstUsed, this);
		f_mutexUnlock( m_pBufferMgr->m_hMutex);
	}

	m_bPending = FALSE;
	m_uiStartTime = 0;
}
コード例 #15
0
/********************************************************************
Desc: Output a string in the DATA_COLUMN
*********************************************************************/
void gigaOutputStr(
	FLMUINT			uiRow,
	const char *	pszStr,
	FLMBOOL			bMutexLocked)
{
	if( !bMutexLocked && gv_hWindowMutex != F_MUTEX_NULL)
	{
		f_mutexLock( gv_hWindowMutex);
	}
	
	FTXWinPrintStrXY( gv_pWindow, pszStr, DATA_COLUMN, uiRow);
	
	if( !bMutexLocked && gv_hWindowMutex != F_MUTEX_NULL)
	{
		f_mutexUnlock( gv_hWindowMutex);
	}
}
コード例 #16
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE FLMAPI f_rwlockPromote(
	F_RWLOCK				hReadWriteLock,
	F_SEM					hSem)
{
	RCODE					rc = NE_FLM_OK;
	F_RWLOCK_IMP *		pReadWriteLock = (F_RWLOCK_IMP *)hReadWriteLock;
	FLMBOOL				bMutexLocked = FALSE;
	
	f_mutexLock( pReadWriteLock->hMutex);
	bMutexLocked = TRUE;
	
	if( pReadWriteLock->iRefCnt <= 0)
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP);
		goto Exit;
	}
	
	pReadWriteLock->iRefCnt--;
		
	if( pReadWriteLock->iRefCnt != 0)
	{
		rc = f_notifyWait( pReadWriteLock->hMutex, hSem, (void *)TRUE, 
			&pReadWriteLock->pNotifyList); 
	}
	
	if( RC_OK( rc))
	{
		f_assert( !pReadWriteLock->iRefCnt);
		pReadWriteLock->iRefCnt = -1;
		pReadWriteLock->uiWriteThread = f_threadId();
	}

Exit:

	f_assert( RC_BAD( rc) || pReadWriteLock->iRefCnt);
	
	if( bMutexLocked)
	{
		f_mutexUnlock( pReadWriteLock->hMutex);
	}
	
	return( rc);
}
コード例 #17
0
/****************************************************************************
Desc:
****************************************************************************/
void flmDbgLogUpdate(
	F_Database *	pDatabase,
	FLMUINT64		ui64TransId,
	FLMUINT			uiCollection,
	FLMUINT64		ui64NodeId,
	RCODE				rc,
	char *			pszEvent)
{
	char		pszTmpBuf[ 256];
	char		szErr [12];
	
	if (!g_bDbgLogEnabled)
	{
		return;
	}
	if (RC_BAD( rc))
	{
		f_sprintf( szErr, " RC=%04X", (unsigned)rc);
	}
	else
	{
		szErr [0] = 0;
	}

	if (uiCollection)
	{
		f_sprintf( (char *)pszTmpBuf, "d%X t%I64u c%u n%I64u %s%s",
			(unsigned)((FLMUINT)pDatabase),
			ui64TransId, (unsigned)uiCollection, 
			ui64NodeId, pszEvent, szErr);
	}
	else
	{
		f_sprintf( (char *)pszTmpBuf, "d%X t%I64u %s%s",
			(unsigned)((FLMUINT)pDatabase),
			ui64TransId, pszEvent,
			szErr);
	}

	f_mutexLock( g_hDbgLogMutex);
	_flmDbgOutputMsg( pszTmpBuf);
	f_mutexUnlock( g_hDbgLogMutex);
}
コード例 #18
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE FLMAPI f_rwlockRelease(
	F_RWLOCK				hReadWriteLock)
{
	RCODE					rc = NE_FLM_OK;
	F_RWLOCK_IMP *		pReadWriteLock = (F_RWLOCK_IMP *)hReadWriteLock;
	FLMBOOL				bMutexLocked = FALSE;
	
	f_mutexLock( pReadWriteLock->hMutex);
	bMutexLocked = TRUE;
	
	if( pReadWriteLock->iRefCnt > 0)
	{
		pReadWriteLock->iRefCnt--;
	}
	else if( pReadWriteLock->iRefCnt == -1)
	{
		f_assert( pReadWriteLock->uiWriteThread == f_threadId());
		pReadWriteLock->iRefCnt = 0;
	}
	else
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP);
		goto Exit;
	}
	
	if( !pReadWriteLock->iRefCnt && pReadWriteLock->pNotifyList)
	{
		f_rwlockNotify( pReadWriteLock);
	}
	
Exit:
	
	f_assert( RC_BAD( rc) || pReadWriteLock->iRefCnt >= 0);
	
	if( bMutexLocked)
	{
		f_mutexUnlock( pReadWriteLock->hMutex);
	}

	return( rc);
}
コード例 #19
0
ファイル: flog.cpp プロジェクト: Tyrion-Lannister-274AL/flaim
/****************************************************************************
Desc:	Returns an IF_LogMessageClient object if logging is enabled for the
		specified message type
****************************************************************************/
IF_LogMessageClient * flmBeginLogMessage(
	eLogMessageType	eMsgType)
{
	IF_LogMessageClient *		pNewMsg = NULL;

	f_mutexLock( gv_XFlmSysData.hLoggerMutex);
	
	if( !gv_XFlmSysData.pLogger)
	{
		goto Exit;
	}
		
	if( (pNewMsg = gv_XFlmSysData.pLogger->beginMessage( eMsgType)) != NULL)
	{
		gv_XFlmSysData.uiPendingLogMessages++;
	}
	
Exit:

	f_mutexUnlock( gv_XFlmSysData.hLoggerMutex);
	return( pNewMsg);
}
コード例 #20
0
/********************************************************************
Desc:
*********************************************************************/
void gigaUpdateLoadTimes( void)
{
	FLMUINT		uiElapsedTime;
	FLMUINT		uiCurrTime;
	FLMUINT		uiSecs;
	FLMUINT		uiAddsPerSec;
	char			szElapsedTime [20];

	uiCurrTime = FLM_GET_TIMER();
	uiElapsedTime = FLM_ELAPSED_TIME( uiCurrTime, gv_ui10SecStartTime);

	// Calculate and display the average for the last 10 seconds.

	uiSecs = FLM_TIMER_UNITS_TO_SECS( uiElapsedTime);
	uiAddsPerSec = (gv_uiTotalLoaded - gv_ui10SecTotal) / uiSecs;

	f_mutexLock( gv_hWindowMutex);
	gigaOutputUINT( ADDS_PER_SEC_CURRENT, uiAddsPerSec, TRUE);

	gv_ui10SecTotal = gv_uiTotalLoaded;
	gv_ui10SecStartTime = uiCurrTime;

	// Calculate and display the overall average

	uiElapsedTime = FLM_ELAPSED_TIME( uiCurrTime, gv_uiStartTime);
	uiSecs = FLM_TIMER_UNITS_TO_SECS( uiElapsedTime);
	uiAddsPerSec = gv_uiTotalLoaded / uiSecs;

	gigaOutputUINT( ADDS_PER_SEC_OVERALL, uiAddsPerSec, TRUE);

	f_sprintf( szElapsedTime, "%u:%02u:%02u",
		(unsigned)uiSecs / 3600,
		(unsigned)(uiSecs % 3600) / 60,
		(unsigned)uiSecs % 60);

	gigaOutputStr( ELAPSED_TIME_ROW, szElapsedTime, TRUE);

	f_mutexUnlock( gv_hWindowMutex);
}
コード例 #21
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE FLMAPI f_rwlockTryAcquire(
	F_RWLOCK				hReadWriteLock,
	FLMBOOL				bWriter)
{
	RCODE					rc = NE_FLM_OK;
	F_RWLOCK_IMP *		pReadWriteLock = (F_RWLOCK_IMP *)hReadWriteLock;
	
	f_mutexLock( pReadWriteLock->hMutex);
	
	if( bWriter)
	{
		if( pReadWriteLock->iRefCnt != 0)
		{
			rc = RC_SET( NE_FLM_WAIT_TIMEOUT);
		}
		else
		{
			pReadWriteLock->iRefCnt = -1;
			pReadWriteLock->uiWriteThread = f_threadId();
		}
	}
	else
	{
		if( pReadWriteLock->iRefCnt < 0 || pReadWriteLock->pNotifyList)
		{
			rc = RC_SET( NE_FLM_WAIT_TIMEOUT);
		}
		else
		{
			pReadWriteLock->iRefCnt++;
		}
	}
	
	f_assert( RC_BAD( rc) || pReadWriteLock->iRefCnt);
	f_mutexUnlock( pReadWriteLock->hMutex);
	
	return( rc);
}
コード例 #22
0
/****************************************************************************
Desc:
****************************************************************************/
void FTKAPI F_IOBuffer::setPending( void)
{
	f_assert( !m_bPending);
	
	if( m_pBufferMgr)
	{
		f_assert( m_eList == MGR_LIST_USED);
		
		f_mutexLock( m_pBufferMgr->m_hMutex);
		m_pBufferMgr->unlinkFromList( this);
		m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstPending, this);
		f_mutexUnlock( m_pBufferMgr->m_hMutex);
	}

#ifndef FLM_UNIX
	f_assert( !m_pAsyncClient || 
				 f_semGetSignalCount( ((F_FileAsyncClient *)m_pAsyncClient)->m_hSem) == 0);
#endif

	m_bPending = TRUE;
	m_uiStartTime = FLM_GET_TIMER();
	m_uiEndTime = 0;
}
コード例 #23
0
/****************************************************************************
Desc: Make sure a database is NOT open.  If it is, return an error.
****************************************************************************/
RCODE F_DbSystem::checkDatabaseClosed(
	const char *	pszDbName,
	const char *	pszDataDir)
{
	RCODE				rc = NE_XFLM_OK;
	F_Database *	pDatabase;

	f_mutexLock( gv_XFlmSysData.hShareMutex);
	rc = findDatabase( pszDbName, pszDataDir, &pDatabase);
	f_mutexUnlock( gv_XFlmSysData.hShareMutex);
	if (RC_BAD( rc))
	{
		goto Exit;
	}
	if (pDatabase)
	{
		rc = RC_SET( NE_XFLM_DATABASE_OPEN);
		goto Exit;
	}

Exit:

	return( rc);
}
コード例 #24
0
/****************************************************************************
Desc: This routine will open a database, returning a pointer to an IF_Db
		object that can be used to access it.
****************************************************************************/
RCODE F_DbSystem::openDatabase(
	F_Database *			pDatabase,
	const char *			pszDbPath,
	const char *			pszDataDir,
	const char *			pszRflDir,
	const char *			pszPassword,
	FLMUINT					uiOpenFlags,
	FLMBOOL					bInternalOpen,
	IF_RestoreClient *	pRestoreObj,
	IF_RestoreStatus *	pRestoreStatus,
	IF_FileHdl *			pLockFileHdl,
	IF_Db **					ppDb)
{
	RCODE						rc = NE_XFLM_OK;
	FLMBOOL					bNewDatabase = FALSE;
	FLMBOOL					bMutexLocked = FALSE;
	F_Db *					pDb = NULL;
	FLMBOOL					bNeedToOpen = FALSE;

	// Allocate and initialize an F_Db object.

	if (RC_BAD( rc = allocDb( &pDb, bInternalOpen)))
	{
		goto Exit;
	}

	f_mutexLock( gv_XFlmSysData.hShareMutex);
	bMutexLocked = TRUE;

	// Look up the file using findDatabase to see if we already
	// have the file open.

	if (!pDatabase)
	{
		bNeedToOpen = TRUE;

		// May unlock and re-lock the global mutex.

		if (RC_BAD( rc = findDatabase( pszDbPath, pszDataDir, &pDatabase)))
		{
			goto Exit;
		}
	}

	if (pDatabase)
	{
		if( RC_BAD( rc = pDatabase->checkState( __FILE__, __LINE__)))
		{
			goto Exit;
		}
	}

	if (!pDatabase)
	{
		if (RC_BAD( rc = allocDatabase( pszDbPath, pszDataDir, FALSE, &pDatabase)))
		{
			goto Exit;
		}
		flmAssert( !pLockFileHdl);
		bNewDatabase = TRUE;
	}
	else if( pLockFileHdl)
	{
		flmAssert( pDatabase);
		flmAssert( !pDatabase->m_uiOpenIFDbCount);
		flmAssert( pDatabase->m_uiFlags & DBF_BEING_OPENED);

		pDatabase->m_pLockFileHdl = pLockFileHdl;

		// Set to NULL to prevent lock file from being released below

		pLockFileHdl = NULL;

		bNewDatabase = TRUE;
		bNeedToOpen = TRUE;
	}
	else
	{
		FLMBOOL	bWaited = FALSE;
		flmAssert( !pLockFileHdl);

		if (RC_BAD( rc = pDatabase->verifyOkToUse( &bWaited)))
		{
			goto Exit;
		}

		if (bWaited)
		{
			bNewDatabase = FALSE;
			bNeedToOpen = FALSE;
		}
	}

	// Link the F_Db object to the F_Database object.

	rc = pDb->linkToDatabase( pDatabase);
	f_mutexUnlock( gv_XFlmSysData.hShareMutex);
	bMutexLocked = FALSE;
	if (RC_BAD(rc))
	{
		goto Exit;
	}

	(void)flmStatGetDb( &pDb->m_Stats, pDatabase,
							0, &pDb->m_pDbStats, NULL, NULL);

	if (bNeedToOpen)
	{
		if (RC_BAD( rc = pDatabase->physOpen( 
			pDb, pszDbPath, pszRflDir, pszPassword, uiOpenFlags,
			bNewDatabase, pRestoreObj, pRestoreStatus)))
		{
			goto Exit;
		}
	}

	// Start a checkpoint thread

	if( bNewDatabase && !(uiOpenFlags & XFLM_DONT_REDO_LOG))
	{
		flmAssert( !pDatabase->m_pCPThrd);
		flmAssert( !pDatabase->m_pMaintThrd);

		if( RC_BAD( rc = pDatabase->startCPThread()))
		{
			goto Exit;
		}

		if( !(uiOpenFlags & XFLM_DONT_RESUME_THREADS))
		{
			if( RC_BAD( rc = pDb->startBackgroundIndexing()))
			{
				goto Exit;
			}

			if( RC_BAD( rc = pDatabase->startMaintThread()))
			{
				goto Exit;
			}
		}
	}

Exit:

	if (bMutexLocked)
	{
		f_mutexUnlock( gv_XFlmSysData.hShareMutex);
	}

	if (pLockFileHdl)
	{
		pLockFileHdl->Release();
	}

	if (pDb)
	{
		// completeOpenOrCreate will delete pDb if RC_BAD( rc)

		pDb->completeOpenOrCreate( rc, bNewDatabase);

		if (RC_BAD( rc))
		{
			pDb = NULL;
		}
	}
	*ppDb = (IF_Db *)pDb;
	return( rc);
}
コード例 #25
0
/****************************************************************************
Desc: This routine links a request into a notification list and
		then waits to be notified that the event has occurred.  The mutex
		is assumed to protect the notify list.
****************************************************************************/
RCODE FLMAPI f_notifyWait(
	F_MUTEX						hMutex,
	F_SEM							hSem,
	void *						pvData,
	F_NOTIFY_LIST_ITEM **	ppNotifyList)
{
	RCODE							rc = NE_FLM_OK;
	RCODE							tmpRc;
	F_NOTIFY_LIST_ITEM		stackNotify;
	F_NOTIFY_LIST_ITEM *		pNotify = &stackNotify;
	
	f_assertMutexLocked( hMutex);
	f_assert( pNotify != *ppNotifyList);

	f_memset( &stackNotify, 0, sizeof( F_NOTIFY_LIST_ITEM));
	
	pNotify->uiThreadId = f_threadId();
	pNotify->hSem = F_SEM_NULL;
	
	if( hSem == F_SEM_NULL)
	{
		if( RC_BAD( rc = f_semCreate( &pNotify->hSem)))
		{
			goto Exit;
		}
	}
	else
	{
		pNotify->hSem = hSem;
	}
	
	pNotify->pRc = &rc;
	pNotify->pvData = pvData;
	
	pNotify->pNext = *ppNotifyList;
	*ppNotifyList = pNotify;

	// Unlock the mutex and wait on the semaphore

	f_mutexUnlock( hMutex);

	if( RC_BAD( tmpRc = f_semWait( pNotify->hSem, F_WAITFOREVER)))
	{
		rc = tmpRc;
	}

	// Free the semaphore
	
	if( hSem != pNotify->hSem)
	{
		f_semDestroy( &pNotify->hSem);
	}

	// Relock the mutex

	f_mutexLock( hMutex);

Exit:

	return( rc);
}
コード例 #26
0
/****************************************************************************
Desc:
****************************************************************************/
void flmDbgLogFlush( void)
{
	f_mutexLock( g_hDbgLogMutex);
	_flmDbgLogFlush();
	f_mutexUnlock( g_hDbgLogMutex);
}
コード例 #27
0
/****************************************************************************
Desc:		Thread that will build an index in the background.
			Caller will create a pDb to use.  This pDb must be
			freed at the conclusion of the routine.
****************************************************************************/
FSTATIC RCODE FLMAPI flmBackgroundIndexBuildThrd(
	IF_Thread *			pThread)
{
	RCODE					rc = FERR_OK;
	IXD *					pIxd;
	F_BKGND_IX * 		pBackgroundIx = (F_BKGND_IX *)pThread->getParm1();
	FLMBOOL				bStartedTrans;
	FLMBOOL				bDbInitialized;
	FLMUINT				uiContainerNum;
	FLMUINT				uiFirstDrn;
	FLMUINT				uiIndexNum;
	FDB *					pDb = NULL;
	FLMBOOL				bForcedShutdown = FALSE;
	FLMBOOL				bHitEnd;
	FINDEX_STATUS		savedIxStatus;
	FlmRecord *			pReusableRec = NULL;
	char					szMsg[ 128];
	FLMINT				iErrorLine = 0;
	FLMBOOL				bLimitedMode = FALSE;

	pThread->setThreadStatus( FLM_THREAD_STATUS_INITIALIZING);

	if( (pReusableRec = f_new FlmRecord) != NULL)
	{
		if( RC_BAD( pReusableRec->preallocSpace( 512, 1024 * 64)))
		{
			pReusableRec->Release();
			pReusableRec = NULL;
		}
	}

Loop_Again:

	rc = FERR_OK;
	uiIndexNum = pBackgroundIx->indexStatus.uiIndexNum;
	flmAssert( pThread->getThreadAppId() == uiIndexNum);
	bDbInitialized = FALSE;
	bStartedTrans = FALSE;
	pDb = NULL;

	// We could loop forever on flmOpenFile errors, check if we should exit.

	if( pThread->getShutdownFlag())
	{
		bForcedShutdown = TRUE;
		goto Exit;
	}

	if( RC_BAD( rc = flmOpenFile( pBackgroundIx->pFile,
		NULL, NULL, NULL, 0, TRUE, NULL, NULL,
		pBackgroundIx->pFile->pszDbPassword, &pDb)))
	{

		// If the file is being closed, this is not an error.

		if( pBackgroundIx->pFile->uiFlags & DBF_BEING_CLOSED)
		{
			bForcedShutdown = TRUE;
			rc = FERR_OK;
		}
		else
		{
			iErrorLine = (FLMINT)__LINE__;
		}
		goto Exit;
	}

	flmAssert( pDb->pSFileHdl);

	bDbInitialized = TRUE;
	if (RC_BAD( rc = fdbInit( pDb, FLM_NO_TRANS, 0, 0, &bStartedTrans)))
	{
		iErrorLine = (FLMINT)__LINE__;
		goto Exit;
	}
	flmAssert( !bStartedTrans);
	pDb->uiFlags |= FDB_BACKGROUND_INDEXING;

	for(;;)
	{
		// Set the thread's status

		pThread->setThreadStatus( FLM_THREAD_STATUS_RUNNING);

		// See if we should shut down. 

		if( pThread->getShutdownFlag())
		{
			bForcedShutdown = TRUE;
			break;
		}

		// Obtain the file lock

		flmAssert( !(pDb->uiFlags & FDB_HAS_FILE_LOCK));
		if( RC_BAD( rc = pDb->pFile->pFileLockObj->lock( pDb->hWaitSem,  
			TRUE, FLM_NO_TIMEOUT, FLM_BACKGROUND_LOCK_PRIORITY,
			pDb->pDbStats ? &pDb->pDbStats->LockStats : NULL)))
		{
			if( rc == FERR_IO_FILE_LOCK_ERR)
			{
				// This would only happen if we were signaled to shut down.
				// So, it's ok to exit

				flmAssert( pThread->getShutdownFlag());
				bForcedShutdown = TRUE;
				rc = FERR_OK;
			}
			else
			{
				iErrorLine = (FLMINT)__LINE__;
			}
			goto Exit;
		}

		// The lock needs to be marked as implicit so that flmCommitDbTrans
		// will unlock the file and allow the next update transaction to
		// begin before all writes are complete.

		pDb->uiFlags |= (FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_IMPLICIT);

		// If there are higher priority waiters in the lock queue,
		// or we are being told to shut down, we want to relinquish.

		if( pThread->getShutdownFlag() ||
			pDb->pFile->pFileLockObj->haveHigherPriorityWaiter( 
				FLM_BACKGROUND_LOCK_PRIORITY))
		{
			if (RC_BAD( rc = pDb->pFile->pFileLockObj->unlock()))
			{
				iErrorLine = (FLMINT)__LINE__;
				goto Exit;
			}

			pDb->uiFlags &= ~(FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_IMPLICIT);
			continue;
		}

		// Start an update transaction 

		if( RC_BAD( rc = flmBeginDbTrans( pDb, FLM_UPDATE_TRANS, FLM_NO_TIMEOUT, 
			FLM_DONT_POISON_CACHE)))
		{
			if( rc == FERR_IO_FILE_LOCK_ERR)
			{
				// This would only happen if we were signaled to shut down.
				// So, it's ok to exit

				flmAssert( pThread->getShutdownFlag());
				bForcedShutdown = TRUE;
				rc = FERR_OK;
			}
			else
			{
				iErrorLine = (FLMINT)__LINE__;
			}
			goto Exit;
		}
		bStartedTrans = TRUE;

		if( RC_BAD( rc = fdictGetIndex( pDb->pDict, pDb->pFile->bInLimitedMode,
			uiIndexNum, NULL, &pIxd, TRUE)))
		{
			// Index may have been deleted by another transaction, or
			// there may have been some other error.

			iErrorLine = (FLMINT)__LINE__;
			goto Exit;
		}

		// If we're running in limited mode, then we can't mess with encrypted
		// indexes.  On the other hand, since the index is marked as offline,
		// but not suspended, this thread has to exist, or else it will cause
		// all kinds of problems elsewhere.  So, in such a case, we will simply
		// sleep in an inifinite loop until the shutdown flag is set.
		// (We consider this acceptable becase running in limited mode is not
		// the norm, and Flaim probably won't be up for very long in this mode.)

		if( pDb->pFile->bInLimitedMode && pIxd->uiEncId)
		{
			bLimitedMode = TRUE;
			goto Exit;
		}

		// Look up the tracker info to determine where we need to being indexing

		if (RC_BAD( rc = flmGetIxTrackerInfo( pDb,
			pBackgroundIx->indexStatus.uiIndexNum, &uiContainerNum,
			&uiFirstDrn, NULL, &pBackgroundIx->indexStatus.bSuspended)))
		{
			iErrorLine = (FLMINT)__LINE__;
			goto Exit;
		}

		// If the index is suspended, this thread should have been
		// shut down.  The suspending thread will keep the database
		// locked until we exit.  So, if we have the database locked,
		// the index better not be suspended.

		flmAssert( !pBackgroundIx->indexStatus.bSuspended &&
			!(pIxd->uiFlags & IXD_SUSPENDED));

		if (pIxd->uiContainerNum)
		{
			uiContainerNum = pIxd->uiContainerNum;
			if( uiFirstDrn == DRN_LAST_MARKER)
			{
				goto Exit;
			}
		}
		else
		{
			if( uiFirstDrn == DRN_LAST_MARKER && uiContainerNum == 0xFFFFFFFF)
			{
				goto Exit;
			}
			else
			{
				// The container number from the tracker record
				// may not be a real container.
				// Determine what the next actual container number is.

				if (uiContainerNum != FLM_DATA_CONTAINER)
				{
					while( uiContainerNum < pDb->pDict->uiIttCnt)
					{
						ITT *	pItt = &pDb->pDict->pIttTbl [uiContainerNum];
						if (ITT_IS_CONTAINER( pItt))
						{
							break;
						}
						else
						{
							uiContainerNum++;
						}
					}

					if (uiContainerNum >= pDb->pDict->uiIttCnt)
					{
						uiContainerNum = FLM_DATA_CONTAINER;
					}
				}
			}
		}

		// Setup the DRN range we want to index.

		uiFirstDrn++;
		flmAssert( pIxd->uiLastDrnIndexed == uiFirstDrn - 1);

		// Set the thread's status

		pThread->setThreadStatus( "Indexing %u:%u", 
			(unsigned)uiContainerNum, (unsigned)uiFirstDrn);

		// Read and index up to the highest drn (or record higher than uiEndDrn)
		// or until time runs out.  The 500 is millisecs to take for the transaction.

		f_memcpy( &savedIxStatus, 
			&pBackgroundIx->indexStatus, sizeof( FINDEX_STATUS));

		if( RC_BAD( rc = flmIndexSetOfRecords( pDb,
			uiIndexNum, uiContainerNum, uiFirstDrn, DRN_LAST_MARKER,
			NULL, NULL, NULL, NULL,
			&pBackgroundIx->indexStatus, &bHitEnd, pThread, pReusableRec)))
		{
			// Lock the mutex while copying the saved index status back to
			// the main index status so that someone requesting the index status
			// won't see the status while the memcpy is in progress.

			f_mutexLock( gv_FlmSysData.hShareMutex);
			f_memcpy( &pBackgroundIx->indexStatus, 
				&savedIxStatus, sizeof( FINDEX_STATUS));
			f_mutexUnlock( gv_FlmSysData.hShareMutex);
			iErrorLine = (FLMINT)__LINE__;
			goto Exit;
		}

		if( pBackgroundIx->indexStatus.uiRecordsProcessed - 
			savedIxStatus.uiRecordsProcessed)
		{
			if( RC_BAD( rc = pDb->pFile->pRfl->logIndexSet( uiIndexNum,
						uiContainerNum, uiFirstDrn, 
						pBackgroundIx->indexStatus.uiLastRecordIdIndexed)))
			{
				iErrorLine = (FLMINT)__LINE__;
				goto Exit;
			}
		}

		// Commit the transaction (even if we didn't do any indexing work).

		if( RC_BAD( rc = flmCommitDbTrans( pDb, 0, FALSE)))
		{
			iErrorLine = (FLMINT)__LINE__;
			goto Exit;
		}

		bStartedTrans = FALSE;
		pBackgroundIx->indexStatus.uiTransactions++;

		if( bHitEnd)
		{
			// flmIndexSetOfRecords brought the index on-line

			if( gv_FlmSysData.UpdateEvents.pEventCBList)
			{
				flmDoEventCallback( F_EVENT_UPDATES, 
						F_EVENT_INDEXING_COMPLETE, (void *)uiIndexNum, 
						(void *)0);
			}

			// Log a message

			flmLogIndexingProgress( uiIndexNum, 0);
			break;
		}
	}

Exit:

	pThread->setThreadStatus( FLM_THREAD_STATUS_TERMINATING);

	if( bStartedTrans)
	{
		(void)flmAbortDbTrans( pDb);
		bStartedTrans = FALSE;
	}

	if( pDb && pDb->uiFlags & FDB_HAS_FILE_LOCK)
	{
		(void)pDb->pFile->pFileLockObj->unlock();
		pDb->uiFlags &= ~(FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_IMPLICIT);
	}

	if( bDbInitialized)
	{
		fdbExit( pDb);
		bDbInitialized = FALSE;
	}

	if( pDb)
	{
		(void)FlmDbClose( (HFDB *) &pDb);
	}

	if( RC_BAD(rc) && !bForcedShutdown)
	{
		if (rc == FERR_MEM || rc == FERR_IO_DISK_FULL ||
			rc == FERR_MUST_WAIT_CHECKPOINT)
		{
			// Log the error

			f_sprintf( (char *)szMsg,
				"Background indexing thread %u (index %u)",
				(unsigned)pThread->getThreadId(), (unsigned)uiIndexNum);
			flmLogError( rc, (char *)szMsg, __FILE__, iErrorLine);

			// Sleep a half second and try again.

			pThread->sleep( 500);
			goto Loop_Again;
		}
		else
		{
			f_sprintf( (char *)szMsg,
				"Background indexing thread %u (index %u) -- unrecoverable error.",
				(unsigned)pThread->getThreadId(), (unsigned)uiIndexNum);
			flmLogError( rc, (char *)szMsg, __FILE__, iErrorLine);
		}
	}

	if( pReusableRec)
	{
		flmAssert( pReusableRec->getRefCount() == 1);
		pReusableRec->Release();
	}

	if( bLimitedMode)
	{
		flmAssert( RC_OK( rc));

		for (;;)
		{
			if( pThread->getShutdownFlag())
			{
				break;
			}

			pThread->sleep( 1000);
		}
	}

	// Set the thread's app ID to 0, so that it will not
	// be found now that the thread is terminating (we don't
	// want flmBackgroundIndexGet to find the thread).

	pThread->setThreadAppId( 0);

	// Free the background index structure

	f_mutexLock( gv_FlmSysData.hShareMutex);
	f_free( &pBackgroundIx);
	pThread->setParm1( NULL);
	f_mutexUnlock( gv_FlmSysData.hShareMutex);

	return( rc);
}
コード例 #28
0
/****************************************************************************
Desc: Looks for a background indexing thread that is running with 
		a matching action and value.
Note:	The shared semaphore must be locked on the outside while 
		calling this routine and accessing anything within the F_BKGND_IX
		structure.
****************************************************************************/
F_BKGND_IX * flmBackgroundIndexGet(
	FFILE *			pFile,
	FLMUINT			uiIndexNum,
	FLMBOOL			bMutexLocked,
	FLMUINT *		puiThreadId)
{
	RCODE				rc = FERR_OK;
	IF_Thread *		pThread;
	FLMUINT			uiThreadId;
	F_BKGND_IX *	pBackgroundIx = NULL;

	if( !bMutexLocked)
	{
		f_mutexLock( gv_FlmSysData.hShareMutex);
	}

	uiThreadId = 0;
	for( ;;)
	{
		if( RC_BAD( rc = gv_FlmSysData.pThreadMgr->getNextGroupThread( 
			&pThread, gv_uiBackIxThrdGroup, &uiThreadId)))
		{
			if( rc == FERR_NOT_FOUND)
			{
				rc = FERR_OK;
				break;
			}
			else
			{
				flmAssert( 0);
			}
		}

		if( pThread->getThreadAppId())
		{
			F_BKGND_IX *		pTmpIx = NULL;

			pTmpIx = (F_BKGND_IX *)pThread->getParm1();
			if( pTmpIx->indexStatus.uiIndexNum == uiIndexNum &&
				pTmpIx->pFile == pFile)
			{
				flmAssert( pThread->getThreadAppId() == uiIndexNum);
				pBackgroundIx = pTmpIx;
				pThread->Release();
				if( puiThreadId)
				{
					*puiThreadId = uiThreadId;
				}
				break;
			}
		}
		pThread->Release();
	}

	if( !bMutexLocked)
	{
		f_mutexUnlock( gv_FlmSysData.hShareMutex);
	}

	return( pBackgroundIx);
}
コード例 #29
0
/****************************************************************************
Desc:		Stops a background indexing thread
Notes:	This routine DOES NOT assume that the global mutex is locked.  It
			will lock and unlock the mutex as needed.
****************************************************************************/
FSTATIC void stopBackgroundIndexThread(
	FDB *				pDb,
	FLMUINT			uiIndexNum,
	FLMBOOL			bWait,
	FLMBOOL *		pbStopped)
{
	F_BKGND_IX *	pBackgroundIx;
	FLMUINT			uiThreadId;
	FLMBOOL			bMutexLocked = FALSE;

	if( pbStopped)
	{
		*pbStopped = FALSE;
	}

	for( ;;)
	{
		// Lock the global mutex

		if( !bMutexLocked)
		{
			f_mutexLock( gv_FlmSysData.hShareMutex);
			bMutexLocked = TRUE;
		}

		// Get the background index

		if( (pBackgroundIx = flmBackgroundIndexGet( pDb->pFile,
			uiIndexNum, TRUE, &uiThreadId)) == NULL)
		{
			if( pbStopped)
			{
				*pbStopped = TRUE;
			}
			goto Exit;
		}

		// Set the thread's shutdown flag first.

		gv_FlmSysData.pThreadMgr->setThreadShutdownFlag( uiThreadId);

		// Unlock the global mutex

		f_mutexUnlock( gv_FlmSysData.hShareMutex);
		bMutexLocked = FALSE;

		// The thread may be waiting to start a transaction. 

		pDb->pFile->pFileLockObj->timeoutLockWaiter( uiThreadId);
		pDb->pFile->pWriteLockObj->timeoutLockWaiter( uiThreadId);
		
		if( !bWait)
		{
			break;
		}

		// Wait for the thread to terminate

		f_sleep( 50);
	}

Exit:

	if( bMutexLocked)
	{
		f_mutexUnlock( gv_FlmSysData.hShareMutex);
	}
}
コード例 #30
0
/****************************************************************************
Desc : Return the status of the index.
****************************************************************************/
FLMEXP RCODE FLMAPI FlmIndexStatus(
	HFDB					hDb,
	FLMUINT				uiIndexNum,
	FINDEX_STATUS *	pIndexStatus)
{
	RCODE					rc = FERR_OK;
	FLMBOOL				bStartedAutoTrans = FALSE;
	FLMUINT 				uiLastDrnIndexed;
	FDB *					pDb = (FDB *)hDb;
	F_BKGND_IX *		pBackgroundIx;
	FLMBOOL				bSuspended;
	FLMBOOL				bMutexLocked = FALSE;

	flmAssert( pIndexStatus != NULL);

	if( IsInCSMode( hDb))
	{
		fdbInitCS( pDb);
		rc = flmIndexStatusCS( pDb, uiIndexNum, pIndexStatus);
		goto Exit;
	}

	if( RC_BAD( rc = fdbInit( (FDB *)hDb, FLM_READ_TRANS,
							FDB_TRANS_GOING_OK, 0, &bStartedAutoTrans)))
	{
		goto Exit;
	}

	f_mutexLock( gv_FlmSysData.hShareMutex);
	bMutexLocked = TRUE;

	pBackgroundIx = flmBackgroundIndexGet( pDb->pFile, uiIndexNum, TRUE);
	if( pBackgroundIx)
	{
		f_memcpy( pIndexStatus, &pBackgroundIx->indexStatus, 
			sizeof( FINDEX_STATUS));
		f_mutexUnlock( gv_FlmSysData.hShareMutex);
		bMutexLocked = FALSE;
		flmAssert( pIndexStatus->uiIndexNum == uiIndexNum);
	}
	else
	{
		IXD *		pIxd;
		FLMBOOL	bTrackerIxSuspended;

		if( RC_BAD( rc = fdictGetIndex( 
			pDb->pDict, pDb->pFile->bInLimitedMode,
			uiIndexNum,NULL, &pIxd, TRUE)))
		{
			goto Exit;
		}

		bSuspended = (pIxd->uiFlags & IXD_SUSPENDED)
												? TRUE
												: FALSE;

		f_mutexUnlock( gv_FlmSysData.hShareMutex);
		bMutexLocked = FALSE;

		// Get the index state from the tracker

		if( RC_BAD( rc = flmGetIxTrackerInfo( pDb, uiIndexNum, 
			NULL, &uiLastDrnIndexed, NULL, &bTrackerIxSuspended)))
		{
			if( rc == FERR_NOT_FOUND)
			{
				rc = RC_SET( FERR_BAD_IX);
			}
			goto Exit;
		}

		// Sanity check

#ifdef FLM_DEBUG
		if( pDb->pFile->FileHdr.uiVersionNum >= FLM_FILE_FORMAT_VER_4_51 &&
			bSuspended != bTrackerIxSuspended)
		{
			flmAssert( 0);
		}
#endif

		// Populate the index status structure.

		f_memset( pIndexStatus, 0, sizeof( FINDEX_STATUS));
		pIndexStatus->uiIndexNum = uiIndexNum;
		pIndexStatus->uiLastRecordIdIndexed = uiLastDrnIndexed;
		pIndexStatus->bSuspended = bSuspended;
	}

Exit:

	if( bMutexLocked)
	{
		f_mutexUnlock( gv_FlmSysData.hShareMutex);
	}

	if( bStartedAutoTrans)
	{
		rc = flmEndAutoTrans( pDb, rc);
	}
	flmExit( FLM_INDEX_STATUS, pDb, rc);
	return( rc);
}