Files
mars-flaim/sql/src/fdbcnfig.cpp
dsandersoremutah 58d6cbdace Sync up with latest common toolkit changes.
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@612 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-06-23 21:26:53 +00:00

1308 lines
28 KiB
C++

//------------------------------------------------------------------------------
// Desc: Database config get/set functions
//
// Tabs: 3
//
// Copyright (c) 1996-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id$
//------------------------------------------------------------------------------
#include "flaimsys.h"
/****************************************************************************
Desc: Set the RFL keep files flag.
****************************************************************************/
RCODE F_Db::setRflKeepFilesFlag(
FLMBOOL bKeepFiles)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bDbLocked = FALSE;
// See if the database is being forced to close
if (RC_BAD( rc = checkState( __FILE__, __LINE__)))
{
goto Exit;
}
// Make sure we don't have a transaction going
if (m_eTransType != SFLM_NO_TRANS)
{
rc = RC_SET( NE_SFLM_TRANS_ACTIVE);
goto Exit;
}
// Make sure there is no active backup running
m_pDatabase->lockMutex();
if (m_pDatabase->m_bBackupActive)
{
m_pDatabase->unlockMutex();
rc = RC_SET( NE_SFLM_BACKUP_ACTIVE);
goto Exit;
}
m_pDatabase->unlockMutex();
// Need to lock the database but not start a transaction yet.
if (!(m_uiFlags & (FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_SHARED)))
{
if (RC_BAD( rc = dbLock( FLM_LOCK_EXCLUSIVE, 0,
FLM_NO_TIMEOUT)))
{
goto Exit;
}
bDbLocked = TRUE;
}
// If we aren't changing the keep flag, jump to exit without doing
// anything.
if ((bKeepFiles &&
m_pDatabase->m_lastCommittedDbHdr.ui8RflKeepFiles) ||
(!bKeepFiles &&
!m_pDatabase->m_lastCommittedDbHdr.ui8RflKeepFiles))
{
goto Exit; // Will return NE_SFLM_OK;
}
// Force a checkpoint and roll to the next RFL file numbers.
// When changing from keep to no-keep or vice versa, we need to
// go to a new RFL file so that the new RFL file gets new
// serial numbers and a new keep or no-keep flag.
if (RC_BAD( rc = doCheckpoint( FLM_NO_TIMEOUT)))
{
goto Exit;
}
f_memcpy( &m_pDatabase->m_uncommittedDbHdr,
&m_pDatabase->m_lastCommittedDbHdr,
sizeof( SFLM_DB_HDR));
m_pDatabase->m_uncommittedDbHdr.ui8RflKeepFiles =
(FLMUINT8)(bKeepFiles
? (FLMUINT8)1
: (FLMUINT8)0);
// Force a new RFL file - this will also write out the entire
// log header - including the changes we made above.
if (RC_BAD( rc = m_pDatabase->m_pRfl->finishCurrFile( this, TRUE)))
{
goto Exit;
}
Exit:
if (bDbLocked)
{
dbUnlock();
}
return( rc);
}
/****************************************************************************
Desc: Set the RFL directory for a database.
****************************************************************************/
RCODE F_Db::setRflDir(
const char * pszNewRflDir)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bDbLocked = FALSE;
// See if the database is being forced to close
if (RC_BAD( rc = checkState( __FILE__, __LINE__)))
{
goto Exit;
}
// Make sure we don't have a transaction going
if (m_eTransType != SFLM_NO_TRANS)
{
rc = RC_SET( NE_SFLM_TRANS_ACTIVE);
goto Exit;
}
// Make sure there is no active backup running
m_pDatabase->lockMutex();
if (m_pDatabase->m_bBackupActive)
{
m_pDatabase->unlockMutex();
rc = RC_SET( NE_SFLM_BACKUP_ACTIVE);
goto Exit;
}
m_pDatabase->unlockMutex();
// Make sure the path exists and that it is a directory
// rather than a file.
if (pszNewRflDir && *pszNewRflDir)
{
if (!gv_SFlmSysData.pFileSystem->isDir( pszNewRflDir))
{
rc = RC_SET( NE_FLM_IO_INVALID_FILENAME);
goto Exit;
}
}
// Need to lock the database because we can't change the RFL
// directory until after the checkpoint has completed. The
// checkpoint code will unlock the transaction, but not the
// file if we have an explicit lock. We need to do this to
// prevent another transaction from beginning before we have
// changed the RFL directory.
if (!(m_uiFlags & (FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_SHARED)))
{
if( RC_BAD( rc = dbLock( FLM_LOCK_EXCLUSIVE, 0,
FLM_NO_TIMEOUT)))
{
goto Exit;
}
bDbLocked = TRUE;
}
// Force a checkpoint and roll to the next RFL file numbers. Both
// of these steps are necessary to ensure that we won't have to do
// any recovery using the current RFL file - because we do not
// move the current RFL file to the new directory. Forcing the
// checkpoint ensures that we have no transactions that will need
// to be recovered if we were to crash. Rolling the RFL file number
// ensures that no more transactions will be logged to the current
// RFL file.
if (RC_BAD( rc = doCheckpoint( FLM_NO_TIMEOUT)))
{
goto Exit;
}
// Force a new RFL file.
if (RC_BAD( rc = m_pDatabase->m_pRfl->finishCurrFile( this, FALSE)))
{
goto Exit;
}
// Set the RFL directory to the new value now that we have
// finished the checkpoint and rolled to the next RFL file.
m_pDatabase->lockMutex();
rc = m_pDatabase->m_pRfl->setRflDir( pszNewRflDir);
m_pDatabase->unlockMutex();
Exit:
if (bDbLocked)
{
dbUnlock();
}
return( rc);
}
/****************************************************************************
Desc: Set the RFL file size limits for a database.
****************************************************************************/
RCODE F_Db::setRflFileSizeLimits(
FLMUINT uiMinRflSize,
FLMUINT uiMaxRflSize)
{
RCODE rc = NE_SFLM_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_SFlmSysData.uiMaxFileSize)
{
uiMaxRflSize = gv_SFlmSysData.uiMaxFileSize;
}
if (uiMinRflSize > uiMaxRflSize)
{
uiMinRflSize = uiMaxRflSize;
}
// Start an update transaction. Must not already be one going.
if (m_eTransType != SFLM_NO_TRANS)
{
rc = RC_SET( NE_SFLM_TRANS_ACTIVE);
goto Exit;
}
if (RC_BAD( rc = beginTrans( SFLM_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: Roll to the next RFL file for this database
****************************************************************************/
RCODE F_Db::rflRollToNextFile( void)
{
RCODE rc = NE_SFLM_OK;
// See if the database is being forced to close
if (RC_BAD( rc = checkState( __FILE__, __LINE__)))
{
goto Exit;
}
// NOTE: finishCurrFile will not roll to the next file if the current
// file has not been created.
if (RC_BAD( rc = m_pDatabase->m_pRfl->finishCurrFile( this, FALSE)))
{
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Set keep aborted transactions in RFL flag.
****************************************************************************/
RCODE F_Db::setKeepAbortedTransInRflFlag(
FLMBOOL bKeep
)
{
RCODE rc = NE_SFLM_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 != SFLM_NO_TRANS)
{
rc = RC_SET( NE_SFLM_TRANS_ACTIVE);
goto Exit;
}
if (RC_BAD( rc = beginTrans( SFLM_UPDATE_TRANS)))
{
goto Exit;
}
bStartedTrans = TRUE;
// Change the uncommitted log header
m_pDatabase->m_uncommittedDbHdr.ui8RflKeepAbortedTrans =
(FLMUINT8)(bKeep
? (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: Set auto turn off keep RFL flag.
****************************************************************************/
RCODE F_Db::setAutoTurnOffKeepRflFlag(
FLMBOOL bAutoTurnOff
)
{
RCODE rc = NE_SFLM_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 != SFLM_NO_TRANS)
{
rc = RC_SET( NE_SFLM_TRANS_ACTIVE);
goto Exit;
}
if (RC_BAD( rc = beginTrans( SFLM_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: Retrieves the Checkpoint info for the database passed in. This assumes
global mutex has already been locked.
*****************************************************************************/
void F_Database::getCPInfo(
SFLM_CHECKPOINT_INFO * pCheckpointInfo)
{
FLMUINT uiElapTime;
FLMUINT uiCurrTime;
flmAssert( pCheckpointInfo);
f_memset( pCheckpointInfo, 0, sizeof( SFLM_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->uiRunningTime = FLM_TIMER_UNITS_TO_MILLI( uiElapTime);
}
else
{
pCheckpointInfo->uiRunningTime = 0;
}
pCheckpointInfo->bForcingCheckpoint =
m_pCPInfo->bForcingCheckpoint;
if (m_pCPInfo->uiForceCheckpointStartTime)
{
uiCurrTime = FLM_GET_TIMER();
uiElapTime = FLM_ELAPSED_TIME( uiCurrTime,
m_pCPInfo->uiForceCheckpointStartTime);
pCheckpointInfo->uiForceCheckpointRunningTime =
FLM_TIMER_UNITS_TO_MILLI( uiElapTime);
}
else
{
pCheckpointInfo->uiForceCheckpointRunningTime = 0;
}
pCheckpointInfo->eForceCheckpointReason =
m_pCPInfo->eForceCheckpointReason;
pCheckpointInfo->bWritingDataBlocks =
m_pCPInfo->bWritingDataBlocks;
pCheckpointInfo->uiLogBlocksWritten =
m_pCPInfo->uiLogBlocksWritten;
pCheckpointInfo->uiDataBlocksWritten =
m_pCPInfo->uiDataBlocksWritten;
}
pCheckpointInfo->uiBlockSize = m_uiBlockSize;
pCheckpointInfo->uiDirtyCacheBytes =
m_uiDirtyCacheCount * m_uiBlockSize;
if (m_pCPInfo->uiStartWaitTruncateTime)
{
uiCurrTime = FLM_GET_TIMER();
uiElapTime = FLM_ELAPSED_TIME( uiCurrTime,
m_pCPInfo->uiStartWaitTruncateTime);
pCheckpointInfo->uiWaitTruncateTime =
FLM_TIMER_UNITS_TO_MILLI( uiElapTime);
}
else
{
pCheckpointInfo->uiWaitTruncateTime = 0;
}
}
}
/****************************************************************************
Desc: Retrieves the Checkpoint info for the database.
*****************************************************************************/
void F_Db::getCheckpointInfo(
SFLM_CHECKPOINT_INFO * pCheckpointInfo)
{
m_pDatabase->lockMutex();
m_pDatabase->getCPInfo( pCheckpointInfo);
m_pDatabase->unlockMutex();
}
/****************************************************************************
Desc: Returns current RFL file number
****************************************************************************/
RCODE F_Db::getRflFileNum(
FLMUINT * puiRflFileNum
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
FLMUINT uiLastCPFile;
FLMUINT uiLastTransFile;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_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);
}
/****************************************************************************
Desc: Returns highest not used RFL file number
****************************************************************************/
RCODE F_Db::getHighestNotUsedRflFileNum(
FLMUINT * puiHighestNotUsedRflFileNum
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
FLMUINT uiLastCPFile;
FLMUINT uiLastTransFile;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_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: Returns RFL file size limits for the database
****************************************************************************/
RCODE F_Db::getRflFileSizeLimits(
FLMUINT * puiRflMinFileSize,
FLMUINT * puiRflMaxFileSize
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_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 RFL keep flag for the database
****************************************************************************/
RCODE F_Db::getRflKeepFlag(
FLMBOOL * pbKeep
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_UPDATE_TRANS)))
{
goto Exit;
}
bStartedTrans = TRUE;
}
*pbKeep = m_pDatabase->m_uncommittedDbHdr.ui8RflKeepFiles
? TRUE
: FALSE;
Exit:
if (bStartedTrans)
{
abortTrans();
}
return( rc);
}
/****************************************************************************
Desc: Returns last backup transaction ID for the database
****************************************************************************/
RCODE F_Db::getLastBackupTransID(
FLMUINT64 * pui64LastBackupTransID
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_UPDATE_TRANS)))
{
goto Exit;
}
bStartedTrans = TRUE;
}
*pui64LastBackupTransID =
m_pDatabase->m_uncommittedDbHdr.ui64LastBackupTransID;
Exit:
if (bStartedTrans)
{
abortTrans();
}
return( rc);
}
/****************************************************************************
Desc: Returns blocks changed since the last backup for the database
****************************************************************************/
RCODE F_Db::getBlocksChangedSinceBackup(
FLMUINT * puiBlocksChangedSinceBackup
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_UPDATE_TRANS)))
{
goto Exit;
}
bStartedTrans = TRUE;
}
*puiBlocksChangedSinceBackup =
(FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32BlksChangedSinceBackup;
Exit:
if (bStartedTrans)
{
abortTrans();
}
return( rc);
}
/****************************************************************************
Desc: Returns the auto-turn-off-keep-RFL flag for the database
****************************************************************************/
RCODE F_Db::getAutoTurnOffKeepRflFlag(
FLMBOOL * pbAutoTurnOff
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_UPDATE_TRANS)))
{
goto Exit;
}
bStartedTrans = TRUE;
}
*pbAutoTurnOff = m_pDatabase->m_uncommittedDbHdr.ui8RflAutoTurnOffKeep
? TRUE
: FALSE;
Exit:
if (bStartedTrans)
{
abortTrans();
}
return( rc);
}
/****************************************************************************
Desc: Returns the keep aborted transactions in RFL flag for the database
****************************************************************************/
RCODE F_Db::getKeepAbortedTransInRflFlag(
FLMBOOL * pbKeep
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_UPDATE_TRANS)))
{
goto Exit;
}
bStartedTrans = TRUE;
}
*pbKeep = m_pDatabase->m_uncommittedDbHdr.ui8RflKeepAbortedTrans
? TRUE
: FALSE;
Exit:
if (bStartedTrans)
{
abortTrans();
}
return( rc);
}
/****************************************************************************
Desc: Returns disk space usage for the database
****************************************************************************/
RCODE F_Db::getDiskSpaceUsage(
FLMUINT64 * pui64DataSize,
FLMUINT64 * pui64RollbackSize,
FLMUINT64 * pui64RflSize)
{
RCODE rc = NE_SFLM_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 == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_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_SFLM_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_SFLM_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_SFlmSysData.pFileSystem->isDir( szRflDir))
{
// Open the directory and scan for RFL files.
if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->openDir( szRflDir,
"*", &pDirHdl)))
{
goto Exit;
}
for (;;)
{
if (RC_BAD( rc = pDirHdl->next()))
{
if (rc == NE_FLM_IO_NO_MORE_FILES)
{
rc = NE_SFLM_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_SFlmSysData.pFileSystem->openFile(
szTmpName, FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT,
&pFileHdl)))
{
if (rc == NE_FLM_IO_PATH_NOT_FOUND ||
rc == NE_FLM_IO_INVALID_FILENAME)
{
rc = NE_SFLM_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: Returns the next incremental backup sequence number for the database
****************************************************************************/
RCODE F_Db::getNextIncBackupSequenceNum(
FLMUINT * puiNextIncBackupSequenceNum
)
{
RCODE rc = NE_SFLM_OK;
FLMBOOL bStartedTrans = FALSE;
if (m_eTransType == SFLM_READ_TRANS)
{
rc = RC_SET( NE_SFLM_ILLEGAL_TRANS_OP);
goto Exit;
}
else if (m_eTransType != SFLM_NO_TRANS)
{
if (!okToCommitTrans())
{
rc = RC_SET( NE_SFLM_ABORT_TRANS);
goto Exit;
}
}
else
{
if (RC_BAD( rc = beginTrans( SFLM_UPDATE_TRANS)))
{
goto Exit;
}
bStartedTrans = TRUE;
}
*puiNextIncBackupSequenceNum =
(FLMUINT)m_pDatabase->m_uncommittedDbHdr.ui32IncBackupSeqNum;
Exit:
if (bStartedTrans)
{
abortTrans();
}
return( rc);
}
/****************************************************************************
Desc: Returns list of lock waiters in an object that allows caller to
iterate through the list.
****************************************************************************/
RCODE F_Db::getLockWaiters(
IF_LockInfoClient * pLockInfo
)
{
RCODE rc = NE_SFLM_OK;
if (m_pDatabase->m_pDatabaseLockObj)
{
rc = m_pDatabase->m_pDatabaseLockObj->getLockInfo( pLockInfo);
}
else
{
pLockInfo->setLockCount( 0);
}
return( rc);
}
/****************************************************************************
Desc: Returns RFL directory for the database
****************************************************************************/
void F_Db::getRflDir(
char * pszRflDir
)
{
m_pDatabase->lockMutex();
f_strcpy( pszRflDir, m_pDatabase->m_pRfl->getRflDirPtr());
m_pDatabase->unlockMutex();
}
/****************************************************************************
Desc: Returns database serial number
****************************************************************************/
void F_Db::getSerialNumber(
char * pucSerialNumber)
{
m_pDatabase->lockMutex();
f_memcpy( pucSerialNumber, m_pDatabase->m_lastCommittedDbHdr.ucDbSerialNum,
SFLM_SERIAL_NUM_SIZE);
m_pDatabase->unlockMutex();
}