Files
mars-flaim/sql/src/rfl.h
2006-06-02 22:19:25 +00:00

687 lines
17 KiB
C++

//------------------------------------------------------------------------------
// Desc: This file contains structures and definitions used for roll
// forward logging.
//
// Tabs: 3
//
// Copyright (c) 1998-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id$
//------------------------------------------------------------------------------
#ifndef RFL_H
#define RFL_H
class IXKeyCompare;
// Packet types for roll forward logging
#define RFL_TRNS_BEGIN_PACKET 1
#define RFL_TRNS_COMMIT_PACKET 2
#define RFL_TRNS_ABORT_PACKET 3
#define RFL_REDUCE_PACKET 4
#define RFL_UPGRADE_PACKET 5
#define RFL_INDEX_SUSPEND_PACKET 6
#define RFL_INDEX_RESUME_PACKET 7
#define RFL_BLK_CHAIN_FREE_PACKET 8
#define RFL_ENABLE_ENCRYPTION_PACKET 9
#define RFL_WRAP_KEY_PACKET 10
#define RFL_DATA_PACKET 11
#define RFL_ROLL_OVER_DB_KEY_PACKET 12
#define RFL_ENC_DEF_KEY_PACKET 13
#define RFL_INSERT_ROW_PACKET 14
#define RFL_COLUMN_DATA_PACKET 15
#define RFL_PACKET_TYPE_MASK 0x7F
// Flags for all packets
#define RFL_HAVE_COUNTS_FLAG 0x01
#define RFL_HAVE_DATA_FLAG 0x02
#define RFL_FIRST_FLAG 0x04
#define RFL_LAST_FLAG 0x08
#define RFL_TRUNCATE_FLAG 0x10
#define RFL_GET_PACKET_TYPE(uiPacketType) \
((FLMUINT)((uiPacketType) & RFL_PACKET_TYPE_MASK))
// Definitions for ROLL FORWARD LOG file header format
#define RFL_NAME_POS 0
#define RFL_NAME "RFL6"
#define RFL_NAME_LEN 4
#define RFL_VERSION_POS RFL_NAME_LEN
#define RFL_VERSION "6.00"
#define RFL_VERSION_LEN 4
#define RFL_FILE_NUMBER_POS 8
#define RFL_EOF_POS 12
#define RFL_DB_SERIAL_NUM_POS 16
#define RFL_SERIAL_NUM_POS (RFL_DB_SERIAL_NUM_POS + SFLM_SERIAL_NUM_SIZE)
#define RFL_NEXT_FILE_SERIAL_NUM_POS (RFL_SERIAL_NUM_POS + SFLM_SERIAL_NUM_SIZE)
#define RFL_KEEP_SIGNATURE_POS (RFL_NEXT_FILE_SERIAL_NUM_POS + SFLM_SERIAL_NUM_SIZE)
#define RFL_KEEP_SIGNATURE "----KeepLog----"
#define RFL_NOKEEP_SIGNATURE "--DontKeepLog--"
// Buffer size needs to be a multiple of 512 for direct IO writes.
#define DEFAULT_RFL_WRITE_BUFFERS 8
#define DEFAULT_RFL_BUFFER_SIZE (65536)
// Definitions for packet format and sizes.
#define RFL_PACKET_ADDRESS_OFFSET 0
#define RFL_PACKET_CHECKSUM_OFFSET 4
#define RFL_PACKET_TYPE_OFFSET 5
#define RFL_PACKET_BODY_LENGTH_OFFSET 6
#define RFL_PACKET_OVERHEAD 8
// Direct IO requires that we always write on 512 byte boundaries.
// This means that whenever we write out a packet, we may also
// have to write out up to the last 511 bytes of the prior packet
// in order to be on a 512 byte boundary. Thus, the buffer must
// be able to hold a full packet plus up to 512 bytes of the prior
// packet.
#define RFL_MAX_PACKET_SIZE (65536 - 1024)
#define RFL_MAX_PACKET_BODY_SIZE (RFL_MAX_PACKET_SIZE - RFL_PACKET_OVERHEAD)
typedef struct RflWaiterTag * RFL_WAITER_p;
typedef struct RflWaiterTag
{
FLMUINT uiThreadId;
FLMBOOL bIsWriter;
F_SEM hESem;
RCODE * pRc;
RFL_WAITER_p pNext;
} RFL_WAITER;
typedef struct
{
IF_IOBufferMgr * pBufferMgr; // Write buffer manager
IF_IOBuffer * pIOBuffer;
FLMUINT uiCurrFileNum; // Current file number.
FLMUINT uiRflBufBytes; // Number of bytes currently in the
// pIOBuffer. Always points to
// where the last packet ends when
// writing to the log file.
FLMUINT uiRflFileOffset; // Current offset in file that the
// zeroeth byte in the buffer
// represents.
FLMBOOL bTransInProgress; // Transaction in progress using
// these buffers.
FLMBOOL bOkToWriteHdrs; // Is it OK to update the DB
// headers with this information
SFLM_DB_HDR dbHdr; // DB header to be written with
// this buffer.
SFLM_DB_HDR cpHdr; // Checkpoint header for this
// buffer.
RFL_WAITER * pFirstWaiter;
RFL_WAITER * pLastWaiter;
} RFL_BUFFER;
/**************************************************************************
Desc: This class handles all of the roll-forward logging for FLAIM. There
is one of these objects allocated per F_Database.
**************************************************************************/
class F_Rfl : public F_Object
{
public:
F_Rfl();
~F_Rfl();
RCODE setup(
F_Database * pDatabase,
const char * pszRflDir);
RCODE finishCurrFile(
F_Db * pDb,
FLMBOOL bNewKeepState);
RCODE logBeginTransaction(
F_Db * pDb);
RCODE logEndTransaction(
F_Db * pDb,
FLMUINT uiPacketType,
FLMBOOL bThrowLogAway,
FLMBOOL * pbLoggedTransEnd = NULL);
RCODE logReduce(
F_Db * pDb,
FLMUINT uiCount);
RCODE logIndexSuspendOrResume(
F_Db * pDb,
FLMUINT uiIndexNum,
FLMUINT uiPacketType);
RCODE logUpgrade(
F_Db * pDb,
FLMUINT uiOldVersion);
RCODE logBlockChainFree(
F_Db * pDb,
FLMUINT64 ui64MaintDocID,
FLMUINT uiStartBlkAddr,
FLMUINT uiEndBlkAddr,
FLMUINT uiCount);
RCODE logEncryptionKey(
F_Db * pDb,
FLMUINT uiPacketType,
FLMBYTE * pucKey,
FLMUINT32 ui32KeyLen);
RCODE logEncDefKey(
F_Db * pDb,
FLMUINT uiEncDefNum,
FLMBYTE * pucKeyValue,
FLMUINT uiKeyValueLen,
FLMUINT uiKeySize);
RCODE logRollOverDbKey(
F_Db * pDb);
RCODE logColumnValues(
F_Db * pDb,
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues,
FLMUINT uiNumColumnValues);
RCODE logInsertRow(
F_Db * pDb,
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues,
FLMUINT uiNumColumnValues);
RCODE recovInsertRow(
F_Db * pDb,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
RCODE recover(
F_Db * pDb,
IF_RestoreClient * pRestore,
IF_RestoreStatus * pRestoreStatus);
FLMBOOL atEndOfLog( void);
// Returns full log file name associated with number.
// Will return the full path name.
void getFullRflFileName(
FLMUINT uiFileNum,
char * pszFullRflFileName,
FLMUINT * puiFileNameBufSize,
FLMBOOL * pbNameTruncated = NULL);
// Set the RFL directory. Passing in a NULL or empty
// string will cause the directory to be to the same
// directory where the database is located.
RCODE setRflDir(
const char * pszRflDir);
FINLINE const char * getRflDirPtr( void)
{
return &m_szRflDir [0];
}
FINLINE FLMBOOL isRflDirSameAsDbDir( void)
{
return m_bRflDirSameAsDb;
}
FINLINE FLMUINT getCurrFileNum( void)
{
return m_pCurrentBuf->uiCurrFileNum;
}
FINLINE FLMUINT getCurrWriteOffset( void)
{
return( m_pCurrentBuf->uiRflFileOffset +
m_pCurrentBuf->uiRflBufBytes);
}
FINLINE FLMUINT getCurrReadOffset( void)
{
return( m_uiRflReadOffset + m_pCurrentBuf->uiRflFileOffset);
}
FINLINE FLMUINT getCurrPacketAddress( void)
{
return( m_uiPacketAddress);
}
FINLINE void getCurrSerialNum(
FLMBYTE * pucSerialNum)
{
f_memcpy( pucSerialNum, m_ucCurrSerialNum, SFLM_SERIAL_NUM_SIZE);
}
FINLINE void setCurrSerialNum(
FLMBYTE * pucSerialNum)
{
f_memcpy( m_ucCurrSerialNum, pucSerialNum, SFLM_SERIAL_NUM_SIZE);
}
FINLINE void getNextSerialNum(
FLMBYTE * pucSerialNum)
{
f_memcpy( pucSerialNum, m_ucNextSerialNum, SFLM_SERIAL_NUM_SIZE);
}
FINLINE void setNextSerialNum(
FLMBYTE * pucSerialNum)
{
f_memcpy( m_ucNextSerialNum, pucSerialNum, SFLM_SERIAL_NUM_SIZE);
}
FINLINE FLMUINT64 getCurrTransID( void)
{
return( m_ui64CurrTransID);
}
RCODE truncate(
F_SEM hWaitSem,
FLMUINT uiTruncateSize);
// Public functions, but only intended for internal use
RCODE makeRoom(
F_Db * pDb,
FLMUINT uiAdditionalBytesNeeded,
FLMUINT * puiCurrPacketLenRV,
FLMUINT uiPacketType,
FLMUINT * puiBytesAvailableRV,
FLMUINT * puiPacketCountRV);
FINLINE FLMBYTE * getPacketPtr( void)
{
return( &(m_pCurrentBuf->pIOBuffer->getBuffer()[
m_pCurrentBuf->uiRflBufBytes]));
}
// Close the current RFL file
FINLINE void closeFile( void)
{
if( m_pCurrentBuf->pBufferMgr)
{
flmAssert( !m_pCurrentBuf->pBufferMgr->havePendingIO());
}
if (m_pFileHdl)
{
m_pFileHdl->close();
m_pFileHdl->Release();
m_pFileHdl = NULL;
m_pCurrentBuf->uiCurrFileNum = 0;
m_pCurrentBuf->uiRflBufBytes = 0;
m_pCurrentBuf->uiRflFileOffset = 0;
}
}
FINLINE FLMBOOL seeIfRflVolumeOk( void)
{
return m_bRflVolumeOk;
}
FINLINE void setRflVolumeOk( void)
{
m_bRflVolumeOk = TRUE;
m_bRflVolumeFull = FALSE;
}
FINLINE FLMBOOL isRflVolumeFull( void)
{
return m_bRflVolumeFull;
}
FINLINE RCODE waitPendingWrites( void)
{
if (m_uiRflWriteBufs > 1)
{
return( m_pCurrentBuf->pBufferMgr->waitForAllPendingIO());
}
else
{
return( NE_SFLM_OK);
}
}
RCODE waitForWrites(
F_SEM hWaitSem,
RFL_BUFFER * pBuffer,
FLMBOOL bIsWriter);
RCODE waitForCommit(
F_SEM hWaitSem);
FINLINE void commitDbHdrs(
SFLM_DB_HDR * pDbHdr,
SFLM_DB_HDR * pCPHdr)
{
f_memcpy( &m_pCurrentBuf->dbHdr, pDbHdr, sizeof( SFLM_DB_HDR));
f_memcpy( &m_pCurrentBuf->cpHdr, pCPHdr, sizeof( SFLM_DB_HDR));
m_pCurrentBuf->bOkToWriteHdrs = TRUE;
}
FINLINE void clearDbHdrs( void)
{
m_pCurrentBuf->bOkToWriteHdrs = FALSE;
}
FLMBOOL seeIfRflWritesDone(
F_SEM hWaitSem,
FLMBOOL bForceWait);
void wakeUpWaiter(
RCODE rc,
FLMBOOL bIsWriter);
RCODE completeTransWrites(
F_Db * pDb,
FLMBOOL bCommitting,
FLMBOOL bOkToUnlock);
FINLINE void disableLogging(
FLMUINT * puiToken)
{
*puiToken = ++m_uiDisableCount;
}
FINLINE void enableLogging(
FLMUINT * puiToken)
{
flmAssert( m_uiDisableCount);
flmAssert( *puiToken && *puiToken == m_uiDisableCount);
m_uiDisableCount--;
*puiToken = 0;
}
FINLINE FLMBOOL isLoggingEnabled( void)
{
return( m_uiDisableCount ? FALSE : TRUE);
}
private:
FINLINE FLMBYTE * getPacketBodyPtr( void)
{
return( &(m_pCurrentBuf->pIOBuffer->getBuffer()[
m_pCurrentBuf->uiRflBufBytes + RFL_PACKET_OVERHEAD]));
}
FINLINE FLMBOOL haveBuffSpace(
FLMUINT uiSpaceNeeded
)
{
return( (FLMBOOL)((m_uiBufferSize - m_pCurrentBuf->uiRflBufBytes >=
uiSpaceNeeded)
? (FLMBOOL)TRUE
: (FLMBOOL)FALSE) );
}
// Write the header of an RFL file.
RCODE writeHeader(
FLMUINT uiFileNum,
FLMUINT uiEof,
FLMBYTE * pucSerialNum,
FLMBYTE * pucNextSerialNum,
FLMBOOL bKeepSignature);
// Verify the header of an RFL file.
RCODE verifyHeader(
FLMBYTE * pucHeader,
FLMUINT uiFileNum,
FLMBYTE * pucSerialNum);
// Open a new RFL file.
RCODE openFile(
F_SEM hWaitSem,
FLMUINT uiFileNum,
FLMBYTE * pucSerialNum);
// Create a new RFL file
RCODE createFile(
F_Db * pDb,
FLMUINT uiFileNum,
FLMBYTE * pucSerialNum,
FLMBYTE * pucNextSerialNum,
FLMBOOL bKeepSignature);
void copyLastSector(
RFL_BUFFER * pBuffer,
FLMBYTE * pucOldBuffer,
FLMBYTE * pucNewBuffer,
FLMUINT uiCurrPacketLen,
FLMBOOL bStartingNewFile);
// Position to an offset in the file.
RCODE positionTo(
FLMUINT uiFileOffset);
// Flush data to the current RFL file
RCODE flush(
F_Db * pDb,
RFL_BUFFER * pBuffer,
FLMBOOL bFinalWrite = FALSE,
FLMUINT uiCurrPacketLen = 0,
FLMBOOL bStartingNewFile = FALSE);
void switchBuffers( void);
// Flush all packets except the current one to disk.
// Shift the current one down to close to or at the
// beginning of the buffer.
RCODE shiftPacketsDown(
F_Db * pDb,
FLMUINT uiCurrPacketLen,
FLMBOOL bStartingNewFile);
// See if we need to generate a new RFL file.
RCODE seeIfNeedNewFile(
F_Db * pDb,
FLMUINT uiPacketLen,
FLMBOOL bDoNewIfOverLowLimit);
// Calculate checksum, etc. on current packet.
RCODE finishPacket(
F_Db * pDb,
FLMUINT uiPacketType,
FLMUINT uiPacketBodyLen,
FLMBOOL bDoNewIfOverLowLimit);
// Functions for reading log files
RCODE readPacket(
FLMUINT uiMinBytesNeeded);
RCODE getPacket(
F_Db * pDb,
FLMBOOL bForceNextFile,
FLMUINT * puiPacketTypeRV,
const FLMBYTE ** ppucPacketBodyRV,
FLMUINT * puiPacketBodyLenRV,
FLMBOOL * pbHitEnd);
RCODE setupTransaction(
F_Db * pDb);
void finalizeTransaction( void);
RCODE recovTransBegin(
F_Db * pDb,
eRestoreAction * peAction);
RCODE recovBlockChainFree(
F_Db * pDb,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
RCODE recovIndexSuspendResume(
F_Db * pDb,
FLMUINT uiPacketType,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
RCODE recovReduce(
F_Db * pDb,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
RCODE recovUpgrade(
F_Db * pDb,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
RCODE recovEncryptionKey(
F_Db * pDb,
FLMUINT uiPacketType,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
RCODE recovEncDefKey(
F_Db * pDb,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
RCODE recovRollOverDbKey(
F_Db * pDb,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
FLMBOOL useDataOnlyBlocks(
F_Db * pDb,
FLMUINT uiDataLen);
// Member variables
F_Database * m_pDatabase; // Pointer to database
RFL_BUFFER m_Buf1;
RFL_BUFFER m_Buf2;
F_MUTEX m_hBufMutex;
RFL_BUFFER * m_pCommitBuf; // Current buffer being committedout.
// NULL if no buffer is being committed.
RFL_BUFFER * m_pCurrentBuf; // Current write buffer - points to
// m_Buf1 or m_Buf2
FLMUINT m_uiRflWriteBufs; // Number of RFL buffers
FLMUINT m_uiBufferSize; // Buffer size
FLMBOOL m_bKeepRflFiles; // Keep RFL files after they are
// no longer needed?
FLMUINT m_uiRflMinFileSize; // Minimum RFL file size.
FLMUINT m_uiRflMaxFileSize; // Maximum RFL file size.
IF_FileHdl * m_pFileHdl; // File handle for writing to roll
// forward log file - only need one for
// the writer because we can only have
// one update transaction at a time.
FLMUINT m_uiLastRecoverFileNum;
// Last file number to go to when
// doing recovery.
FLMBYTE m_ucCurrSerialNum [SFLM_SERIAL_NUM_SIZE];
// Current file's serial number.
FLMUINT m_uiTransStartFile; // File the current transaction started
// in.
FLMUINT m_uiTransStartAddr; // Offset of start transaction packet.
FLMUINT64 m_ui64CurrTransID; // Current transaction ID.
FLMUINT64 m_ui64LastTransID; // Last transaction ID.
FLMUINT64 m_ui64LastLoggedCommitTransID;
// Last committed transaction that
// was logged to the RFL
FLMUINT m_uiOperCount; // Operations that have been logged for
// this transaction.
FLMUINT m_uiRflReadOffset; // Offset we are reading from in the
// buffer - only used when in reading
// mode.
FLMUINT m_uiPacketAddress; // Current packet's address in the file.
FLMUINT m_uiFileEOF; // End of file for current file.
// Only used when reading.
IF_RestoreClient * m_pRestore; // Restore object.
IF_RestoreStatus * m_pRestoreStatus;
// Restore status object
char m_szRflDir [F_PATH_MAX_SIZE];
// RFL directory
FLMBOOL m_bRflDirSameAsDb;
FLMBOOL m_bCreateRflDir;
FLMBYTE m_ucNextSerialNum [ SFLM_SERIAL_NUM_SIZE];
// Next file's serial number.
FLMBOOL m_bRflVolumeOk; // Did we have a problem accessing the
// RFL volume?
FLMBOOL m_bRflVolumeFull; // Did we have a problem accessing the
// RFL volume?
FLMUINT m_uiLastLfNum; // Last logical file used in restore/recover
eLFileType m_eLastLfType; // The Last Lfile Type
IXKeyCompare * m_pIxCompareObject;
IF_ResultSetCompare * m_pCompareObject;
FLMUINT m_uiDisableCount; // Is logging currently disabled
F_Pool m_tmpPool;
friend class F_RflOStream;
};
// Prototypes for roll forward logging functions.
FLMBYTE RflCalcChecksum(
FLMBYTE * pucPacket,
FLMUINT uiPacketBodyLen);
void rflGetBaseFileName(
FLMUINT uiFileNum,
char * pszBaseNameOut,
FLMUINT * puiFileNameBufSize,
FLMBOOL * pbNameTruncated = NULL);
RCODE rflGetDirAndPrefix(
const char * pszDbFileName,
const char * pszRflDirIn,
char * pszRflDirOut);
RCODE rflGetFileName(
const char * szDbName,
const char * szRflDir,
FLMUINT uiFileNum,
char * pszRflFileName);
FLMBOOL rflGetFileNum(
const char * pszRflFileName,
FLMUINT * puiFileNum);
#endif // ifdef RFL_H