git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
1507 lines
38 KiB
C
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
|