Files
mars-flaim/sql/src/flaimsys.h
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

4429 lines
99 KiB
C++

//------------------------------------------------------------------------------
// Desc: This is the master header file for FLAIM. It is included by nearly
// all of the source files.
// Tabs: 3
//
// Copyright (c) 1991-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$
//------------------------------------------------------------------------------
#ifndef FLAIMSYS_H
#define FLAIMSYS_H
// Public includes
#include "flaimsql.h"
#if defined( FLM_WIN)
// Conversion from XXX to YYY, possible loss of data
#pragma warning( disable : 4244)
// Local variable XXX may be used without having been initialized
#pragma warning( disable : 4701)
// Function XXX not inlined
#pragma warning( disable : 4710)
#endif
#if defined( FLM_WATCOM_NLM)
// Disable "Warning! W549: col(XX) 'sizeof' operand contains
// compiler generated information"
#pragma warning 549 9
#endif
// Put all forward references here
class F_Database;
class F_Dict;
class F_Db;
class F_NameTable;
class F_Rfl;
class F_Btree;
class F_Query;
class F_DbRebuild;
class F_DbCheck;
class F_DbInfo;
class F_KeyCollector;
class FSIndexCursor;
class FSTableCursor;
class FDynSearchSet;
class F_CachedBlock;
class F_Row;
class F_GlobalCacheMgr;
class F_BlockCacheMgr;
class F_RowCacheMgr;
class F_BTreeIStream;
class F_BTreeIStreamPool;
class F_QueryResultSet;
class F_BTreeInfo;
class F_RebuildRowIStream;
class F_DbInfo;
// Some in-line functions included by other header files.
// Misc. global constants
#ifdef DEFINE_NUMBER_MAXIMUMS
#define GV_EXTERN
#else
#define GV_EXTERN extern
#endif
GV_EXTERN FLMBOOL gv_b32BitPlatform
#ifdef DEFINE_NUMBER_MAXIMUMS
= (FLMBOOL)(sizeof( FLMUINT) == 4 ? TRUE : FALSE)
#endif
;
GV_EXTERN FLMUINT gv_uiMaxUInt32Val
#ifdef DEFINE_NUMBER_MAXIMUMS
= (FLMUINT)0xFFFFFFFF
#endif
;
GV_EXTERN FLMUINT gv_uiMaxUIntVal
#ifdef DEFINE_NUMBER_MAXIMUMS
= (FLMUINT)(~(FLMUINT)0)
#endif
;
GV_EXTERN FLMUINT gv_uiMaxSignedIntVal
#ifdef DEFINE_NUMBER_MAXIMUMS
= (FLMUINT)((((~(FLMUINT)0) << 1) >> 1))
#endif
;
GV_EXTERN FLMUINT64 gv_ui64MaxSignedIntVal
#ifdef DEFINE_NUMBER_MAXIMUMS
= (FLMUINT64)((((~(FLMUINT64)0) << 1) >> 1))
#endif
;
/*****************************************************************************
Desc:
******************************************************************************/
FINLINE RCODE convertToUINT(
FLMUINT64 ui64Num,
FLMBOOL bNeg,
FLMUINT * puiNum)
{
if( bNeg)
{
return( RC_SET( NE_SFLM_CONV_NUM_UNDERFLOW));
}
if( gv_b32BitPlatform && ui64Num > 0xFFFFFFFF)
{
return( RC_SET( NE_SFLM_CONV_NUM_OVERFLOW));
}
*puiNum = (FLMUINT)ui64Num;
return( NE_SFLM_OK);
}
/*****************************************************************************
Desc:
******************************************************************************/
FINLINE RCODE convertToUINT32(
FLMUINT64 ui64Num,
FLMBOOL bNeg,
FLMUINT32 * pui32Num)
{
if( bNeg)
{
return( RC_SET( NE_SFLM_CONV_NUM_UNDERFLOW));
}
if( ui64Num > 0xFFFFFFFF)
{
return( RC_SET( NE_SFLM_CONV_NUM_OVERFLOW));
}
*pui32Num = (FLMUINT32)ui64Num;
return( NE_SFLM_OK);
}
/*****************************************************************************
Desc:
******************************************************************************/
FINLINE RCODE convertToUINT64(
FLMUINT64 ui64Num,
FLMBOOL bNeg,
FLMUINT64 * pui64Num)
{
if( bNeg)
{
return( RC_SET( NE_SFLM_CONV_NUM_UNDERFLOW));
}
*pui64Num = ui64Num;
return( NE_SFLM_OK);
}
/*****************************************************************************
Desc:
******************************************************************************/
FINLINE RCODE convertToINT(
FLMUINT64 ui64Num,
FLMBOOL bNeg,
FLMINT * piNum)
{
if( bNeg)
{
if (ui64Num == (FLMUINT64)(FLM_MAX_INT) + 1)
{
*piNum = FLM_MIN_INT;
}
else if( ui64Num > (FLMUINT64)(FLM_MAX_INT) + 1)
{
return( RC_SET( NE_SFLM_CONV_NUM_UNDERFLOW));
}
else
{
*piNum = -((FLMINT)ui64Num);
}
}
else
{
if( ui64Num > (FLMUINT64)FLM_MAX_INT)
{
return( RC_SET( NE_SFLM_CONV_NUM_OVERFLOW));
}
*piNum = (FLMINT)ui64Num;
}
return( NE_SFLM_OK);
}
/*****************************************************************************
Desc:
******************************************************************************/
FINLINE RCODE convertToINT32(
FLMUINT64 ui64Num,
FLMBOOL bNeg,
FLMINT32 * pi32Num)
{
if( bNeg)
{
if (ui64Num == (FLMUINT64)(FLM_MAX_INT32) + 1)
{
*pi32Num = FLM_MIN_INT32;
}
else if( ui64Num > (FLMUINT64)(FLM_MAX_INT32) + 1)
{
return( RC_SET( NE_SFLM_CONV_NUM_UNDERFLOW));
}
else
{
*pi32Num = -((FLMINT32)ui64Num);
}
}
else
{
if( ui64Num > (FLMUINT64)FLM_MAX_INT32)
{
return( RC_SET( NE_SFLM_CONV_NUM_OVERFLOW));
}
*pi32Num = (FLMINT32)ui64Num;
}
return( NE_SFLM_OK);
}
/*****************************************************************************
Desc:
******************************************************************************/
FINLINE RCODE convertToINT64(
FLMUINT64 ui64Num,
FLMBOOL bNeg,
FLMINT64 * pi64Num)
{
if( bNeg)
{
if( ui64Num > gv_ui64MaxSignedIntVal + 1)
{
return( RC_SET( NE_SFLM_CONV_NUM_UNDERFLOW));
}
*pi64Num = -(FLMINT64)ui64Num;
}
else
{
if( ui64Num > gv_ui64MaxSignedIntVal)
{
return( RC_SET( NE_SFLM_CONV_NUM_OVERFLOW));
}
*pi64Num = (FLMINT64)ui64Num;
}
return( NE_SFLM_OK);
}
// NOTE: ENCRYPT_MIN_CHUNK_SIZE should always be a power of 2
// getEncLen supposes that it is.
#define ENCRYPT_MIN_CHUNK_SIZE 16
#define ENCRYPT_BOUNDARY_MASK (~(ENCRYPT_MIN_CHUNK_SIZE - 1))
/*****************************************************************************
Desc: Calculate the number of bytes extra there are beyond the closest
encryption boundary.
******************************************************************************/
FINLINE FLMUINT extraEncBytes(
FLMUINT uiDataLen)
{
// This works if ENCRYPT_MIN_CHUNK_SIZE is a power of 2
// Otherwise, it needs to be changed to uiDataLen % ENCRYPT_MIN_CHUNK_SIZE
return( uiDataLen & (ENCRYPT_MIN_CHUNK_SIZE - 1));
}
/*****************************************************************************
Desc: Calculate the encryption length for a piece of data.
******************************************************************************/
FINLINE FLMUINT getEncLen(
FLMUINT uiDataLen)
{
return( extraEncBytes( uiDataLen)
? ((uiDataLen + ENCRYPT_MIN_CHUNK_SIZE) & ENCRYPT_BOUNDARY_MASK)
: uiDataLen);
}
/****************************************************************************
Storage conversion functions.
****************************************************************************/
#define FLM_MAX_NUM_BUF_SIZE 9
RCODE flmStorage2Number(
eDataType eDataTyp,
FLMUINT uiBufLen,
const FLMBYTE * pucBuf,
FLMUINT * puiNum,
FLMINT * piNum);
RCODE flmStorage2Number64(
eDataType eDataTyp,
FLMUINT uiBufLen,
const FLMBYTE * pucBuf,
FLMUINT64 * pui64Num,
FLMINT64 * pi64Num);
RCODE flmNumber64ToStorage(
FLMUINT64 ui64Num,
FLMUINT * puiBufLen,
FLMBYTE * pucBuf,
FLMBOOL bNegative,
FLMBOOL bCollation);
RCODE FlmUINT2Storage(
FLMUINT uiNum,
FLMUINT * puiBufLen,
FLMBYTE * pucBuf);
RCODE FlmINT2Storage(
FLMINT iNum,
FLMUINT * puiBufLen,
FLMBYTE * pucBuf);
RCODE flmUTF8ToStorage(
const FLMBYTE * pucUTF8,
FLMUINT uiBytesInBuffer,
FLMBYTE * pucBuf,
FLMUINT * puiBufLength);
RCODE flmGetCharCountFromStorageBuf(
const FLMBYTE ** ppucBuf,
FLMUINT uiBufSize,
FLMUINT * puiNumChars,
FLMUINT * puiSenLen = NULL);
RCODE flmStorage2UTF8(
FLMUINT uiType,
FLMUINT uiBufLength,
const FLMBYTE * pucBuffer,
FLMUINT * puiOutBufLen,
FLMBYTE * pucOutBuf);
RCODE flmStorage2UTF8(
FLMUINT uiType,
FLMUINT uiBufLength,
const FLMBYTE * pucBuffer,
F_DynaBuf * pBuffer);
RCODE flmStorage2Unicode(
FLMUINT uiType,
FLMUINT uiBufLength,
const FLMBYTE * pucBuffer,
FLMUINT * puiOutBufLen,
void * pOutBuf);
RCODE flmStorage2Unicode(
FLMUINT uiType,
FLMUINT uiStorageLength,
const FLMBYTE * pucStorageBuffer,
F_DynaBuf * pBuffer);
RCODE flmUnicode2Storage(
const FLMUNICODE * puzStr,
FLMUINT uiStrLen,
FLMBYTE * pucBuf,
FLMUINT * puiBufLength,
FLMUINT * puiCharCount);
RCODE flmStorageNum2StorageText(
const FLMBYTE * pucNum,
FLMUINT uiNumLen,
FLMBYTE * pucBuffer,
FLMUINT * puiBufLen);
/****************************************************************************
Desc: Returns the size of buffer needed to hold the unicode string in
FLAIM's storage format.
****************************************************************************/
FINLINE RCODE FlmGetUnicodeStorageLength(
FLMUNICODE * puzStr,
FLMUINT * puiByteCount)
{
FLMUINT uiByteCount;
RCODE rc;
if( RC_BAD( rc = flmUnicode2Storage( puzStr, 0, NULL,
&uiByteCount, NULL)))
{
return( rc);
}
*puiByteCount = uiByteCount + sizeof( FLMUNICODE);
return( NE_SFLM_OK);
}
/****************************************************************************
Desc: Copies and formats a Unicode string into FLAIM's storage format.
The Unicode string must be in little-endian byte order.
Unicode values that are not represented as WordPerfect 6.x characters
are preserved as non-WP characters.
****************************************************************************/
FINLINE RCODE FlmUnicode2Storage(
FLMUNICODE * puzStr,
FLMUINT * puiBufLength, // [IN] size of pBuf,
// [OUT] amount of pBuf used to hold puzStr
FLMBYTE * pBuf)
{
return( flmUnicode2Storage( puzStr, 0, pBuf, puiBufLength, NULL));
}
/****************************************************************************
Desc: Converts from FLAIM's internal storage format to a Unicode string
****************************************************************************/
FINLINE RCODE FlmStorage2Unicode(
FLMUINT uiType,
FLMUINT uiBufLength,
FLMBYTE * pBuffer,
FLMUINT * puiOutBufLen,
FLMUNICODE * puzOutBuf)
{
return( flmStorage2Unicode( uiType, uiBufLength, pBuffer,
puiOutBufLen, puzOutBuf));
}
/****************************************************************************
Desc: Convert storage text into a null-terminated UTF-8 string
****************************************************************************/
FINLINE RCODE FlmStorage2UTF8(
FLMUINT uiType,
FLMUINT uiBufLength,
FLMBYTE * pBuffer,
FLMUINT * puiOutBufLenRV,
// [IN] Specified the number of bytes available in buffer.
// [OUT] Returns the number of bytes of UTF-8 text. This value
// does not include a terminating NULL byte in the buffer.
FLMBYTE * pOutBuffer)
// [OUT] The buffer that will hold the output UTF-8 text.
// If this value is NULL then only bufLenRV will computed so that
// the caller may know how many bytes to allocate for a buffer.
{
return( flmStorage2UTF8( uiType, uiBufLength,
pBuffer, puiOutBufLenRV, pOutBuffer));
}
// Internal includes
#include "fcollate.h"
#include "fdict.h"
#include "fstructs.h"
#include "fcache.h"
#include "flmstat.h"
#include "fbtrset.h"
#include "fcollate.h"
#include "f_btree.h"
#include "f_btpool.h"
#include "rfl.h"
#include "filesys.h"
#include "flog.h"
#include "f_nici.h"
#include "sqlstatement.h"
/****************************************************************************
Desc:
****************************************************************************/
typedef struct FlmVectorElementTag
{
FLMUINT uiColumnNum;
FLMUINT uiFlags;
#define VECT_SLOT_HAS_DATA 0x01
#define VECT_SLOT_HAS_ID 0x02
#define VECT_SLOT_RIGHT_TRUNCATED 0x04
#define VECT_SLOT_LEFT_TRUNCATED 0x08
#define VECT_SLOT_HAS_COLUMN_NUM 0x10
#define VECT_SLOT_IS_ATTR 0x20
#define VECT_SLOT_IS_DATA 0x40
eDataType eDataTyp;
FLMUINT uiDataLength;
FLMUINT uiDataOffset;
} F_VECTOR_ELEMENT;
/*****************************************************************************
Desc: Used to build keys and data components
*****************************************************************************/
class F_DataVector : public F_Object
{
public:
// Constructor/Destructor
F_DataVector();
virtual ~F_DataVector();
// Setter methods
FINLINE void setRowID(
FLMUINT64 ui64RowId)
{
m_ui64RowId = ui64RowId;
}
RCODE setColumnNum(
FLMUINT uiElementNumber,
FLMUINT uiColumnNum,
FLMBOOL bIsData);
RCODE setINT(
FLMUINT uiElementNumber,
FLMINT iNum);
RCODE setINT64(
FLMUINT uiElementNumber,
FLMINT64 i64Num);
RCODE setUINT(
FLMUINT uiElementNumber,
FLMUINT uiNum);
RCODE setUINT64(
FLMUINT uiElementNumber,
FLMUINT64 ui64Num);
RCODE setUnicode(
FLMUINT uiElementNumber,
const FLMUNICODE * puzUnicode);
RCODE setUTF8(
FLMUINT uiElementNumber,
const FLMBYTE * pszUtf8,
FLMUINT uiBytesInBuffer = 0);
FINLINE RCODE setBinary(
FLMUINT uiElementNumber,
const void * pvBinary,
FLMUINT uiBinaryLen)
{
return( storeValue( uiElementNumber,
SFLM_BINARY_TYPE, (FLMBYTE *)pvBinary, uiBinaryLen));
}
FINLINE void setRightTruncated(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) != NULL)
{
setRightTruncated( pVector);
}
else
{
// Need to set some data value before setting
// truncated.
flmAssert( 0);
}
}
FINLINE void setLeftTruncated(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) != NULL)
{
setLeftTruncated( pVector);
}
else
{
// Need to set some data value before setting
// truncated.
flmAssert( 0);
}
}
FINLINE void clearRightTruncated(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) != NULL)
{
clearRightTruncated( pVector);
}
else
{
// Need to set some data value before clearing
// truncated.
flmAssert( 0);
}
}
FINLINE void clearLeftTruncated(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) != NULL)
{
clearLeftTruncated( pVector);
}
else
{
// Need to set some data value before clearing
// truncated.
flmAssert( 0);
}
}
FINLINE FLMBOOL isRightTruncated(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) != NULL)
{
return( isRightTruncated( pVector));
}
return( FALSE);
}
FINLINE FLMBOOL isLeftTruncated(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) != NULL)
{
return( isLeftTruncated( pVector));
}
return( FALSE);
}
// Getter methods
FINLINE FLMUINT64 getRowId( void)
{
return( m_ui64RowId);
}
FINLINE FLMUINT getColumnNum(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_COLUMN_NUM)) == NULL)
{
return( 0);
}
else
{
return( pVector->uiColumnNum);
}
}
FINLINE FLMBOOL isDataComponent(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_COLUMN_NUM)) == NULL)
{
return( FALSE);
}
else
{
return( (pVector->uiFlags & VECT_SLOT_IS_DATA) ? TRUE : FALSE);
}
}
FINLINE FLMBOOL isKeyComponent(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_COLUMN_NUM)) == NULL)
{
return( FALSE);
}
else
{
return( (pVector->uiFlags & VECT_SLOT_IS_DATA) ? FALSE : TRUE);
}
}
FLMUINT getDataLength(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) == NULL)
{
return( 0);
}
else
{
return( pVector->uiDataLength);
}
}
eDataType getDataType(
FLMUINT uiElementNumber)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) == NULL)
{
return( SFLM_UNKNOWN_TYPE);
}
else
{
return( pVector->eDataTyp);
}
}
RCODE getUTF8Ptr(
FLMUINT uiElementNumber,
const FLMBYTE ** ppszUTF8,
FLMUINT * puiBufLen);
FINLINE RCODE getINT(
FLMUINT uiElementNumber,
FLMINT * piNum)
{
F_VECTOR_ELEMENT * pVector;
return( (RCODE)((pVector = getVector( uiElementNumber,
VECT_SLOT_HAS_DATA)) != NULL
? flmStorage2Number( pVector->eDataTyp,
pVector->uiDataLength,
(FLMBYTE *)getDataPtr( pVector),
NULL, piNum)
: RC_SET( NE_SFLM_NOT_FOUND)));
}
FINLINE RCODE getINT64(
FLMUINT uiElementNumber,
FLMINT64 * pi64Num)
{
F_VECTOR_ELEMENT * pVector;
return( (RCODE)((pVector = getVector( uiElementNumber,
VECT_SLOT_HAS_DATA)) != NULL
? flmStorage2Number64( pVector->eDataTyp,
pVector->uiDataLength,
(FLMBYTE *)getDataPtr( pVector),
NULL, pi64Num)
: RC_SET( NE_SFLM_NOT_FOUND)));
}
FINLINE RCODE getUINT(
FLMUINT uiElementNumber,
FLMUINT * puiNum)
{
F_VECTOR_ELEMENT * pVector;
return( (RCODE)((pVector = getVector( uiElementNumber,
VECT_SLOT_HAS_DATA)) != NULL
? flmStorage2Number( pVector->eDataTyp,
pVector->uiDataLength,
(FLMBYTE *)getDataPtr( pVector),
puiNum, NULL)
: RC_SET( NE_SFLM_NOT_FOUND)));
}
FINLINE RCODE getUINT64(
FLMUINT uiElementNumber,
FLMUINT64 * pui64Num)
{
F_VECTOR_ELEMENT * pVector;
return( (RCODE)((pVector = getVector( uiElementNumber,
VECT_SLOT_HAS_DATA)) != NULL
? flmStorage2Number64( pVector->eDataTyp,
pVector->uiDataLength,
(FLMBYTE *)getDataPtr( pVector),
pui64Num, NULL)
: RC_SET( NE_SFLM_NOT_FOUND)));
}
RCODE getUnicode(
FLMUINT uiElementNumber,
FLMUNICODE ** ppuzUnicode);
FINLINE RCODE getUnicode(
FLMUINT uiElementNumber,
F_DynaBuf * pBuffer)
{
F_VECTOR_ELEMENT * pVector;
return( (RCODE)((pVector = getVector( uiElementNumber,
VECT_SLOT_HAS_DATA)) != NULL
? flmStorage2Unicode( pVector->eDataTyp,
pVector->uiDataLength,
(FLMBYTE *)getDataPtr( pVector),
pBuffer)
: RC_SET( NE_SFLM_NOT_FOUND)));
}
FINLINE RCODE getUnicode(
FLMUINT uiElementNumber,
FLMUNICODE * puzUnicode,
FLMUINT * puiBufLen)
{
F_VECTOR_ELEMENT * pVector;
return( (RCODE)((pVector = getVector( uiElementNumber,
VECT_SLOT_HAS_DATA)) != NULL
? flmStorage2Unicode( pVector->eDataTyp,
pVector->uiDataLength,
(FLMBYTE *)getDataPtr( pVector),
puiBufLen, puzUnicode)
: RC_SET( NE_SFLM_NOT_FOUND)));
}
FINLINE RCODE getUTF8(
FLMUINT uiElementNumber,
FLMBYTE * pszUTF8,
FLMUINT * puiBufLen)
{
F_VECTOR_ELEMENT * pVector;
return( (RCODE)((pVector = getVector( uiElementNumber,
VECT_SLOT_HAS_DATA)) != NULL
? flmStorage2UTF8( pVector->eDataTyp,
pVector->uiDataLength,
(FLMBYTE *)getDataPtr( pVector),
puiBufLen, pszUTF8)
: RC_SET( NE_SFLM_NOT_FOUND)));
}
FINLINE RCODE getUTF8(
FLMUINT uiElementNumber,
F_DynaBuf * pBuffer)
{
F_VECTOR_ELEMENT * pVector;
return( (RCODE)((pVector = getVector( uiElementNumber,
VECT_SLOT_HAS_DATA)) != NULL
? flmStorage2UTF8( pVector->eDataTyp,
pVector->uiDataLength,
(FLMBYTE *)getDataPtr( pVector),
pBuffer)
: RC_SET( NE_SFLM_NOT_FOUND)));
}
FINLINE RCODE getBinary(
FLMUINT uiElementNumber,
void * pvBuffer,
FLMUINT * puiLength)
{
F_VECTOR_ELEMENT * pVector;
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) != NULL)
{
*puiLength = f_min( (*puiLength), pVector->uiDataLength);
if (pvBuffer && *puiLength)
{
f_memcpy( pvBuffer, getDataPtr( pVector), *puiLength);
}
return( NE_SFLM_OK);
}
else
{
*puiLength = 0;
}
return( RC_SET( NE_SFLM_NOT_FOUND));
}
FINLINE RCODE getBinary(
FLMUINT uiElementNumber,
F_DynaBuf * pBuffer)
{
F_VECTOR_ELEMENT * pVector;
pBuffer->truncateData( 0);
if ((pVector = getVector( uiElementNumber, VECT_SLOT_HAS_DATA)) != NULL)
{
return( pBuffer->appendData( getDataPtr( pVector),
pVector->uiDataLength));
}
return( RC_SET( NE_SFLM_NOT_FOUND));
}
RCODE outputKey(
F_Db * pDb,
FLMUINT uiIndexNum,
FLMUINT uiMatchFlags,
FLMBYTE * pucKeyBuf,
FLMUINT uiKeyBufSize,
FLMUINT * puiKeyLen,
FLMUINT uiSearchKeyFlag);
RCODE outputData(
F_Db * pDb,
FLMUINT uiIndexNum,
FLMBYTE * pucDataBuf,
FLMUINT uiDataBufSize,
FLMUINT * puiDataLen);
RCODE inputKey(
F_Db * pDb,
FLMUINT uiIndexNum,
const FLMBYTE * pucKey,
FLMUINT uiKeyLen);
RCODE inputData(
F_Db * pDb,
FLMUINT uiIndexNum,
const FLMBYTE * pucData,
FLMUINT uiDataLen);
// Miscellaneous methods
void reset( void);
FINLINE const void * getDataPtr(
FLMUINT uiElementNumber)
{
return( getDataPtr( getVector( uiElementNumber, VECT_SLOT_HAS_DATA)));
}
RCODE copyVector(
F_DataVector * pSrcVector);
private:
RCODE allocVectorArray(
FLMUINT uiElementNumber);
RCODE storeValue(
FLMINT uiElementNumber,
eDataType eDataTyp,
const FLMBYTE * pucData,
FLMUINT uiDataLen,
FLMBYTE ** ppucDataPtr = NULL);
FINLINE F_VECTOR_ELEMENT * getVector(
FLMUINT uiElementNumber,
FLMUINT uiTestFlags)
{
F_VECTOR_ELEMENT * pVector;
if (uiElementNumber >= m_uiNumElements)
{
return( NULL);
}
pVector = &m_pVectorElements [uiElementNumber];
if (!(pVector->uiFlags & uiTestFlags))
{
return( NULL);
}
else
{
return( pVector);
}
}
FINLINE FLMBOOL isRightTruncated(
F_VECTOR_ELEMENT * pVector)
{
return( (pVector->uiFlags & VECT_SLOT_RIGHT_TRUNCATED)
? TRUE
: FALSE);
}
FINLINE void setRightTruncated(
F_VECTOR_ELEMENT * pVector)
{
pVector->uiFlags |= VECT_SLOT_RIGHT_TRUNCATED;
}
FINLINE void clearRightTruncated(
F_VECTOR_ELEMENT * pVector)
{
pVector->uiFlags &= (~(VECT_SLOT_RIGHT_TRUNCATED));
}
FINLINE FLMBOOL isLeftTruncated(
F_VECTOR_ELEMENT * pVector)
{
return( (pVector->uiFlags & VECT_SLOT_LEFT_TRUNCATED)
? TRUE
: FALSE);
}
FINLINE void setLeftTruncated(
F_VECTOR_ELEMENT * pVector)
{
pVector->uiFlags |= VECT_SLOT_LEFT_TRUNCATED;
}
FINLINE void clearLeftTruncated(
F_VECTOR_ELEMENT * pVector)
{
pVector->uiFlags &= (~(VECT_SLOT_LEFT_TRUNCATED));
}
FINLINE void * getDataPtr(
F_VECTOR_ELEMENT * pVector)
{
if (!pVector || !pVector->uiDataLength)
{
return( NULL);
}
else if (pVector->uiDataLength <= sizeof( FLMUINT))
{
return( (void *)&pVector->uiDataOffset);
}
else
{
return( (void *)(m_pucDataBuf + pVector->uiDataOffset));
}
}
#define MIN_VECTOR_ELEMENTS 6
F_VECTOR_ELEMENT m_VectorArray [MIN_VECTOR_ELEMENTS];
F_VECTOR_ELEMENT * m_pVectorElements; // Pointer to vector elements
FLMUINT m_uiVectorArraySize; // Size of vector array
FLMUINT m_uiNumElements; // Number of elements actually
// populated in the array.
FLMBYTE m_ucIntDataBuf[ 32]; // Internal data buffer
FLMBYTE * m_pucDataBuf; // Values stored here
FLMUINT m_uiDataBufLength; // Bytes of data allocated
FLMUINT m_uiDataBufOffset; // Current offset into allocated
// data buffer.
FLMUINT64 m_ui64RowId; // Row ID;
friend class F_Db;
friend class FSIndexCursor;
friend class FSTableCursor;
friend class F_QueryResultSet;
};
// Flags for the m_uiFlags member of the F_Db object
#define FDB_UPDATED_DICTIONARY 0x0001
// Flag indicating whether the file's
// local dictionary was updated
// during the transaction.
#define FDB_DO_TRUNCATE 0x0002
// Truncate log extents at the end
// of a transaction.
#define FDB_HAS_FILE_LOCK 0x0004
// FDB has a file lock.
#define FDB_FILE_LOCK_SHARED 0x0008
// File lock is shared. Update
// transactions are not allowed when
// the lock is shared.
#define FDB_FILE_LOCK_IMPLICIT 0x0010
// File lock is implicit - means file
// lock was obtained when the update
// transaction began and cannot be
// released by a call to FlmDbUnlock.
#define FDB_DONT_KILL_TRANS 0x0020
// Do not attempt to kill an active
// read transaction on this database
// handle. This is used by FlmDbBackup.
#define FDB_INTERNAL_OPEN 0x0040
// FDB is an internal one used by a
// background thread.
#define FDB_DONT_POISON_CACHE 0x0080
// If blocks are read from disk during
// a transaction, release them at the LRU
// end of the cache chain.
#define FDB_UPGRADING 0x0100
// Database is being upgraded.
#define FDB_REPLAYING_RFL 0x0200
// Database is being recovered
#define FDB_REPLAYING_COMMIT 0x0400
// During replay of the RFL, this
// is an actual call to FlmDbTransCommit.
#define FDB_BACKGROUND_INDEXING 0x0800
// FDB is being used by a background indexing
// thread
#define FDB_HAS_WRITE_LOCK 0x1000
// FDB has the write lock
#define FDB_REBUILDING_DATABASE 0x2000
// Database is being rebuilt
#define FDB_SWEEP_SCHEDULED 0x4000
// Sweep operation scheduled due to a
// dictionary change during the transaction
/*****************************************************************************
Desc: Class for performing database backup.
*****************************************************************************/
class F_Backup : public F_Object
{
public:
F_Backup();
virtual ~F_Backup();
FINLINE FLMUINT64 getBackupTransId( void)
{
return( m_ui64TransId);
}
FINLINE FLMUINT64 getLastBackupTransId( void)
{
return( m_ui64LastBackupTransId);
}
RCODE backup(
const char * pszBackupPath,
const char * pszPassword,
IF_BackupClient * pClient,
IF_BackupStatus * pStatus,
FLMUINT * puiIncSeqNum);
RCODE endBackup( void);
private:
void reset( void);
F_Db * m_pDb;
eDbTransType m_eTransType;
FLMUINT64 m_ui64TransId;
FLMUINT64 m_ui64LastBackupTransId;
FLMUINT m_uiDbVersion;
FLMUINT m_uiBlkChgSinceLastBackup;
FLMBOOL m_bTransStarted;
FLMUINT m_uiBlockSize;
FLMUINT m_uiLogicalEOF;
FLMUINT m_uiFirstReqRfl;
FLMUINT m_uiIncSeqNum;
FLMBOOL m_bCompletedBackup;
eDbBackupType m_eBackupType;
RCODE m_backupRc;
FLMBYTE m_ucNextIncSerialNum[ SFLM_SERIAL_NUM_SIZE];
char m_szDbPath[ F_PATH_MAX_SIZE];
SFLM_DB_HDR m_dbHdr;
friend class F_Db;
};
/*****************************************************************************
Desc: An implementation of IF_Backup_Client that backs up to the
local hard disk.
*****************************************************************************/
class F_DefaultBackupClient : public IF_BackupClient
{
public:
F_DefaultBackupClient(
const char * pszBackupPath);
virtual ~F_DefaultBackupClient();
RCODE WriteData(
const void * pvBuffer,
FLMUINT uiBytesToWrite);
virtual FLMINT FLMAPI getRefCount( void)
{
return( IF_BackupClient::getRefCount());
}
virtual FLMINT FLMAPI AddRef( void)
{
return( IF_BackupClient::AddRef());
}
virtual FLMINT FLMAPI Release( void)
{
return( IF_BackupClient::Release());
}
private:
char m_szPath[ F_PATH_MAX_SIZE];
IF_MultiFileHdl * m_pMultiFileHdl;
FLMUINT64 m_ui64Offset;
RCODE m_rc;
};
/*****************************************************************************
Desc: The F_FSRestore class is used to read backup and RFL files from
a disk file system.
*****************************************************************************/
class F_FSRestore : public IF_RestoreClient
{
public:
virtual ~F_FSRestore();
F_FSRestore();
RCODE setup(
const char * pszDbPath,
const char * pszBackupSetPath,
const char * pszRflDir);
RCODE openBackupSet( void);
RCODE openIncFile(
FLMUINT uiFileNum);
RCODE openRflFile(
FLMUINT uiFileNum);
RCODE read(
FLMUINT uiLength,
void * pvBuffer,
FLMUINT * puiBytesRead);
RCODE close( void);
RCODE abortFile( void);
virtual FLMINT FLMAPI getRefCount( void)
{
return( IF_RestoreClient::getRefCount());
}
virtual FLMINT FLMAPI AddRef( void)
{
return( IF_RestoreClient::AddRef());
}
virtual FLMINT FLMAPI Release( void)
{
return( IF_RestoreClient::Release());
}
protected:
IF_FileHdl * m_pFileHdl;
IF_MultiFileHdl * m_pMultiFileHdl;
FLMUINT64 m_ui64Offset;
FLMUINT m_uiDbVersion;
char m_szDbPath[ F_PATH_MAX_SIZE];
char m_szBackupSetPath[ F_PATH_MAX_SIZE];
char m_szRflDir[ F_PATH_MAX_SIZE];
FLMBOOL m_bSetupCalled;
FLMBOOL m_bOpen;
};
/*****************************************************************************
Desc: Default implementation of a restore status object than can
be inherited by a user implementation.
*****************************************************************************/
class F_DefaultRestoreStatus : public IF_RestoreStatus
{
public:
F_DefaultRestoreStatus()
{
}
RCODE reportProgress(
eRestoreAction * peAction,
FLMUINT64, // ui64BytesToDo,
FLMUINT64) // ui64BytesDone
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportError(
eRestoreAction * peAction,
RCODE) // rcErr
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportBeginTrans(
eRestoreAction * peAction,
FLMUINT64) // ui64TransId
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportCommitTrans(
eRestoreAction * peAction,
FLMUINT64) // ui64TransId
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportAbortTrans(
eRestoreAction * peAction,
FLMUINT64) // ui64TransId
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportRemoveData(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT, // uiLfNum,
FLMUINT, // uiKeyLen,
FLMBYTE *) // pucKey
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportInsertData(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT, // uiLfNum,
FLMUINT, // uiKeyLen,
FLMBYTE *) // pucKey
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportReplaceData(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT, // uiLfNum,
FLMUINT, // uiKeyLen,
FLMBYTE *) // pucKey
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportLFileCreate(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT) // uiLfNum
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportLFileUpdate(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT, // uiLfNum,
FLMUINT, // uiRootBlk,
FLMUINT64, // ui64NextNodeId,
FLMUINT64, // ui64FirstDocId,
FLMUINT64 // ui64LastDocId
)
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportUpdateDict(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT, // uiDictType,
FLMUINT, // uiDictNum,
FLMBOOL) // bDeleting
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportIndexSuspend(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT) // uiIndexNum
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportIndexResume(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT) // uiIndexNum
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportReduce(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT) // uiCount
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportUpgrade(
eRestoreAction * peAction,
FLMUINT64, // ui64TransId,
FLMUINT, // uiOldDbVersion,
FLMUINT) // uiNewDbVersion
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportEnableEncryption(
eRestoreAction * peAction,
FLMUINT64 // ui64TransId
)
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportWrapKey(
eRestoreAction * peAction,
FLMUINT64) // ui64TransId
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportOpenRflFile(
eRestoreAction * peAction,
FLMUINT) // uiFileNum
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
RCODE reportRflRead(
eRestoreAction * peAction,
FLMUINT, // uiFileNum,
FLMUINT) // uiBytesRead
{
*peAction = SFLM_RESTORE_ACTION_CONTINUE;
return( NE_SFLM_OK);
}
virtual FLMINT FLMAPI getRefCount( void)
{
return( IF_RestoreStatus::getRefCount());
}
virtual FLMINT FLMAPI AddRef( void)
{
return( IF_RestoreStatus::AddRef());
}
virtual FLMINT FLMAPI Release( void)
{
return( IF_RestoreStatus::Release());
}
};
typedef struct KEY_GEN_INFO
{
F_TABLE * pTable;
F_INDEX * pIndex;
F_Row * pRow;
F_COLUMN_VALUE * pColumnValues;
FLMBOOL bIsAsia;
FLMBOOL bIsCompound;
FLMBOOL bAddKeys;
FLMBYTE * pucKeyBuf;
FLMBYTE * pucData;
FLMUINT uiDataBufSize;
FLMBOOL bDataBufAllocated;
} KEY_GEN_INFO;
#define FLM_NO_TIMEOUT 0xFF
/*****************************************************************************
Desc: Thread's database object - returned by openDatabase, createDatabase in F_DbSystem class
*****************************************************************************/
class F_Db : public F_Object
{
public:
F_Db(
FLMBOOL bInternalOpen);
virtual ~F_Db();
RCODE transBegin(
eDbTransType eTransType,
FLMUINT uiMaxLockWait = FLM_NO_TIMEOUT,
FLMUINT uiFlags = 0,
SFLM_DB_HDR * pDbHeader = NULL);
RCODE transBegin(
F_Db * pDb);
RCODE transCommit(
FLMBOOL * pbEmpty = NULL);
RCODE transAbort( void);
FINLINE eDbTransType getTransType( void)
{
return( m_eTransType);
}
RCODE doCheckpoint(
FLMUINT uiTimeout);
RCODE dbLock(
eLockType eLockType,
FLMINT iPriority,
FLMUINT uiTimeout);
RCODE dbUnlock( void);
RCODE getLockType(
eLockType * peLockType,
FLMBOOL * pbImplicit);
RCODE getLockInfo(
FLMINT iPriority,
eLockType * peCurrLockType,
FLMUINT * puiThreadId,
FLMUINT * puiNumExclQueued,
FLMUINT * puiNumSharedQueued,
FLMUINT * puiPriorityCount);
RCODE dupTrans(
FLMUINT64 ui64TransId);
RCODE demoteTrans( void);
RCODE cancelTrans(
FLMUINT64 ui64TransId);
RCODE getCommitCnt(
FLMUINT64 * pui64CommitCount);
// Index methods
RCODE indexStatus(
FLMUINT uiIndexNum,
SFLM_INDEX_STATUS * pIndexStatus);
RCODE indexGetNext(
FLMUINT * puiIndexNum);
RCODE indexSuspend(
FLMUINT uiIndexNum);
RCODE indexResume(
FLMUINT uiIndexNum);
// Retrieval Functions
RCODE keyRetrieve(
FLMUINT uiIndex,
F_DataVector * pSearchKey,
FLMUINT uiFlags,
F_DataVector * pFoundKey);
RCODE enableEncryption( void);
RCODE wrapKey(
const char * pszPassword = NULL);
RCODE rollOverDbKey( void);
RCODE reduceSize(
FLMUINT uiCount,
FLMUINT * puiCountRV);
RCODE upgrade(
IF_UpgradeClient * pUpgradeClient);
RCODE backupBegin(
eDbBackupType eBackupType,
eDbTransType eTransType,
FLMUINT uiMaxLockWait,
F_Backup ** ppBackup);
void getRflFileName(
FLMUINT uiFileNum,
FLMBOOL bBaseOnly,
char * pszFileName,
FLMUINT * puiFileNameBufSize,
FLMBOOL * pbNameTruncated = NULL);
// Configuration methods
RCODE setRflKeepFilesFlag(
FLMBOOL bKeep);
RCODE getRflKeepFlag(
FLMBOOL * pbKeep);
RCODE setRflDir(
const char * pszNewRflDir);
void getRflDir(
char * pszRflDir);
RCODE getRflFileNum(
FLMUINT * puiRflFileNum);
RCODE getHighestNotUsedRflFileNum(
FLMUINT * puiHighestNotUsedRflFileNum);
RCODE setRflFileSizeLimits(
FLMUINT uiMinRflSize,
FLMUINT uiMaxRflSize);
RCODE getRflFileSizeLimits(
FLMUINT * puiRflMinFileSize,
FLMUINT * puiRflMaxFileSize);
RCODE rflRollToNextFile( void);
RCODE setKeepAbortedTransInRflFlag(
FLMBOOL bKeep);
RCODE getKeepAbortedTransInRflFlag(
FLMBOOL * pbKeep);
RCODE setAutoTurnOffKeepRflFlag(
FLMBOOL bAutoTurnOff);
RCODE getAutoTurnOffKeepRflFlag(
FLMBOOL * pbAutoTurnOff);
FINLINE void setFileExtendSize(
FLMUINT uiFileExtendSize)
{
m_pDatabase->m_uiFileExtendSize = uiFileExtendSize;
}
FINLINE FLMUINT getFileExtendSize( void)
{
return( m_pDatabase->m_uiFileExtendSize);
}
FINLINE void setAppData(
void * pvAppData)
{
m_pvAppData = pvAppData;
}
FINLINE void * getAppData( void)
{
return( m_pvAppData);
}
FINLINE void setDeleteStatusObject(
IF_DeleteStatus * pDeleteStatus)
{
if (m_pDeleteStatus)
{
m_pDeleteStatus->Release();
}
if ((m_pDeleteStatus = pDeleteStatus) != NULL)
{
m_pDeleteStatus->AddRef();
}
}
FINLINE void setCommitClientObject(
IF_CommitClient * pCommitClient)
{
if (m_pCommitClient)
{
m_pCommitClient->Release();
}
m_pCommitClient = pCommitClient;
if (m_pCommitClient)
{
m_pCommitClient->AddRef();
}
}
FINLINE void setIndexingClientObject(
IF_IxClient * pIxClient)
{
if (m_pIxClient)
{
m_pIxClient->Release();
}
m_pIxClient = pIxClient;
if (m_pIxClient)
{
m_pIxClient->AddRef();
}
}
FINLINE void setIndexingStatusObject(
IF_IxStatus * ifpIxStatus)
{
if (m_pIxStatus)
{
m_pIxStatus->Release();
}
m_pIxStatus = ifpIxStatus;
if (m_pIxStatus)
{
m_pIxStatus->AddRef();
}
}
// Configuration information getting methods
FINLINE FLMUINT getDbVersion( void)
{
return( (FLMUINT)m_pDatabase->m_lastCommittedDbHdr.ui32DbVersion);
}
FINLINE FLMUINT getBlockSize( void)
{
return( m_pDatabase->m_uiBlockSize);
}
FINLINE FLMUINT getDefaultLanguage( void)
{
return( m_pDatabase->m_uiDefaultLanguage);
}
FINLINE FLMUINT64 getTransID( void)
{
if (m_eTransType != SFLM_NO_TRANS)
{
return( m_ui64CurrTransID);
}
else if (m_uiFlags & FDB_HAS_FILE_LOCK)
{
return( m_pDatabase->m_lastCommittedDbHdr.ui64CurrTransID);
}
return( 0);
}
void getCheckpointInfo(
SFLM_CHECKPOINT_INFO * pCheckpointInfo);
RCODE getDbControlFileName(
char * pszControlFileName,
FLMUINT uiControlFileBufSize)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiLen = f_strlen( m_pDatabase->m_pszDbPath);
if (uiLen + 1 > uiControlFileBufSize)
{
uiLen = uiControlFileBufSize - 1;
rc = RC_SET( NE_SFLM_BUFFER_OVERFLOW);
}
f_memcpy( pszControlFileName, m_pDatabase->m_pszDbPath, uiLen);
pszControlFileName [uiLen] = 0;
return( rc);
}
RCODE getLockWaiters(
IF_LockInfoClient * pLockInfo);
RCODE getLastBackupTransID(
FLMUINT64 * pui64LastBackupTransID);
RCODE getBlocksChangedSinceBackup(
FLMUINT * puiBlocksChangedSinceBackup);
RCODE getNextIncBackupSequenceNum(
FLMUINT * puiNextIncBackupSequenceNum);
void getSerialNumber(
char * pucSerialNumber);
RCODE getDiskSpaceUsage(
FLMUINT64 * pui64DataSize,
FLMUINT64 * pui64RollbackSize,
FLMUINT64 * pui64RflSize);
FINLINE RCODE getMustCloseRC( void)
{
return( m_pDatabase->m_rcMustClose);
}
FINLINE RCODE getAbortRC( void)
{
return( m_AbortRc);
}
FINLINE RCODE startTransaction(
eDbTransType eReqTransType,
FLMBOOL * pbStartedTrans)
{
RCODE rc;
if( m_eTransType != SFLM_NO_TRANS)
{
return( RC_SET_AND_ASSERT( NE_SFLM_ILLEGAL_TRANS_OP));
}
if( !pbStartedTrans)
{
return( RC_SET( NE_SFLM_NO_TRANS_ACTIVE));
}
if( RC_BAD( rc = transBegin( eReqTransType)))
{
return( rc);
}
*pbStartedTrans = TRUE;
return( NE_SFLM_OK);
}
FINLINE RCODE checkTransaction(
eDbTransType eReqTransType,
FLMBOOL * pbStartedTrans)
{
if( m_AbortRc)
{
return( m_AbortRc);
}
else if( m_eTransType >= eReqTransType)
{
return( NE_SFLM_OK);
}
return( startTransaction( eReqTransType, pbStartedTrans));
}
FINLINE void setMustAbortTrans(
RCODE rc)
{
if( RC_BAD( rc) && RC_OK( m_AbortRc))
{
m_AbortRc = rc;
}
}
FINLINE RCODE checkState(
const char * pszFileName,
FLMINT iLineNumber)
{
RCODE rc = NE_SFLM_OK;
if (m_bMustClose)
{
m_pDatabase->logMustCloseReason( pszFileName, iLineNumber);
rc = RC_SET( NE_SFLM_MUST_CLOSE_DATABASE);
}
return( rc);
}
FINLINE F_Database * getDatabase( void)
{
return m_pDatabase;
}
RCODE backgroundIndexBuild(
IF_Thread * pThread,
FLMBOOL * pbShutdown,
FLMINT * piErrorLine);
FINLINE FLMUINT getLogicalEOF( void)
{
return( m_uiLogicalEOF);
}
// Key Collector object, used when checking indexes
FINLINE void setKeyCollector(
F_KeyCollector * pKeyColl)
{
m_pKeyColl = pKeyColl;
}
FINLINE F_KeyCollector * getKeyCollector( void)
{
return m_pKeyColl;
}
RCODE waitForMaintenanceToComplete( void);
FINLINE F_Dict * getDict( void)
{
return( m_pDict);
}
void removeTableRows(
FLMUINT uiTableNum,
FLMUINT64 ui64TransId);
RCODE insertRow(
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues);
RCODE updateRow(
FLMUINT uiTableNum,
F_Row ** ppRow,
F_COLUMN_VALUE * pColumnValues);
RCODE deleteRow(
FLMUINT uiTableNum,
FLMUINT64 ui64RowId,
FLMBOOL bLogDelete);
RCODE deleteSelectedRows(
FLMUINT uiTableNum,
SQLQuery * pSqlQuery);
RCODE updateSelectedRows(
FLMUINT uiTableNum,
SQLQuery * pSqlQuery,
COLUMN_SET * pFirstColumnSet,
FLMUINT uiNumColumnsToSet);
RCODE createTable(
FLMUINT uiTableNum,
const char * pszTableName,
FLMUINT uiTableNameLen,
FLMUINT uiEncDefNum,
F_COLUMN_DEF * pColumnDefs,
FLMUINT uiNumColumnDefs);
RCODE dropTable(
FLMUINT uiTableNum);
RCODE createIndex(
FLMUINT uiTableNum,
FLMUINT uiIndexNum,
const char * pszIndexName,
FLMUINT uiIndexNameLen,
FLMUINT uiEncDefNum,
FLMUINT uiFlags,
F_INDEX_COL_DEF * pIxColDefs,
FLMUINT uiNumIxColDefs);
RCODE dropIndex(
FLMUINT uiIndexNum);
private:
// This routine assumes that the database mutex is locked
FINLINE void linkToDict(
F_Dict * pDict)
{
if (pDict != m_pDict)
{
if (m_pDict)
{
unlinkFromDict();
}
if ((m_pDict = pDict) != NULL)
{
pDict->incrUseCount();
}
}
}
// This routine assumes the database mutex is locked.
FINLINE void unlinkFromDict( void)
{
if (m_pDict)
{
// If the use count goes to zero and the F_Dict is not the first one
// in the file's list or it is not linked to a file, unlink the F_Dict
// object from its database and delete it.
if (!m_pDict->decrUseCount() &&
(m_pDict->getPrev() || !m_pDict->getDatabase()))
{
m_pDict->unlinkFromDatabase();
}
m_pDict = NULL;
}
}
RCODE linkToDatabase(
F_Database * pDatabase);
void unlinkFromDatabase();
RCODE initDbFiles(
const char * pszRflDir,
SFLM_CREATE_OPTS * pCreateOpts);
RCODE beginBackgroundTrans(
IF_Thread * pThread);
RCODE beginTrans(
eDbTransType eTransType,
FLMUINT uiMaxLockWait = FLM_NO_TIMEOUT,
FLMUINT uiFlags = 0,
SFLM_DB_HDR * pDbHdr = NULL);
RCODE beginTrans(
F_Db * pDb);
RCODE commitTrans(
FLMUINT uiNewLogicalEOF,
FLMBOOL bForceCheckpoint,
FLMBOOL * pbEmpty = NULL);
RCODE abortTrans(
FLMBOOL bOkToLogAbort = TRUE);
RCODE readRollbackLog(
FLMUINT uiLogEOF,
FLMUINT * puiCurrAddr,
F_BLK_HDR * pBlkHdr,
FLMBOOL * pbIsBeforeImageBlk);
RCODE processBeforeImage(
FLMUINT uiLogEOF,
FLMUINT * puiCurrAddrRV,
F_BLK_HDR * pBlkHdr,
FLMBOOL bDoingRecovery,
FLMUINT64 ui64MaxTransID);
RCODE physRollback(
FLMUINT uiLogEOF,
FLMUINT uiFirstLogBlkAddr,
FLMBOOL bDoingRecovery,
FLMUINT64 ui64MaxTransID);
void completeOpenOrCreate(
RCODE rc,
FLMBOOL bNewDatabase);
RCODE startBackgroundIndexing( void);
void unlinkFromTransList(
FLMBOOL bCommitting);
RCODE lockExclusive(
FLMUINT uiMaxLockWait);
void unlockExclusive( void);
RCODE readDictionary( void);
RCODE dictCreate( void);
RCODE dictReadLFH( void);
RCODE dictReadEncDefs( void);
RCODE dictReadTables( void);
RCODE dictReadColumns( void);
RCODE dictReadIndexes( void);
RCODE dictReadIndexComponents( void);
RCODE dictOpen( void);
RCODE dictClone( void);
RCODE createNewDict( void);
FINLINE void getDbHdrInfo(
SFLM_DB_HDR * pDbHdr)
{
// IMPORTANT NOTE: Any changes to this method should also be
// mirrored with changes to the other getDbHdrInfo call - see below.
m_ui64CurrTransID = pDbHdr->ui64CurrTransID;
m_uiLogicalEOF = (FLMUINT)pDbHdr->ui32LogicalEOF;
// If we are doing a read transaction, this is only needed
// if we are checking the database.
m_uiFirstAvailBlkAddr = (FLMUINT)pDbHdr->ui32FirstAvailBlkAddr;
}
FINLINE void getDbHdrInfo(
F_Db * pDb)
{
m_ui64CurrTransID = pDb->m_ui64CurrTransID;
m_uiLogicalEOF = pDb->m_uiLogicalEOF;
// If we are doing a read transaction, this is only needed
// if we are checking the database.
m_uiFirstAvailBlkAddr = pDb->m_uiFirstAvailBlkAddr;
}
FINLINE FLMBOOL okToCommitTrans( void)
{
return( m_eTransType == SFLM_READ_TRANS ||
m_AbortRc == NE_SFLM_OK
? TRUE
: FALSE);
}
RCODE processDupKeys(
F_INDEX * pIndex);
RCODE keysCommit(
FLMBOOL bCommittingTrans,
FLMBOOL bSortKeys = TRUE);
RCODE refUpdate(
F_INDEX * pIndex,
KREF_ENTRY * pKrefEntry,
FLMBOOL bNormalUpdate);
FINLINE RCODE flushKeys( void)
{
RCODE rc = NE_SFLM_OK;
if( m_bKrefSetup)
{
if( m_uiKrefCount)
{
if (RC_BAD( rc = keysCommit( FALSE)))
{
goto Exit;
}
}
m_pKrefReset = m_pKrefPool->poolMark();
}
Exit:
return( rc);
}
RCODE krefCntrlCheck( void);
void krefCntrlFree( void);
FINLINE FLMBOOL isKrefOverThreshold( void)
{
if( (((m_pKrefPool->getBlockSize() * 3) - 250) <= m_uiTotalKrefBytes) ||
m_uiKrefCount > (m_uiKrefTblSize - 128))
{
return( TRUE);
}
return( FALSE);
}
RCODE addToKrefTbl(
FLMUINT uiKeyLen,
FLMUINT uiDataLen);
RCODE buildData(
ICD * pIcd,
FLMUINT uiDataComponent,
FLMUINT uiKeyLen,
FLMUINT uiDataLen);
RCODE finishKeyComponent(
ICD * pIcd,
FLMUINT uiKeyComponent,
FLMUINT uiKeyLen);
RCODE genTextKeyComponents(
F_COLUMN * pColumn,
ICD * pIcd,
FLMUINT uiKeyComponent,
FLMUINT uiKeyLen,
FLMBYTE ** ppucTmpBuf,
FLMUINT * puiTmpBufSize,
void ** ppvMark);
RCODE genOtherKeyComponent(
F_COLUMN * pColumn,
ICD * pIcd,
FLMUINT uiKeyComponent,
FLMUINT uiKeyLen);
RCODE buildKeys(
ICD * pIcd,
FLMUINT uiKeyComponent,
FLMUINT uiKeyLen);
RCODE buildKeys(
F_INDEX * pIndex,
F_TABLE * pTable,
F_Row * pRow,
FLMBOOL bAddKeys,
F_COLUMN_VALUE * pColumnValues);
RCODE updateIndexKeys(
FLMUINT uiTableNum,
F_Row * pRow,
FLMBOOL bAddKeys,
F_COLUMN_VALUE * pColumnValues);
void indexingAfterCommit( void);
void indexingAfterAbort( void);
RCODE addToStopList(
FLMUINT uiIndexNum);
RCODE addToStartList(
FLMUINT uiIndexNum);
void stopBackgroundIndexThread(
FLMUINT uiIndexNum,
FLMBOOL bWait,
FLMBOOL * pbStopped);
RCODE startIndexBuild(
FLMUINT uiIndexNum);
RCODE setIxStateInfo(
FLMUINT uiIndexNum,
FLMUINT64 ui64LastRowIndexed,
FLMUINT uiState);
RCODE indexSetOfRows(
FLMUINT uiIndexNum,
FLMUINT64 ui64StartRowId,
FLMUINT64 ui64EndRowId,
IF_IxStatus * pIxStatus,
IF_IxClient * pIxClient,
SFLM_INDEX_STATUS * pIndexStatus,
FLMBOOL * pbHitEnd,
IF_Thread * pThread);
RCODE readBlkHdr(
FLMUINT uiBlkAddress,
F_BLK_HDR * pBlkHdr,
FLMINT * piType);
SFLM_LFILE_STATS * getLFileStatPtr(
LFILE * pLFile);
#define FLM_UPD_ADD 0x00001
#define FLM_UPD_INTERNAL_CHANGE 0x00004
RCODE getCachedBTree(
FLMUINT uiTableNum,
F_Btree ** ppBTree);
RCODE flushDirtyRows( void);
RCODE maintBlockChainFree(
FLMUINT64 ui64MaintRowId,
FLMUINT uiStartBlkAddr,
FLMUINT uiBlocksToFree,
FLMUINT uiExpectedEndBlkAddr,
FLMUINT * puiBlocksFreed);
RCODE encryptData(
FLMUINT uiEncDefNum,
FLMBYTE * pucIV,
FLMBYTE * pucBuffer,
FLMUINT uiBufferSize,
FLMUINT uiDataLen,
FLMUINT * puiEncryptedLength);
RCODE decryptData(
FLMUINT uiEncDefNum,
FLMBYTE * pucIV,
void * pvInBuf,
FLMUINT uiInLen,
void * pvOutBuf,
FLMUINT uiOutBufLen);
RCODE createDbKey();
// Private data members.
F_Database * m_pDatabase; // Pointer to F_Database object
F_Dict * m_pDict; // Pointer to dictionary object
F_Db * m_pNextForDatabase; // Next F_Db associated with F_Database
// NOTE: gv_SFlmSysData.hShareMutex
// must be locked to set this
F_Db * m_pPrevForDatabase; // Prev F_Db associated with F_Database
// NOTE: gv_SFlmSysData.hShareMutex
// must be locked to set this
void * m_pvAppData; // Application data that is used
// to associate this F_Db with
// an object in the application
// space.
FLMUINT m_uiThreadId; // Thread that started the current
// transaction, if any. NOTE:
// Only set on transaction begin.
// Hence, if operations are performed
// by multiple threads, within the
// transaction, it will not necessarily
// reflect the thread that is currently
// using the F_Db.
FLMBOOL m_bMustClose; // An error has occurred that requires
// the application to stop using (close)
// this FDB
F_SuperFileHdl * m_pSFileHdl; // Pointer to the super file handle
FLMUINT m_uiFlags; // Flags for this F_Db.
// TRANSACTION STATE STUFF
FLMUINT m_uiTransCount; // Transaction counter for the F_Db.
// Incremented whenever a transaction
// is started on this F_Db. Used so
// that FLAIM can tell if an implicit
// transaction it started is still in
// effect. This should NOT be
// confused with update transaction
// IDs.
eDbTransType m_eTransType; // Type of transaction
RCODE m_AbortRc; // If not NE_SFLM_OK, transaction must be
// aborted.
FLMUINT64 m_ui64CurrTransID;// Current transaction ID.
FLMUINT m_uiFirstAvailBlkAddr; // Address of first block in avail list
FLMUINT m_uiLogicalEOF; // Current logical end of file. New
// blocks are allocated at this address.
FLMUINT m_uiUpgradeCPFileNum;
FLMUINT m_uiUpgradeCPOffset;
// RFL file number and offset to set
// RFL to during an upgrade operation
// that happens during a restore or
// recovery.
FLMUINT m_uiTransEOF; // Address of logical end of file
// when the last transaction
// committed. A block beyond this
// point in the file is going to be
// a new block and will not need to
// be logged.
F_TMSTAMP m_TransStartTime; // Transaction start time, for stats
// KREF STUFF
KEY_GEN_INFO m_keyGenInfo; // Information for generating index
// keys.
KREF_ENTRY ** m_pKrefTbl; // Pointer to KREF table, which is an array
// of KREF_ENTRY * pointers.
FLMUINT m_uiKrefTblSize; // KREF table size.
FLMUINT m_uiKrefCount; // Number of entries in KREF table that
// are currently used.
FLMUINT m_uiTotalKrefBytes; // Total number of entries allocated
// in the pool.
FLMBYTE * m_pucKrefKeyBuf; // Pointer to temporary key buffer.
FLMBOOL m_bKrefSetup; // True if the KRef table has been initialized.
F_Pool * m_pKrefPool; // Memory pool to use
FLMBOOL m_bReuseKrefPool; // Reuse pool instead of free it?
FLMBOOL m_bKrefCompoundKey; // True if a compound key has been processed.
void * m_pKrefReset; // Used to reset the Kref pool on
// indexing failures
F_Pool m_tmpKrefPool; // KREF pool to be used during
// read transactions - only used when
// checking indexes.
// UPDATE TRANSACTION STUFF
FLMBOOL m_bHadUpdOper; // Did this transaction have any
// updates?
FLMUINT m_uiBlkChangeCnt; // Number of times ScaLogPhysBlk has
// been called during this transaction.
// This is used by the cursor code to
// know when it is necessary to
// re-position in the B-Tree.0
IXD_FIXUP * m_pIxdFixups; // List of indexes whose IXD needs
// to be restored to its prior
// state if the transaction aborts
// READ TRANSACTION STUFF
F_Db * m_pNextReadTrans; // Next active read transaction for
// this database.
// NOTE: If uiKilledTime (see below)
// is non-zero, then transaction is
// in killed list.
F_Db * m_pPrevReadTrans; // Previous active read transaction
// for this database.
// NOTE: If m_uiKilledTime (see below)
// is non-zero, then transaction is
// in killed list.
FLMUINT m_uiInactiveTime; // If non-zero, this is the last time
// the checkpoint thread marked this
// transaction as inactive. If zero,
// it means that the transaction is
// active, or it has not been marked
// by the checkpoint thread as
// inactive. If it stays non-zero for
// five or more minutes, it will be
// killed.
FLMUINT m_uiKilledTime; // Time transaction was killed, if
// non-zero.
// Misc. DB Info.
FLMBOOL m_bItemStateUpdOk;// This variable is used to ensure
// that FlmDbSweep / recovery are the
// only ways that:
// 1) an element or attribute's state
// can be changed to 'unused'
// 2) a 'purge' element or attribute
// can be deleted
F_Pool m_tempPool; // Temporary memory pool. It
// is only used for the duration of
// a FLAIM operation and then reset.
// The first block in the pool is
// retained between operations to
// help performance.
// Callback functions.
IF_DeleteStatus * m_pDeleteStatus; // Handles status info coming back
// from deleting a BTree
IF_IxClient * m_pIxClient; // Indexing callback
IF_IxStatus * m_pIxStatus; // Indexing status callback
IF_CommitClient * m_pCommitClient; // Commit callback
SFLM_STATS * m_pStats;
SFLM_DB_STATS * m_pDbStats; // DB statistics pointer.
SFLM_LFILE_STATS * m_pLFileStats; // LFILE statistics pointer.
FLMUINT m_uiLFileAllocSeq;// Allocation sequence number for
// LFILE statistics array so we
// can tell if the array has been
// reallocated and we need to reset
// our pLFileStats pointer.
SFLM_STATS m_Stats; // Statistics kept here until end
// of transaction.
FLMBOOL m_bStatsInitialized;// Has statistics structure been
// initialized?
F_BKGND_IX * m_pIxStartList; // Indexing threads to start at
// the conclusion of the transaction.
F_BKGND_IX * m_pIxStopList; // Indexing threads to stop at
// the conclusion of the transaction.
F_Btree * m_pCachedBTree; // BTree object used for node operations
F_KeyCollector * m_pKeyColl; // Special purpose object used when checking
// indexes in the F_DbCheck class.
FLMUINT m_uiDirtyRowCount;
F_SEM m_hWaitSem; // Semaphore that is used when
// waiting for reads to complete
friend class F_Database;
friend class F_Dict;
friend class F_DbSystem;
friend class F_Rfl;
friend class F_Btree;
friend class F_Backup;
friend class F_Row;
friend class F_BTreeIStream;
friend class F_DataVector;
friend class F_DbRebuild;
friend class F_DbCheck;
friend class F_Query;
friend class FSIndexCursor;
friend class FSTableCursor;
friend class F_BtRSFactory;
friend class F_BtResultSet;
friend class F_CachedBlock;
friend class F_BlockCacheMgr;
friend class F_RowCacheMgr;
friend class F_GlobalCacheMgr;
friend class F_QueryResultSet;
friend class F_BTreeInfo;
friend class SQLQuery;
friend class SQLStatement;
};
typedef struct BTREE_INFO
{
FLMUINT uiLfNum;
char * pszLfName;
FLMUINT uiNumLevels;
SFLM_BTREE_LEVEL_INFO levelInfo [MAX_LEVELS];
} BTREE_INFO;
/*****************************************************************************
Desc: Object for gathering B-Tree information.
*****************************************************************************/
class F_BTreeInfo : public F_Object
{
public:
F_BTreeInfo()
{
m_pIndexArray = NULL;
m_uiIndexArraySize = 0;
m_uiNumIndexes = 0;
m_pTableArray = NULL;
m_uiTableArraySize = 0;
m_uiNumTables = 0;
m_pool.poolInit( 512);
}
virtual ~F_BTreeInfo()
{
if (m_pIndexArray)
{
f_free( &m_pIndexArray);
}
if (m_pTableArray)
{
f_free( &m_pTableArray);
}
m_pool.poolFree();
}
FINLINE void clearBTreeInfo( void)
{
m_uiNumIndexes = 0;
m_uiNumTables = 0;
}
RCODE collectIndexInfo(
F_Db * pDb,
FLMUINT uiIndexNum,
IF_BTreeInfoStatus * pInfoStatus);
RCODE collectTableInfo(
F_Db * pDb,
FLMUINT uiTableNum,
IF_BTreeInfoStatus * pInfoStatus);
FINLINE FLMUINT getNumIndexes( void)
{
return( m_uiNumIndexes);
}
FINLINE FLMUINT getNumTables( void)
{
return( m_uiNumTables);
}
FINLINE FLMBOOL getIndexInfo(
FLMUINT uiNthIndex,
FLMUINT * puiIndexNum,
char ** ppszIndexName,
FLMUINT * puiNumLevels)
{
if (uiNthIndex < m_uiNumIndexes)
{
*puiIndexNum = m_pIndexArray [uiNthIndex].uiLfNum;
*puiNumLevels = m_pIndexArray [uiNthIndex].uiNumLevels;
*ppszIndexName = m_pIndexArray [uiNthIndex].pszLfName;
return( TRUE);
}
else
{
*puiIndexNum = 0;
*ppszIndexName = NULL;
*puiNumLevels = 0;
return( FALSE);
}
}
FINLINE FLMBOOL getTableInfo(
FLMUINT uiNthTable,
FLMUINT * puiTableNum,
char ** ppszTableName,
FLMUINT * puiNumLevels)
{
if (uiNthTable < m_uiNumTables)
{
*puiTableNum = m_pTableArray [uiNthTable].uiLfNum;
*puiNumLevels = m_pTableArray [uiNthTable].uiNumLevels;
*ppszTableName = m_pTableArray [uiNthTable].pszLfName;
return( TRUE);
}
else
{
*puiTableNum = 0;
*puiNumLevels = 0;
*ppszTableName = NULL;
return( FALSE);
}
}
FINLINE FLMBOOL getIndexLevelInfo(
FLMUINT uiNthIndex,
FLMUINT uiBTreeLevel,
SFLM_BTREE_LEVEL_INFO * pLevelInfo)
{
if (uiNthIndex < m_uiNumIndexes &&
uiBTreeLevel < m_pIndexArray [uiNthIndex].uiNumLevels)
{
f_memcpy( pLevelInfo,
&(m_pIndexArray [uiNthIndex].levelInfo [uiBTreeLevel]),
sizeof( SFLM_BTREE_LEVEL_INFO));
return( TRUE);
}
else
{
return( FALSE);
}
}
FINLINE FLMBOOL getTableLevelInfo(
FLMUINT uiNthTable,
FLMUINT uiBTreeLevel,
SFLM_BTREE_LEVEL_INFO * pLevelInfo)
{
if (uiNthTable < m_uiNumTables &&
uiBTreeLevel < m_pTableArray [uiNthTable].uiNumLevels)
{
f_memcpy( pLevelInfo,
&(m_pTableArray [uiNthTable].levelInfo [uiBTreeLevel]),
sizeof( SFLM_BTREE_LEVEL_INFO));
return( TRUE);
}
else
{
return( FALSE);
}
}
private:
RCODE collectBlockInfo(
F_Db * pDb,
LFILE * pLFile,
BTREE_INFO * pBTreeInfo,
F_BTREE_BLK_HDR * pBlkHdr,
F_INDEX * pIndex);
RCODE collectBTreeInfo(
F_Db * pDb,
LFILE * pLFile,
BTREE_INFO * pBTreeInfo,
const char * pszName,
F_INDEX * pIndex);
FINLINE RCODE doCallback( void)
{
if (m_pInfoStatus)
{
return( m_pInfoStatus->infoStatus( m_uiCurrLfNum, m_bIsTable,
m_pszCurrLfName, m_uiCurrLevel,
m_ui64CurrLfBlockCount, m_ui64CurrLevelBlockCount,
m_ui64TotalBlockCount));
}
else
{
return( NE_SFLM_OK);
}
}
BTREE_INFO * m_pIndexArray;
FLMUINT m_uiIndexArraySize;
FLMUINT m_uiNumIndexes;
BTREE_INFO * m_pTableArray;
FLMUINT m_uiTableArraySize;
FLMUINT m_uiNumTables;
F_Pool m_pool;
// Items for the callback function.
IF_BTreeInfoStatus * m_pInfoStatus;
FLMUINT m_uiBlockSize;
FLMUINT m_uiCurrLfNum;
FLMBOOL m_bIsTable;
char * m_pszCurrLfName;
FLMUINT m_uiCurrLevel;
FLMUINT64 m_ui64CurrLfBlockCount;
FLMUINT64 m_ui64CurrLevelBlockCount;
FLMUINT64 m_ui64TotalBlockCount;
};
RCODE ixKeyCompare(
F_Db * pDb,
F_INDEX * pIndex,
FLMBOOL bCompareRowId,
F_DataVector * pSearchKey1,
F_Row * pRow1,
const void * pvKey1,
FLMUINT uiKeyLen1,
F_DataVector * pSearchKey2,
F_Row * pRow2,
const void * pvKey2,
FLMUINT uiKeyLen2,
FLMINT * piCompare);
/********************************************************************
Desc: Class for comparing two keys in an index.
********************************************************************/
class IXKeyCompare : public IF_ResultSetCompare
{
public:
IXKeyCompare()
{
// m_pDb is used to sort truncated keys if necessary.
// m_pIxd is used for comparison
m_pDb = NULL;
m_pIndex = NULL;
m_pSearchKey = NULL;
m_bCompareRowId = TRUE;
m_pOldRow = NULL;
}
virtual ~IXKeyCompare()
{
}
FINLINE RCODE FLMAPI compare(
const void * pvKey1,
FLMUINT uiKeyLen1,
const void * pvKey2,
FLMUINT uiKeyLen2,
FLMINT * piCompare)
{
return( ixKeyCompare( m_pDb, m_pIndex, m_bCompareRowId,
m_pSearchKey, m_pOldRow, pvKey1, uiKeyLen1,
m_pSearchKey, m_pOldRow, pvKey2, uiKeyLen2,
piCompare));
}
FINLINE void setIxInfo(
F_Db * pDb,
F_INDEX * pIndex)
{
m_pDb = pDb;
m_pIndex = pIndex;
}
FINLINE void setSearchKey(
F_DataVector * pSearchKey)
{
m_pSearchKey = pSearchKey;
}
FINLINE void setCompareRowId(
FLMBOOL bCompareRowId)
{
m_bCompareRowId = bCompareRowId;
}
FINLINE void setOldRow(
F_Row * pOldRow)
{
m_pOldRow = pOldRow;
}
virtual FLMINT FLMAPI getRefCount( void)
{
return( IF_ResultSetCompare::getRefCount());
}
virtual FLMINT FLMAPI AddRef( void)
{
return( IF_ResultSetCompare::AddRef());
}
virtual FLMINT FLMAPI Release( void)
{
return( IF_ResultSetCompare::Release());
}
private:
F_Db * m_pDb;
F_INDEX * m_pIndex;
F_DataVector * m_pSearchKey;
FLMBOOL m_bCompareRowId;
F_Row * m_pOldRow;
};
/*=============================================================================
Desc: Result set class for queries that do sorting.
=============================================================================*/
class F_QueryResultSet : public F_Object
{
public:
F_QueryResultSet()
{
m_pBTree = NULL;
m_pResultSetDb = NULL;
m_pSrcDb = NULL;
m_pIndex = NULL;
m_uiCurrPos = FLM_MAX_UINT;
m_uiCount = 0;
m_bPositioned = FALSE;
m_hMutex = F_MUTEX_NULL;
}
~F_QueryResultSet();
// Initialize the result set
RCODE initResultSet(
FLMBOOL bUseIxCompareObj,
FLMBOOL bEnableEncryption);
FINLINE void setIxInfo(
F_Db * pSrcDb,
F_INDEX * pIndex)
{
m_pSrcDb = pSrcDb;
m_pIndex = pIndex;
m_compareObj.setIxInfo( pSrcDb, pIndex);
}
// Entry Add and Sort Methods
RCODE addEntry( // Variable or fixed length entry coming in
FLMBYTE * pucKey, // key for sorting.
FLMUINT uiKeyLength,
FLMBOOL bLockMutex);
// Methods to read entries.
RCODE getFirst(
FLMBYTE * pucKey,
FLMUINT uiKeyBufSize,
FLMUINT * puiKeyLen,
FLMBOOL bLockMutex);
RCODE getLast(
FLMBYTE * pucKey,
FLMUINT uiKeyBufSize,
FLMUINT * puiKeyLen,
FLMBOOL bLockMutex);
RCODE getNext(
FLMBYTE * pucKey,
FLMUINT uiKeyBufSize,
FLMUINT * puiKeyLen,
FLMBOOL bLockMutex);
RCODE getPrev(
FLMBYTE * pucKey,
FLMUINT uiKeyBufSize,
FLMUINT * puiKeyLen,
FLMBOOL bLockMutex);
RCODE getCurrent(
FLMBYTE * pucKey,
FLMUINT uiKeyBufSize,
FLMUINT * puiKeyLen,
FLMBOOL bLockMutex);
RCODE positionToEntry(
FLMBYTE * pucKey,
FLMUINT uiKeyBufSize,
FLMUINT * puiKeyLen,
F_DataVector * pSearchKey,
FLMUINT uiFlags,
FLMBOOL bLockMutex);
RCODE positionToEntry(
FLMUINT uiPosition,
FLMBYTE * pucKey,
FLMUINT uiKeyBufSize,
FLMUINT * puiKeyLen,
FLMBOOL bLockMutex);
FINLINE FLMUINT getCount( void)
{
return( m_uiCount);
}
FINLINE FLMUINT getCurrPos( void)
{
return( m_uiCurrPos);
}
FINLINE void lockMutex( void)
{
f_mutexLock( m_hMutex);
}
FINLINE void unlockMutex( void)
{
f_mutexUnlock( m_hMutex);
}
private:
char m_szResultSetDibName [F_PATH_MAX_SIZE];
F_Db * m_pResultSetDb;
F_Btree * m_pBTree;
LFILE m_LFile;
F_Db * m_pSrcDb;
F_INDEX * m_pIndex;
IXKeyCompare m_compareObj;
FLMUINT m_uiCurrPos;
FLMUINT m_uiCount;
FLMBOOL m_bPositioned;
F_MUTEX m_hMutex;
};
typedef struct RS_WAITER
{
FLMUINT uiThreadId; // Thread of waiter
F_SEM hESem; // Semaphore to signal to wake up thread.
RCODE * pRc; // Pointer to return code that is to
// be set.
FLMUINT uiWaitStartTime;
// Time we started waiting.
FLMUINT uiTimeLimit; // Maximum time (milliseconds) to wait
// before timing out.
FLMUINT uiNumToWaitFor;// Wait until we get at least this many
// in the result set - or until the
// result set is complete.
RS_WAITER * pNext; // Next lock waiter in list.
RS_WAITER * pPrev; // Previous lock waiter in list.
} RS_WAITER;
/*****************************************************************************
Desc: FLAIM database system object
******************************************************************************/
class F_DbSystem : public F_Object
{
public:
F_DbSystem()
{
m_refCnt = 1;
}
virtual ~F_DbSystem()
{
}
virtual FLMINT FLMAPI AddRef( void);
virtual FLMINT FLMAPI Release( void);
RCODE init( void);
RCODE updateIniFile(
const char * pszParamName,
const char * pszValue);
void exit();
void getFileSystem(
IF_FileSystem ** ppFileSystem);
RCODE createDatabase(
const char * pszDbFileName,
const char * pszDataDir,
const char * pszRflDir,
SFLM_CREATE_OPTS * pCreateOpts,
FLMBOOL bTempDb,
F_Db ** ppDb);
FINLINE RCODE createDatabase(
const char * pszDbFileName,
const char * pszDataDir,
const char * pszRflDir,
SFLM_CREATE_OPTS * pCreateOpts,
F_Db ** ppDb)
{
return( createDatabase( pszDbFileName, pszDataDir, pszRflDir,
pCreateOpts, FALSE, ppDb));
}
RCODE openDatabase(
const char * pszDbFileName,
const char * pszDataDir,
const char * pszRflDir,
const char * pszPassword,
FLMUINT uiOpenFlags,
F_Db ** ppDb);
RCODE dbRebuild(
const char * pszSourceDbPath,
const char * pszSourceDataDir,
const char * pszDestDbPath,
const char * pszDestDataDir,
const char * pszDestRflDir,
const char * pszDictPath,
const char * pszPassword,
SFLM_CREATE_OPTS * pCreateOpts,
FLMUINT64 * pui64TotRows,
FLMUINT64 * pui64RowsRecov,
IF_DbRebuildStatus * pRebuildStatus);
RCODE dbCheck(
const char * pszDbFileName,
const char * pszDataDir,
const char * pszRflDir,
const char * pszPassword,
FLMUINT uiFlags,
F_DbInfo ** ppDbInfo,
IF_DbCheckStatus * pDbCheck);
FINLINE RCODE dbDup(
F_Db * pDb,
F_Db ** ppDb)
{
return( openDatabase( pDb->m_pDatabase, NULL, NULL, NULL, NULL, 0,
FALSE, NULL, NULL, NULL, ppDb));
}
FINLINE RCODE setDynamicMemoryLimit(
FLMUINT uiCacheAdjustPercent,
FLMUINT uiCacheAdjustMin,
FLMUINT uiCacheAdjustMax,
FLMUINT uiCacheAdjustMinToLeave)
{
return( gv_SFlmSysData.pGlobalCacheMgr->setDynamicMemoryLimit(
uiCacheAdjustPercent, uiCacheAdjustMin,
uiCacheAdjustMax, uiCacheAdjustMinToLeave));
}
FINLINE RCODE setHardMemoryLimit(
FLMUINT uiPercent,
FLMBOOL bPercentOfAvail,
FLMUINT uiMin,
FLMUINT uiMax,
FLMUINT uiMinToLeave,
FLMBOOL bPreallocate)
{
return( gv_SFlmSysData.pGlobalCacheMgr->setHardMemoryLimit( uiPercent,
bPercentOfAvail, uiMin, uiMax, uiMinToLeave, bPreallocate));
}
// Determine if dyamic cache adjusting is supported.
FINLINE FLMBOOL getDynamicCacheSupported( void)
{
#ifdef FLM_CAN_GET_PHYS_MEM
return( TRUE);
#else
return( FALSE);
#endif
}
FINLINE void getCacheInfo(
SFLM_CACHE_INFO * pCacheInfo)
{
gv_SFlmSysData.pGlobalCacheMgr->getCacheInfo( pCacheInfo);
}
// Enable/disable cache debugging mode
void enableCacheDebug(
FLMBOOL bDebug);
FLMBOOL cacheDebugEnabled( void);
// Clear cache
FINLINE RCODE clearCache(
F_Db * pDb)
{
return( gv_SFlmSysData.pGlobalCacheMgr->clearCache( pDb));
}
// Close all files that have not been used for the specified number of
// seconds.
RCODE closeUnusedFiles(
FLMUINT uiSeconds);
// Start gathering statistics.
void startStats( void);
// Stop gathering statistics.
void stopStats( void);
// Reset statistics.
void resetStats( void);
RCODE getStats(
SFLM_STATS * pFlmStats);
void freeStats(
SFLM_STATS * pFlmStats);
// Set the maximum number of queries to save.
void setQuerySaveMax(
FLMUINT uiMaxToSave);
FLMUINT getQuerySaveMax( void);
// Set temporary directory.
RCODE setTempDir(
const char * pszPath);
RCODE getTempDir(
char * pszPath);
// Maximum seconds between checkpoints.
void setCheckpointInterval(
FLMUINT uiSeconds);
FLMUINT getCheckpointInterval( void);
// Set interval for dynamically adjusting cache limit.
void setCacheAdjustInterval(
FLMUINT uiSeconds);
FLMUINT getCacheAdjustInterval( void);
// Set interval for dynamically cleaning out old cache blocks and records.
void setCacheCleanupInterval(
FLMUINT uiSeconds);
FLMUINT getCacheCleanupInterval( void);
// Set interval for cleaning up unused structures.
void setUnusedCleanupInterval(
FLMUINT uiSeconds);
FLMUINT getUnusedCleanupInterval( void);
// Set maximum time for an item to be unused.
void setMaxUnusedTime(
FLMUINT uiSeconds);
FLMUINT getMaxUnusedTime( void);
// Specify the logger object
void setLogger(
IF_LoggerClient * pLogger);
// Enable or disable use of ESM
void enableExtendedServerMemory(
FLMBOOL bEnable);
FLMBOOL extendedServerMemoryEnabled( void);
void deactivateOpenDb(
const char * pszDbFileName,
const char * pszDataDir);
// Maximum dirty cache.
void setDirtyCacheLimits(
FLMUINT uiMaxDirty,
FLMUINT uiLowDirty);
void getDirtyCacheLimits(
FLMUINT * puiMaxDirty,
FLMUINT * puiLowDirty);
RCODE getThreadInfo(
IF_ThreadInfo ** ppThreadInfo);
RCODE registerForEvent(
eEventCategory eCategory,
IF_EventClient * pEventClient);
void deregisterForEvent(
eEventCategory eCategory,
IF_EventClient * pEventClient);
RCODE getNextMetaphone(
IF_IStream * pIStream,
FLMUINT * puiMetaphone,
FLMUINT * puiAltMetaphone = NULL);
RCODE dbCopy(
const char * pszSrcDbName,
const char * pszSrcDataDir,
const char * pszSrcRflDir,
const char * pszDestDbName,
const char * pszDestDataDir,
const char * pszDestRflDir,
IF_DbCopyStatus * ifpStatus);
RCODE dropDatabase(
const char * pszDbName,
const char * pszDataDir,
const char * pszRflDir,
FLMBOOL bRemoveRflFiles);
RCODE dbRename(
const char * pszDbName,
const char * pszDataDir,
const char * pszRflDir,
const char * pszNewDbName,
FLMBOOL bOverwriteDestOk,
IF_DbRenameStatus * ifpStatus);
RCODE dbRestore(
const char * pszDbPath,
const char * pszDataDir,
const char * pszRflDir,
const char * pszBackupPath,
const char * pszPassword,
IF_RestoreClient * pRestoreObj,
IF_RestoreStatus * pRestoreStatus);
RCODE strCmp(
FLMUINT uiCompFlags,
FLMUINT uiLanguage,
FLMUNICODE * uzStr1,
FLMUNICODE * uzStr2,
FLMINT * piCmp);
FLMBOOL errorIsFileCorrupt(
RCODE rc);
static FLMBOOL _errorIsFileCorrupt(
RCODE rc)
{
F_DbSystem dbSystem;
return( dbSystem.errorIsFileCorrupt( rc));
}
const char * checkErrorToStr(
eCorruptionType eCorruption);
FINLINE void freeMem(
void ** ppMem)
{
f_free( ppMem);
}
FINLINE RCODE internalDbOpen(
F_Database * pDatabase,
F_Db ** ppDb)
{
RCODE rc = NE_SFLM_OK;
F_Db * pDb;
if (RC_OK( rc = openDatabase( pDatabase, NULL, NULL, NULL,
NULL, 0, TRUE, NULL, NULL, NULL, &pDb)))
{
*ppDb = (F_Db *)pDb;
}
return( rc);
}
static FINLINE FLMBOOL validBlockSize(
FLMUINT uiBlockSize)
{
if( uiBlockSize == 4096 || uiBlockSize == 8192)
{
return( TRUE);
}
return( FALSE);
}
RCODE waitToClose(
const char * pszDbPath);
private:
// Methods
RCODE readIniFile( void);
RCODE setCacheParams(
IF_IniFile * pIniFile);
void cleanup( void);
FINLINE RCODE internalDbDup(
F_Db * pDb,
F_Db ** ppDb)
{
return( openDatabase( pDb->m_pDatabase, NULL, NULL,
NULL, NULL, 0, TRUE, NULL, NULL, NULL, ppDb));
}
void initFastBlockCheckSum( void);
RCODE allocDb(
F_Db ** ppDb,
FLMBOOL bInternalOpen);
RCODE findDatabase(
const char * pszDbPath,
const char * pszDataDir,
F_Database ** ppDatabase);
RCODE checkDatabaseClosed(
const char * pszDbName,
const char * pszDataDir);
RCODE allocDatabase(
const char * pszDbPath,
const char * pszDataDir,
FLMBOOL bTempDb,
F_Database ** ppDatabase);
RCODE openDatabase(
F_Database * pDatabase,
const char * pszDbPath,
const char * pszDataDir,
const char * pszRflDir,
const char * pszPassword,
FLMUINT uiOpenFlags,
FLMBOOL bInternalOpen,
IF_RestoreClient * pRestoreObj,
IF_RestoreStatus * pRestoreStatus,
IF_FileHdl * pLockFileHdl,
F_Db ** pDb);
RCODE copyDb(
const char * pszSrcDbName,
const char * pszSrcDataDir,
const char * pszSrcRflDir,
const char * pszDestDbName,
const char * pszDestDataDir,
const char * pszDestRflDir,
IF_DbCopyStatus * ifpStatus);
static RCODE FLMAPI monitorThrd(
IF_Thread * pThread);
static RCODE FLMAPI cacheCleanupThrd(
IF_Thread * pThread);
static void checkNotUsedObjects( void);
static FLMATOMIC m_flmSysSpinLock;
static FLMUINT m_uiFlmSysStartupCount;
friend class F_Db;
friend class F_Database;
friend class F_DbRebuild;
friend class F_DbCheck;
};
// Supported text types
typedef enum
{
SFLM_UNICODE_TEXT = 1,
SFLM_UTF8_TEXT
} eSFlmTextType;
void flmGetDbBasePath(
char * pszBaseDbName,
const char * pszDbName,
FLMUINT * puiBaseDbNameLen);
/*------------------------------------------------------
FLAIM Processing Hooks (call-backs)
-------------------------------------------------------*/
#define FLM_DATA_LEFT_TRUNCATED 0x10 // Data is left truncated
#define FLM_DATA_RIGHT_TRUNCATED 0x20 // Data is right truncated
RCODE flmReadStorageAsText(
IF_IStream * pIStream,
FLMBYTE * pucStorageData,
FLMUINT uiDataLen,
eDataType eDataTyp,
void * pvBuffer,
FLMUINT uiBufLen,
eSFlmTextType eTextType,
FLMUINT uiMaxCharsToRead,
FLMUINT uiCharOffset,
FLMUINT * puiCharsRead,
FLMUINT * puiBufferBytesUsed);
RCODE flmReadStorageAsBinary(
IF_IStream * pIStream,
void * pvBuffer,
FLMUINT uiBufLen,
FLMUINT uiByteOffset,
FLMUINT * puiBytesRead);
RCODE flmReadStorageAsNumber(
IF_IStream * pIStream,
eDataType eDataTyp,
FLMUINT64 * pui64Number,
FLMBOOL * pbNeg);
RCODE flmReadLine(
IF_IStream * pIStream,
FLMBYTE * pucBuffer,
FLMUINT * puiSize);
#define FLM_ENCRYPT_CHUNK_SIZE 512
/*****************************************************************************
Desc:
******************************************************************************/
class F_BTreeIStream : public IF_PosIStream
{
public:
F_BTreeIStream()
{
m_pucBuffer = NULL;
m_pBTree = NULL;
m_bReleaseBTree = FALSE;
reset();
}
virtual ~F_BTreeIStream()
{
reset();
}
FINLINE void reset( void)
{
m_pNextInPool = NULL;
if( m_pBTree && m_bReleaseBTree)
{
m_pBTree->btClose();
gv_SFlmSysData.pBtPool->btpReturnBtree( &m_pBTree);
m_pBTree = NULL;
}
if( m_pucBuffer != &m_ucBuffer [0])
{
f_free( &m_pucBuffer);
}
m_pDb = NULL;
m_uiTableNum = 0;
m_ui64RowId = 0;
m_pBTree = NULL;
m_bReleaseBTree = FALSE;
m_uiKeyLength = 0;
m_uiStreamSize = 0;
m_uiBufferBytes = 0;
m_uiBufferOffset = 0;
m_uiBufferStartOffset = 0;
m_uiBufferSize = sizeof( m_ucBuffer);
m_pucBuffer = &m_ucBuffer [0];
m_ui32BlkAddr = 0;
m_uiOffsetIndex = 0;
m_uiDataLength = 0;
}
RCODE openStream(
F_Db * pDb,
FLMUINT uiTableNum,
FLMUINT64 ui64RowId,
FLMUINT32 ui32BlkAddr = 0,
FLMUINT uiOffsetIndex = 0);
RCODE openStream(
F_Db * pDb,
F_Btree * pBTree,
FLMUINT uiFlags,
FLMUINT uiTableNum,
FLMUINT64 ui64RowId,
FLMUINT32 ui32BlkAddr = 0,
FLMUINT uiOffsetIndex = 0);
FINLINE FLMUINT64 FLMAPI totalSize( void)
{
return( m_uiStreamSize);
}
FINLINE FLMUINT64 FLMAPI remainingSize( void)
{
return( m_uiStreamSize - (m_uiBufferStartOffset + m_uiBufferOffset));
}
FINLINE RCODE FLMAPI closeStream( void)
{
reset();
return( NE_SFLM_OK);
}
RCODE FLMAPI positionTo(
FLMUINT64 ui64Position);
FINLINE FLMUINT64 FLMAPI getCurrPosition( void)
{
return( m_uiBufferStartOffset + m_uiBufferOffset);
}
RCODE FLMAPI read(
void * pvBuffer,
FLMUINT uiBytesToRead,
FLMUINT * puiBytesRead);
FLMINT FLMAPI Release( void);
FINLINE FLMUINT32 getBlkAddr( void)
{
return( m_ui32BlkAddr);
}
FINLINE FLMUINT getOffsetIndex( void)
{
return( m_uiOffsetIndex);
}
private:
F_BTreeIStream * m_pNextInPool;
F_Db * m_pDb;
F_Btree * m_pBTree;
FLMUINT m_uiTableNum;
FLMUINT64 m_ui64RowId;
FLMUINT m_uiStreamSize;
FLMUINT m_uiKeyLength;
FLMUINT m_uiBufferBytes;
FLMUINT m_uiBufferSize;
FLMUINT m_uiBufferOffset;
FLMUINT m_uiBufferStartOffset;
FLMUINT m_uiDataLength;
FLMBYTE m_ucBuffer[ FLM_ENCRYPT_CHUNK_SIZE];
FLMBYTE * m_pucBuffer;
FLMUINT m_uiOffsetIndex;
FLMUINT32 m_ui32BlkAddr;
FLMBOOL m_bReleaseBTree;
FLMBYTE m_ucKey[ FLM_MAX_NUM_BUF_SIZE];
friend class F_Row;
friend class F_Db;
friend class F_BTreeIStreamPool;
};
/*===========================================================================
Desc: Pool manager for b-tree istream objects
===========================================================================*/
class F_BTreeIStreamPool : public F_Object
{
public:
F_BTreeIStreamPool()
{
m_pFirstBTreeIStream = NULL;
m_hMutex = F_MUTEX_NULL;
}
~F_BTreeIStreamPool();
RCODE setup( void);
RCODE allocBTreeIStream(
F_BTreeIStream ** ppBTreeIStream);
void insertBTreeIStream(
F_BTreeIStream * pBTreeIStream);
private:
F_BTreeIStream * m_pFirstBTreeIStream;
F_MUTEX m_hMutex;
friend class F_BTreeIStream;
};
typedef struct RSIxKeyTag
{
FLMBYTE pucRSKeyBuf[ SFLM_MAX_KEY_SIZE];
FLMUINT uiRSKeyLen;
FLMBYTE pucRSDataBuf[ SFLM_MAX_KEY_SIZE];
FLMUINT uiRSDataLen;
} RS_IX_KEY;
/******************************************************************************
Desc:
******************************************************************************/
class F_KeyCollector : public F_Object
{
public:
F_KeyCollector(
F_DbCheck * pDbCheck)
{
m_pDbCheck = pDbCheck;
m_ui64TotalKeys = 0;
}
~F_KeyCollector(){}
RCODE addKey(
F_Db * pDb,
F_INDEX * pIndex,
KREF_ENTRY * pKref);
FLMUINT64 getTotalKeys()
{
return m_ui64TotalKeys;
}
private:
F_DbCheck * m_pDbCheck;
FLMUINT64 m_ui64TotalKeys;
friend class F_DbCheck;
};
typedef struct
{
FLMUINT64 ui64BytesUsed;
FLMUINT64 ui64ElementCount;
FLMUINT64 ui64ContElementCount;
FLMUINT64 ui64ContElmBytes;
FLMUINT uiBlockCount;
FLMINT iErrCode;
FLMUINT uiNumErrors;
} BLOCK_INFO;
typedef struct
{
FLMUINT64 ui64KeyCount;
BLOCK_INFO BlockInfo;
} LEVEL_INFO;
typedef struct
{
FLMUINT uiLfNum;
eLFileType eLfType;
FLMUINT uiRootBlk;
FLMUINT uiNumLevels;
LEVEL_INFO * pLevelInfo;
} LF_HDR;
/******************************************************************************
Desc:
******************************************************************************/
typedef struct State_Info
{
F_Db * pDb;
FLMUINT32 ui32BlkAddress;
FLMUINT32 ui32NextBlkAddr;
FLMUINT32 ui32PrevBlkAddr;
FLMUINT32 ui32LastChildAddr;
FLMUINT uiElmLastFlag;
FLMUINT64 ui64KeyCount;
FLMUINT64 ui64KeyRefs;
FLMUINT uiBlkType;
FLMUINT uiLevel;
FLMUINT uiRootLevel;
FLMUINT uiElmOffset;
FLMBYTE * pucElm;
FLMUINT uiElmLen;
FLMUINT uiElmKeyLenOffset; // New
FLMUINT uiElmKeyOffset; // New
FLMBYTE * pucElmKey;
FLMUINT uiElmKeyLen;
FLMUINT uiCurKeyLen; // Used in Rebuild...
FLMUINT uiElmDataLenOffset; // New
FLMUINT uiElmDataOffset; // uiElmRecOffset;
FLMUINT uiElmDataLen; // uiElmRecLen;
FLMBYTE * pucElmData; // pucElmRec;
FLMUINT uiElmCounts; // New
FLMUINT uiElmCountsOffset; // New
FLMUINT uiElmOADataLenOffset;
FLMUINT uiElmOADataLen;
FLMUINT64 ui64ElmNodeId;
FLMBOOL bValidKey;
F_BLK_HDR * pBlkHdr;
BLOCK_INFO BlkInfo;
F_BtResultSet * pNodeRS;
F_BtResultSet * pXRefRS;
FLMUINT uiCurrLf;
} STATE_INFO;
/******************************************************************************
Desc:
******************************************************************************/
typedef struct
{
FLMUINT uiStartOfEntry;
FLMUINT uiEndOfEntry;
} BlkStruct;
/******************************************************************************
Desc: DbCheck object for verifying the condition of the database.
******************************************************************************/
class F_DbCheck : public F_Object
{
public:
F_DbCheck( void)
{
m_pXRefRS = NULL;
m_pDb = NULL;
m_pIndex = NULL;
m_pTable = NULL;
m_pLFile = NULL;
m_pDbInfo = NULL;
m_pBtPool = NULL;
m_pResultSetDb = NULL;
m_pRandGen = NULL;
m_pDbCheckStatus = NULL;
f_memset( m_szResultSetDibName, 0, sizeof( m_szResultSetDibName));
m_bPhysicalCorrupt = FALSE;
m_bIndexCorrupt = FALSE;
m_LastStatusRc = NE_SFLM_OK;
m_uiFlags = 0;
m_bStartedUpdateTrans = FALSE;
m_puiIxArray = NULL;
m_pIxRSet = NULL;
m_bGetNextRSKey = FALSE;
f_memset( &m_IxKey1, 0, sizeof( m_IxKey1));
f_memset( &m_IxKey2, 0, sizeof( m_IxKey2));
m_pCurrRSKey = NULL;
m_pPrevRSKey = NULL;
m_pBlkEntries = NULL;
m_uiBlkEntryArraySize = 0;
}
~F_DbCheck();
RCODE dbCheck(
const char * pszDbFileName,
const char * pszDataDir,
const char * pszRflDir,
const char * pszPassword,
FLMUINT uiFlags,
F_DbInfo ** ppDbInfo,
IF_DbCheckStatus * pDbCheck);
private:
FINLINE RCODE chkCallProgFunc( void)
{
if (m_pDbCheckStatus && RC_OK( m_LastStatusRc))
{
m_LastStatusRc = m_pDbCheckStatus->reportProgress( &m_Progress);
}
return( m_LastStatusRc);
}
RCODE chkReportError(
FLMINT iErrCode,
FLMUINT uiErrLocale,
FLMUINT uiErrLfNumber,
FLMUINT uiErrLfType,
FLMUINT uiErrBTreeLevel,
FLMUINT uiErrBlkAddress,
FLMUINT uiErrParentBlkAddress,
FLMUINT uiErrElmOffset,
FLMUINT64 ui64ErrNodeId);
FINLINE SFLM_PROGRESS_CHECK_INFO * getProgress( void)
{
return( &m_Progress);
}
RCODE getBtResultSet(
F_BtResultSet ** ppBtRSet);
RCODE createAndOpenResultSetDb( void);
RCODE closeAndDeleteResultSetDb( void);
RCODE getDictInfo( void);
RCODE verifyBlkChain(
BLOCK_INFO * pBlkInfo,
FLMUINT uiLocale,
FLMUINT uiFirstBlkAddr,
FLMUINT uiBlkType,
FLMBOOL * pbStartOverRV);
RCODE verifyLFHBlocks(
FLMBOOL * pbStartOverRV);
RCODE verifyAvailList(
FLMBOOL * pbStartOverRV);
RCODE blkRead(
FLMUINT uiBlkAddress,
F_BLK_HDR ** ppBlkHdr,
F_CachedBlock ** ppSCache,
FLMINT * piBlkErrCodeRV);
RCODE verifySubTree(
STATE_INFO * pParentState,
STATE_INFO * pStateInfo,
FLMUINT uiBlkAddress,
FLMBYTE ** ppucResetKey,
FLMUINT uiResetKeyLen,
FLMUINT64 ui64ResetNodeId);
RCODE verifyBTrees(
FLMBOOL * pbStartOverRV);
RCODE setupLfTable();
RCODE setupIxInfo( void);
RCODE getLfInfo(
LF_HDR * pLogicalFile,
LFILE * pLFile);
RCODE verifyNodePointers(
STATE_INFO * pStateInfo,
FLMINT * piErrCode);
RCODE verifyDOChain(
STATE_INFO * pParentState,
FLMUINT uiBlkAddr,
FLMINT * piElmErrCode);
RCODE chkGetNextRSKey( void);
RCODE verifyIXRSet(
STATE_INFO * pStateInfo);
RCODE resolveIXMissingKey(
STATE_INFO * pStateInfo);
RCODE verifyComponentInDoc(
ICD * pIcd,
FLMUINT uiComponent,
F_DataVector * pKey,
FLMBOOL * pbInDoc);
RCODE getKeySource(
FLMBYTE * pucKey,
FLMUINT uiKeyLen,
FLMBOOL * pbKeyInDoc,
FLMBOOL * pbKeyInIndex);
RCODE resolveRSetMissingKey(
STATE_INFO * pStateInfo);
RCODE chkVerifyKeyExists(
FLMBYTE * pucKey,
FLMUINT uiKeyLen,
FLMBOOL * pbFoundRV);
RCODE addDelKeyRef(
FLMBYTE * pucKey,
FLMUINT uiKeyLen,
FLMBOOL bDelete);
RCODE reportIxError(
STATE_INFO * pStateInfo,
FLMINT iErrCode,
FLMBYTE * pucErrKey,
FLMUINT uiErrKeyLen,
FLMBOOL * pbFixErrRV);
RCODE startUpdate( void);
RCODE keyToVector(
FLMBYTE * pucKey,
FLMUINT uiKeyLen,
F_DataVector ** ppKeyRV);
RCODE verifyIXRefs(
STATE_INFO * pStateInfo,
FLMUINT64 ui64ResetNodeId);
RCODE verifyBlockStructure(
FLMUINT uiBlockSize,
F_BTREE_BLK_HDR * pBlkHdr);
RCODE chkEndUpdate( void);
F_Db * m_pDb;
F_TABLE * m_pTable;
F_INDEX * m_pIndex;
LFILE * m_pLFile;
F_DbInfo * m_pDbInfo;
F_BtResultSet * m_pXRefRS;
F_BtPool * m_pBtPool;
IF_RandomGenerator * m_pRandGen;
char m_szResultSetDibName [F_PATH_MAX_SIZE];
F_Db * m_pResultSetDb;
IF_DbCheckStatus * m_pDbCheckStatus;
FLMBOOL m_bPhysicalCorrupt;
FLMBOOL m_bIndexCorrupt;
SFLM_PROGRESS_CHECK_INFO m_Progress;
RCODE m_LastStatusRc;
FLMUINT m_uiFlags;
FLMBOOL m_bStartedUpdateTrans;
FLMUINT * m_puiIxArray;
F_BtResultSet * m_pIxRSet;
FLMBOOL m_bGetNextRSKey;
RS_IX_KEY m_IxKey1;
RS_IX_KEY m_IxKey2;
RS_IX_KEY * m_pCurrRSKey;
RS_IX_KEY * m_pPrevRSKey;
BlkStruct * m_pBlkEntries;
FLMUINT m_uiBlkEntryArraySize;
friend class F_DbInfo;
friend class F_KeyCollector;
};
// Check Error Codes
/*
** WARNING: ANY CHANGES MADE TO THE CHECK ERROR CODE DEFINES MUST BE
** REFLECTED IN THE FlmCorruptStrings TABLE FOUND IN FLERRSTR.CPP
*/
#define FLM_BAD_CHAR 1
#define FLM_BAD_ASIAN_CHAR 2
#define FLM_BAD_CHAR_SET 3
#define FLM_BAD_TEXT_FIELD 4
#define FLM_BAD_NUMBER_FIELD 5
#define FLM_BAD_FIELD_TYPE 6
#define FLM_BAD_IX_DEF 7
#define FLM_MISSING_REQ_KEY_FIELD 8
#define FLM_BAD_TEXT_KEY_COLL_CHAR 9
#define FLM_BAD_TEXT_KEY_CASE_MARKER 10
#define FLM_BAD_NUMBER_KEY 11
#define FLM_BAD_BINARY_KEY 12
#define FLM_BAD_CONTEXT_KEY 13
#define FLM_BAD_KEY_FIELD_TYPE 14
//#define Not_Used_15 15
//#define Not_Used_16 16
//#define Not_Used_17 17
#define FLM_BAD_KEY_LEN 18
#define FLM_BAD_LFH_LIST_PTR 19
#define FLM_BAD_LFH_LIST_END 20
#define FLM_INCOMPLETE_NODE 21 // Not really an error. Part of a field has been split across entries
#define FLM_BAD_BLK_END 22
#define FLM_KEY_COUNT_MISMATCH 23
#define FLM_REF_COUNT_MISMATCH 24
#define FLM_BAD_CONTAINER_IN_KEY 25
#define FLM_BAD_BLK_HDR_ADDR 26
#define FLM_BAD_BLK_HDR_LEVEL 27
#define FLM_BAD_BLK_HDR_PREV 28
/*
** WARNING: ANY CHANGES MADE TO THE CHECK ERROR CODE DEFINES MUST BE
** REFLECTED IN THE FlmCorruptStrings TABLE FOUND IN FLERRSTR.CPP
*/
#define FLM_BAD_BLK_HDR_NEXT 29
#define FLM_BAD_BLK_HDR_TYPE 30
#define FLM_BAD_BLK_HDR_ROOT_BIT 31
#define FLM_BAD_BLK_HDR_BLK_END 32
#define FLM_BAD_BLK_HDR_LF_NUM 33
#define FLM_BAD_AVAIL_LIST_END 34
#define FLM_BAD_PREV_BLK_NEXT 35
#define FLM_BAD_FIRST_ELM_FLAG 36 // NOTE: This is only needed during rebuild
#define FLM_BAD_LAST_ELM_FLAG 37 // NOTE: This is only needed during rebuild
#define FLM_BAD_LEM 38
#define FLM_BAD_ELM_LEN 39
#define FLM_BAD_ELM_KEY_SIZE 40
#define FLM_BAD_ELM_KEY 41
#define FLM_BAD_ELM_KEY_ORDER 42
#define FLM_BAD_ELM_KEY_COMPRESS 43 // NOTE: 5.x keys are not compressed
#define FLM_BAD_CONT_ELM_KEY 44
#define FLM_NON_UNIQUE_FIRST_ELM_KEY 45
#define FLM_BAD_ELM_OFFSET 46
#define FLM_BAD_ELM_INVALID_LEVEL 47
#define FLM_BAD_ELM_FLD_NUM 48
#define FLM_BAD_ELM_FLD_LEN 49
#define FLM_BAD_ELM_FLD_TYPE 50
#define FLM_BAD_ELM_END 51
#define FLM_BAD_PARENT_KEY 52
#define FLM_BAD_ELM_DOMAIN_SEN 53
#define FLM_BAD_ELM_BASE_SEN 54
#define FLM_BAD_ELM_IX_REF 55
#define FLM_BAD_ELM_ONE_RUN_SEN 56
#define FLM_BAD_ELM_DELTA_SEN 57
#define FLM_BAD_ELM_DOMAIN 58
/*
** WARNING: ANY CHANGES MADE TO THE CHECK ERROR CODE DEFINES MUST BE
** REFLECTED IN THE FlmCorruptStrings TABLE FOUND IN FLERRSTR.CPP
*/
#define FLM_BAD_LAST_BLK_NEXT 59
#define FLM_BAD_FIELD_PTR 60
#define FLM_REBUILD_REC_EXISTS 61
#define FLM_REBUILD_KEY_NOT_UNIQUE 62
#define FLM_NON_UNIQUE_ELM_KEY_REF 63
#define FLM_OLD_VIEW 64
#define FLM_COULD_NOT_SYNC_BLK 65
#define FLM_IX_REF_REC_NOT_FOUND 66
#define FLM_IX_KEY_NOT_FOUND_IN_REC 67
#define FLM_KEY_NOT_IN_KEY_REFSET 68
#define FLM_BAD_BLK_CHECKSUM 69
#define FLM_BAD_LAST_DRN 70
#define FLM_BAD_FILE_SIZE 71
#define FLM_BAD_FIRST_LAST_ELM_FLAG 72
#define FLM_BAD_DATE_FIELD 73
#define FLM_BAD_TIME_FIELD 74
#define FLM_BAD_TMSTAMP_FIELD 75
#define FLM_BAD_DATE_KEY 76
#define FLM_BAD_TIME_KEY 77
#define FLM_BAD_TMSTAMP_KEY 78
#define FLM_BAD_BLOB_FIELD 79
/*
** WARNING: ANY CHANGES MADE TO THE CHECK ERROR CODE DEFINES MUST BE
** REFLECTED IN THE FlmCorruptStrings TABLE FOUND IN FLERRSTR.CPP
*/
#define FLM_BAD_PCODE_IXD_TBL 80
#define FLM_NODE_QUARANTINED 81
#define FLM_BAD_BLK_TYPE 82
#define FLM_BAD_ELEMENT_CHAIN 83
#define FLM_BAD_ELM_EXTRA_DATA 84
#define FLM_BAD_BLOCK_STRUCTURE 85
#define FLM_BAD_ROOT_PARENT 86
#define FLM_BAD_ROOT_LINK 87
#define FLM_BAD_PARENT_LINK 88
#define FLM_BAD_INVALID_ROOT 89
#define FLM_BAD_FIRST_CHILD_LINK 90
#define FLM_BAD_LAST_CHILD_LINK 91
#define FLM_BAD_PREV_SIBLING_LINK 92
#define FLM_BAD_NEXT_SIBLING_LINK 93
#define FLM_BAD_ANNOTATION_LINK 94
#define FLM_UNSUPPORTED_NODE_TYPE 95
#define FLM_BAD_INVALID_NAME_ID 96
#define FLM_BAD_INVALID_PREFIX_ID 97
#define FLM_BAD_DATA_BLOCK_COUNT 98
#define FLM_BAD_AVAIL_SIZE 99
#define FLM_BAD_NODE_TYPE 100
#define FLM_BAD_CHILD_ELM_COUNT 101
#define FLM_NUM_CORRUPT_ERRORS 101
/*
** WARNING: ANY CHANGES MADE TO THE CHECK ERROR CODE DEFINES MUST BE
** REFLECTED IN THE FlmCorruptStrings TABLE FOUND IN FLERRSTR.CPP
*/
class F_DbInfo : public F_Object
{
public:
F_DbInfo()
{
m_uiLogicalCorruptions = 0;
m_uiLogicalRepairs = 0;
m_ui64FileSize = 0;
m_uiNumIndexes = 0;
m_uiNumTables = 0;
m_uiNumLogicalFiles = 0;
m_pLogicalFiles = NULL;
f_memset( &m_dbHdr, 0, sizeof( m_dbHdr));
f_memset( &m_AvailBlocks, 0, sizeof( m_AvailBlocks));
f_memset( &m_LFHBlocks, 0, sizeof( m_LFHBlocks));
}
virtual ~F_DbInfo()
{
freeLogicalFiles();
}
FINLINE void freeLogicalFiles( void)
{
FLMUINT uiLoop;
if (m_pLogicalFiles)
{
for (uiLoop = 0; uiLoop < m_uiNumLogicalFiles; uiLoop++)
{
if (m_pLogicalFiles [uiLoop].pLevelInfo)
{
f_free( &m_pLogicalFiles [uiLoop].pLevelInfo);
}
}
f_free( &m_pLogicalFiles);
}
m_uiNumLogicalFiles = 0;
m_uiNumIndexes = 0;
m_uiNumTables = 0;
}
FINLINE FLMUINT getNumTables( void)
{
return( m_uiNumTables);
}
FINLINE FLMUINT getNumIndexes( void)
{
return( m_uiNumIndexes);
}
FINLINE FLMUINT getNumLogicalFiles( void)
{
return( m_uiNumLogicalFiles);
}
FINLINE FLMUINT64 getFileSize( void)
{
return( m_ui64FileSize);
}
FINLINE SFLM_DB_HDR * getDbHdr( void)
{
return( &m_dbHdr);
}
FINLINE void getAvailBlockStats(
FLMUINT64 * pui64BytesUsed,
FLMUINT * puiBlockCount,
FLMINT * piLastError,
FLMUINT * puiNumErrors)
{
*pui64BytesUsed = m_LFHBlocks.ui64BytesUsed;
*puiBlockCount = m_AvailBlocks.uiBlockCount;
*piLastError = m_AvailBlocks.iErrCode;
*puiNumErrors = m_AvailBlocks.uiNumErrors;
}
FINLINE void getLFHBlockStats(
FLMUINT64 * pui64BytesUsed,
FLMUINT * puiBlockCount,
FLMINT * piLastError,
FLMUINT * puiNumErrors)
{
*pui64BytesUsed = m_LFHBlocks.ui64BytesUsed;
*puiBlockCount = m_LFHBlocks.uiBlockCount;
*piLastError = m_LFHBlocks.iErrCode;
*puiNumErrors = m_LFHBlocks.uiNumErrors;
}
void getBTreeInfo(
FLMUINT uiNthLogicalFile,
FLMUINT * puiLfNum,
eLFileType * peLfType,
FLMUINT * puiRootBlkAddress,
FLMUINT * puiNumLevels);
void getBTreeBlockStats(
FLMUINT uiNthLogicalFile,
FLMUINT uiLevel,
FLMUINT64 * pui64KeyCount,
FLMUINT64 * pui64BytesUsed,
FLMUINT64 * pui64ElementCount,
FLMUINT64 * pui64ContElementCount,
FLMUINT64 * pui64ContElmBytes,
FLMUINT * puiBlockCount,
FLMINT * piLastError,
FLMUINT * puiNumErrors);
private:
FLMUINT m_uiLogicalCorruptions;
FLMUINT m_uiLogicalRepairs;
FLMUINT64 m_ui64FileSize;
FLMUINT m_uiNumIndexes;
FLMUINT m_uiNumTables;
FLMUINT m_uiNumLogicalFiles;
LF_HDR * m_pLogicalFiles;
SFLM_DB_HDR m_dbHdr;
BLOCK_INFO m_AvailBlocks;
BLOCK_INFO m_LFHBlocks;
friend class F_DbCheck;
};
#define REBUILD_BLK_SIZE (1024 * 50)
#define REBUILD_RSET_ENTRY_SIZE 21
/*=============================================================================
Desc: Class to rebuild a broken database. This class is used by
F_DbSystem::dbRebuild()
=============================================================================*/
class F_DbRebuild : public F_Object
{
public:
// Constructor and Destructor
F_DbRebuild( void)
{
m_pDb = NULL;
m_pSFileHdl = NULL;
}
~F_DbRebuild()
{
}
RCODE dbRebuild(
const char * pszSourceDbPath,
const char * pszSourceDataDir,
const char * pszDestDbPath,
const char * pszDestDataDir,
const char * pszDestRflDir,
const char * pDictPath,
const char * pszPassword,
SFLM_CREATE_OPTS * pCreateOpts,
FLMUINT64 * pui64TotNodes,
FLMUINT64 * pui64NodesRecov,
FLMUINT64 * pui64QuarantinedNodes,
IF_DbRebuildStatus * pRebuildStatus);
FINLINE FLMUINT getBlockSize( void)
{
return( m_dbHdr.ui16BlockSize);
}
FINLINE RCODE reportStatus(
FLMBOOL bForce = FALSE)
{
RCODE rc = NE_SFLM_OK;
if( m_pRebuildStatus)
{
FLMUINT uiCurrentTime = FLM_GET_TIMER();
FLMUINT uiElapTime = FLM_ELAPSED_TIME( uiCurrentTime, m_uiLastStatusTime);
uiElapTime = FLM_TIMER_UNITS_TO_SECS( uiElapTime);
if( bForce || uiElapTime >= 1)
{
m_uiLastStatusTime = uiCurrentTime;
m_callbackData.bStartFlag = FALSE;
if( RC_BAD( rc = m_pRebuildStatus->reportRebuild( &m_callbackData)))
{
m_cbrc = rc;
goto Exit;
}
}
}
Exit:
return( rc);
}
private:
RCODE rebuildDatabase( void);
RCODE recoverNodes(
FLMBOOL bRecoverDictionary);
FINLINE void buildRSetEntry(
FLMBYTE ucPrefix,
FLMUINT uiCollection,
FLMUINT64 ui64NodeId,
FLMUINT uiBlockAddr,
FLMUINT uiElmNumber,
FLMBYTE * pucBuffer)
{
pucBuffer[ 0] = ucPrefix;
UD2FBA( (FLMUINT32)uiCollection, &pucBuffer[ 1]);
U642FBA( ui64NodeId, &pucBuffer[ 5]);
UD2FBA( (FLMUINT32)uiBlockAddr, &pucBuffer[ 13]);
UD2FBA( (FLMUINT32)uiElmNumber, &pucBuffer[ 17]);
}
FINLINE void extractRSetEntry(
FLMBYTE * pucBuffer,
FLMUINT * puiCollection,
FLMUINT64 * pui64NodeId,
FLMUINT * puiBlockAddr,
FLMUINT * puiElmNumber)
{
if( puiCollection)
{
*puiCollection = FB2UD( &pucBuffer[ 1]);
}
if( pui64NodeId)
{
*pui64NodeId = FB2U64( &pucBuffer[ 5]);
}
if( puiBlockAddr)
{
*puiBlockAddr = FB2UD( &pucBuffer[ 13]);
}
if( puiElmNumber)
{
*puiElmNumber = FB2UD( &pucBuffer[ 17]);
}
}
RCODE recoverTree(
F_RebuildRowIStream * pIStream,
IF_ResultSet * pNonRootRSet,
F_Row * pRecovCachedNode,
FLMBYTE * pucNodeIV);
FINLINE RCODE reportCorruption(
eCorruptionType eCorruption,
FLMUINT uiErrBlkAddress,
FLMUINT uiErrElmOffset,
FLMUINT64 ui64ErrRowId)
{
RCODE rc;
if( m_pRebuildStatus)
{
m_corruptInfo.eCorruption = eCorruption;
m_corruptInfo.uiErrBlkAddress = uiErrBlkAddress;
m_corruptInfo.uiErrElmOffset = uiErrElmOffset;
m_corruptInfo.ui64ErrRowId = ui64ErrRowId;
rc = m_pRebuildStatus->reportRebuildErr( &m_corruptInfo);
m_corruptInfo.eCorruption = SFLM_NO_CORRUPTION;
return( rc);
}
return( NE_SFLM_OK);
}
RCODE determineBlkSize(
FLMUINT * puiBlkSizeRV);
F_Db * m_pDb;
F_SuperFileHdl * m_pSFileHdl;
IF_DbRebuildStatus * m_pRebuildStatus;
FLMBOOL m_bBadHeader;
FLMUINT m_uiLastStatusTime;
SFLM_DB_HDR m_dbHdr;
SFLM_CREATE_OPTS m_createOpts;
SFLM_REBUILD_INFO m_callbackData;
SFLM_CORRUPT_INFO m_corruptInfo;
RCODE m_cbrc;
friend class F_RebuildRowIStream;
};
RCODE chkBlkRead(
F_DbInfo * pDbInfo,
FLMUINT uiBlkAddress,
F_BLK_HDR ** ppBlkHdr,
F_CachedBlock ** ppSCache,
FLMINT * piBlkErrCodeRV);
FLMINT flmCompareKeys(
FLMBYTE * pBuf1,
FLMUINT uiBuf1Len,
FLMBYTE * pBuf2,
FLMUINT uiBuf2Len);
void flmInitReadState(
STATE_INFO * pStateInfo,
FLMBOOL * pbStateInitialized,
FLMUINT uiVersionNum,
F_Db * pDb,
LF_HDR * pLogicalFile,
FLMUINT uiLevel,
FLMUINT uiBlkType,
FLMBYTE * pucKeyBuffer);
FLMINT flmVerifyBlockHeader(
STATE_INFO * pStateInfo,
BLOCK_INFO * pBlockInfoRV,
FLMUINT uiBlockSize,
FLMUINT uiExpNextBlkAddr,
FLMUINT uiExpPrevBlkAddr,
FLMBOOL bCheckEOF);
RCODE flmVerifyElement(
STATE_INFO * pStateInfo,
LFILE * pLFile,
F_INDEX * pIndex,
FLMINT * piErrCode);
void getEntryInfo(
F_BTREE_BLK_HDR * pBlkHdr,
FLMUINT uiOffset,
FLMBYTE ** ppucElm,
FLMUINT * puiElmLen,
FLMUINT * puiElmKeyLen,
FLMUINT * puiElmDataLen,
FLMBYTE ** ppucElmKey,
FLMBYTE ** ppucElmData);
FINLINE RCODE F_RowCacheMgr::makeWriteCopy(
F_Db * pDb,
F_Row ** ppRow)
{
if ((*ppRow)->getLowTransId() < pDb->m_ui64CurrTransID)
{
return( gv_SFlmSysData.pRowCacheMgr->_makeWriteCopy( pDb, ppRow));
}
return( NE_SFLM_OK);
}
/****************************************************************************
Desc:
*****************************************************************************/
class FLMEXP F_SuperFileClient : public IF_SuperFileClient
{
public:
F_SuperFileClient();
virtual ~F_SuperFileClient();
RCODE setup(
const char * pszCFileName,
const char * pszDataDir);
FLMUINT FLMAPI getFileNumber(
FLMUINT uiBlockAddr);
FLMUINT FLMAPI getFileOffset(
FLMUINT uiBlockAddr);
FLMUINT FLMAPI getBlockAddress(
FLMUINT uiFileNumber,
FLMUINT uiFileOffset);
RCODE FLMAPI getFilePath(
FLMUINT uiFileNumber,
char * pszPath);
static void bldSuperFileExtension(
FLMUINT uiFileNum,
char * pszFileExtension);
private:
char * m_pszCFileName;
char * m_pszDataFileBaseName;
FLMUINT m_uiExtOffset;
FLMUINT m_uiDataExtOffset;
};
// More includes
#include "sqlquery.h"
#include "fscursor.h"
#endif // FLAIMSYS_H