Exemple #1
0
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);
}
Exemple #4
0
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);
}