/**************************************************************************** Desc: This routine functions as a thread. It keeps the gigaload screen up to date. ****************************************************************************/ RCODE FLMAPI gigaScreenThread( IF_Thread * pThread) { FLMUINT uiCurrTime; for (;;) { // See if we should shut down. if( pThread->getShutdownFlag()) { break; } uiCurrTime = FLM_GET_TIMER(); // Update the display gigaUpdateMemInfo(); pThread->sleep( 1000); } return( FERR_OK); }
/**************************************************************************** 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); } }
/**************************************************************************** Desc: ****************************************************************************/ void TestBase::beginTest( const char * pszTestName) { m_pszTestName = pszTestName; display( m_pszTestName); display( " ... "); m_uiStartTime = FLM_GET_TIMER(); }
/**************************************************************************** Desc: ****************************************************************************/ void TestBase::endTest( FLMBOOL bPassed) { FLMUINT uiEndTime = FLM_GET_TIMER(); FLMUINT uiElapsedMilli = FLM_TIMER_UNITS_TO_MILLI( FLM_ELAPSED_TIME( uiEndTime, m_uiStartTime)); displayTestResults( bPassed, uiElapsedMilli); if (m_bLog) { logTestResults( bPassed); } (void)m_pReporter->recordUnitTestResults( m_pszTestName, bPassed, m_szFailInfo); }
/******************************************************************** 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); }
/**************************************************************************** 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; }
/**************************************************************************** Desc: Index a set of documents or until time runs out. ****************************************************************************/ RCODE F_Db::indexSetOfRows( FLMUINT uiIndexNum, FLMUINT64 ui64StartRowId, FLMUINT64 ui64EndRowId, IF_IxStatus * pIxStatus, IF_IxClient * pIxClient, SFLM_INDEX_STATUS * pIndexStatus, FLMBOOL * pbHitEnd, IF_Thread * pThread) { RCODE rc = NE_SFLM_OK; FLMUINT64 ui64RowId; FLMUINT64 ui64LastRowId = 0; F_INDEX * pIndex = NULL; F_TABLE * pTable; IF_LockObject * pDatabaseLockObj = m_pDatabase->m_pDatabaseLockObj; FLMBOOL bHitEnd = FALSE; FLMUINT uiCurrTime; FLMUINT uiLastStatusTime = 0; FLMUINT uiStartTime; FLMUINT uiMinTU; FLMUINT uiStatusIntervalTU; FLMUINT64 ui64RowsProcessed = 0; FLMBOOL bRelinquish = FALSE; FLMBYTE ucKey[ FLM_MAX_NUM_BUF_SIZE]; FLMUINT uiKeyLen; void * pvTmpPoolMark = m_tempPool.poolMark(); F_Btree * pbtree = NULL; FLMBOOL bNeg; FLMUINT uiBytesProcessed; F_Row * pRow = NULL; uiMinTU = FLM_MILLI_TO_TIMER_UNITS( 500); uiStatusIntervalTU = FLM_SECS_TO_TIMER_UNITS( 10); uiStartTime = FLM_GET_TIMER(); if (RC_BAD( rc = krefCntrlCheck())) { goto Exit; } pIndex = m_pDict->getIndex( uiIndexNum); flmAssert( pIndex); flmAssert( !(pIndex->uiFlags & IXD_SUSPENDED)); // Get a btree if (RC_BAD( rc = gv_SFlmSysData.pBtPool->btpReserveBtree( &pbtree))) { goto Exit; } pTable = m_pDict->getTable( pIndex->uiTableNum); flmAssert( pTable); if (RC_BAD( rc = pbtree->btOpen( this, &pTable->lfInfo, FALSE, TRUE))) { goto Exit; } uiKeyLen = sizeof( ucKey); if (RC_BAD( rc = flmNumber64ToStorage( ui64StartRowId, &uiKeyLen, ucKey, FALSE, TRUE))) { goto Exit; } if( RC_BAD( rc = pbtree->btLocateEntry( ucKey, sizeof( ucKey), &uiKeyLen, FLM_INCL))) { if (rc == NE_SFLM_EOF_HIT || rc == NE_SFLM_NOT_FOUND) { rc = NE_SFLM_OK; bHitEnd = TRUE; goto Commit_Keys; } goto Exit; } for (;;) { // See what row we're on if (RC_BAD( rc = flmCollation2Number( uiKeyLen, ucKey, &ui64RowId, &bNeg, &uiBytesProcessed))) { goto Exit; } if (ui64RowId > ui64EndRowId) { break; } if( RC_BAD( rc = gv_SFlmSysData.pRowCacheMgr->retrieveRow( this, pIndex->uiTableNum, ui64RowId, &pRow))) { goto Exit; } if (RC_BAD( rc = buildKeys( pIndex, pTable, pRow, TRUE, NULL))) { goto Exit; } // See if there is an indexing callback if (pIxClient) { if (RC_BAD( rc = pIxClient->doIndexing( this, uiIndexNum, pIndex->uiTableNum, pRow))) { goto Exit; } } ui64LastRowId = ui64RowId; ui64RowsProcessed++; if (pIndexStatus) { pIndexStatus->ui64RowsProcessed++; pIndexStatus->ui64LastRowIndexed = ui64LastRowId; } // Get the current time uiCurrTime = FLM_GET_TIMER(); // Break out if someone is waiting for an update transaction. if (pThread) { if (pThread->getShutdownFlag()) { bRelinquish = TRUE; break; } if (pDatabaseLockObj->getWaiterCount()) { // See if our minimum run time has elapsed if (FLM_ELAPSED_TIME( uiCurrTime, uiStartTime) >= uiMinTU) { if (ui64RowsProcessed < 50) { // If there are higher priority waiters in the lock queue, // we want to relinquish. if (pDatabaseLockObj->haveHigherPriorityWaiter( FLM_BACKGROUND_LOCK_PRIORITY)) { bRelinquish = TRUE; break; } } else { bRelinquish = TRUE; break; } } } else { // Even if no one has requested a lock for a long time, we // still want to periodically commit our transaction so // we won't lose more than uiMaxCPInterval timer units worth // of work if we crash. We will run until we exceed the checkpoint // interval and we see that someone (the checkpoint thread) is // waiting for the write lock. if (FLM_ELAPSED_TIME( uiCurrTime, uiStartTime) > gv_SFlmSysData.uiMaxCPInterval && m_pDatabase->m_pWriteLockObj->getWaiterCount()) { bRelinquish = TRUE; break; } } } if (FLM_ELAPSED_TIME( uiCurrTime, uiLastStatusTime) >= uiStatusIntervalTU) { uiLastStatusTime = uiCurrTime; if( pIxStatus) { if( RC_BAD( rc = pIxStatus->reportIndex( ui64LastRowId))) { goto Exit; } } // Send indexing completed event notification if( gv_SFlmSysData.EventHdrs[ SFLM_EVENT_UPDATES].pEventCBList) { flmDoEventCallback( SFLM_EVENT_UPDATES, SFLM_EVENT_INDEXING_PROGRESS, this, f_threadId(), 0, uiIndexNum, ui64LastRowId, NE_SFLM_OK); } // Log a progress message flmLogIndexingProgress( uiIndexNum, ui64LastRowId); } // Need to go to the next row. if( RC_BAD( rc = pbtree->btNextEntry( ucKey, sizeof( ucKey), &uiKeyLen))) { if (rc == NE_SFLM_EOF_HIT) { rc = NE_SFLM_OK; bHitEnd = TRUE; break; } goto Exit; } } Commit_Keys: if (RC_BAD( rc = keysCommit( TRUE))) { goto Exit; } // If at the end, change index state. if (bHitEnd) { if (RC_BAD( rc = setIxStateInfo( uiIndexNum, 0, 0))) { goto Exit; } // setIxStateInfo may have changed to a new dictionary, so pIxd is no // good after this point pIndex = NULL; } else if (ui64RowsProcessed) { if (RC_BAD( rc = setIxStateInfo( uiIndexNum, ui64LastRowId, IXD_OFFLINE))) { goto Exit; } // setIxStateInfo may have changed to a new dictionary, so pIndex is no // good after this point pIndex = NULL; } // Log the rows that were indexed, if any if (ui64LastRowId) { if (RC_BAD( rc = m_pDatabase->m_pRfl->logIndexSet( this, uiIndexNum, ui64StartRowId, ui64LastRowId))) { goto Exit; } } Exit: // We want to make one last call if we are in the foreground or if // we actually did some indexing. if (gv_SFlmSysData.EventHdrs[ SFLM_EVENT_UPDATES].pEventCBList) { flmDoEventCallback( SFLM_EVENT_UPDATES, SFLM_EVENT_INDEXING_PROGRESS, this, f_threadId(), 0, uiIndexNum, (FLMUINT64)(bHitEnd ? (FLMUINT64)0 : ui64LastRowId), NE_SFLM_OK); } flmLogIndexingProgress( uiIndexNum, (FLMUINT64)(bHitEnd ? (FLMUINT64)0 : ui64LastRowId)); if (pIxStatus) { (void) pIxStatus->reportIndex( ui64LastRowId); } if (pbHitEnd) { *pbHitEnd = bHitEnd; } krefCntrlFree(); m_tempPool.poolReset( pvTmpPoolMark); if (pbtree) { gv_SFlmSysData.pBtPool->btpReturnBtree( &pbtree); } if (pRow) { pRow->ReleaseRow(); } return( rc); }
/**************************************************************************** Desc: Retrieves the Checkpoint info for the database passed in. This assumes global mutex has already been locked. *****************************************************************************/ void F_Database::getCPInfo( XFLM_CHECKPOINT_INFO * pCheckpointInfo) { FLMUINT uiElapTime; FLMUINT uiCurrTime; flmAssert( pCheckpointInfo); f_memset( pCheckpointInfo, 0, sizeof( XFLM_CHECKPOINT_INFO)); if (m_pCPInfo) { pCheckpointInfo->bRunning = m_pCPInfo->bDoingCheckpoint; if (pCheckpointInfo->bRunning) { if (m_pCPInfo->uiStartTime) { uiCurrTime = FLM_GET_TIMER(); uiElapTime = FLM_ELAPSED_TIME( uiCurrTime, m_pCPInfo->uiStartTime); pCheckpointInfo->ui32RunningTime = (FLMUINT32)FLM_TIMER_UNITS_TO_MILLI( uiElapTime); } else { pCheckpointInfo->ui32RunningTime = 0; } pCheckpointInfo->bForcingCheckpoint = m_pCPInfo->bForcingCheckpoint; if (m_pCPInfo->uiForceCheckpointStartTime) { uiCurrTime = FLM_GET_TIMER(); uiElapTime = FLM_ELAPSED_TIME( uiCurrTime, m_pCPInfo->uiForceCheckpointStartTime); pCheckpointInfo->ui32ForceCheckpointRunningTime = (FLMUINT32)FLM_TIMER_UNITS_TO_MILLI( uiElapTime); } else { pCheckpointInfo->ui32ForceCheckpointRunningTime = 0; } pCheckpointInfo->ui32ForceCheckpointReason = (FLMUINT32)m_pCPInfo->iForceCheckpointReason; pCheckpointInfo->bWritingDataBlocks = m_pCPInfo->bWritingDataBlocks; pCheckpointInfo->ui32LogBlocksWritten = (FLMUINT32)m_pCPInfo->uiLogBlocksWritten; pCheckpointInfo->ui32DataBlocksWritten = (FLMUINT32)m_pCPInfo->uiDataBlocksWritten; } pCheckpointInfo->ui32BlockSize = (FLMUINT32)m_uiBlockSize; pCheckpointInfo->ui32DirtyCacheBytes = (FLMUINT32)(m_uiDirtyCacheCount * m_uiBlockSize); if (m_pCPInfo->uiStartWaitTruncateTime) { uiCurrTime = FLM_GET_TIMER(); uiElapTime = FLM_ELAPSED_TIME( uiCurrTime, m_pCPInfo->uiStartWaitTruncateTime); pCheckpointInfo->ui32WaitTruncateTime = (FLMUINT32)FLM_TIMER_UNITS_TO_MILLI( uiElapTime); } else { pCheckpointInfo->ui32WaitTruncateTime = 0; } } }
/**************************************************************************** Desc: Try to perform a checkpoint on the database. Returns TRUE if we need to terminate. ****************************************************************************/ FLMBOOL F_Database::tryCheckpoint( IF_Thread * pThread, CP_INFO * pCPInfo) { RCODE rc = NE_XFLM_OK; FLMBOOL bTerminate = FALSE; FLMBOOL bForceCheckpoint; FLMINT iForceReason; FLMUINT uiCurrTime; XFLM_DB_STATS * pDbStats; // See if we should terminate the thread. if (pThread->getShutdownFlag()) { // Set terminate flag to TRUE and then see if // we have been set up to do one final checkpoint // to flush dirty buffers to disk. bTerminate = TRUE; } // Determine if we need to force a checkpoint. bForceCheckpoint = FALSE; iForceReason = 0; uiCurrTime = (FLMUINT)FLM_GET_TIMER(); if (bTerminate) { bForceCheckpoint = TRUE; iForceReason = XFLM_CP_SHUTTING_DOWN_REASON; } else if (!m_pRfl->seeIfRflVolumeOk() || RC_BAD( m_CheckpointRc)) { bForceCheckpoint = TRUE; iForceReason = XFLM_CP_RFL_VOLUME_PROBLEM; } else if ((FLM_ELAPSED_TIME( uiCurrTime, m_uiLastCheckpointTime) >= gv_XFlmSysData.uiMaxCPInterval) || (!gv_XFlmSysData.uiMaxCPInterval)) { bForceCheckpoint = TRUE; iForceReason = XFLM_CP_TIME_INTERVAL_REASON; } if (gv_XFlmSysData.Stats.bCollectingStats) { // Statistics are being collected for the system. Therefore, // if we are not currently collecting statistics in the // start. If we were collecting statistics, but the // start time was earlier than the start time in the system // statistics structure, reset the statistics. if (!pCPInfo->Stats.bCollectingStats) { flmStatStart( &pCPInfo->Stats); } else if (pCPInfo->Stats.uiStartTime < gv_XFlmSysData.Stats.uiStartTime) { flmStatReset( &pCPInfo->Stats, FALSE); } (void)flmStatGetDb( &pCPInfo->Stats, this, 0, &pDbStats, NULL, NULL); } else { pDbStats = NULL; } // Lock write object - If we are forcing a checkpoint // wait until we get the lock. Otherwise, if we can't get // the lock without waiting, don't do anything. if (bForceCheckpoint || (gv_XFlmSysData.pBlockCacheMgr->m_uiMaxDirtyCache && (m_uiDirtyCacheCount + m_uiLogCacheCount) * m_uiBlockSize > gv_XFlmSysData.pBlockCacheMgr->m_uiMaxDirtyCache)) { if (RC_BAD( rc = dbWriteLock( pCPInfo->hWaitSem, pDbStats))) { // THIS SHOULD NEVER HAPPEN BECAUSE dbWriteLock will // wait forever for the lock! RC_UNEXPECTED_ASSERT( rc); goto Exit; } pThread->setThreadStatusStr( "Forcing checkpoint"); // Must wait for any RFL writes to complete. (void)m_pRfl->seeIfRflWritesDone( pCPInfo->hWaitSem, TRUE); } else { if (RC_BAD( dbWriteLock( pCPInfo->hWaitSem, pDbStats, 0))) { goto Exit; } pThread->setThreadStatus( FLM_THREAD_STATUS_RUNNING); // See if we actually need to do the checkpoint. If the // current transaction ID and the last checkpoint transaction // ID are the same, no updates have occurred that would require // a checkpoint to take place. if (m_lastCommittedDbHdr.ui64RflLastCPTransID == m_lastCommittedDbHdr.ui64CurrTransID || !m_pRfl->seeIfRflWritesDone( pCPInfo->hWaitSem, FALSE)) { dbWriteUnlock(); goto Exit; } } // Do the checkpoint. (void)doCheckpoint( pCPInfo->hWaitSem, pDbStats, pCPInfo->pSFileHdl, FALSE, bForceCheckpoint, iForceReason, 0, 0); if (pDbStats) { (void)flmStatUpdate( &pCPInfo->Stats); } dbWriteUnlock(); // Set the thread's status pThread->setThreadStatus( FLM_THREAD_STATUS_SLEEPING); Exit: return( bTerminate); }
/******************************************************************** Desc: Loads the database with objects. *********************************************************************/ RCODE gigaLoadDatabase( void) { RCODE rc = NE_FLM_OK; FLMBOOL bTransActive = FALSE; FLMBOOL bCommitTrans = FALSE; FLMUINT uiObjsInTrans = 0; FLMUINT uiChar = 0; FLMUINT bSuspend = FALSE; FlmRecord * pNewRec = NULL; // Set cache size, if specified on command line. if( gv_uiCacheSize) { if( RC_BAD( rc = FlmSetHardMemoryLimit( 0, FALSE, 0, gv_uiCacheSize, 0))) { gigaOutputRcErr( "setting cache size", rc); goto Exit; } } // Set block cache percentage, if it is not default. if( gv_uiBlockCachePercentage != 50) { if( RC_BAD( rc = FlmConfig( FLM_BLOCK_CACHE_PERCENTAGE, (void *)gv_uiBlockCachePercentage, (void *)0))) { gigaOutputRcErr( "setting block cache percentage", rc); goto Exit; } } // Set the maximum and low dirty cache, if one was specified if( gv_uiMaxDirtyCache) { if( RC_BAD( rc = FlmConfig( FLM_MAX_DIRTY_CACHE, (void *)gv_uiMaxDirtyCache, (void *)gv_uiLowDirtyCache))) { gigaOutputRcErr( "setting maximum dirty cache", rc); goto Exit; } } // Set checkpoint interval, if one is specified. if( gv_uiCPInterval != 0xFFFFFFFF) { if( RC_BAD( rc = FlmConfig( FLM_MAX_CP_INTERVAL, (void *)gv_uiCPInterval, (void *)0))) { gigaOutputRcErr( "setting checkpoint interval", rc); goto Exit; } } // Enable/Disable direct I/O if( RC_BAD( rc = FlmConfig( FLM_DIRECT_IO_STATE, (void *)!gv_bDisableDirectIO, NULL))) { goto Exit; } // Create the database. (void)FlmDbRemove( gv_szDibName, gv_szDataDir, gv_szRflDir, TRUE); if( RC_BAD( rc = FlmDbCreate( gv_szDibName, gv_szDataDir, gv_szRflDir, NULL, gv_pszGigaDictionary, NULL, &gv_hDb))) { gigaOutputRcErr( "creating database", rc); goto Exit; } if( RC_BAD( rc = FlmDbConfig( gv_hDb, FDB_RFL_FOOTPRINT_SIZE, (void *)(512 * 1024 * 1024), NULL))) { goto Exit; } if( RC_BAD( rc = FlmDbConfig( gv_hDb, FDB_RBL_FOOTPRINT_SIZE, (void *)(512 * 1024 * 1024), NULL))) { goto Exit; } // Create the display gv_uiTotalLoaded = 0; gv_ui10SecTotal = 0; f_mutexLock( gv_hWindowMutex); FTXWinClear( gv_pWindow); f_mutexUnlock( gv_hWindowMutex); gigaOutputLabel( MAX_CACHE_ROW, "Maximum Cache Size (bytes)"); gigaOutputLabel( USED_CACHE_ROW, "Cache Used (bytes)"); gigaOutputLabel( ITEMS_CACHED_ROW, "Cache Used (items)"); gigaOutputLabel( DIRTY_CACHE_ROW, "Dirty Cache (bytes)"); gigaOutputLabel( LOG_CACHE_ROW, "Log Cache (bytes)"); gigaOutputLabel( FREE_CACHE_ROW, "Free Cache (bytes)"); gigaOutputLabel( CP_STATE_ROW, "Checkpoint State"); gigaUpdateMemInfo(); gigaOutputLabel( DB_NAME_ROW, "Database Name"); gigaOutputStr( DB_NAME_ROW, gv_szDibName); gigaOutputLabel( TOTAL_TO_LOAD_ROW, "Total To Load"); gigaOutputUINT( TOTAL_TO_LOAD_ROW, gv_uiTotalToLoad); gigaOutputLabel( TRANS_SIZE_ROW, "Transaction Size"); gigaOutputUINT( TRANS_SIZE_ROW, gv_uiTransSize); gigaOutputLabel( TOTAL_LOADED_ROW, "Total Loaded"); gigaOutputUINT( TOTAL_LOADED_ROW, gv_uiTotalLoaded); gigaOutputLabel( ADDS_PER_SEC_CURRENT, "Adds/Sec. (10 secs)"); gigaOutputUINT( ADDS_PER_SEC_CURRENT, 0); gigaOutputLabel( ADDS_PER_SEC_OVERALL, "Adds/Sec. (overall)"); gigaOutputUINT( ADDS_PER_SEC_OVERALL, 0); gigaOutputLabel( ELAPSED_TIME_ROW, "Elapsed Time"); gigaOutputStr( ELAPSED_TIME_ROW, "<none>"); if( RC_BAD( rc = gigaStartScreenThread())) { goto Exit; } gv_ui10SecStartTime = gv_uiStartTime = FLM_GET_TIMER(); gv_ui10Secs = FLM_SECS_TO_TIMER_UNITS( 10); gv_ui1Sec = FLM_SECS_TO_TIMER_UNITS( 1); for( ;;) { // See if we have been told to shut down, or if the user // has pressed escape. if( gv_bShutdown) { break; } // Every 127 objects, see if character was pressed and update // count on screen. if( (gv_uiTotalLoaded & 0x7F) == 0) { f_yieldCPU(); if( (uiChar = gigaSeeIfQuit()) != 0) { if( uiChar == FKB_ESCAPE) { break; } else if( uiChar == 's' || uiChar == 'S') { bSuspend = TRUE; } } // Check for other keyboard options } else if( (gv_uiTotalLoaded & 0x7) == 0) { FLMUINT uiElapsedTime; FLMUINT uiCurrTime; uiCurrTime = FLM_GET_TIMER(); // If at least 10 seconds have elapsed, redisplay the average // rate values. if( (uiElapsedTime = FLM_ELAPSED_TIME( uiCurrTime, gv_ui10SecStartTime)) >= gv_ui10Secs) { gigaUpdateLoadTimes(); } } // Start a transaction, if one is not going. if( !bTransActive) { if( bSuspend) { uiChar = gigaGetInput( "Load suspended, press any character to continue loading: ", NULL); bSuspend = FALSE; } if( RC_BAD( rc = gigaStartTrans())) { goto Exit; } bTransActive = TRUE; bCommitTrans = FALSE; uiObjsInTrans = 0; } // Increment the load counters and determine if this will be the // last object of the transaction. gv_uiTotalLoaded++; uiObjsInTrans++; if( uiObjsInTrans == gv_uiTransSize || gv_uiTotalLoaded == gv_uiTotalToLoad) { bCommitTrans = TRUE; } // Create a new object. if( RC_BAD( rc = gigaMakeNewRecord( &pNewRec))) { goto Exit; } if( RC_BAD( rc = FlmRecordAdd( gv_hDb, FLM_DATA_CONTAINER, NULL, pNewRec, FLM_DONT_INSERT_IN_CACHE))) { goto Exit; } // Commit when we reach the transaction size or the total to load. // NOTE: The bCommitTrans flag is set above. if( bCommitTrans) { if( RC_BAD( rc = gigaCommitTrans())) { goto Exit; } bTransActive = FALSE; } // See if we are done. if( gv_uiTotalLoaded == gv_uiTotalToLoad) { flmAssert( !bTransActive); break; } } Exit: if( pNewRec) { pNewRec->Release(); } if( bTransActive) { (void)FlmDbTransAbort( gv_hDb); } if( gv_hDb != HFDB_NULL) { FlmDbCheckpoint( gv_hDb, FLM_NO_TIMEOUT); gigaStopScreenThread(); FlmDbClose( &gv_hDb); // This will cause us to wait for the last checkpoint // to finish. (void)FlmConfig( FLM_CLOSE_FILE, (void *)gv_szDibName, (void *)gv_szDataDir); } gigaUpdateLoadTimes(); gigaStopScreenThread(); f_threadDestroy( &gv_pIxManagerThrd); return( rc); }
/**************************************************************************** Name: flstIndexManagerThread Desc: Thread that displays the current status of all indexes in a database Note: The caller must open the database and pass a handle to the thread. The handle will be closed when the thread exits. *****************************************************************************/ RCODE FTKAPI flstIndexManagerThread( IF_Thread * pThread) { RCODE rc = NE_XFLM_OK; F_DynamicList * pList = f_new F_DynamicList; FTX_WINDOW * pTitleWin; FTX_WINDOW * pListWin; FTX_WINDOW * pHeaderWin; FTX_WINDOW * pMsgWin; FLMUINT uiIterations = 0; FLMUINT uiScreenCols; FLMUINT uiScreenRows; FLMUINT uiIndex; FLMUINT uiUpdateInterval; FLMUINT uiLastUpdateTime; IX_DISPLAY_INFO IxDispInfo; IX_DISPLAY_INFO * pDispInfo; DLIST_NODE * pTmpNd; FLMUINT uiKey; FLMBOOL bShowOnline = TRUE; F_Db * pDb = (F_Db *)pThread->getParm1(); FLMUINT uiOneSec; FLMBOOL bScreenLocked = FALSE; IX_Event event; FLMBOOL bRegisteredForEvent = FALSE; IF_DbSystem * pDbSystem = NULL; event.setDispInfo( &IxDispInfo); #define FIMT_TITLE_HEIGHT 1 #define FIMT_HEADER_HEIGHT 4 #define FIMT_LOG_HEIGHT 10 f_memset( &IxDispInfo, 0, sizeof( IX_DISPLAY_INFO)); IxDispInfo.hScreenMutex = F_MUTEX_NULL; IxDispInfo.pDb = (F_Db *)pDb; IxDispInfo.bShowTime = TRUE; if( RC_BAD( f_mutexCreate( &IxDispInfo.hScreenMutex))) { goto Exit; } if( RC_BAD( FTXScreenInit( "Index Manager", &IxDispInfo.pScreen))) { goto Exit; } FTXScreenGetSize( IxDispInfo.pScreen, &uiScreenCols, &uiScreenRows); FTXScreenDisplay( IxDispInfo.pScreen); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, 0, FIMT_TITLE_HEIGHT, &pTitleWin))) { goto Exit; } FTXWinSetBackFore( pTitleWin, FLM_RED, FLM_WHITE); FTXWinClear( pTitleWin); FTXWinPrintStr( pTitleWin, "FLAIM Index Manager"); FTXWinSetCursorType( pTitleWin, FLM_CURSOR_INVISIBLE); FTXWinOpen( pTitleWin); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, FIMT_HEADER_HEIGHT, &pHeaderWin))) { goto Exit; } FTXWinMove( pHeaderWin, 0, FIMT_TITLE_HEIGHT); FTXWinSetBackFore( pHeaderWin, FLM_BLUE, FLM_WHITE); FTXWinClear( pHeaderWin); FTXWinSetCursorType( pHeaderWin, FLM_CURSOR_INVISIBLE); FTXWinSetScroll( pHeaderWin, FALSE); FTXWinSetLineWrap( pHeaderWin, FALSE); FTXWinOpen( pHeaderWin); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, uiScreenRows - FIMT_TITLE_HEIGHT - FIMT_HEADER_HEIGHT - FIMT_LOG_HEIGHT, &pListWin))) { goto Exit; } FTXWinMove( pListWin, 0, FIMT_TITLE_HEIGHT + FIMT_HEADER_HEIGHT); FTXWinOpen( pListWin); pList->setup( pListWin); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, FIMT_LOG_HEIGHT, &IxDispInfo.pLogWin))) { goto Exit; } FTXWinDrawBorder( IxDispInfo.pLogWin); FTXWinMove( IxDispInfo.pLogWin, 0, uiScreenRows - FIMT_LOG_HEIGHT); FTXWinSetBackFore( IxDispInfo.pLogWin, FLM_BLUE, FLM_WHITE); FTXWinClear( IxDispInfo.pLogWin); FTXWinSetCursorType( IxDispInfo.pLogWin, FLM_CURSOR_INVISIBLE); FTXWinSetScroll( IxDispInfo.pLogWin, TRUE); FTXWinSetLineWrap( IxDispInfo.pLogWin, FALSE); FTXWinOpen( IxDispInfo.pLogWin); if( RC_BAD( rc = FlmAllocDbSystem( &pDbSystem))) { goto Exit; } if (RC_BAD( rc = pDbSystem->registerForEvent( XFLM_EVENT_UPDATES, &event))) { goto Exit; } bRegisteredForEvent = TRUE; FTXWinSetFocus( pListWin); uiIterations = 0; uiUpdateInterval = FLM_SECS_TO_TIMER_UNITS( 1); uiOneSec = FLM_SECS_TO_TIMER_UNITS( 1); uiLastUpdateTime = 0; while( !gv_bShutdown) { FLMUINT uiCurrTime = FLM_GET_TIMER(); if( bScreenLocked) { f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; } if( FLM_ELAPSED_TIME( uiCurrTime, uiLastUpdateTime) >= uiUpdateInterval) { Update_Screen: if( !bScreenLocked) { f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; } FTXWinSetCursorPos( pHeaderWin, 0, 1); if( IxDispInfo.bShowTime) { FTXWinPrintf( pHeaderWin, "Index Index State Last Rate Keys Documents Time"); } else { FTXWinPrintf( pHeaderWin, "Index Index State Last Rate Keys Documents Trans"); } FTXWinClearToEOL( pHeaderWin); FTXWinPrintf( pHeaderWin, "\n"); FTXWinPrintf( pHeaderWin, "Num. Name DOC"); if (RC_BAD( rc = pDb->transBegin( XFLM_READ_TRANS))) { goto Exit; } pTmpNd = pList->getFirst(); uiIndex = 0; for( ;;) { if( RC_BAD( pDb->indexGetNext( &uiIndex))) { break; } // Remove all invalid entries while( pTmpNd && pTmpNd->uiKey < uiIndex) { uiKey = pTmpNd->uiKey; pTmpNd = pTmpNd->pNext; pList->remove( uiKey); } if (RC_BAD( rc = pDb->indexStatus( uiIndex, &IxDispInfo.IndexStatus))) { goto Exit; } if( !bShowOnline && IxDispInfo.IndexStatus.eState == XFLM_INDEX_ONLINE) { if( pTmpNd && pTmpNd->uiKey == uiIndex) { uiKey = pTmpNd->uiKey; pTmpNd = pTmpNd->pNext; pList->remove( uiKey); } continue; } if( pTmpNd && pTmpNd->uiKey == uiIndex) { FLMUINT uiOldest; FLMUINT uiElapsed; pDispInfo = (IX_DISPLAY_INFO *)pTmpNd->pvData; f_strcpy( IxDispInfo.szName, pDispInfo->szName); // Copy the saved information. f_memcpy( &IxDispInfo.ui64SaveDocsProcessed [0], &pDispInfo->ui64SaveDocsProcessed [0], sizeof( FLMUINT) * MAX_VALS_TO_SAVE); f_memcpy( &IxDispInfo.uiDocSaveTime [0], &pDispInfo->uiDocSaveTime [0], sizeof( FLMUINT) * MAX_VALS_TO_SAVE); uiOldest = IxDispInfo.uiOldestSaved = pDispInfo->uiOldestSaved; // Recalculate the indexing rate. uiCurrTime = FLM_GET_TIMER(); uiElapsed = (uiCurrTime - IxDispInfo.uiDocSaveTime [uiOldest]) / uiOneSec; if (uiElapsed && IxDispInfo.IndexStatus.ui64DocumentsProcessed) { if( IxDispInfo.ui64SaveDocsProcessed[ uiOldest] < IxDispInfo.IndexStatus.ui64DocumentsProcessed) { IxDispInfo.uiIndexingRate = // Records processed in time period (FLMUINT)((IxDispInfo.IndexStatus.ui64DocumentsProcessed - IxDispInfo.ui64SaveDocsProcessed [uiOldest]) / uiElapsed); } else { IxDispInfo.uiIndexingRate = 0; } } else { IxDispInfo.uiIndexingRate = 0; } // Overwrite the oldest with the current data. IxDispInfo.uiDocSaveTime [uiOldest] = uiCurrTime; IxDispInfo.ui64SaveDocsProcessed [uiOldest] = IxDispInfo.IndexStatus.ui64DocumentsProcessed; // Move oldest pointer for next update. if (++IxDispInfo.uiOldestSaved == MAX_VALS_TO_SAVE) { IxDispInfo.uiOldestSaved = 0; } } else { FLMUINT uiLoop; FLMUINT uiBufLen; F_DataVector srchKey; uiCurrTime = FLM_GET_TIMER(); IxDispInfo.uiIndexingRate = 0; for (uiLoop = 0; uiLoop < MAX_VALS_TO_SAVE; uiLoop++) { IxDispInfo.ui64SaveDocsProcessed [uiLoop] = IxDispInfo.IndexStatus.ui64DocumentsProcessed; IxDispInfo.uiDocSaveTime [uiLoop] = uiCurrTime; } IxDispInfo.uiOldestSaved = 0; // Retrieve index name if (RC_BAD( srchKey.setUINT( 0, ELM_INDEX_TAG))) { break; } if (RC_BAD( srchKey.setUINT( 1, uiIndex))) { break; } if (RC_BAD( rc = pDb->keyRetrieve( XFLM_DICT_NUMBER_INDEX, &srchKey, XFLM_EXACT, &srchKey))) { if (rc != NE_XFLM_NOT_FOUND) { break; } } else { F_DOMNode * pNode = NULL; if (RC_BAD( rc = pDb->getNode( XFLM_DICT_COLLECTION, srchKey.getDocumentID(), &pNode))) { if (rc != NE_XFLM_DOM_NODE_NOT_FOUND) { break; } } else { uiBufLen = sizeof( IxDispInfo.szName); rc = pNode->getAttributeValueUTF8( pDb, ATTR_NAME_TAG, (FLMBYTE *)IxDispInfo.szName, uiBufLen); pNode->Release(); if (rc != NE_XFLM_OK && rc != NE_XFLM_DOM_NODE_NOT_FOUND && rc != NE_XFLM_CONV_DEST_OVERFLOW) { break; } } } } pList->update( uiIndex, ixDisplayHook, &IxDispInfo, sizeof( IxDispInfo)); pList->refresh(); if( pTmpNd && pTmpNd->uiKey == uiIndex) { pTmpNd = pTmpNd->pNext; } } pDb->transAbort(); uiLastUpdateTime = FLM_GET_TIMER(); pList->refresh(); } if( !bScreenLocked) { f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; } if( RC_OK( FTXWinTestKB( pListWin))) { FLMUINT uiChar; FTXWinInputChar( pListWin, &uiChar); f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; switch( uiChar) { case 'O': case 'o': { bShowOnline = !bShowOnline; goto Update_Screen; } case '+': case 'r': { if( (pTmpNd = pList->getCurrent()) != NULL) { if (RC_BAD( rc = pDb->indexResume( pTmpNd->uiKey))) { goto Exit; } goto Update_Screen; } break; } case 's': { if( (pTmpNd = pList->getCurrent()) != NULL) { if (RC_BAD( rc = pDb->indexSuspend( pTmpNd->uiKey))) { goto Exit; } goto Update_Screen; } break; } case FKB_ALT_S: case 'S': { f_mutexLock( IxDispInfo.hScreenMutex); FTXMessageWindow( IxDispInfo.pScreen, FLM_RED, FLM_WHITE, "Suspending all indexes ....", NULL, &pMsgWin); f_mutexUnlock( IxDispInfo.hScreenMutex); if (RC_OK( pDb->transBegin( XFLM_UPDATE_TRANS))) { uiIndex = 0; for( ;;) { if( RC_BAD( pDb->indexGetNext( &uiIndex))) { break; } if (RC_BAD( pDb->indexSuspend( uiIndex))) { break; } } if (RC_BAD( pDb->transCommit())) { (void)pDb->transAbort(); } } if( pMsgWin) { f_mutexLock( IxDispInfo.hScreenMutex); FTXWinFree( &pMsgWin); f_mutexUnlock( IxDispInfo.hScreenMutex); } goto Update_Screen; } case 'R': case FKB_ALT_R: { f_mutexLock( IxDispInfo.hScreenMutex); FTXMessageWindow( IxDispInfo.pScreen, FLM_RED, FLM_WHITE, "Resuming all indexes ", NULL, &pMsgWin); f_mutexUnlock( IxDispInfo.hScreenMutex); if (RC_OK( pDb->transBegin( XFLM_UPDATE_TRANS))) { uiIndex = 0; for( ;;) { if( RC_BAD( pDb->indexGetNext( &uiIndex))) { break; } if (RC_BAD( pDb->indexResume( uiIndex))) { break; } } if (RC_BAD( pDb->transCommit())) { (void)pDb->transAbort(); break; } } if( pMsgWin) { f_mutexLock( IxDispInfo.hScreenMutex); FTXWinFree( &pMsgWin); f_mutexUnlock( IxDispInfo.hScreenMutex); } goto Update_Screen; } case 'T': case 't': { IxDispInfo.bShowTime = !IxDispInfo.bShowTime; goto Update_Screen; } case '?': { FTX_WINDOW * pHelpWin = NULL; FTX_WINDOW * pHelpTitle = NULL; F_DynamicList * pHelpList = NULL; FLMUINT uiItem = 0; char szTmpBuf [100]; f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; if( (pHelpList = f_new F_DynamicList) == NULL) { goto Help_Exit; } if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, 1, &pHelpTitle))) { goto Help_Exit; } FTXWinSetBackFore( pHelpTitle, FLM_RED, FLM_WHITE); FTXWinClear( pHelpTitle); FTXWinSetCursorType( pHelpTitle, FLM_CURSOR_INVISIBLE); FTXWinSetScroll( pHelpTitle, FALSE); FTXWinSetLineWrap( pHelpTitle, FALSE); FTXWinPrintf( pHelpTitle, "FLAIM Index Manager - Help"); FTXWinOpen( pHelpTitle); if( RC_BAD( FTXWinInit( IxDispInfo.pScreen, uiScreenCols, uiScreenRows - 1, &pHelpWin))) { goto Help_Exit; } FTXWinDrawBorder( pHelpWin); FTXWinOpen( pHelpWin); pHelpList->setup( pHelpWin); f_sprintf( szTmpBuf, "R, ALT_R Resume all indexes"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, "S, ALT_S Suspend all indexes"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, "o, O Toggle display of on-line indexes"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, "+, r Resume selected index with auto on-line option"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); f_sprintf( szTmpBuf, "s Suspend selected index"); pHelpList->update( ++uiItem, NULL, szTmpBuf, sizeof( szTmpBuf)); pHelpList->refresh(); pHelpWin = pHelpList->getListWin(); f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; while( !gv_bShutdown) { f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; if( RC_OK( FTXWinTestKB( pHelpWin))) { FLMUINT uiTmpChar; FTXWinInputChar( pHelpWin, &uiTmpChar); if( uiTmpChar == FKB_ESCAPE) { break; } pHelpList->defaultKeyAction( uiTmpChar); } f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; f_sleep( 10); } Help_Exit: if( !bScreenLocked) { f_mutexLock( IxDispInfo.hScreenMutex); bScreenLocked = TRUE; } if( pHelpList) { pHelpList->Release(); } if( pHelpTitle) { FTXWinFree( &pHelpTitle); } f_mutexUnlock( IxDispInfo.hScreenMutex); bScreenLocked = FALSE; break; } case FKB_ESCAPE: { goto Exit; } default: { f_mutexLock( IxDispInfo.hScreenMutex); pList->defaultKeyAction( uiChar); f_mutexUnlock( IxDispInfo.hScreenMutex); break; } } f_mutexLock( IxDispInfo.hScreenMutex); pList->refresh(); f_mutexUnlock( IxDispInfo.hScreenMutex); } uiIterations++; if( pThread->getShutdownFlag()) { break; } f_sleep( 1); } Exit: if( pList) { pList->Release(); } if (bRegisteredForEvent) { pDbSystem->deregisterForEvent( XFLM_EVENT_UPDATES, &event); } if( IxDispInfo.pScreen) { FTXScreenFree( &IxDispInfo.pScreen); } if( IxDispInfo.hScreenMutex != F_MUTEX_NULL) { f_mutexDestroy( &IxDispInfo.hScreenMutex); } if( pDb != NULL) { pDb->Release(); } if( pDbSystem) { pDbSystem->Release(); } return( rc); }
/*API~*********************************************************************** Desc: Creates a new FLAIM database. *END************************************************************************/ RCODE XFLAPI F_DbSystem::dbCreate( const char * pszFilePath, // [IN] Full path file name of the database which is to be created. const char * pszDataDir, // [IN] Directory for data files. const char * pszRflDir, // [IN] RFL directory. NULL indicates that the RFL files should // be put in the same directory as the database. const char * pszDictFileName, // [IN] Full path of a file containing dictionary definitions to be // imported into the dictionary collection during database // creation. This is only used if pszDictBuf is NULL. If // both pszDictFileName and pszDictBuf are NULL, the database // will be created with an empty dictionary. const char * pszDictBuf, // [IN] Buffer containing dictionary definitions in external XML // format. If the value of this parameter is NULL, // pszDictFileName will be used. XFLM_CREATE_OPTS * pCreateOpts, // [IN] Create options for the database. All members of the // structure should be initialized through a call to f_memset: // // f_memset( pCreateOpts, 0, sizeof( XFLM_CREATE_OPTS)); // // Once initialized, the values of specific members can be set to // reflect the options desired when the database is created (such // as block size and various roll-forward logging options). If // NULL is passed as the value of this parameter, default options // will be used. FLMBOOL bTempDb, // [IN] Flag indicating whether this is a temporary database. // Should try to minimize writing to disk if this is the case. IF_Db ** ppDb // [OUT] Pointer to a database object. If the creation is // successful, the database object will be initialized. ) { RCODE rc = NE_XFLM_OK; F_Db * pDb = NULL; F_Database * pDatabase = NULL; FLMBOOL bDatabaseCreated = FALSE; FLMBOOL bNewDatabase = FALSE; FLMBOOL bMutexLocked = FALSE; FLMUINT uiRflToken = 0; // Make sure the path looks valid if (!pszFilePath || !pszFilePath [0]) { rc = RC_SET( NE_FLM_IO_INVALID_FILENAME); goto Exit; } // Allocate and initialize an F_Db structure. if (RC_BAD( rc = allocDb( &pDb, FALSE))) { goto Exit; } f_mutexLock( gv_XFlmSysData.hShareMutex); bMutexLocked = TRUE; for( ;;) { // See if we already have the file open. // May unlock and re-lock the global mutex. if (RC_BAD( rc = findDatabase( pszFilePath, pszDataDir, &pDatabase))) { goto Exit; } // Didn't find the database if (!pDatabase) { break; } // See if file is open or being opened. if (pDatabase->m_uiOpenIFDbCount || (pDatabase->m_uiFlags & DBF_BEING_OPENED)) { rc = RC_SET( NE_FLM_IO_ACCESS_DENIED); goto Exit; } // Free the F_Database object. May temporarily unlock the global mutex. // For this reason, we must call findDatabase again (see above) after // freeing the object. pDatabase->freeDatabase(); pDatabase = NULL; } // Allocate a new F_Database object if (RC_BAD( rc = allocDatabase( pszFilePath, pszDataDir, bTempDb, &pDatabase))) { goto Exit; } bNewDatabase = TRUE; pDatabase->m_uiMaxFileSize = gv_XFlmSysData.uiMaxFileSize; // 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; } // If the database has not already been created, do so now. if (RC_OK( gv_XFlmSysData.pFileSystem->doesFileExist( pszFilePath))) { rc = RC_SET( NE_XFLM_FILE_EXISTS); goto Exit; } // Create the .db file. pDb->m_pSFileHdl->setMaxAutoExtendSize( gv_XFlmSysData.uiMaxFileSize); pDb->m_pSFileHdl->setExtendSize( pDb->m_pDatabase->m_uiFileExtendSize); if (RC_BAD( rc = pDb->m_pSFileHdl->createFile( 0))) { goto Exit; } bDatabaseCreated = TRUE; (void)flmStatGetDb( &pDb->m_Stats, pDatabase, 0, &pDb->m_pDbStats, NULL, NULL); // We must have exclusive access. Create a lock file for that // purpose, if there is not already a lock file. // NOTE: No need for a lock file if this is a temporary database. if (!bTempDb) { if (RC_BAD( rc = pDatabase->getExclAccess( pszFilePath))) { goto Exit; } } if (RC_BAD( rc = pDb->initDbFiles( pszRflDir, pszDictFileName, pszDictBuf, pCreateOpts))) { goto Exit; } // Disable RFL logging (m_pRfl was initialized in initDbFiles) if( pDatabase->m_pRfl) { pDatabase->m_pRfl->disableLogging( &uiRflToken); } // Set FFILE stuff to same state as a completed checkpoint. pDatabase->m_uiFirstLogCPBlkAddress = 0; pDatabase->m_uiLastCheckpointTime = (FLMUINT)FLM_GET_TIMER(); // Create a checkpoint thread - no need if this is a temporary // database. if (!bTempDb) { if (RC_BAD( rc = pDatabase->startCPThread())) { goto Exit; } if( RC_BAD( rc = pDatabase->startMaintThread())) { goto Exit; } } Exit: if (bMutexLocked) { f_mutexUnlock( gv_XFlmSysData.hShareMutex); } if (pDb) { pDb->completeOpenOrCreate( rc, bNewDatabase); // completeOpenOrCreate will delete pDb if RC_BAD( rc) if (RC_BAD( rc)) { pDb = NULL; } else { *ppDb = (IF_Db *)pDb; pDb = NULL; // This isn't strictly necessary, but it makes it // obvious that we are no longer using the object. } } if (RC_BAD( rc)) { if (bDatabaseCreated) { gv_pXFlmDbSystem->dbRemove( pszFilePath, pszDataDir, pszRflDir, TRUE); } } else if( uiRflToken) { pDatabase->m_pRfl->enableLogging( &uiRflToken); } return( rc); }