Files
mars-flaim/sql/src/ffilehdr.cpp
ahodgkinson a4912ad9f6 Changed license to LGPL.
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@1012 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2007-01-23 11:59:09 +00:00

463 lines
12 KiB
C++

//------------------------------------------------------------------------------
// Desc: Routines for accessing information in the database header.
// Tabs: 3
//
// Copyright (c) 1995-2007 Novell, Inc. All Rights Reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version 2.1
// of the License.
//
// This library 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
// Library Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; 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"
FSTATIC RCODE verifyDbHdr(
SFLM_DB_HDR * pDbHdr);
/********************************************************************
Desc: This routine adjusts the block size that is passe in (wBlkSize)
to the nearest valid block size.
*********************************************************************/
FLMUINT flmAdjustBlkSize(
FLMUINT uiBlkSize)
{
FLMUINT uiTmpBlkSize;
uiTmpBlkSize = SFLM_MIN_BLOCK_SIZE;
while (uiBlkSize > uiTmpBlkSize && uiTmpBlkSize < SFLM_MAX_BLOCK_SIZE)
{
uiTmpBlkSize <<= 1;
}
return( uiTmpBlkSize);
}
/********************************************************************
Desc: This routine initializes a SFLM_DB_HDR structure.
*********************************************************************/
void flmInitDbHdr(
SFLM_CREATE_OPTS * pCreateOpts,
FLMBOOL bCreatingDatabase,
FLMBOOL bTempDb,
SFLM_DB_HDR * pDbHdr)
{
FLMUINT uiMinRflFileSize;
FLMUINT uiMaxRflFileSize;
if (bCreatingDatabase)
{
f_memset( pDbHdr, 0, sizeof( SFLM_DB_HDR));
}
// If pCreateOpts is non-NULL, copy it into the file header.
f_strcpy( (char *)pDbHdr->szSignature, SFLM_DB_SIGNATURE);
pDbHdr->ui8IsLittleEndian = SFLM_NATIVE_IS_LITTLE_ENDIAN;
if (pCreateOpts)
{
pDbHdr->ui16BlockSize = (FLMUINT16)pCreateOpts->uiBlockSize;
pDbHdr->ui8DefaultLanguage = (FLMUINT8)pCreateOpts->uiDefaultLanguage;
if (pCreateOpts->bKeepRflFiles)
{
pDbHdr->ui8RflKeepFiles = 1;
}
if (pCreateOpts->bLogAbortedTransToRfl)
{
pDbHdr->ui8RflKeepAbortedTrans = 1;
}
if( (uiMinRflFileSize = pCreateOpts->uiMinRflFileSize) == 0)
{
uiMinRflFileSize = SFLM_DEFAULT_MIN_RFL_FILE_SIZE;
}
if( (uiMaxRflFileSize = pCreateOpts->uiMaxRflFileSize) == 0)
{
uiMaxRflFileSize = SFLM_DEFAULT_MAX_RFL_FILE_SIZE;
}
}
else
{
// If pCreateOpts is NULL, initialize some default values.
pDbHdr->ui16BlockSize = SFLM_DEFAULT_BLKSIZ;
pDbHdr->ui8DefaultLanguage = SFLM_DEFAULT_LANG;
uiMinRflFileSize = SFLM_DEFAULT_MIN_RFL_FILE_SIZE;
uiMaxRflFileSize = SFLM_DEFAULT_MAX_RFL_FILE_SIZE;
}
// Make sure the RFL size 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 (uiMaxRflFileSize < RFL_MAX_PACKET_SIZE + 512)
{
uiMaxRflFileSize = RFL_MAX_PACKET_SIZE + 512;
}
if (uiMaxRflFileSize > gv_SFlmSysData.uiMaxFileSize)
{
uiMaxRflFileSize = gv_SFlmSysData.uiMaxFileSize;
}
if (uiMinRflFileSize > uiMaxRflFileSize)
{
uiMinRflFileSize = uiMaxRflFileSize;
}
pDbHdr->ui32RflMinFileSize = (FLMUINT32)uiMinRflFileSize;
pDbHdr->ui32RflMaxFileSize = (FLMUINT32)uiMaxRflFileSize;
// Only allow database to be created with current version number
pDbHdr->ui32DbVersion = SFLM_CURRENT_VERSION_NUM;
pDbHdr->ui8BlkChkSummingEnabled = 1;
// Round block size up to nearest legal block size.
pDbHdr->ui16BlockSize =
(FLMUINT16)flmAdjustBlkSize( (FLMUINT)pDbHdr->ui16BlockSize);
if (!bTempDb)
{
pDbHdr->ui32FirstLFBlkAddr = (FLMUINT32)FSBlkAddress(1, 0);
}
// If creating a database, initialize some more items.
if (bCreatingDatabase)
{
// Set the logical EOF.
if (!bTempDb)
{
pDbHdr->ui32LogicalEOF = pDbHdr->ui32FirstLFBlkAddr +
(FLMUINT32)pDbHdr->ui16BlockSize;
}
else
{
pDbHdr->ui32LogicalEOF = (FLMUINT32)FSBlkAddress(1, 0);
}
pDbHdr->ui64CurrTransID = (FLMUINT64)0;
pDbHdr->ui32RflCurrFileNum = 1;
// Putting a zero in this value tells the RFL code that the
// RFL file should be created - overwriting it if it already
// exists.
pDbHdr->ui32RflLastCPFileNum = 1;
pDbHdr->ui32RflLastCPOffset = 512;
pDbHdr->ui32RblEOF = pDbHdr->ui16BlockSize;
// Set the database serial number
f_createSerialNumber( pDbHdr->ucDbSerialNum);
// Set the "current" RFL serial number - will be stamped into the RFL
// file when it is first created.
f_createSerialNumber( pDbHdr->ucLastTransRflSerialNum);
// Set the "next" RFL serial number
f_createSerialNumber( pDbHdr->ucNextRflSerialNum);
// Set the incremental backup serial number and sequence number
f_createSerialNumber( pDbHdr->ucIncBackupSerialNum);
pDbHdr->ui32IncBackupSeqNum = 1;
// Set the file size limits
pDbHdr->ui32MaxFileSize = (FLMUINT32)gv_SFlmSysData.uiMaxFileSize;
// Need at least two blocks to create a database!
flmAssert( (FLMUINT)pDbHdr->ui32MaxFileSize >=
(FLMUINT)pDbHdr->ui16BlockSize * 2);
}
}
/***************************************************************************
Desc: This routine changes the endian-ness of the passed in 64 bit number.
If it was big-endian, it will be converted to little-endian and
vice versa.
*****************************************************************************/
void convert64(
FLMUINT64 * pui64Num
)
{
FLMBYTE * pucTmp = (FLMBYTE *)pui64Num;
FLMBYTE ucTmp;
// Swap bytes 0 and 7
ucTmp = pucTmp [0];
pucTmp [0] = pucTmp [7];
pucTmp [7] = ucTmp;
// Swap bytes 1 and 6
ucTmp = pucTmp [1];
pucTmp [1] = pucTmp [6];
pucTmp [6] = ucTmp;
// Swap bytes 2 and 5
ucTmp = pucTmp [2];
pucTmp [2] = pucTmp [5];
pucTmp [5] = ucTmp;
// Swap bytes 3 and 4
ucTmp = pucTmp [3];
pucTmp [3] = pucTmp [4];
pucTmp [4] = ucTmp;
}
/***************************************************************************
Desc: This routine changes the endian-ness of the passed in 32 bit number.
If it was big-endian, it will be converted to little-endian and
vice versa.
*****************************************************************************/
void convert32(
FLMUINT32 * pui32Num
)
{
FLMBYTE * pucTmp = (FLMBYTE *)pui32Num;
FLMBYTE ucTmp;
// Swap bytes 0 and 3
ucTmp = pucTmp [0];
pucTmp [0] = pucTmp [3];
pucTmp [3] = ucTmp;
// Swap bytes 1 and 2
ucTmp = pucTmp [1];
pucTmp [1] = pucTmp [2];
pucTmp [2] = ucTmp;
}
/***************************************************************************
Desc: This routine changes the endian-ness of the passed in 16 bit number.
If it was big-endian, it will be converted to little-endian and
vice versa.
*****************************************************************************/
void convert16(
FLMUINT16 * pui16Num
)
{
FLMBYTE * pucTmp = (FLMBYTE *)pui16Num;
FLMBYTE ucTmp;
// Swap bytes 0 and 1
ucTmp = pucTmp [0];
pucTmp [0] = pucTmp [1];
pucTmp [1] = ucTmp;
}
/***************************************************************************
Desc: This routine changed a database header to native platform format.
*****************************************************************************/
void convertDbHdr(
SFLM_DB_HDR * pDbHdr
)
{
// This routine should only be called to convert a header to native
// format.
flmAssert( hdrIsNonNativeFormat( pDbHdr));
convert16( &pDbHdr->ui16BlockSize);
convert32( &pDbHdr->ui32DbVersion);
convert64( &pDbHdr->ui64LastRflCommitID);
convert32( &pDbHdr->ui32RflLastFileNumDeleted);
convert32( &pDbHdr->ui32RflCurrFileNum);
convert32( &pDbHdr->ui32RflLastTransOffset);
convert32( &pDbHdr->ui32RflLastCPFileNum);
convert32( &pDbHdr->ui32RflLastCPOffset);
convert64( &pDbHdr->ui64RflLastCPTransID);
convert32( &pDbHdr->ui32RflMinFileSize);
convert32( &pDbHdr->ui32RflMaxFileSize);
convert64( &pDbHdr->ui64CurrTransID);
convert64( &pDbHdr->ui64TransCommitCnt);
convert32( &pDbHdr->ui32RblEOF);
convert32( &pDbHdr->ui32RblFirstCPBlkAddr);
convert32( &pDbHdr->ui32FirstAvailBlkAddr);
convert32( &pDbHdr->ui32FirstLFBlkAddr);
convert32( &pDbHdr->ui32LogicalEOF);
convert32( &pDbHdr->ui32MaxFileSize);
convert64( &pDbHdr->ui64LastBackupTransID);
convert32( &pDbHdr->ui32IncBackupSeqNum);
convert32( &pDbHdr->ui32BlksChangedSinceBackup);
convert32( &pDbHdr->ui32HdrCRC);
pDbHdr->ui8IsLittleEndian = SFLM_NATIVE_IS_LITTLE_ENDIAN;
}
/***************************************************************************
Desc: This routine verifies that the header is a real FLAIM header.
It will also change the endian-ness if need be. This should always
be called immediately after reading a header from disk.
*****************************************************************************/
FSTATIC RCODE verifyDbHdr(
SFLM_DB_HDR * pDbHdr
)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiLen;
FLMUINT32 ui32CRC;
// Calculate the checksum before doing any conversions.
ui32CRC = calcDbHdrCRC( pDbHdr);
// Convert the header to native platform format if necessary.
if (hdrIsNonNativeFormat( pDbHdr))
{
convertDbHdr( pDbHdr);
}
// Check the signature.
uiLen = f_strlen( SFLM_DB_SIGNATURE);
if (f_memcmp( pDbHdr->szSignature, SFLM_DB_SIGNATURE, uiLen) != 0)
{
rc = RC_SET( NE_SFLM_NOT_FLAIM);
goto Exit;
}
// See if the database version is OK.
switch (pDbHdr->ui32DbVersion)
{
case SFLM_CURRENT_VERSION_NUM:
{
break;
}
default:
{
if (pDbHdr->ui32DbVersion > SFLM_CURRENT_VERSION_NUM)
{
rc = RC_SET( NE_SFLM_NEWER_FLAIM);
}
else
{
rc = RC_SET( NE_SFLM_UNSUPPORTED_VERSION);
}
goto Exit;
}
}
// Validate the checksum
if (ui32CRC != pDbHdr->ui32HdrCRC)
{
rc = RC_SET( NE_SFLM_HDR_CRC);
goto Exit;
}
Exit:
return( rc);
}
/***************************************************************************
Desc: This routine reads and verifies the information contained in the
file header and log header of a FLAIM database.
*****************************************************************************/
RCODE flmReadAndVerifyHdrInfo(
SFLM_DB_STATS * pDbStats,
IF_FileHdl * pFileHdl,
SFLM_DB_HDR * pDbHdr,
FLMUINT32 * pui32CalcCRC)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiBytesRead;
// Read the database header.
f_memset( pDbHdr, 0, sizeof( SFLM_DB_HDR));
if (RC_BAD( rc = pFileHdl->read( (FLMUINT)0, sizeof( SFLM_DB_HDR),
pDbHdr, &uiBytesRead)))
{
if (rc != NE_FLM_IO_END_OF_FILE)
{
if (pDbStats)
{
pDbStats->uiReadErrors++;
}
}
else
{
if (pui32CalcCRC)
{
*pui32CalcCRC = calcDbHdrCRC( pDbHdr);
}
// Get what we can out of the header.
if (hdrIsNonNativeFormat( pDbHdr))
{
convertDbHdr( pDbHdr);
}
}
goto Exit;
}
if (pui32CalcCRC)
{
*pui32CalcCRC = calcDbHdrCRC( pDbHdr);
}
if (uiBytesRead < sizeof( SFLM_DB_HDR))
{
// Still get what we can out of the header.
if (hdrIsNonNativeFormat( pDbHdr))
{
convertDbHdr( pDbHdr);
}
rc = RC_SET( NE_SFLM_NOT_FLAIM);
goto Exit;
}
else
{
// This routine will convert to native format if it is not
// in native format.
if (RC_BAD( rc = verifyDbHdr( pDbHdr)))
{
goto Exit;
}
}
Exit:
return( rc);
}