Files
mars-flaim/flaim/src/filesys.h
dsandersoremutah c55dab446f Renamed version4 to flaim and version5 to xflaim
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-01-27 21:06:39 +00:00

1507 lines
38 KiB
C

//-------------------------------------------------------------------------
// Desc: Definitions for internal database structure.
// Tabs: 3
//
// Copyright (c) 1990-1993,1995-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: filesys.h 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
//-------------------------------------------------------------------------
#ifndef FILESYS_H
#define FILESYS_H
#include "flaimsys.h"
#include "fpackon.h"
// IMPORTANT NOTE: No other include files should follow this one except
// for fpackoff.h
/**
*** B-tree ELEMENT Definitions
***
*** Portable element definitions are the basic unit of storage within
*** any b-tree block. The new format has changed to support longer
*** keys up to 1023 bytes long.
***
*** KEY:
*** BBE - B-tree Block Element
*** BNE - B-tree Non-leaf element
*** BUE - B-tree Unknown Element - don't know if leaf or non-leaf
***
*** CONT - the element 'does' continue to the next element
*** DOMAIN- for the new reference set organization in non-leaf blks
*** PKC - number of bytes used in the previous key (PKC)
*** KL - key Length - # of bytes to represent the right most key info
*** RL - number of bytes in the record portion of the element
*** KEY - starts the key bounded by KEY_LEN
*** CHILD_BLK - Three byte address of the childs block (non-leaf elms)
***
*** LEAF ELEMENT FORMAT
**/
/* BYTE 0 - BITS 0,1 - First and last element markers */
#define BBE_FIRST_FLAG 0x80 /* First element in a list */
#define BBE_LAST_FLAG 0x40 /* Last element in a list */
#define BBE_IS_FIRST(elm) ((*(elm)) & BBE_FIRST_FLAG )
#define BBE_NOT_FIRST(elm) (!((*(elm)) & BBE_FIRST_FLAG ))
#define BBE_SET_FIRST(elm) ((*(elm)) |= BBE_FIRST_FLAG)
#define BBE_CLR_FIRST(elm) ((*(elm)) = (FLMBYTE)(*(elm) & ~(BBE_FIRST_FLAG)))
#define BBE_IS_LAST(elm) ((*(elm)) & BBE_LAST_FLAG )
#define BBE_NOT_LAST(elm) (!((*(elm)) & BBE_LAST_FLAG ))
#define BBE_SET_LAST(elm) ((*(elm)) |= (FLMBYTE)(BBE_LAST_FLAG))
#define BBE_CLR_LAST(elm) ((*(elm)) = (FLMBYTE)(*(elm) & ~(BBE_LAST_FLAG)))
#define BBE_IS_FIRST_LAST(e) ((*(e)) & (BBE_FIRST_FLAG|BBE_LAST_FLAG))
#define BBE_MIDDLE_FLAG (BBE_FIRST_FLAG|BBE_LAST_FLAG)
#define BBE_IS_MIDDLE(elm) (!((*(elm)) & (BBE_MIDDLE_FLAG)))
#define BBE_SET_MIDDLE(elm) ((*(elm)) = (FLMBYTE)(*(elm) & ~(BBE_MIDDLE_FLAG)))
/* BYTE 0 - BITS 2,3 - Key Length High Bits */
#define BBE_KL_HBITS 0x30 /* High bits for key length */
/* BYTE 0 - BITS 4,5,6,7 - Previous Key Count - [0..15] */
#define BBE_PKC 0
#define BBE_PKC_MAX 0x0F
/* BBE_SET_PKC should clear out all other values */
#define BBE_SET_PKC(elm,val) ((*(elm)) = (FLMBYTE)(BBE_PKC_MAX & (val)))
#define BBE_CHK_PKC(val) (((val) <= BBE_PKC_MAX) ? val : BBE_PKC_MAX)
#define BBE_GET_PKC(elm) ((*(elm)) & BBE_PKC_MAX)
#define BBE_GETR_PKC(elm) (*(elm) & 0x3F) /* Get raw value with KL_HBITS */
/* BYTE 1 - Key Length */
#define BBE_KL 1
/* RAW MODE - used for fast value grabs */
#define BBE_SETR_KL(elm,val) ((elm)[BBE_KL] = (val))
#define BBE_KL_SHIFT_BITS 4
#define BBE_SET_KL(elm,val) \
{ \
if( (val) > 0xFF) \
*(elm) |= (FLMBYTE)(((val) >> BBE_KL_SHIFT_BITS) & BBE_KL_HBITS); \
(elm)[BBE_KL] = (FLMBYTE) (val); \
}
/* RAW MODE */
#define BBE_GETR_KL(elm) ((elm)[BBE_KL])
#define BBE_GET_KL(elm) (((*(elm) & BBE_KL_HBITS) << BBE_KL_SHIFT_BITS) + \
(elm)[BBE_KL])
/* BYTE 2 - Record Length */
#define BBE_RL 2
#define BBE_SET_RL(elm,val) (((elm)[BBE_RL]) = (FLMBYTE)(val))
#define BBE_GET_RL(elm) ( (elm)[BBE_RL])
/* BYTE 3 - KEY */
#define BBE_KEY 3
/* #define BBE_LEM_LEN 3 - defined in filesys.h */
/**
*** Non-leaf element format
**/
/* BYTE 0 - BIT 0 - DOMAIN FLAG */
#define BNE_DOMAIN 0x80
#define BNE_IS_DOMAIN(elm) ((*(elm)) & BNE_DOMAIN)
#define BNE_SET_DOMAIN(elm) ((*(elm)) |= BNE_DOMAIN)
#define BNE_CLR_DOMAIN(elm) ((*(elm)) = *(elm) & (~(BNE_DOMAIN)))
#define BNE_DOMAIN_LEN 3
/* BYTE 0 - BITS 1,2 */
/* Use BBE_KL_HBITS codes */
/* BYTE 0 - Bits 3,4,5,6,7 */
/* Use BBE_xxx_PKC macros */
/* BYTE 1 */
/* Use BBE_xxx_KL macros */
/* BYTES 2-5 - CHILD BLOCK ADDRESS - 4 byte number */
#define BNE_CHILD_BLOCK 2
#define BNE_CHILD_COUNT 6
/* BYTE 6 or 10 - Start of Key */
#define BNE_KEY_START 6
#define BNE_KEY_COUNTS_START 10
#define BNE_DATA_CHILD_BLOCK 4
#define BNE_DATA_OVHD 8
/* The domain value in 3-byte high-low format will follow the key */
/*************************************************
***
*** GENERAL MANIPULATION MACROS
***
*** LEN - Length of element
*** REC_OFS - Offset into the record portion (skip the key)
*** REC_PTR - Address of where record portion starts
*** KEY_OFS - Offset into where the key starts
***
**************************************************/
/**
*** Compute the complete length of a leaf and non-leaf element
**/
#define BBE_LEN(elm) (BBE_GET_RL(elm) + BBE_GET_KL(elm) + BBE_KEY)
#define BNE_LEN(stack,elm) (BBE_GET_KL(elm) + stack->uiElmOvhd + \
(BNE_IS_DOMAIN(elm) ? BNE_DOMAIN_LEN : 0))
#define BBE_REC_OFS(elm) (BBE_GET_KL(elm) + BBE_KEY)
#define BBE_REC_PTR(elm) (&(elm)[ BBE_REC_OFS(elm) ] )
/**
*** Record OPCODE's used in the storage of data record field values.
*** All opcodes are prefixed by FOP which is Field OPcode.
*** l = bits used to represent the storage length of the field value
*** ab = bit flags for number of bytes for TAG_NUM and LENGTH
*** ffff = 4 bits are used for the field type (0..15)
*** vvv = value of levels to shift out to (0..7)
*** c = The context flag - 0 is sibling - 1 is child
*** z = bits used for a compressed tNum (field number)
*** VALUE = value portion of the field
*** x = future large field (over 64K) flag
*** i = ID is 2 bytes (0) or 4 bytes long
*** o = Local field number - Version 1.2
**/
#define FOP_STANDARD 0 /* Use 1 left bit 0cll llll
zzzz zzzz
VALUE */
#define FOP_IS_STANDARD(p) (! (*(p) & 0x80) )
#define FSTA_MAX_FLD_NUM 0xFF
#define FSTA_MAX_FLD_LEN 0x3F /* 63 */
#define FSTA_LEVEL(p) ((*p) & 0x40)
#define FSTA_FLD_LEN(p) ((*p) & 0x3F)
#define FSTA_FLD_NUM(p) (*(p+1))
#define FSTA_OVHD 2
#define FOP_GET_FLD_FLAGS(p) ((*p) & 0x07)
#define FOP_2BYTE_FLDNUM(bv) ((bv) & 0x02)
#define FOP_2BYTE_FLDLEN(bv) ((bv) & 0x01)
#define FOP_LOCAL_FLDNUM(bv) ((bv) & 0x04)
#define FOP_TAGGED 0x80 /* Use 4 left bits 1000 coab
0000 ffff
tNum | LENGTH | VALUE*/
#define FOP_IS_TAGGED(p) ((*(p) & 0xF0) == FOP_TAGGED)
#define FTAG_LEVEL(p) ((*p) & 0x08)
#define FTAG_FLD_TYPE(p) ((*(p+1)) & 0x0F)
#define FTAG_OVHD 2
#define FTAG_LOCAL_FLAG 0x04
#define FOP_OPEN 0x90 /* Use 4 left bits 1001 cxab
tNum | LENGTH | VALUE*/
#define FOP_IS_OPEN(p) ((*(p) & 0xF0) == FOP_OPEN)
#define FOPE_LEVEL(p) ((*p) & 0x08)
#define FOP_SET_LEVEL 0xA0 /* Use 5 left bits 1010 0vvv */
#define FOP_IS_SET_LEVEL(p) ((*(p) & 0xF8) == FOP_SET_LEVEL)
#define FOP_LEVEL_MAX 0x07
#define FSLEV_GET(p) (*(p) & FOP_LEVEL_MAX)
#define FOP_NO_VALUE 0xA8 /* Use 5 left bits 1010 1ca0
a = 0 FLD_NUM=1 byte
a = 1 FLD_NUM=2 byte */
#define FOP_IS_NO_VALUE(p) ((*(p) & 0xF8) == FOP_NO_VALUE)
#define FNOV_LEVEL(p) ((*p) & 0x04)
#define FNOV_OVHD 2
#define FOP_RECORD_INFO 0xB0 /* Use 7 bits 1011 000b
LENGTH (1 or 2 bytes)
VALUE */
#define FOP_IS_RECORD_INFO(p) ((*(p) & 0xFE) == FOP_RECORD_INFO)
#define FOP_ENCRYPTED 0xE0 /* Use 7 left bits 1110 000c
ffff abab
tNum | LENGTH | eNum | eLENGTH | eVALUE */
#define FOP_IS_ENCRYPTED(p) ((*(p) & 0xFE) == FOP_ENCRYPTED)
#define FENC_LEVEL(p) ((*p) & 0x01)
#define FENC_FLD_TYPE(p) (((*(p+1)) & 0xF0) >> 4)
#define FENC_TAG_SZ(p) (((*(p+1)) & 0x08) >> 3)
#define FENC_LEN_SZ(p) (((*(p+1)) & 0x04) >> 2)
#define FENC_ETAG_SZ(p) (((*(p+1)) & 0x02) >> 1)
#define FENC_ELEN_SZ(p) ((*(p+1)) & 0x01)
#define DIN_KEY_SIZ 4
#define ELM_DIN_OVHD (BBE_KEY+DIN_KEY_SIZ)/* Database record overhead */
#define MAX_REC_ELM 250 /* Max length of record portion */
#define MAX_FLD_OVHD 10 /* Max field overhead + 2 to spare */
/* Supports up to 64K fields*/
/*
*** SEN - Simple Encoded Number
***
*** This is the variable length numbering system that can store
*** up to a 36 bit number in 1 to 5 bytes.
*** The SEN is the backbone to the index reference list compression
*** and the standard format for other functions that need to represent
*** a number in a variable number of bytes.
*/
#define SEN_1B_CODE 0x00 /* SEN 1 byte code */
#define SEN_1B_VAL 127 /* Max 1 byte value - 7 bits */
#define SEN_2B_CODE 0x80 /* SEN 2 byte code */
#define SEN_2B_CMSK 0xC0 /* Mask to check for code */
#define SEN_2B_VAL 16383 /* Max 2 byte value - 14 bits */
#define SEN_2B_MASK 0x3F
#define SEN_3B_CODE 0xC0 /* SEN 3 byte code */
#define SEN_3B_CMSK 0xF0 /* Mask to check for code */
#define SEN_3B_VAL 1048575 /* Max 3 byte value - 20 bits */
#define SEN_3B_MASK 0x0F
#define SEN_4B_CODE 0xD0 /* SEN 4 byte code */
#define SEN_4B_CMSK 0xF0 /* Mask to check for code */
#define SEN_4B_VAL 268435455 /* Max 4 byte value - 28 bits */
#define SEN_4B_MASK 0x0F
#define SEN_5B_CODE 0xE0 /* SEN 5 byte code */
#define SEN_5B_CMSK 0xF0 /* Mask to check for code */
#define SEN_5B_MASK 0x0F
#define SEN_FLAG 0xF0 /* Flag that contains some meaning */
#define SEN_MAX_SIZ 7 /* A -2,000,000,000 is biggest SEN */
#define SEN_DOMAIN 0xFC /* A domain in SEN format follows */
#define SEN_UPDATE_VER 0xFD /* Future */
/**
*** DIN - Dual Integer Numbers
**/
#define DIN_ONE_RUN_LV 0xF0 /* Lowest value for one runs */
#define DIN_MAX_1B_ONE_RUN 9 /* Maximum one byte one run value */
#define DIN_ONE_RUN_HV 0xF8 /* High value for one runs */
#define DIN_IS_ONE_RUN(b) (((b)==1) || \
(((b) >= DIN_ONE_RUN_LV) && ((b) <= DIN_ONE_RUN_HV)))
#define DIN_IS_REAL_ONE_RUN(b) \
(((b) >= DIN_ONE_RUN_LV) && ((b) <= DIN_ONE_RUN_HV))
/*
*** Reference Set Definitions
***
*/
/**
*** The reference set maximums are computed from the most bytes that
*** contain the maximum number of items that can exist within a
*** single domain.
*** The REF_SET_MAX_SIZ must contain more than one domain or the
*** set compression is not working as designed.
*** The minimum value of REF_SET_MAX_SIZ should >= 180. The worst pattern
*** is 02 01 02 01 02 01 = total must be > 256. 170 references + overhead
***
*** REF_SET_FIRST_MAX is not used at this point.
**/
#define REF_SET_MAX_SIZ 180 /* 170 references + extra stuff */
#define REF_SPLIT_50_50 50 /* Be really conservative */
#define REF_SPLIT_90_10 0 /* Split at first break */
#define SPLIT_90_10 0
#define SPLIT_50_50 1
/***************************************************************
**
** Defined Constants that the File system cares about
**
****************************************************************/
// B-tree chain end indicator
#define BT_END ((FLMUINT)0xFFFFFFFFL)
// Domains are used for direct access to the index reference sets
#define DIN_DOMAIN(din) ((din) >> 8)
#define DRN_DOMAIN(drn) ((drn) >> 8)
#define ZERO_DOMAIN ((FLMUINT) 0)
#define MAX_DOMAIN ((FLMUINT) 0x1000000)
/*
***
*** B-tree Block Scan Return Codes
*** In bsStatus
*/
#define BT_EQ_KEY 0 /* Keys are equal */
#define BT_GT_KEY 1 /* Key is greater than */
/* Less than should loop until greater*/
#define BT_LT_KEY 2 /* Not equal - cursor information */
#define BT_END_OF_DATA 0xFFFF /* Hit the end of the data */
#define DRN_LAST_MARKER ((FLMUINT) 0xFFFFFFFF)
#define DRN_LAST_MARKER_LEN 11
/**-----------------------------------------------------------------------
*** Block Header Layout
*** Add new block types here. Can support up to 16 different block
*** types at this time. In the future the middle 2 bits of the BH_TYPE
*** will represent a code for the current block size for variable blocks.
***----------------------------------------------------------------------*/
#define BH_CHECKSUM_LOW 0 /* Low order bits of checksum. */
/* Ver 3.0 low byte of blk address used
in the checksum value. */
#define BH_ADDR 0 /* Block address */
#define BH_PREV_BLK 4 /* Previous block in the chain */
#define BH_NEXT_BLK 8 /* Next block in the chain */
#define BACKCHAIN_CNT 36 /* Number of chains in a back chain */
#define BH_TYPE 12 /* Block type - defined below */
#define BHT_FREE 0 // Free block - avail list
#define BHT_LEAF 1 // Leaf block
#define BHT_LFH_BLK 4 // LFH Header block
#define BHT_PCODE_BLK 5 // PCODE block
#define BHT_NON_LEAF 6 // Non-leaf block - variable key size
#define BHT_NON_LEAF_DATA 7 // Non-leaf block data block - fixed key size
#define BHT_NON_LEAF_COUNTS 8 // Non-leaf index with counts
#define BHT_BI_BLK 0x30
// These bits get ORed in to type if the
// block is a Before Image block that
// should be restored on transaction
// abort. This is only set when a block
// is written to the log, so it only
// needs to be unset when the block is
// read back from the log.
#define BH_GET_TYPE(blk) \
(((blk)[BH_TYPE]) & 0x0F )
#define BH_SET_BI(blk) \
(((blk)[BH_TYPE]) |= BHT_BI_BLK)
#define BH_UNSET_BI(blk) \
(((blk)[BH_TYPE]) &= (~(BHT_BI_BLK)))
#define BH_IS_BI(blk) \
((((blk)[BH_TYPE]) & BHT_BI_BLK) == BHT_BI_BLK)
#define BHT_ROOT_BLK 0x80
#define BH_IS_ROOT_BLK(blk) \
(((blk)[BH_TYPE]) & BHT_ROOT_BLK)
#define BH_SET_ROOT_BLK(blk) \
((blk)[BH_TYPE] |= BHT_ROOT_BLK)
/**----------------------------------------------------------------------
*** The maximum levels in any b-tree be 8 levels with version 3.x.
*** We will not worry about 2x compatibility problems until we understand
*** what needs to be done on the 2x to 30 conversion.
*** Very long keys in index records (500-1000 bytes) could easily run
*** out of 8 levels, but this is very unlikely at this time.
***----------------------------------------------------------------------*/
#define BH_LEVEL 13 /* Block level (B-tree only) */
#define BH_MAX_LEVELS 8 /* Max allowable b-tree levels */
#define MAX_LEVELS BH_MAX_LEVELS
#define BH_ELM_END 14 /* End of the elements in a block */
#define BH_BLK_END 14 /* End of the elements in a block */
#define BH_TRANS_ID 16 /* Last transaction to update this block */
#define BH_PREV_TRANS_ID 20 /* Previous transaction to update block */
#define BH_PREV_BLK_ADDR 24 /* Pointer to previous image of blk */
#define BH_LOG_FILE_NUM 28 /* Logical file number of block */
#define BH_ENCRYPTED 30 /* Flag indicating if block is encrypted */
#define BH_CHECKSUM_HIGH 31 /* High order bits of checksum */
#define BH_OVHD 32 /* Overhead in the block header */
/* NOTE: BH_OVHD MUST ALWAYS BE A MULTIPLE OF 4 FOR ENCRYPTION TO WORK PROPERLY */
/* Avail List definitions */
#define BH_NEXT_BACKCHAIN 4 /* Backchains of avail list - 4 bytes */
#define BH_PREV_BACKCHAIN0 30 /* Avail blocks as of version 3 not encrypted */
#define BH_PREV_BACKCHAIN1 13 /* Prev backchain contains 3 bytes */
#define BH_PREV_BACKCHAIN2 28 /* at different locations in the header */
#define BH_PREV_BACKCHAIN3 29 /* Level and logical file num are used */
#define BBE_LEM_LEN 3 /* Length of leaf last element marker*/
/* Should be using stack->bsElmOvhd instead */
/**-----------------------------------
*** GENERAL STACK/BLOCK HEADER MACROS
***----------------------------------*/
#define GET_BH_ADDR( pBlk) \
(FB2UD(&(pBlk)[BH_ADDR]))
#define SET_BH_ADDR( pBlk, dwAddr) \
UD2FBA( dwAddr, &(pBlk)[BH_ADDR] )
/* Block access from the cache pointer */
#define GET_CABLKPTR(stack) \
((stack)->pSCache->pucBlk)
#define CABLK_ELM(stack,elm) \
((stack)->pSCache->pucBlk[ (elm) ])
/* Block access from the pBlk */
#define SET_BLKPTR(stack) \
((stack)->pBlk = stack->pSCache->pucBlk)
#define BLK_PTR(stack) \
((stack)->pBlk)
#define BLK_ELM(stack,elm) \
((stack)->pBlk[ (elm) ])
#define BLK_ELM_ADDR(stack,elm) \
(&((stack)->pBlk[ (elm) ]))
#define CURRENT_ELM(stack) \
(&((stack)->pBlk[ stack->uiCurElm ]))
FINLINE void flmCopyDrnKey(
FLMBYTE * pucDest,
FLMBYTE * pucSrc)
{
#ifdef FLM_UNIX
f_memcpy( pucDest, pucSrc, sizeof( FLMUINT32));
#else
*((FLMUINT32 *)pucDest) = *((FLMUINT32 *)pucSrc);
#endif
}
/*
*** Resolving the block address into components.
*/
#define MAX_DATA_FILE_NUM_VER40 0x1FF
#define MAX_LOG_FILE_NUM_VER40 0x3FF
#define MAX_DATA_FILE_NUM_VER43 0x7FF
#define MAX_LOG_FILE_NUM_VER43 0xFFF
#define MAX_DATA_BLOCK_FILE_NUMBER(uiDbVersion) \
(FLMUINT)(((uiDbVersion) >= FLM_VER_4_3) \
? MAX_DATA_FILE_NUM_VER43 \
: MAX_DATA_FILE_NUM_VER40)
#define FIRST_LOG_BLOCK_FILE_NUMBER(uiDbVersion) \
(FLMUINT)(MAX_DATA_BLOCK_FILE_NUMBER(uiDbVersion) + 1)
#define MAX_LOG_BLOCK_FILE_NUMBER(uiDbVersion) \
(FLMUINT)(((uiDbVersion) >= FLM_VER_4_3) \
? MAX_LOG_FILE_NUM_VER43 \
: MAX_LOG_FILE_NUM_VER40)
#define FSGetFileNumber( uiBlkAddr) \
((uiBlkAddr) & MAX_LOG_FILE_NUM_VER43)
#define FSGetFileOffset( udBlkAddr) \
((udBlkAddr) & 0xFFFFF000)
#define FSBlkAddress( iFileNum, udFileOfs) \
((udFileOfs) + (iFileNum))
// Max file size and log threshold.
#define MAX_FILE_SIZE_VER40 ((FLMUINT)0x7FF00000)
#define LOG_THRESHOLD_SIZE ((FLMUINT) 0x40000)
FINLINE FLMUINT flmGetMaxFileSize(
FLMUINT uiDbVersion,
FLMBYTE * pucLogHdr)
{
FLMUINT uiMaxSize = MAX_FILE_SIZE_VER40;
if( uiDbVersion >= FLM_VER_4_3)
{
uiMaxSize = (FB2UW( &(pucLogHdr[ LOG_MAX_FILE_SIZE]))) << 16;
if( !uiMaxSize)
{
uiMaxSize = MAX_FILE_SIZE_VER40;
}
}
return( uiMaxSize);
}
// Very large threshhold is the size we will allow the physical
// log to grow to before we force a truncation. At the low end,
// it is about 10 megabytes. At the high end it is about
// 1 gigabyte.
#define LOW_VERY_LARGE_LOG_THRESHOLD_SIZE ((FLMUINT)0xA00000)
#define HIGH_VERY_LARGE_LOG_THRESHOLD_SIZE ((FLMUINT) 0x40000000)
// RFL_TRUNCATE_SIZE is the size we will let an RFL file grow to
// before we truncate it back. RFL files are only truncated if
// we are configured to delete old RFL files.
#define RFL_TRUNCATE_SIZE ((FLMUINT)1024 * (FLMUINT)1024 * (FLMUINT)10)
/****************************************************************************
Shared Cache Routines
****************************************************************************/
void ScaCleanupCache(
FLMUINT uiMaxLockTime);
void ScaFreeModifiedBlocks(
FDB_p pDb);
FLMBOOL flmNeededByReadTrans(
FFILE * pFile,
FLMUINT uiLowTransId,
FLMUINT uiHighTransId);
void ScaReleaseLogBlocks(
FFILE_p pFile);
RCODE ScaGetBlock(
FDB_p pDb,
LFILE * pLFile,
FLMUINT uiBlkType,
FLMUINT uiBlkAddress,
FLMUINT * puiNumLooksRV,
SCACHE ** ppSCacheRV);
RCODE ScaCreateBlock(
FDB_p pDb,
LFILE * pLFile,
SCACHE ** ppSCacheRV);
void ScaHoldCache(
SCACHE * pSCache);
void ScaReleaseCache(
SCACHE * pSCache,
FLMBOOL bMutexAlreadyLocked);
RCODE ScaLogPhysBlk(
FDB_p pDb,
SCACHE ** ppSCacheRV);
RCODE ScaInit(
FLMUINT uiMaxSharedCache);
RCODE ScaConfig(
FLMUINT uiType,
void * pvValue1,
void * pvValue2);
void ScaExit( void);
void ScaFreeFileCache(
FFILE_p pFile);
RCODE ScaDoCheckpoint(
DB_STATS * pDbStats,
F_SuperFileHdl * pSFileHdl,
FFILE * pFile,
FLMBOOL bDoTruncate,
FLMBOOL bForceCheckpoint,
FLMINT iForceReason,
FLMUINT uiCPFileNum,
FLMUINT uiCPOffset);
RCODE ScaEncryptBlock(
FFILE * pFile,
FLMBYTE * pucBuffer,
FLMUINT uiBufLen,
FLMUINT uiBlockSize);
RCODE ScaDecryptBlock(
FFILE * pFile,
FLMBYTE * pucBuffer);
FLMUINT64 FSGetSizeInBytes(
FLMUINT uiMaxFileSize,
FLMUINT uiBlkAddress);
RCODE FSGetBlock(
FDB_p pDb,
LFILE * pLFile,
FLMUINT uiBlkAddress,
BTSK_p pStack);
void FSReleaseStackCache(
BTSK_p pStack,
FLMUINT uiNumLevels,
FLMBOOL bMutexAlreadyLocked);
RCODE FSBlockFree(
FDB_p pDb,
SCACHE * pSCache);
RCODE FSBlockFixLinks(
FDB_p pDb,
LFILE * pLFile,
SCACHE * pSCache);
RCODE FSBlockUseNextAvail(
FDB_p pDb,
LFILE * pLFile,
SCACHE ** ppSCacheRV);
FLMUINT ALGetNBC(
FLMBYTE * pBlkBuf);
#define ALGetNBC( pBlkBuf) \
(FB2UD( &pBlkBuf [BH_NEXT_BACKCHAIN]))
void ALPutNBC(
FLMBYTE * pBlkBuf,
FLMUINT uiAddr);
#define ALPutNBC(pBlkBuf,uiAddr) \
(UD2FBA( uiAddr, &(pBlkBuf)[ BH_NEXT_BACKCHAIN]))
RCODE FSCombineBlks(
FDB_p pDb,
LFILE * lfd,
BTSK ** stackRV);
FLMUINT FSBlkBuildPKC(
BTSK_p stack,
FLMBYTE * pkcBuf,
FLMUINT uiFlags);
#define FSBBPKC_BEFORE_CURELM 0
#define FSBBPKC_AT_CURELM 1
RCODE FSBlkMoveElms(
BTSK_p newBlkStk,
FLMBYTE * inElm,
FLMUINT uiInsElmLen,
FLMBYTE * elmPKCBuf);
FLMUINT FSRefFirst(
BTSK_p stack,
DIN_STATE_p state,
FLMUINT * puiDomainRV);
RCODE FSNextRecord(
FDB_p pDb,
LFILE * pLFile,
BTSK * pStack);
RCODE FSRefNext(
FDB_p pDb,
LFILE * lfd,
BTSK_p stk,
DIN_STATE_p state,
FLMUINT * puiDrnRV);
RCODE FSRefSearch(
BTSK_p stack,
DIN_STATE_p state,
FLMUINT * dinRV);
FLMUINT DINNextVal(
FLMBYTE * dinPtr,
DIN_STATE_p state);
FLMUINT SENNextVal(
FLMBYTE ** senPtrRV);
FLMUINT DINOneRunVal(
FLMBYTE * dinPtr,
DIN_STATE_p state);
FLMUINT FSGetDomain(
FLMBYTE ** curElmRV,
FLMUINT uiElmOvhd);
RCODE FSBtPrevElm(
FDB_p pDb,
LFILE * lfd,
BTSK_p stack);
FLMUINT FSRefLast(
BTSK_p stack,
DIN_STATE_p state,
FLMUINT * domainRV);
FLMUINT FSGetPrevRef(
FLMBYTE * pCurRef,
DIN_STATE_p pState,
FLMUINT uiTarget);
RCODE FSRefPrev(
FDB_p pDb,
LFILE * lfd,
BTSK_p stk,
DIN_STATE_p state,
FLMUINT * drnRV);
RCODE FSBtDelete(
FDB_p pDb,
LFILE * lfd,
BTSK_p * stack);
RCODE FSDelParentElm(
FDB_p pDb,
LFILE * lfd,
BTSK_p * stackRV);
RCODE FSNewLastBlkElm(
FDB_p pDb,
LFILE * logDef,
BTSK_p * stackRV,
FLMUINT uiFlags);
#define FSNLBE_GREATER 0x01
#define FSNLBE_LESS 0x02
#define FSNLBE_POSITION 0x04
RCODE FSBlkDelElm(
BTSK * stack);
void FSSetChildBlkAddr(
FLMBYTE * childElmPtr,
FLMUINT uiBlkAddr,
FLMUINT uiElmOvhd);
RCODE FSBtReplace(
FDB_p pDb,
LFILE * lfd,
BTSK_p * stackRV,
FLMBYTE * elm,
FLMUINT uiElmLen);
RCODE FSBtInsert(
FDB_p pDb,
LFILE * lfd,
BTSK_p * stackRV,
FLMBYTE * elm,
FLMUINT uiElmLen);
FLMUINT FSSetElmOvhd(
FLMBYTE * elm,
FLMUINT uiElmOvhd,
FLMUINT pkc,
FLMUINT uiKeyLen,
FLMBYTE * byteOneAddr);
RCODE FSReadRecord(
FDB_p pDb,
LFILE * pLFile,
FLMUINT drn,
FlmRecord ** ppRecord,
FLMUINT * puiRecTransId,
FLMBOOL * pbMostCurrent);
RCODE FSReadElement(
FDB_p pDb,
POOL * pPool,
LFILE * pLFile,
FLMUINT drn,
BTSK_p pStack,
FLMBOOL bOkToPreallocSpace,
FlmRecord ** ppRecord,
FLMUINT * puiRecTransId,
FLMBOOL * pbMostCurrent);
RCODE FSRecUpdate(
FDB_p pDb,
LFILE * lfd,
FlmRecord * pRecord,
FLMUINT drn,
FLMUINT uiAddAppendFlags);
#define REC_UPD_NEW_RECORD 2
#define REC_UPD_ADD 1
#define REC_UPD_MODIFY 0
#define REC_UPD_DELETE 0
RCODE FSGetNextDrn(
FDB_p pDb,
LFILE * lfd,
FLMBOOL bUpdateNextDrn,
FLMUINT * drnRV);
RCODE FSSetNextDrn(
FDB_p pDb,
BTSK_p stack,
FLMUINT drn,
FLMBOOL bManditory);
RCODE FSRefUpdate(
FDB * pDb,
LFILE * pLFile,
KREF_ENTRY_p pKref);
void FSFreeIxCounts(
FDB * pDb);
RCODE FSCommitIxCounts(
FDB * pDb);
RCODE FSUpdateBlkCounts(
FDB * pDb,
BTSK * pStack,
FLMUINT uiNewCount);
RCODE FSUpdateAdjacentBlkCounts(
FDB * pDb,
LFILE * pLFile,
BTSK * pStack,
BTSK * pNextBlkStk);
RCODE FSChangeCount(
FDB * pDb,
BTSK_p pStack,
FLMBOOL bAddReference);
RCODE FSChangeBlkCounts(
FDB * pDb,
BTSK * pStack,
FLMINT iDelta);
RCODE FSGetBtreeRefPosition(
FDB * pDb,
BTSK * pStack,
DIN_STATE * pDinState,
FLMUINT * puiRefPosition);
RCODE FSPositionSearch(
FDB * pDb,
LFILE * pLFile,
FLMUINT uiRefPosition,
BTSK ** ppStack,
FLMUINT * puiRecordId,
FLMUINT * puiDomain,
DIN_STATE * pDinState);
RCODE FSPositionScan(
BTSK * pStack,
FLMUINT uiRelativePosition,
FLMUINT * puiRelativePosInElement,
FLMUINT * puiRecordId,
FLMUINT * puiDomain,
DIN_STATE * pDinState);
RCODE FSPositionToRef(
BTSK * pStack,
FLMUINT uiRelativePosition,
FLMUINT * puiRecordId,
FLMUINT * puiDomain,
DIN_STATE * pDinState);
RCODE FSSetInsertRef(
FLMBYTE * dest,
FLMBYTE * src,
FLMUINT drn,
FLMUINT * puiSetLenRV);
RCODE FSSetDeleteRef(
FLMBYTE * dest,
FLMBYTE * src,
FLMUINT drn,
FLMUINT * puiSetLenRV);
FLMUINT SENValLen(
FLMBYTE * senPtr);
#define SENValLen(ptr) \
(SENLenArray[ *(ptr) >> 4 ])
FLMUINT SENPutNextVal(
FLMBYTE ** senPtrRV,
FLMUINT senValue );
FLMUINT DINPutOneRunVal(
FLMBYTE * dinPtr,
DIN_STATE_p state,
FLMUINT value);
RCODE FSRefSplit(
FDB * pDb,
LFILE * lfd,
BTSK_p * stkRV,
FLMBYTE * elmBuf,
FLMUINT drn,
FLMUINT uiDeleteFlag,
FLMUINT uiSplitFactor);
RCODE FSBtSearch(
FDB * pDb,
LFILE * pLFile,
BTSK_p * ppStackRV,
FLMBYTE * pKey,
FLMUINT uiKeyLen,
FLMUINT uiDrnDomain);
RCODE FSBtSearchEnd(
FDB * pDb,
LFILE * pLFile,
BTSK_p * pStackRV,
FLMUINT uiDrn);
RCODE FSGetRootBlock(
FDB * pDb,
LFILE ** ppLFile,
LFILE * pTmpLFile,
BTSK_p pStack);
RCODE FSBtScan(
BTSK_p stk,
FLMBYTE * key,
FLMUINT uiKeyLen,
FLMUINT uiDrnDomain);
RCODE FSBtScanNonLeafData(
BTSK_p pStack,
FLMUINT uiDrn);
void FSBlkToStack(
BTSK_p stack);
RCODE FSBtScanTo(
BTSK_p stk,
FLMBYTE * key,
FLMUINT uiKeyLen,
FLMUINT drnDomain);
RCODE FSBlkNextElm(
BTSK_p stack);
RCODE FSBtNextElm(
FDB_p pDb,
LFILE * pLFile,
BTSK_p pStack);
RCODE FSAdjustStack(
FDB_p pDb,
LFILE * pLFile,
BTSK_p stack,
FLMBOOL bMovedNext);
RCODE FSBlkSplit(
FDB_p pDb,
LFILE * pLFile,
BTSK_p * stkRV,
FLMBYTE * elm,
FLMUINT uiElmLen);
RCODE dbLock(
FDB_p pDb,
FLMUINT uiMaxLockWait);
RCODE dbUnlock(
FDB_p pDb);
RCODE flmLFileInit(
FDB_p pDb,
LFILE * pLFile);
RCODE flmLFileRead(
FDB_p pDb,
LFILE * pLFile);
RCODE flmBufferToLFile(
FLMBYTE * pBuf,
LFILE * pLFile,
FLMUINT uiBlkAddress,
FLMUINT uiOffsetInBlk);
RCODE flmLFileWrite(
FDB_p pDb,
LFILE * pLFile);
RCODE flmLFileCreate(
FDB_p pDb,
LFILE * pLFile,
FLMUINT uiLfNum,
FLMUINT uiLfType);
RCODE flmLFileDictUpdate(
FDB_p pDb,
LFILE * pDictLFile,
FLMUINT * puiDrnRV,
FlmRecord * pNewDictRecord,
FlmRecord * pOldDictRecord,
FLMBOOL bDoInBackground,
FLMBOOL bCreateSuspended,
FLMBOOL * pbLogCompleteIndexSet,
FLMBOOL bRebuildOp = FALSE);
RCODE FSComputeRecordBlocks(
BTSK_p pFromStack,
BTSK_p pUntilStack,
FLMUINT * puiLeafBlocksBetween,
FLMUINT * puiTotalRecords,
FLMBOOL * pbTotalsEstimated);
RCODE FSComputeIndexCounts(
BTSK_p pFromStack,
BTSK_p pUntilStack,
FLMUINT * puiLeafBlocksBetween,
FLMUINT * puiTotalKeys,
FLMUINT * puiTotalRefs,
FLMBOOL * pbTotalsEstimated);
FLMUINT FSElementRefCount(
BTSK_p pStack);
RCODE FSBlockCounts(
BTSK_p pStack,
FLMUINT uiFirstElement,
FLMUINT uiLastElement,
FLMUINT * puiFirstKeyCount,
FLMUINT * puiElementCount,
FLMUINT * puiRefCount);
RCODE flmWriteLogHdr(
DB_STATS * pDbStats,
F_SuperFileHdl * pSFileHdl,
FFILE * pFile,
FLMBYTE * pucLogHdr,
FLMBYTE * pucCPLogHdr,
FLMBOOL bIsCheckpoint);
RCODE flmPhysRollback(
FDB * pDb,
FLMUINT uiLogEOF,
FLMUINT uiFirstLogBlkAddr,
FLMBOOL bDoingRecovery,
FLMUINT uiMaxTransID);
RCODE lgFlushLogBuffer(
DB_STATS * pDbStats,
F_SuperFileHdl * pSFileHdl,
FFILE * pFile,
FLMBOOL bDoAsync);
RCODE lgOutputBlock(
DB_STATS * pDbStats,
F_SuperFileHdl * pSFileHdl,
FFILE_p pFile,
SCACHE * pLogBlock,
FLMBYTE * pucBlk,
FLMBOOL bDoAsync,
FLMUINT * puiLogEofRV);
void lgSetSyncCheckpoint(
FFILE_p pFile,
FLMUINT uiCheckpoint,
FLMUINT uiBlkAddress);
FLMUINT lgHdrCheckSum(
FLMBYTE * pucLogHdr,
FLMBOOL bCompare);
RCODE FSVersionConversion40(
FDB_p pDb,
FLMUINT uiNewVersion,
STATUS_HOOK fnStatusCallback,
void * pvUserData);
/*
Desc: Get the previous backchain (PBC) address given an block
Return: Address of PBC
*/
FINLINE FLMUINT ALGetPBC(
FLMBYTE * pucBlkBuf)
{
FLMUINT uiPbcAddr;
uiPbcAddr = ((FLMUINT) pucBlkBuf [BH_PREV_BACKCHAIN1]) << 24;
uiPbcAddr |= ((FLMUINT) pucBlkBuf [BH_PREV_BACKCHAIN2]) << 16;
uiPbcAddr |= ((FLMUINT) pucBlkBuf [BH_PREV_BACKCHAIN3]) << 8;
uiPbcAddr |= (FLMUINT) pucBlkBuf [BH_PREV_BACKCHAIN0];
return( uiPbcAddr);
}
/*
Desc: Get the previous backchain (PBC) address given an block
*/
FINLINE void ALPutPBC(
FLMBYTE * pucBlkBuf,
FLMUINT uiAddr)
{
pucBlkBuf [BH_PREV_BACKCHAIN1] = (FLMBYTE) (uiAddr >> 24);
pucBlkBuf [BH_PREV_BACKCHAIN2] = (FLMBYTE) (uiAddr >> 16);
pucBlkBuf [BH_PREV_BACKCHAIN3] = (FLMBYTE) (uiAddr >> 8);
// Code doesn't support old pre 3.0 format
pucBlkBuf [BH_PREV_BACKCHAIN0] = (FLMBYTE) uiAddr;
}
/*
Desc: Free Chain - reset the avail block with zeros
*/
FINLINE void ALResetAvailBlk(
FLMBYTE * pucBlkBuf)
{
UD2FBA( 0, &pucBlkBuf [BH_NEXT_BACKCHAIN]);
// This is ok to set the [0] backchain - doubles as encryption value.
pucBlkBuf [BH_PREV_BACKCHAIN0] =
pucBlkBuf [BH_PREV_BACKCHAIN1] =
pucBlkBuf [BH_PREV_BACKCHAIN2] =
pucBlkBuf [BH_PREV_BACKCHAIN3] = 0;
}
/*
Desc: Compare 2 PKC buffers
Return: Number of bytes that were equal (from left to right)
*/
FINLINE FLMUINT FSElmComparePKC(
FLMBYTE * pPkcBuf1,
FLMUINT uiPkcBufLen1,
FLMBYTE * pPkcBuf2,
FLMUINT uiPkcBufLen2)
{
FLMUINT uiMinBytes = f_min( uiPkcBufLen1, uiPkcBufLen2);
FLMUINT uiEqualBytes = 0;
while( uiMinBytes--)
{
if( *pPkcBuf1++ != *pPkcBuf2++)
{
break;
}
uiEqualBytes++;
}
return( uiEqualBytes);
}
/*
Desc: Returns the parent element's child block value
Return: Address of child block
*/
FINLINE FLMUINT FSChildBlkAddr(
BTSK_p pStack)
{
FLMBYTE * childBlkPtr;
FLMUINT uiElmOvhd = pStack->uiElmOvhd;
if( uiElmOvhd == BNE_KEY_START || uiElmOvhd == BNE_KEY_COUNTS_START)
{
childBlkPtr = BLK_ELM_ADDR( pStack, pStack->uiCurElm + BNE_CHILD_BLOCK );
return( FB2UD( childBlkPtr));
}
else if( uiElmOvhd == BNE_DATA_OVHD)
{
childBlkPtr = BLK_ELM_ADDR( pStack, pStack->uiCurElm + BNE_DATA_CHILD_BLOCK );
return( FB2UD( childBlkPtr));
}
else
{
flmAssert( 0);
return( BNE_KEY_START);
}
}
/*
Desc: Release the current block in the 'stack'
Out: pStack->pBlk, pSCache are set to NULL values.
Notes: Supports a NULL block (defined as pSCache == NULL)
*/
FINLINE void FSReleaseBlock(
BTSK_p pStack,
FLMBOOL bMutexAlreadyLocked)
{
// Release the current block, if any
if( pStack->pSCache)
{
ScaReleaseCache( pStack->pSCache, bMutexAlreadyLocked);
pStack->pSCache = NULL;
pStack->pBlk = NULL;
// NOTE: Do NOT unset pStack->uiBlkAddr. There are cases where we
// will release the block, but come back later and re-get it using
// the block address that is in the stack.
}
}
/*
Desc: Log the current block. The pointer to the block buffer may
change on the log call.
Out: pStack->pBlk may be changed
*/
FINLINE RCODE FSLogPhysBlk(
FDB_p pDb,
BTSK_p pStack)
{
RCODE rc;
if( RC_OK( rc = ScaLogPhysBlk( pDb, &pStack->pSCache)))
{
pStack->pBlk = pStack->pSCache->pucBlk;
}
else
{
ScaReleaseCache( pStack->pSCache, FALSE);
pStack->pBlk = NULL;
pStack->pSCache = NULL;
}
return( rc);
}
/*
Desc: Initialize a stack array for cache access. Set all of the pSCache
pointers in the array to NULL. This will prevent them from being
released if they were never filled with anything.
*/
FINLINE void FSInitStackCache(
BTSK_p pStack,
FLMUINT uiNumLevels)
{
while( uiNumLevels--)
{
pStack->pSCache = NULL;
pStack->pBlk = NULL;
pStack->uiBlkAddr = BT_END;
pStack++;
}
}
/*
Desc: Returns TRUE if a 3x address is less than another address.
This will also work with 2x address.
*/
FINLINE FLMBOOL FSAddrIsBelow(
FLMUINT uiAddress1,
FLMUINT uiAddress2)
{
if( FSGetFileNumber( uiAddress1) == FSGetFileNumber( uiAddress2))
{
if( FSGetFileOffset( uiAddress1) >= FSGetFileOffset( uiAddress2))
{
return( FALSE);
}
}
else if( FSGetFileNumber( uiAddress1) > FSGetFileNumber( uiAddress2))
{
return( FALSE);
}
return( TRUE);
}
/*
Desc: Returns TRUE if a 3x address is less than or equal another address.
This will also work with 2x address.
*/
FINLINE FLMBOOL FSAddrIsAtOrBelow(
FLMUINT uiAddress1,
FLMUINT uiAddress2)
{
if( FSGetFileNumber( uiAddress1) == FSGetFileNumber( uiAddress2))
{
if( FSGetFileOffset( uiAddress1) > FSGetFileOffset( uiAddress2))
{
return( FALSE);
}
}
else if( FSGetFileNumber( uiAddress1) > FSGetFileNumber( uiAddress2))
{
return( FALSE);
}
return( TRUE);
}
/*
Desc: Put the next DIN value - high level without one run worries
Out: value put into dinPtr[state[0]]
Return: length of DIN
*/
FINLINE FLMUINT DINPutNextVal(
FLMBYTE * dinPtr,
DIN_STATE_p state,
FLMUINT value)
{
FLMUINT uiLength;
dinPtr += state->uiOffset;
uiLength = SENPutNextVal( &dinPtr, value);
state->uiOffset += uiLength;
return( uiLength);
}
/*
Desc: This routine gets the number of bytes to encrypt for a block.
For encrypted blocks (new to FLM_VER_4_6), it must return the
block end rounded up to the next 16 byte boundary. For
non-encrypted blocks, in order to maintain compatibility on
a database that has been converted, we must return the block
end rounded up to the next 4 byte boundary. This is because
when a database is converted to 4.60, we don't go through
and recalculate the checksums on every block to go to 16 byte
boundaries. Already-existing blocks will have been calcuated
to a four byte boundary. We can check BH_ENCRYPTED for new
blocks that are on the 16 byte boundary, because that flag was
never set prior to version 4.60, and in 4.60+ that is the only
type of block where it will be set to a 16 byte boundary.
Ret: encryption size - FLMUINT
*/
FINLINE FLMUINT getEncryptSize(
FLMBYTE * pBlk)
{
FLMUINT uiLen = (FLMUINT)FB2UW( &pBlk [BH_ELM_END]);
if (!pBlk [BH_ENCRYPTED])
{
if (uiLen % sizeof( FLMUINT32) != 0)
{
uiLen += (FLMUINT)(sizeof( FLMUINT32) - (uiLen % sizeof( FLMUINT32)));
}
}
else if (uiLen < BH_OVHD)
{
uiLen = BH_OVHD;
}
else
{
if (uiLen % 16)
{
uiLen += (FLMUINT)(16 - (uiLen % 16));
}
}
return( uiLen);
}
/*
Desc: return the first DRN in an elements reference list
In: BTSK_p stack, state - should be DIN_STATE_SIZ
* puiDomain - returns the elements domain
Out: state information updated to refer to the last reference & puiDomain
Return: DIN the din of the first reference
*/
FINLINE FLMUINT FSRefFirst(
BTSK_p pStack,
DIN_STATE_p pState,
FLMUINT * puiDomain)
{
FLMBYTE * pCurElm = CURRENT_ELM( pStack);
// Point past the domain, ignore return value
*puiDomain = FSGetDomain( &pCurElm, pStack->uiElmOvhd);
RESET_DINSTATE_p( pState);
// Don't use DIN because state must be set to zero after getting value
return( SENNextVal( &pCurElm));
}
/*
Desc: This routine locks the write lock on a database.
*/
FINLINE RCODE dbWriteLock(
FFILE_p pFile,
DB_STATS * pDbStats = NULL,
FLMUINT uiTimeout = FLM_NO_TIMEOUT)
{
RCODE rc = FERR_OK;
if( RC_BAD( rc = pFile->pWriteLockObj->Lock( FALSE, NULL,
(FLMBOOL)(uiTimeout ? TRUE : FALSE),
TRUE, uiTimeout, 0, pDbStats)))
{
goto Exit;
}
Exit:
return( rc);
}
/*
Desc: This routine unlocks the write lock on a database.
*/
FINLINE void dbWriteUnlock(
FFILE_p pFile,
DB_STATS * pDbStats = NULL)
{
(void)pFile->pWriteLockObj->Unlock( FALSE, NULL, FALSE, pDbStats);
}
typedef struct Update_Cursor
{
BTSK_p pStack; // Points to current stack level
FLMUINT uiDrn; // Domain Record Number
FLMUINT uiBufLen; // Length of the buffer
FLMUINT uiUsedLen; // Used length in the buffer
FLMUINT uiFlags; // Bit flags for values below
#define UCUR_REPLACE 1 // Replace current element
#define UCUR_INSERT 2 // Insert current element
#define UCUR_LAST_TIME 4 // Set on last insert/replace
FLMBYTE pKeyBuf[ DIN_KEY_SIZ ]; // Holds the DIN key
FLMBYTE pElmBuf[ ELM_DIN_OVHD + 256]; // Holds each element
} UCUR;
RCODE FSFlushElement(
FDB * pDb,
LFILE * pLFile,
UCUR * updCur);
#include "fpackoff.h"
#endif