void Animator::animate(int mode, float speed, int seq, float trans) { if (!mode && !speed) { _mode = 0; return; } if (seq < 0 || seq >= _seqs.size()) return; _seq = seq; _mode = mode; _seq_len = _seqs[_seq].frames; _speed = speed; _time = _speed >= 0 ? 0 : _seq_len; if (trans <= 0) { updateAnim(); if (!_speed) _mode = 0; return; } _mode |= 0x8000; _trans_time = 0; _trans_speed = 1 / trans; beginTrans(); }
/**************************************************************************** Desc: See if any F_INDEX structures need indexing in the background. ****************************************************************************/ RCODE F_Db::startBackgroundIndexing( void) { RCODE rc = NE_SFLM_OK; FLMBOOL bStartedTrans = FALSE; FLMUINT uiIndexNum; F_INDEX * pIndex; if (RC_BAD( rc = checkState( __FILE__, __LINE__))) { goto Exit; } if (m_eTransType != SFLM_NO_TRANS) { if (!okToCommitTrans()) { rc = RC_SET( NE_SFLM_ABORT_TRANS); goto Exit; } } else { // Need to have at least a read transaction going. if (RC_BAD( rc = beginTrans( SFLM_READ_TRANS))) { goto Exit; } bStartedTrans = TRUE; } for (uiIndexNum = 1, pIndex = m_pDict->m_pIndexTbl; uiIndexNum <= m_pDict->m_uiHighestIndexNum; uiIndexNum++, pIndex++) { // Restart any indexes that are off-line but not suspended if ((pIndex->uiFlags & (IXD_OFFLINE | IXD_SUSPENDED)) == IXD_OFFLINE) { flmAssert( flmBackgroundIndexGet( m_pDatabase, uiIndexNum, FALSE) == NULL); if (RC_BAD( rc = startIndexBuild( uiIndexNum))) { goto Exit; } } } Exit: if (bStartedTrans) { (void)abortTrans(); } return( rc); }
/**************************************************************************** Desc: Returns current RFL file number ****************************************************************************/ RCODE XFLAPI F_Db::getRflFileNum( FLMUINT * puiRflFileNum ) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; FLMUINT uiLastCPFile; FLMUINT uiLastTransFile; if (m_eTransType == XFLM_READ_TRANS) { rc = RC_SET( NE_XFLM_ILLEGAL_TRANS_OP); goto Exit; } else if (m_eTransType != XFLM_NO_TRANS) { if (!okToCommitTrans()) { rc = RC_SET( NE_XFLM_ABORT_TRANS); goto Exit; } } else { if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; } // Get the CP and last trans RFL file numbers. Need to // return the higher of the two. No need to lock the // mutex because we are in an update transaction. uiLastCPFile = (FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32RflLastCPFileNum; uiLastTransFile = (FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32RflCurrFileNum; *puiRflFileNum = uiLastCPFile > uiLastTransFile ? uiLastCPFile : uiLastTransFile; Exit: if (bStartedTrans) { abortTrans(); } return( rc); }
int cmd_begin(ClientData clientdata, Tcl_Interp* ip, int ac, char* av[]) { CMDFUNC(cmd_begin); CHECK(1, 2, NULL); CHECKCONNECTED; if(ac > 1) { int degree = _atoi(av[1]); CALL(beginTrans(degree)); } else { CALL(beginTrans()); } #ifdef USE_VERIFY v->begin(); #endif if(res != SVAS_FAILURE) { tid_t __t; CALL(trans(&__t);)
/**************************************************************************** Desc: Returns highest not used RFL file number ****************************************************************************/ RCODE XFLAPI F_Db::getHighestNotUsedRflFileNum( FLMUINT * puiHighestNotUsedRflFileNum ) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; FLMUINT uiLastCPFile; FLMUINT uiLastTransFile; if (m_eTransType == XFLM_READ_TRANS) { rc = RC_SET( NE_XFLM_ILLEGAL_TRANS_OP); goto Exit; } else if (m_eTransType != XFLM_NO_TRANS) { if (!okToCommitTrans()) { rc = RC_SET( NE_XFLM_ABORT_TRANS); goto Exit; } } else { if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; } // Get the CP and last trans RFL file numbers. Need to // return the lower of the two minus 1. uiLastCPFile = (FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32RflLastCPFileNum; uiLastTransFile = (FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32RflCurrFileNum; *puiHighestNotUsedRflFileNum = (FLMUINT)((uiLastCPFile < uiLastTransFile ? uiLastCPFile : uiLastTransFile) - 1); Exit: if (bStartedTrans) { abortTrans(); } return( rc); }
/**************************************************************************** Desc: Set auto turn off keep RFL flag. ****************************************************************************/ RCODE XFLAPI F_Db::setAutoTurnOffKeepRflFlag( FLMBOOL bAutoTurnOff ) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; // See if the database is being forced to close if (RC_BAD( rc = checkState( __FILE__, __LINE__))) { goto Exit; } // Start an update transaction. Must not already be one going. if (m_eTransType != XFLM_NO_TRANS) { rc = RC_SET( NE_XFLM_TRANS_ACTIVE); goto Exit; } if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; // Change the uncommitted log header m_pDatabase->m_uncommittedDbHdr.ui8RflAutoTurnOffKeep = (FLMUINT8)(bAutoTurnOff ? (FLMUINT8)1 : (FLMUINT8)0); // Commit the transaction. bStartedTrans = FALSE; if (RC_BAD( rc = commitTrans( 0, FALSE))) { goto Exit; } Exit: if (bStartedTrans) { abortTrans(); } return( rc); }
/**************************************************************************** Desc: Returns RFL file size limits for the database ****************************************************************************/ RCODE XFLAPI F_Db::getRflFileSizeLimits( FLMUINT * puiRflMinFileSize, FLMUINT * puiRflMaxFileSize ) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; if (m_eTransType == XFLM_READ_TRANS) { rc = RC_SET( NE_XFLM_ILLEGAL_TRANS_OP); goto Exit; } else if (m_eTransType != XFLM_NO_TRANS) { if (!okToCommitTrans()) { rc = RC_SET( NE_XFLM_ABORT_TRANS); goto Exit; } } else { if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; } if (puiRflMinFileSize) { *puiRflMinFileSize = (FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32RflMinFileSize; } if (puiRflMaxFileSize) { *puiRflMaxFileSize = (FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32RflMaxFileSize; } Exit: if (bStartedTrans) { abortTrans(); } return( rc); }
/**************************************************************************** Desc: Returns the keep aborted transactions in RFL flag for the database ****************************************************************************/ RCODE XFLAPI F_Db::getKeepAbortedTransInRflFlag( FLMBOOL * pbKeep ) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; if (m_eTransType == XFLM_READ_TRANS) { rc = RC_SET( NE_XFLM_ILLEGAL_TRANS_OP); goto Exit; } else if (m_eTransType != XFLM_NO_TRANS) { if (!okToCommitTrans()) { rc = RC_SET( NE_XFLM_ABORT_TRANS); goto Exit; } } else { if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; } *pbKeep = m_pDatabase->m_uncommittedDbHdr.ui8RflKeepAbortedTrans ? TRUE : FALSE; Exit: if (bStartedTrans) { abortTrans(); } return( rc); }
/**************************************************************************** Desc: Returns blocks changed since the last backup for the database ****************************************************************************/ RCODE XFLAPI F_Db::getBlocksChangedSinceBackup( FLMUINT * puiBlocksChangedSinceBackup ) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; if (m_eTransType == XFLM_READ_TRANS) { rc = RC_SET( NE_XFLM_ILLEGAL_TRANS_OP); goto Exit; } else if (m_eTransType != XFLM_NO_TRANS) { if (!okToCommitTrans()) { rc = RC_SET( NE_XFLM_ABORT_TRANS); goto Exit; } } else { if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; } *puiBlocksChangedSinceBackup = (FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32BlksChangedSinceBackup; Exit: if (bStartedTrans) { abortTrans(); } return( rc); }
/**************************************************************************** Desc: Returns last backup transaction ID for the database ****************************************************************************/ RCODE XFLAPI F_Db::getLastBackupTransID( FLMUINT64 * pui64LastBackupTransID ) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; if (m_eTransType == XFLM_READ_TRANS) { rc = RC_SET( NE_XFLM_ILLEGAL_TRANS_OP); goto Exit; } else if (m_eTransType != XFLM_NO_TRANS) { if (!okToCommitTrans()) { rc = RC_SET( NE_XFLM_ABORT_TRANS); goto Exit; } } else { if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; } *pui64LastBackupTransID = m_pDatabase->m_uncommittedDbHdr.ui64LastBackupTransID; Exit: if (bStartedTrans) { abortTrans(); } return( rc); }
/**************************************************************************** Desc: ****************************************************************************/ RCODE F_Db::beginBackgroundTrans( IF_Thread * pThread) { RCODE rc = NE_SFLM_OK; RetryLock: // Obtain the file lock flmAssert( !(m_uiFlags & FDB_HAS_FILE_LOCK)); if( RC_BAD( rc = m_pDatabase->m_pDatabaseLockObj->lock( m_hWaitSem, TRUE, FLM_NO_TIMEOUT, FLM_BACKGROUND_LOCK_PRIORITY, m_pDbStats ? &m_pDbStats->LockStats : NULL))) { if( rc == NE_SFLM_DATABASE_LOCK_REQ_TIMEOUT) { // This would only happen if we were signaled to shut down. // So, it's ok to exit flmAssert( pThread->getShutdownFlag()); } goto Exit; } // The lock needs to be marked as implicit so that commitTrans // will unlock the database and allow the next update transaction to // begin before all writes are complete. m_uiFlags |= (FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_IMPLICIT); // If there are higher priority waiters in the lock queue, // we want to relinquish. if( m_pDatabase->m_pDatabaseLockObj->haveHigherPriorityWaiter( FLM_BACKGROUND_LOCK_PRIORITY)) { if( pThread->getShutdownFlag()) { goto Exit; } if( RC_BAD( rc = m_pDatabase->m_pDatabaseLockObj->unlock())) { goto Exit; } m_uiFlags &= ~(FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_IMPLICIT); goto RetryLock; } // If we are shutting down, relinquish and exit. if( pThread->getShutdownFlag()) { rc = RC_SET( NE_SFLM_DATABASE_LOCK_REQ_TIMEOUT); goto Exit; } // Start an update transaction if( RC_BAD( rc = beginTrans( SFLM_UPDATE_TRANS, FLM_NO_TIMEOUT, SFLM_DONT_POISON_CACHE))) { if( rc == NE_SFLM_DATABASE_LOCK_REQ_TIMEOUT) { // This would only happen if we were signaled to shut down. // So, it's ok to exit flmAssert( pThread->getShutdownFlag()); } goto Exit; } Exit: if( RC_BAD( rc)) { if( m_uiFlags & FDB_HAS_FILE_LOCK) { (void)m_pDatabase->m_pDatabaseLockObj->unlock(); m_uiFlags &= ~(FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_IMPLICIT); } } return( rc); }
/**************************************************************************** Desc: Returns disk space usage for the database ****************************************************************************/ RCODE XFLAPI F_Db::getDiskSpaceUsage( FLMUINT64 * pui64DataSize, FLMUINT64 * pui64RollbackSize, FLMUINT64 * pui64RflSize) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; FLMUINT uiEndAddress; FLMUINT uiLastFileNumber; FLMUINT64 ui64LastFileSize; char szTmpName [F_PATH_MAX_SIZE]; char szRflDir [F_PATH_MAX_SIZE]; IF_FileHdl * pFileHdl = NULL; IF_DirHdl * pDirHdl = NULL; if (m_eTransType == XFLM_READ_TRANS) { rc = RC_SET( NE_XFLM_ILLEGAL_TRANS_OP); goto Exit; } else if (m_eTransType != XFLM_NO_TRANS) { if (!okToCommitTrans()) { rc = RC_SET( NE_XFLM_ABORT_TRANS); goto Exit; } } else { if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; } // See if they want the database files sizes. if (pui64DataSize) { uiEndAddress = m_uiLogicalEOF; uiLastFileNumber = FSGetFileNumber( uiEndAddress); // Last file number better be in the proper range. flmAssert( uiLastFileNumber >= 1 && uiLastFileNumber <= MAX_DATA_BLOCK_FILE_NUMBER); // Get the actual size of the last file. if (RC_BAD( rc = m_pSFileHdl->getFileSize( uiLastFileNumber, &ui64LastFileSize))) { if (rc == NE_FLM_IO_PATH_NOT_FOUND || rc == NE_FLM_IO_INVALID_FILENAME) { if (uiLastFileNumber > 1) { rc = NE_XFLM_OK; ui64LastFileSize = 0; } else { // Should always be a data file #1 RC_UNEXPECTED_ASSERT( rc); goto Exit; } } else { goto Exit; } } // One of two situations exists with respect to the last // file: 1) it has not been fully written out yet (blocks // are still cached, or 2) it has been written out and // extended beyond what the logical EOF shows. We want // the larger of these two possibilities. if (FSGetFileOffset( uiEndAddress) > ui64LastFileSize) { ui64LastFileSize = FSGetFileOffset( uiEndAddress); } if (uiLastFileNumber == 1) { // Only one file - use last file's size. *pui64DataSize = ui64LastFileSize; } else { // Size is the sum of full size for all files except the last one, // plus the calculated (or actual) size of the last one. (*pui64DataSize) = (FLMUINT64)(uiLastFileNumber - 1) * (FLMUINT64)m_pDatabase->m_uiMaxFileSize + ui64LastFileSize; } } // See if they want the rollback files sizes. if (pui64RollbackSize) { uiEndAddress = (FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32RblEOF; uiLastFileNumber = FSGetFileNumber( uiEndAddress); // Last file number better be in the proper range. flmAssert( !uiLastFileNumber || (uiLastFileNumber >= FIRST_LOG_BLOCK_FILE_NUMBER && uiLastFileNumber <= MAX_LOG_BLOCK_FILE_NUMBER)); // Get the size of the last file number. if (RC_BAD( rc = m_pSFileHdl->getFileSize( uiLastFileNumber, &ui64LastFileSize))) { if (rc == NE_FLM_IO_PATH_NOT_FOUND || rc == NE_FLM_IO_INVALID_FILENAME) { if (uiLastFileNumber) { rc = NE_XFLM_OK; ui64LastFileSize = 0; } else { // Should always have rollback file #0 RC_UNEXPECTED_ASSERT( rc); goto Exit; } } else { goto Exit; } } // If the EOF offset for the last file is greater than the // actual file size, use it instead of the actual file size. if (FSGetFileOffset( uiEndAddress) > ui64LastFileSize) { ui64LastFileSize = FSGetFileOffset( uiEndAddress); } // Special case handling here because rollback file numbers start with // zero and then skip to a file number that is one beyond the // highest data file number - so the calculation for file size needs // to account for this. if (!uiLastFileNumber) { *pui64RollbackSize = ui64LastFileSize; } else { FLMUINT uiFirstLogFileNum = FIRST_LOG_BLOCK_FILE_NUMBER; // Add full size of file zero plus a full size for every file // except the last one. (*pui64RollbackSize) = (FLMUINT64)(uiLastFileNumber - uiFirstLogFileNum + 1) * (FLMUINT64)m_pDatabase->m_uiMaxFileSize + ui64LastFileSize; } } // See if they want the roll-forward log file sizes. if (pui64RflSize) { char * pszDbFileName = m_pDatabase->m_pszDbPath; *pui64RflSize = 0; // Scan the RFL directory for // RFL files. The call below to rflGetDirAndPrefix is done // to get the prefix. It will not return the correct // RFL directory name, because we are passing in a NULL // RFL directory path (which may or may not be correct). // That's OK, because we get the RFL directory directly // from the F_Rfl object anyway. if (RC_BAD( rc = rflGetDirAndPrefix( pszDbFileName, NULL, szRflDir))) { goto Exit; } // We need to get the RFL directory from the F_Rfl object. m_pDatabase->lockMutex(); f_strcpy( szRflDir, m_pDatabase->m_pRfl->getRflDirPtr()); m_pDatabase->unlockMutex(); // See if the directory exists. If not, we are done. if (gv_XFlmSysData.pFileSystem->isDir( szRflDir)) { // Open the directory and scan for RFL files. if (RC_BAD( rc = gv_XFlmSysData.pFileSystem->openDir( szRflDir, "*", &pDirHdl))) { goto Exit; } for (;;) { if (RC_BAD( rc = pDirHdl->next())) { if (rc == NE_FLM_IO_NO_MORE_FILES) { rc = NE_XFLM_OK; break; } else { goto Exit; } } pDirHdl->currentItemPath( szTmpName); // If the item looks like an RFL file name, get // its size. if (!pDirHdl->currentItemIsDir() && rflGetFileNum( szTmpName, &uiLastFileNumber)) { // Open the file and get its size. if (RC_BAD( rc = gv_XFlmSysData.pFileSystem->openFile( szTmpName, gv_XFlmSysData.uiFileOpenFlags, &pFileHdl))) { if (rc == NE_FLM_IO_PATH_NOT_FOUND || rc == NE_FLM_IO_INVALID_FILENAME) { rc = NE_XFLM_OK; ui64LastFileSize = 0; } else { goto Exit; } } else { if (RC_BAD( rc = pFileHdl->size( &ui64LastFileSize))) { goto Exit; } } if (pFileHdl) { pFileHdl->Release(); pFileHdl = NULL; } (*pui64RflSize) += ui64LastFileSize; } } } } Exit: if (pFileHdl) { pFileHdl->Release(); } if (pDirHdl) { pDirHdl->Release(); } if (bStartedTrans) { abortTrans(); } return( rc); }
/**************************************************************************** Desc: Set the RFL file size limits for a database. ****************************************************************************/ RCODE XFLAPI F_Db::setRflFileSizeLimits( FLMUINT uiMinRflSize, FLMUINT uiMaxRflSize) { RCODE rc = NE_XFLM_OK; FLMBOOL bStartedTrans = FALSE; // See if the database is being forced to close if (RC_BAD( rc = checkState( __FILE__, __LINE__))) { goto Exit; } // Make sure the limits are valid. // Maximum must be enough to hold at least one packet plus // the RFL header. Minimum must not be greater than the // maximum. NOTE: Minimum and maximum are allowed to be // equal, but in all cases, maximum takes precedence over // minimum. We will first NOT exceed the maximum. Then, // if possible, we will go above the minimum. if (uiMaxRflSize < RFL_MAX_PACKET_SIZE + 512) { uiMaxRflSize = RFL_MAX_PACKET_SIZE + 512; } if (uiMaxRflSize > gv_XFlmSysData.uiMaxFileSize) { uiMaxRflSize = gv_XFlmSysData.uiMaxFileSize; } if (uiMinRflSize > uiMaxRflSize) { uiMinRflSize = uiMaxRflSize; } // Start an update transaction. Must not already be one going. if (m_eTransType != XFLM_NO_TRANS) { rc = RC_SET( NE_XFLM_TRANS_ACTIVE); goto Exit; } if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bStartedTrans = TRUE; // Commit the transaction. m_pDatabase->m_uncommittedDbHdr.ui32RflMinFileSize = (FLMUINT32)uiMinRflSize; m_pDatabase->m_uncommittedDbHdr.ui32RflMaxFileSize = (FLMUINT32)uiMaxRflSize; bStartedTrans = FALSE; if (RC_BAD( rc = commitTrans( 0, FALSE))) { goto Exit; } Exit: if (bStartedTrans) { abortTrans(); } return( rc); }
/**************************************************************************** Desc: Create a database - initialize all physical areas & data dictionary. ****************************************************************************/ RCODE F_Db::initDbFiles( const char * pszRflDir, const char * pszDictFileName, // Name of dictionary file. This // is only used if pszDictBuf is // NULL. If both pszDictFileName // and pszDictBuf are NULL, the // file will be craeted with an empty // dictionary. const char * pszDictBuf, // Buffer containing dictionary in // XML format. If NULL, // pszDictFileName will be used. XFLM_CREATE_OPTS * pCreateOpts) // Create options for the database. { RCODE rc = NE_XFLM_OK; FLMUINT bTransStarted = FALSE; FLMBYTE * pucBuf = NULL; FLMUINT uiBlkSize; FLMUINT uiWriteBytes; FLMUINT uiRflToken = 0; XFLM_DB_HDR * pDbHdr; F_BLK_HDR * pBlkHdr; F_CachedBlock * pSCache = NULL; FLMBYTE * pucWrappingKey = NULL; FLMUINT32 ui32KeyLen = 0; // Determine what size of buffer to allocate. uiBlkSize = (FLMUINT)(pCreateOpts ? flmAdjustBlkSize( (FLMUINT)pCreateOpts->ui32BlockSize) : (FLMUINT)XFLM_DEFAULT_BLKSIZ); // Allocate a buffer for writing. if (RC_BAD( rc = f_alloc( (FLMUINT)uiBlkSize, &pucBuf))) { goto Exit; } // Initialize the database header structure. pDbHdr = (XFLM_DB_HDR *)pucBuf; flmInitDbHdr( pCreateOpts, TRUE, m_pDatabase->m_bTempDb, pDbHdr); m_pDatabase->m_uiBlockSize = (FLMUINT)pDbHdr->ui16BlockSize; m_pDatabase->m_uiDefaultLanguage = (FLMUINT)pDbHdr->ui8DefaultLanguage; m_pDatabase->m_uiMaxFileSize = (FLMUINT)pDbHdr->ui32MaxFileSize; m_pDatabase->m_uiSigBitsInBlkSize = calcSigBits( uiBlkSize); f_memcpy( &m_pDatabase->m_lastCommittedDbHdr, pDbHdr, sizeof( XFLM_DB_HDR)); // Create the first block file. if (!m_pDatabase->m_bTempDb) { if (RC_BAD( rc = m_pSFileHdl->createFile( 1))) { goto Exit; } } if( RC_OK( rc = createDbKey())) { if (RC_BAD( rc = m_pDatabase->m_pWrappingKey->getKeyToStore( &pucWrappingKey, &ui32KeyLen, m_pDatabase->m_pszDbPasswd, NULL))) { goto Exit; } f_memcpy( m_pDatabase->m_lastCommittedDbHdr.DbKey, pucWrappingKey, ui32KeyLen); m_pDatabase->m_lastCommittedDbHdr.ui32DbKeyLen = ui32KeyLen; m_pDatabase->m_rcLimitedCode = NE_XFLM_OK; m_pDatabase->m_bInLimitedMode = FALSE; m_pDatabase->m_bHaveEncKey = TRUE; } else if( rc == NE_XFLM_ENCRYPTION_UNAVAILABLE) { rc = NE_XFLM_OK; m_pDatabase->m_rcLimitedCode = NE_XFLM_ENCRYPTION_UNAVAILABLE; m_pDatabase->m_bInLimitedMode = TRUE; m_pDatabase->m_bHaveEncKey = FALSE; } else { goto Exit; } // Write out the log header if (RC_BAD( rc = m_pDatabase->writeDbHdr( m_pDbStats, m_pSFileHdl, &m_pDatabase->m_lastCommittedDbHdr, NULL, TRUE))) { goto Exit; } // Initialize and output the first LFH block if (m_pDatabase->m_bTempDb) { getDbHdrInfo( &m_pDatabase->m_lastCommittedDbHdr); if (RC_BAD( rc = m_pDatabase->createBlock( this, &pSCache))) { goto Exit; } pBlkHdr = (F_BLK_HDR *)pSCache->m_pBlkHdr; m_pDatabase->m_lastCommittedDbHdr.ui32FirstLFBlkAddr = pBlkHdr->ui32BlkAddr; } else { // Copy the Db header to the checkpointDbHdr buffer. // This is now the first official checkpoint version of the log // header. It must be copied to the checkpointDbHdr buffer so that // it will not be lost in subsequent calls to flmWriteDbHdr. f_memcpy( &m_pDatabase->m_checkpointDbHdr, &m_pDatabase->m_lastCommittedDbHdr, sizeof( XFLM_DB_HDR)); f_memset( pucBuf, 0, uiBlkSize); pBlkHdr = (F_BLK_HDR *)pucBuf; pBlkHdr->ui32BlkAddr = m_pDatabase->m_lastCommittedDbHdr.ui32FirstLFBlkAddr; pBlkHdr->ui64TransID = 0; } pBlkHdr->ui8BlkType = BT_LFH_BLK; pBlkHdr->ui16BlkBytesAvail = (FLMUINT16)(uiBlkSize - SIZEOF_STD_BLK_HDR); blkSetNativeFormat( pBlkHdr); if (!m_pDatabase->m_bTempDb) { pBlkHdr->ui32BlkCRC = calcBlkCRC( pBlkHdr, SIZEOF_STD_BLK_HDR); if (RC_BAD( rc = m_pSFileHdl->writeBlock( pBlkHdr->ui32BlkAddr, uiBlkSize, pucBuf, &uiWriteBytes))) { goto Exit; } // Force things to disk. if (RC_BAD( rc = m_pSFileHdl->flush())) { goto Exit; } } // Allocate the pRfl object. Could not do this until this point // because we need to have the version number, block size, etc. // setup in the database header flmAssert( !m_pDatabase->m_pRfl); if (!m_pDatabase->m_bTempDb) { if ((m_pDatabase->m_pRfl = f_new F_Rfl) == NULL) { rc = RC_SET( NE_XFLM_MEM); goto Exit; } if( RC_BAD( rc = m_pDatabase->m_pRfl->setup( m_pDatabase, pszRflDir))) { goto Exit; } // Disable RFL logging m_pDatabase->m_pRfl->disableLogging( &uiRflToken); // Start an update transaction and populate the dictionary. // This also creates the default collections and indexes. if (RC_BAD( rc = beginTrans( XFLM_UPDATE_TRANS))) { goto Exit; } bTransStarted = TRUE; if (RC_BAD( rc = dictCreate( pszDictFileName, pszDictBuf))) { goto Exit; } // Because the checkpoint thread has not yet been created, // flmCommitDbTrans will force a checkpoint when it completes, // ensuring a consistent database state. bTransStarted = FALSE; if (RC_BAD( rc = commitTrans( 0, TRUE))) { goto Exit; } } else { // The uncommitted header must have all of the stuff from the committed header // in order for this to be able to work as if an update transaction was in // progress. f_memcpy( &m_pDatabase->m_uncommittedDbHdr, &m_pDatabase->m_lastCommittedDbHdr, sizeof( XFLM_DB_HDR)); } Exit: // Free the temporary buffer, if it was allocated. f_free( &pucBuf); if (pucWrappingKey) { f_free( &pucWrappingKey); } if (bTransStarted) { abortTrans(); } if( uiRflToken) { m_pDatabase->m_pRfl->enableLogging( &uiRflToken); } if (pSCache) { ScaReleaseCache( pSCache, FALSE); } return( rc); }