Files
mars-flaim/flaim/src/filesys.h
ahodgkinson 9d36b441c6 Fixed Solaris compiler warnings.
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@519 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-06-06 19:00:19 +00:00

1516 lines
40 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"
struct UCUR;
// 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)
//
// BYTE 0 - BITS 0,1 - First and last element markers
#define BBE_FIRST_FLAG 0x80
#define BBE_LAST_FLAG 0x40
#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
// 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)
// BYTE 1 - Key Length
#define BBE_KL 1
#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); \
}
#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
//
// 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 OPCODEs 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
// a = bit flag for number of bytes for TAG_NUM
// b = bit flag for number of bytes for value 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 flag
// i = ID is 2 bytes (0) or 4 bytes long
// e = Value is encrypted
#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
#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 cxab
// 0000 ffff tNum | LENGTH | VALUE
#define FOP_IS_TAGGED(p) ((*(p) & 0xF0) == FOP_TAGGED)
#define FTAG_LEVEL(p) ((*p) & 0x08)
#define FTAG_GET_FLD_TYPE(c) ((c) & 0x0F)
#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 DIN_KEY_SIZ 4
#define ELM_DIN_OVHD (BBE_KEY + DIN_KEY_SIZ)
#define MAX_REC_ELM 250 // Max length of record portion
#define MAX_FLD_OVHD 14 // Max field overhead
// Extended field flags (for open and free fields)
#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 FOP_LARGE 0xD0
/****************************************************************************
Desc:
****************************************************************************/
inline FLMBOOL FOP_IS_LARGE(
FLMBYTE * pucFOP)
{
// 1101 xxec
// fieldType (1 byte, 0000 ffff)
// tagNum (2 bytes)
// dataLen (4 bytes)
//
// If encrypted, the following are also present:
//
// encryptionId (2 bytes)
// encryptionLength (4 bytes)
if( (*pucFOP & 0xF0) == FOP_LARGE)
{
return( TRUE);
}
return( FALSE);
}
/****************************************************************************
Desc:
****************************************************************************/
inline FLMBOOL FLARGE_LEVEL(
FLMBYTE * pucFOP)
{
flmAssert( FOP_IS_LARGE( pucFOP));
if( (*pucFOP & 0x01))
{
return( TRUE);
}
return( FALSE);
}
/****************************************************************************
Desc:
****************************************************************************/
inline FLMBOOL FLARGE_ENCRYPTED(
FLMBYTE * pucFOP)
{
flmAssert( FOP_IS_LARGE( pucFOP));
if( (*pucFOP & 0x02))
{
return( TRUE);
}
return( FALSE);
}
/****************************************************************************
Desc:
****************************************************************************/
inline FLMBYTE FLARGE_FLD_TYPE(
FLMBYTE * pucFOP)
{
flmAssert( FOP_IS_LARGE( pucFOP));
return( *(pucFOP + 1) & 0x0F);
}
/****************************************************************************
Desc:
****************************************************************************/
inline FLMUINT FLARGE_TAG_NUM(
FLMBYTE * pucFOP)
{
flmAssert( FOP_IS_LARGE( pucFOP));
return( FB2UW( &pucFOP[ 2]));
}
/****************************************************************************
Desc:
****************************************************************************/
inline FLMUINT FLARGE_DATA_LEN(
FLMBYTE * pucFOP)
{
flmAssert( FOP_IS_LARGE( pucFOP));
return( FB2UD( &pucFOP[ 4]));
}
/****************************************************************************
Desc:
****************************************************************************/
inline FLMUINT FLARGE_ETAG_NUM(
FLMBYTE * pucFOP)
{
flmAssert( FLARGE_ENCRYPTED( pucFOP));
return( FB2UW( &pucFOP[ 8]));
}
/****************************************************************************
Desc:
****************************************************************************/
inline FLMUINT FLARGE_EDATA_LEN(
FLMBYTE * pucFOP)
{
flmAssert( FLARGE_ENCRYPTED( pucFOP));
return( FB2UD( &pucFOP[ 10]));
}
// 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 // -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))
// 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
// B-tree chain end indicator
#define BT_END ((FLMUINT32)0xFFFFFFFF)
// At the end of an element list
#define ELEMENT_END ((FLMUINT16) 0xFFFF)
// 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
#define BT_EQ_KEY 0
#define BT_GT_KEY 1
#define BT_LT_KEY 2
#define BT_END_OF_DATA 0xFFFF
#define DRN_LAST_MARKER ((FLMUINT) 0xFFFFFFFF)
#define DRN_LAST_MARKER_LEN 11
// Block Header Layout
#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
#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
#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
#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 ]))
inline 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_FILE_FORMAT_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_FILE_FORMAT_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_FILE_FORMAT_VER_4_3)
{
uiMaxSize = ((FLMUINT)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)
void ScaCleanupCache(
FLMUINT uiMaxLockTime);
void ScaFreeModifiedBlocks(
FDB * pDb);
FLMBOOL flmNeededByReadTrans(
FFILE * pFile,
FLMUINT uiLowTransId,
FLMUINT uiHighTransId);
void ScaReleaseLogBlocks(
FFILE * pFile);
RCODE ScaGetBlock(
FDB * pDb,
LFILE * pLFile,
FLMUINT uiBlkType,
FLMUINT uiBlkAddress,
FLMUINT * puiNumLooksRV,
SCACHE ** ppSCacheRV);
RCODE ScaCreateBlock(
FDB * pDb,
LFILE * pLFile,
SCACHE ** ppSCacheRV);
void ScaHoldCache(
SCACHE * pSCache);
void ScaReleaseCache(
SCACHE * pSCache,
FLMBOOL bMutexAlreadyLocked);
RCODE ScaLogPhysBlk(
FDB * pDb,
SCACHE ** ppSCacheRV);
RCODE ScaInit(
FLMUINT uiMaxSharedCache);
RCODE ScaConfig(
FLMUINT uiType,
void * pvValue1,
void * pvValue2);
void ScaExit( void);
void ScaFreeFileCache(
FFILE * 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 * pDb,
LFILE * pLFile,
FLMUINT uiBlkAddress,
BTSK * pStack);
void FSReleaseStackCache(
BTSK * pStack,
FLMUINT uiNumLevels,
FLMBOOL bMutexAlreadyLocked);
RCODE FSBlockFree(
FDB * pDb,
SCACHE * pSCache);
RCODE FSBlockFixLinks(
FDB * pDb,
LFILE * pLFile,
SCACHE * pSCache);
RCODE FSBlockUseNextAvail(
FDB * 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 * pDb,
LFILE * lfd,
BTSK ** stackRV);
FLMUINT FSBlkBuildPKC(
BTSK * stack,
FLMBYTE * pkcBuf,
FLMUINT uiFlags);
#define FSBBPKC_BEFORE_CURELM 0
#define FSBBPKC_AT_CURELM 1
RCODE FSBlkMoveElms(
BTSK * newBlkStk,
FLMBYTE * inElm,
FLMUINT uiInsElmLen,
FLMBYTE * elmPKCBuf);
inline FLMUINT FSRefFirst(
BTSK * stack,
DIN_STATE * state,
FLMUINT * puiDomainRV);
RCODE FSNextRecord(
FDB * pDb,
LFILE * pLFile,
BTSK * pStack);
RCODE FSRefNext(
FDB * pDb,
LFILE * lfd,
BTSK * stk,
DIN_STATE * state,
FLMUINT * puiDrnRV);
RCODE FSRefSearch(
BTSK * stack,
DIN_STATE * state,
FLMUINT * dinRV);
FLMUINT DINNextVal(
FLMBYTE * dinPtr,
DIN_STATE * state);
FLMUINT SENNextVal(
FLMBYTE ** senPtrRV);
FLMUINT DINOneRunVal(
FLMBYTE * dinPtr,
DIN_STATE * state);
FLMUINT FSGetDomain(
FLMBYTE ** curElmRV,
FLMUINT uiElmOvhd);
RCODE FSBtPrevElm(
FDB * pDb,
LFILE * lfd,
BTSK * stack);
FLMUINT FSRefLast(
BTSK * stack,
DIN_STATE * state,
FLMUINT * domainRV);
FLMUINT FSGetPrevRef(
FLMBYTE * pCurRef,
DIN_STATE * pState,
FLMUINT uiTarget);
RCODE FSRefPrev(
FDB * pDb,
LFILE * lfd,
BTSK * stk,
DIN_STATE * state,
FLMUINT * drnRV);
RCODE FSBtDelete(
FDB * pDb,
LFILE * lfd,
BTSK ** stack);
RCODE FSDelParentElm(
FDB * pDb,
LFILE * lfd,
BTSK ** stackRV);
RCODE FSNewLastBlkElm(
FDB * pDb,
LFILE * logDef,
BTSK ** 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 * pDb,
LFILE * lfd,
BTSK ** stackRV,
FLMBYTE * elm,
FLMUINT uiElmLen);
RCODE FSBtInsert(
FDB * pDb,
LFILE * lfd,
BTSK ** stackRV,
FLMBYTE * elm,
FLMUINT uiElmLen);
FLMUINT FSSetElmOvhd(
FLMBYTE * elm,
FLMUINT uiElmOvhd,
FLMUINT pkc,
FLMUINT uiKeyLen,
FLMBYTE * byteOneAddr);
RCODE FSReadRecord(
FDB * pDb,
LFILE * pLFile,
FLMUINT drn,
FlmRecord ** ppRecord,
FLMUINT * puiRecTransId,
FLMBOOL * pbMostCurrent);
RCODE FSReadElement(
FDB * pDb,
F_Pool * pPool,
LFILE * pLFile,
FLMUINT drn,
BTSK * pStack,
FLMBOOL bOkToPreallocSpace,
FlmRecord ** ppRecord,
FLMUINT * puiRecTransId,
FLMBOOL * pbMostCurrent);
RCODE FSRecUpdate(
FDB * 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 * pDb,
LFILE * lfd,
FLMBOOL bUpdateNextDrn,
FLMUINT * drnRV);
RCODE FSSetNextDrn(
FDB * pDb,
BTSK * stack,
FLMUINT drn,
FLMBOOL bManditory);
RCODE FSRefUpdate(
FDB * pDb,
LFILE * pLFile,
KREF_ENTRY * 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 * 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 * state,
FLMUINT value);
RCODE FSRefSplit(
FDB * pDb,
LFILE * lfd,
BTSK ** stkRV,
FLMBYTE * elmBuf,
FLMUINT drn,
FLMUINT uiDeleteFlag,
FLMUINT uiSplitFactor);
RCODE FSBtSearch(
FDB * pDb,
LFILE * pLFile,
BTSK ** ppStackRV,
FLMBYTE * pKey,
FLMUINT uiKeyLen,
FLMUINT uiDrnDomain);
RCODE FSBtSearchEnd(
FDB * pDb,
LFILE * pLFile,
BTSK ** pStackRV,
FLMUINT uiDrn);
RCODE FSGetRootBlock(
FDB * pDb,
LFILE ** ppLFile,
LFILE * pTmpLFile,
BTSK * pStack);
RCODE FSBtScan(
BTSK * stk,
FLMBYTE * key,
FLMUINT uiKeyLen,
FLMUINT uiDrnDomain);
RCODE FSBtScanNonLeafData(
BTSK * pStack,
FLMUINT uiDrn);
void FSBlkToStack(
BTSK * stack);
RCODE FSBtScanTo(
BTSK * stk,
FLMBYTE * key,
FLMUINT uiKeyLen,
FLMUINT drnDomain);
RCODE FSBlkNextElm(
BTSK * stack);
RCODE FSBtNextElm(
FDB * pDb,
LFILE * pLFile,
BTSK * pStack);
RCODE FSAdjustStack(
FDB * pDb,
LFILE * pLFile,
BTSK * stack,
FLMBOOL bMovedNext);
RCODE FSBlkSplit(
FDB * pDb,
LFILE * pLFile,
BTSK ** stkRV,
FLMBYTE * elm,
FLMUINT uiElmLen);
RCODE dbLock(
FDB * pDb,
FLMUINT uiMaxLockWait);
RCODE dbUnlock(
FDB * pDb);
RCODE flmLFileInit(
FDB * pDb,
LFILE * pLFile);
RCODE flmLFileRead(
FDB * pDb,
LFILE * pLFile);
RCODE flmBufferToLFile(
FLMBYTE * pBuf,
LFILE * pLFile,
FLMUINT uiBlkAddress,
FLMUINT uiOffsetInBlk);
RCODE flmLFileWrite(
FDB * pDb,
LFILE * pLFile);
RCODE flmLFileCreate(
FDB * pDb,
LFILE * pLFile,
FLMUINT uiLfNum,
FLMUINT uiLfType);
RCODE flmLFileDictUpdate(
FDB * pDb,
LFILE ** ppDictLFile,
FLMUINT * puiDrnRV,
FlmRecord * pNewDictRecord,
FlmRecord * pOldDictRecord,
FLMBOOL bDoInBackground,
FLMBOOL bCreateSuspended,
FLMBOOL * pbLogCompleteIndexSet,
FLMBOOL bRebuildOp = FALSE);
RCODE FSComputeRecordBlocks(
BTSK * pFromStack,
BTSK * pUntilStack,
FLMUINT * puiLeafBlocksBetween,
FLMUINT * puiTotalRecords,
FLMBOOL * pbTotalsEstimated);
RCODE FSComputeIndexCounts(
BTSK * pFromStack,
BTSK * pUntilStack,
FLMUINT * puiLeafBlocksBetween,
FLMUINT * puiTotalKeys,
FLMUINT * puiTotalRefs,
FLMBOOL * pbTotalsEstimated);
FLMUINT FSElementRefCount(
BTSK * pStack);
RCODE FSBlockCounts(
BTSK * 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 * pFile,
SCACHE * pLogBlock,
FLMBYTE * pucBlk,
FLMBOOL bDoAsync,
FLMUINT * puiLogEofRV);
void lgSetSyncCheckpoint(
FFILE * pFile,
FLMUINT uiCheckpoint,
FLMUINT uiBlkAddress);
FLMUINT lgHdrCheckSum(
FLMBYTE * pucLogHdr,
FLMBOOL bCompare);
RCODE FSVersionConversion40(
FDB * pDb,
FLMUINT uiNewVersion,
STATUS_HOOK fnStatusCallback,
void * pvUserData);
RCODE FSFlushElement(
FDB * pDb,
LFILE * pLFile,
UCUR * updCur);
/****************************************************************************
Desc: Get the previous backchain (PBC) address given an block
****************************************************************************/
inline 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
****************************************************************************/
inline 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
****************************************************************************/
inline 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)
****************************************************************************/
inline 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
****************************************************************************/
inline FLMUINT FSChildBlkAddr(
BTSK * 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
{
// Pre 3.x format is no longer supported.
// Corruption
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)
****************************************************************************/
inline void FSReleaseBlock(
BTSK * pStack, // Stack of variables for each level
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
****************************************************************************/
inline RCODE FSLogPhysBlk(
FDB * pDb,
BTSK * 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.
****************************************************************************/
inline void FSInitStackCache(
BTSK * 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.
****************************************************************************/
inline 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.
****************************************************************************/
inline 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
****************************************************************************/
inline FLMUINT DINPutNextVal(
FLMBYTE * dinPtr,
DIN_STATE * 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_FILE_FORMAT_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
****************************************************************************/
inline 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 * 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
****************************************************************************/
inline FLMUINT FSRefFirst(
BTSK * pStack, // Small stack to hold b-tree variables
DIN_STATE * pState, // Holds offset, one run number, etc.
FLMUINT * puiDomain) // Returns the elements domain
{
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:
****************************************************************************/
typedef struct UCUR
{
BTSK * 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;
#include "fpackoff.h"
#endif