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
This commit is contained in:
852
flaim/src/fsrecget.cpp
Normal file
852
flaim/src/fsrecget.cpp
Normal file
@@ -0,0 +1,852 @@
|
||||
//-------------------------------------------------------------------------
|
||||
// Desc: Read a record from the database.
|
||||
// Tabs: 3
|
||||
//
|
||||
// Copyright (c) 1991-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: fsrecget.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#include "flaimsys.h"
|
||||
|
||||
typedef struct Field_State
|
||||
{
|
||||
// State information to position to the field within the element
|
||||
FLMBYTE * pElement; // Points to the element within block
|
||||
FLMUINT uiFieldType; // Storage field type
|
||||
FLMUINT uiFieldLen; // Length of storage if known
|
||||
FLMUINT uiPosInElm; // Position within the element
|
||||
FLMUINT uiTagNum; // Field tag/data dictionary number
|
||||
FLMUINT uiLevel; // Current level number
|
||||
FLMUINT uiEncId; // EncDef ID if encrypted
|
||||
FLMUINT uiEncFieldLen; // Encrypted field length
|
||||
} FSTATE;
|
||||
|
||||
typedef struct Data_Piece
|
||||
{ // Data is garbage when uiFieldLen is 0.
|
||||
FLMBYTE * pData; // Points to data within the block.
|
||||
FLMUINT uiLength; // Length of this data piece
|
||||
struct Data_Piece * pNext; // Next data piece or NULL
|
||||
} DATAPIECE;
|
||||
|
||||
typedef struct Temporary_Field
|
||||
{
|
||||
FLMUINT uiLevel;
|
||||
FLMUINT uiFieldID;
|
||||
FLMUINT uiFieldType;
|
||||
FLMUINT uiFieldLen;
|
||||
FLMUINT uiEncId;
|
||||
FLMUINT uiEncFieldLen;
|
||||
DATAPIECE DataPiece;
|
||||
} TEMPFIELD;
|
||||
|
||||
#define NUM_FIELDS_IN_ARRAY 16
|
||||
|
||||
typedef struct Field_Group
|
||||
{
|
||||
TEMPFIELD pFields[ NUM_FIELDS_IN_ARRAY]; // Allocated array of fields
|
||||
struct Field_Group * pNext; // Next temporary field group
|
||||
} FLDGROUP;
|
||||
|
||||
typedef struct Locked_Block
|
||||
{
|
||||
SCACHE * pSCache;
|
||||
struct Locked_Block *pNext;
|
||||
} LOCKED_BLOCK;
|
||||
|
||||
FSTATIC RCODE FSGetFldOverhead(
|
||||
FDB_p pDb,
|
||||
FSTATE * fState);
|
||||
|
||||
/***************************************************************************
|
||||
Desc: Retrieves a record given a DRN
|
||||
*****************************************************************************/
|
||||
RCODE FSReadRecord( // Was FSRecordGet
|
||||
FDB_p pDb,
|
||||
LFILE * pLFile,
|
||||
FLMUINT uiDrn,
|
||||
FlmRecord ** ppRecord, // [out] returned record
|
||||
FLMUINT * puiRecTransId, // [out] record's transaction ID
|
||||
FLMBOOL * pbMostCurrent) // [out] true if record is most current
|
||||
{
|
||||
RCODE rc;
|
||||
BTSK stackBuf[ BH_MAX_LEVELS ];
|
||||
BTSK_p pStack = NULL;
|
||||
FLMBYTE pKeyBuf[ DIN_KEY_SIZ ];
|
||||
FLMBYTE pDrnBuf[ DIN_KEY_SIZ ];
|
||||
|
||||
FSInitStackCache( &stackBuf [0], BH_MAX_LEVELS);
|
||||
|
||||
pStack = stackBuf; // Initialize the stack
|
||||
pStack->pKeyBuf = pKeyBuf;
|
||||
|
||||
// Search the B-TREE for the record
|
||||
longToByte( uiDrn, pDrnBuf);
|
||||
if( RC_OK( rc = FSBtSearch( pDb, pLFile, &pStack, pDrnBuf, 4, 0)))
|
||||
{
|
||||
rc = RC_SET( FERR_NOT_FOUND);
|
||||
if( ( pStack->uiCmpStatus == BT_EQ_KEY) && (uiDrn != DRN_LAST_MARKER))
|
||||
{
|
||||
rc = FSReadElement( pDb, &pDb->TempPool, pLFile, uiDrn, pStack,
|
||||
TRUE, ppRecord, puiRecTransId, pbMostCurrent);
|
||||
}
|
||||
}
|
||||
FSReleaseStackCache( stackBuf, BH_MAX_LEVELS, FALSE);
|
||||
return( rc );
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Desc: Low level routine to retrieve and build an internal tree record.
|
||||
The caller is responsible for freeing memory that the record
|
||||
is placed into. This routine is called by FSRecordGet()
|
||||
Ret: FERR_OK (0)
|
||||
FERR_NOT_FOUND - field not found
|
||||
FERR_MEM - ran out of memeory
|
||||
FERR_DATA_ERROR - the data is somehow corrupt
|
||||
**************************************************************************/
|
||||
RCODE FSReadElement(
|
||||
FDB_p pDb,
|
||||
POOL * pPool,
|
||||
LFILE * pLFile,
|
||||
FLMUINT uiDrn,
|
||||
BTSK_p pStack,
|
||||
FLMBOOL bOkToPreallocSpace,
|
||||
FlmRecord ** ppRecord, // [out] returned record
|
||||
FLMUINT * puiRecTransId, // [out] record's transaction ID
|
||||
FLMBOOL * pbMostCurrent) // [out] true if record is most current
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
FlmRecord * pRecord = NULL;
|
||||
FLMBYTE * pCurElm; // Points to the current element
|
||||
void * pvPoolMark = GedPoolMark( pPool);
|
||||
FLMUINT uiElmRecLen; // Length of element's record
|
||||
FLMUINT uiFieldLen; // Length of the field
|
||||
FLMUINT uiLowestTransId; // Lowest transaction ID.
|
||||
FLMUINT uiFieldCount;
|
||||
FLMUINT uiTrueDataSpace;
|
||||
FLMUINT uiFieldPos;
|
||||
FLMBOOL bMostCurrent;
|
||||
TEMPFIELD * pField;
|
||||
FLDGROUP * pFldGroup = NULL;
|
||||
FLDGROUP * pFirstFldGroup = NULL;
|
||||
DATAPIECE * pDataPiece;
|
||||
LOCKED_BLOCK * pLockedBlock = NULL;
|
||||
FSTATE fState;
|
||||
FLMUINT uiEncFieldLen;
|
||||
#ifdef FLM_DBG_LOG
|
||||
char szTmpBuf[ 80];
|
||||
#endif
|
||||
|
||||
#ifdef FLM_DBG_LOG
|
||||
flmAssert( pStack->uiKeyLen == DIN_KEY_SIZ &&
|
||||
(FLMUINT)byteToLong( pStack->pKeyBuf) == uiDrn);
|
||||
#endif
|
||||
|
||||
// Initialize variables
|
||||
fState.uiLevel = 0;
|
||||
uiFieldCount = 0;
|
||||
uiTrueDataSpace = 0;
|
||||
uiFieldPos = NUM_FIELDS_IN_ARRAY;
|
||||
|
||||
// Check to make sure we are positioned at the first element.
|
||||
pCurElm = CURRENT_ELM( pStack );
|
||||
if( !BBE_IS_FIRST( pCurElm))
|
||||
{
|
||||
rc = RC_SET( FERR_DATA_ERROR);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
uiLowestTransId = FB2UD( &pStack->pBlk[ BH_TRANS_ID]);
|
||||
bMostCurrent = (pStack->pSCache->uiHighTransID == 0xFFFFFFFF) ? TRUE : FALSE;
|
||||
|
||||
#ifdef FLM_DBG_LOG
|
||||
f_sprintf( szTmpBuf, "Rd1:L%X,H%X",
|
||||
(unsigned)uiLowestTransId, (unsigned)pStack->pSCache->uiHighTransID);
|
||||
|
||||
flmDbgLogWrite( pDb->pFile->uiFFileId, pStack->pSCache->uiBlkAddress, uiDrn,
|
||||
pDb->LogHdr.uiCurrTransID, szTmpBuf);
|
||||
#endif
|
||||
|
||||
// Loop on each element in the record
|
||||
for( ;;)
|
||||
{
|
||||
// Setup all variables to process the current element
|
||||
|
||||
uiElmRecLen = BBE_GET_RL( pCurElm );
|
||||
if( uiElmRecLen == 0)
|
||||
{
|
||||
rc = RC_SET( FERR_EOF_HIT);
|
||||
break;
|
||||
}
|
||||
pCurElm += BBE_REC_OFS( pCurElm );
|
||||
fState.uiPosInElm = 0;
|
||||
|
||||
// Loop on each field within this element.
|
||||
while( fState.uiPosInElm < uiElmRecLen)
|
||||
{
|
||||
fState.pElement = pCurElm;
|
||||
if( RC_BAD( rc = FSGetFldOverhead( pDb, &fState)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
uiFieldLen = fState.uiFieldLen;
|
||||
uiEncFieldLen = fState.uiEncFieldLen;
|
||||
|
||||
// Old record info data - skip past for now
|
||||
if( fState.uiTagNum == 0)
|
||||
{
|
||||
fState.uiPosInElm += (uiEncFieldLen ? uiEncFieldLen : uiFieldLen);
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !pRecord)
|
||||
{
|
||||
// Create a new data record or use the existing data record.
|
||||
|
||||
if( *ppRecord)
|
||||
{
|
||||
if( (*ppRecord)->isReadOnly())
|
||||
{
|
||||
(*ppRecord)->Release();
|
||||
*ppRecord = NULL;
|
||||
|
||||
if( (pRecord = f_new FlmRecord) == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reuse the existing FlmRecord object.
|
||||
|
||||
pRecord = *ppRecord;
|
||||
*ppRecord = NULL;
|
||||
pRecord->clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (pRecord = f_new FlmRecord) == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
pRecord->setContainerID( pLFile->uiLfNum);
|
||||
pRecord->setID( uiDrn);
|
||||
}
|
||||
|
||||
// Check if out of fields in the tempoary field group.
|
||||
if( uiFieldPos >= NUM_FIELDS_IN_ARRAY)
|
||||
{
|
||||
FLDGROUP * pTempFldGroup;
|
||||
|
||||
uiFieldPos = 0;
|
||||
// Allocate the first field group from the pool.
|
||||
if( (pTempFldGroup = (FLDGROUP *) GedPoolAlloc(
|
||||
pPool, sizeof( FLDGROUP))) == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
pTempFldGroup->pNext = NULL;
|
||||
if( pFldGroup)
|
||||
{
|
||||
pFldGroup->pNext = pTempFldGroup;
|
||||
}
|
||||
else
|
||||
{
|
||||
pFirstFldGroup = pTempFldGroup;
|
||||
}
|
||||
pFldGroup = pTempFldGroup;
|
||||
}
|
||||
|
||||
uiFieldCount++;
|
||||
pField = &pFldGroup->pFields[ uiFieldPos++];
|
||||
pField->uiLevel = fState.uiLevel;
|
||||
pField->uiFieldID = fState.uiTagNum;
|
||||
pField->uiFieldType = fState.uiFieldType;
|
||||
pField->uiFieldLen = fState.uiFieldLen;
|
||||
pField->uiEncId = fState.uiEncId;
|
||||
pField->uiEncFieldLen = fState.uiEncFieldLen;
|
||||
pDataPiece = &pField->DataPiece;
|
||||
|
||||
if( uiFieldLen || uiEncFieldLen)
|
||||
{
|
||||
FLMUINT uiDataPos = 0;
|
||||
|
||||
if( fState.uiEncFieldLen)
|
||||
{
|
||||
uiTrueDataSpace += FLM_ENC_FLD_OVERHEAD;
|
||||
|
||||
// Binary data needs to account for alignment issues.
|
||||
|
||||
if (fState.uiFieldType == FLM_BINARY_TYPE)
|
||||
{
|
||||
// Adjust for the decrypted data.
|
||||
uiTrueDataSpace = ((uiTrueDataSpace + FLM_ALLOC_ALIGN) &
|
||||
(~(FLM_ALLOC_ALIGN) & 0x7FFFFFFF));
|
||||
}
|
||||
|
||||
uiTrueDataSpace += fState.uiFieldLen + fState.uiEncFieldLen;
|
||||
|
||||
// Store the encrypted field length rather than the decrypted field length
|
||||
// This will allow the gathering of the encrypted or decrypted field data
|
||||
// to use the same code.
|
||||
uiFieldLen = uiEncFieldLen;
|
||||
|
||||
}
|
||||
else if( fState.uiFieldLen > 4)
|
||||
{
|
||||
|
||||
// Binary data needs to account for alignment issues.
|
||||
|
||||
if (fState.uiFieldType == FLM_BINARY_TYPE)
|
||||
{
|
||||
if( fState.uiFieldLen >= 0xFF)
|
||||
{
|
||||
// Align so that the data is aligned - not the length
|
||||
|
||||
uiTrueDataSpace += sizeof( FLMUINT16);
|
||||
uiTrueDataSpace = ((uiTrueDataSpace + FLM_ALLOC_ALIGN) &
|
||||
(~(FLM_ALLOC_ALIGN) & 0x7FFFFFFF));
|
||||
uiTrueDataSpace -= sizeof( FLMUINT16);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiTrueDataSpace = ((uiTrueDataSpace + FLM_ALLOC_ALIGN) &
|
||||
(~(FLM_ALLOC_ALIGN) & 0x7FFFFFFF));
|
||||
}
|
||||
}
|
||||
|
||||
uiTrueDataSpace += fState.uiFieldLen;
|
||||
|
||||
// Field values with lengths greater than 255 bytes are
|
||||
// stored length-preceded. A single byte flags field precedes the length.
|
||||
|
||||
if (fState.uiFieldLen >= 0xFF)
|
||||
{
|
||||
uiTrueDataSpace += sizeof( FLMUINT16) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Value may start in the next element.
|
||||
|
||||
while( uiDataPos < uiFieldLen)
|
||||
{
|
||||
// Need to read next element for the value portion?
|
||||
|
||||
if( fState.uiPosInElm >= uiElmRecLen)
|
||||
{
|
||||
if( BBE_IS_LAST( CURRENT_ELM( pStack )))
|
||||
{
|
||||
rc = RC_SET( FERR_DATA_ERROR);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// If we are going to the next block, lock down this block
|
||||
// beacause data pointers are pointing to it.
|
||||
|
||||
if( RC_BAD( FSBlkNextElm( pStack))) // Better be FERR_BT_END_OF_DATA
|
||||
{
|
||||
LOCKED_BLOCK * pLastLockedBlock = pLockedBlock;
|
||||
|
||||
if( (pLockedBlock = (LOCKED_BLOCK *) GedPoolAlloc( pPool,
|
||||
sizeof( LOCKED_BLOCK))) == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ScaHoldCache( pStack->pSCache);
|
||||
pLockedBlock->pSCache = pStack->pSCache;
|
||||
pLockedBlock->pNext = pLastLockedBlock;
|
||||
|
||||
if( RC_BAD(rc = FSBtNextElm( pDb, pLFile, pStack)))
|
||||
{
|
||||
rc = (rc == FERR_BT_END_OF_DATA)
|
||||
? RC_SET( FERR_DATA_ERROR)
|
||||
: rc;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( uiLowestTransId > FB2UD( &pStack->pBlk[ BH_TRANS_ID]))
|
||||
{
|
||||
uiLowestTransId = FB2UD( &pStack->pBlk[ BH_TRANS_ID]);
|
||||
}
|
||||
|
||||
if( !bMostCurrent)
|
||||
{
|
||||
bMostCurrent = (pStack->pSCache->uiHighTransID ==
|
||||
0xFFFFFFFF) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
#ifdef FLM_DBG_LOG
|
||||
f_sprintf( szTmpBuf, "Rd2:L%X,H%X",
|
||||
(unsigned)FB2UD( &pStack->pBlk[ BH_TRANS_ID]),
|
||||
(unsigned)pStack->pSCache->uiHighTransID);
|
||||
|
||||
flmDbgLogWrite( pDb->pFile->uiFFileId,
|
||||
pStack->pSCache->uiBlkAddress, uiDrn,
|
||||
pDb->LogHdr.uiCurrTransID, szTmpBuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
pCurElm = CURRENT_ELM( pStack);
|
||||
uiElmRecLen = BBE_GET_RL( pCurElm);
|
||||
pCurElm += BBE_REC_OFS( pCurElm);
|
||||
fState.uiPosInElm = 0;
|
||||
}
|
||||
|
||||
// Compare number of bytes left if value <= # bytes left in element
|
||||
|
||||
if( uiFieldLen - uiDataPos <= uiElmRecLen - fState.uiPosInElm)
|
||||
{
|
||||
FLMUINT uiDelta = uiFieldLen - uiDataPos;
|
||||
|
||||
pDataPiece->pData = &pCurElm[ fState.uiPosInElm];
|
||||
pDataPiece->uiLength = uiDelta;
|
||||
fState.uiPosInElm += uiDelta;
|
||||
pDataPiece->pNext = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take what is there and get next element to grab some more.
|
||||
FLMUINT uiBytesToMove = uiElmRecLen - fState.uiPosInElm;
|
||||
DATAPIECE * pNextDataPiece;
|
||||
|
||||
pDataPiece->pData = &pCurElm[ fState.uiPosInElm];
|
||||
pDataPiece->uiLength = uiBytesToMove;
|
||||
fState.uiPosInElm += uiBytesToMove;
|
||||
uiDataPos += uiBytesToMove;
|
||||
|
||||
if( (pNextDataPiece = (DATAPIECE *)
|
||||
GedPoolAlloc( pPool, sizeof( DATAPIECE))) == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
pDataPiece->pNext = pNextDataPiece;
|
||||
pDataPiece = pNextDataPiece;
|
||||
}
|
||||
}
|
||||
} // End if uiFieldLen
|
||||
} // End of while( fState.uiPosInElm < uiElmRecLen)
|
||||
|
||||
// Done?
|
||||
|
||||
if( BBE_IS_LAST( CURRENT_ELM( pStack)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Position to next element
|
||||
|
||||
if( RC_BAD( FSBlkNextElm( pStack))) // Better be FERR_BT_END_OF_DATA
|
||||
{
|
||||
LOCKED_BLOCK * pLastLockedBlock = pLockedBlock;
|
||||
|
||||
if( (pLockedBlock = (LOCKED_BLOCK *) GedPoolAlloc( pPool,
|
||||
sizeof( LOCKED_BLOCK))) == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ScaHoldCache( pStack->pSCache);
|
||||
pLockedBlock->pSCache = pStack->pSCache;
|
||||
pLockedBlock->pNext = pLastLockedBlock;
|
||||
|
||||
if( RC_BAD(rc = FSBtNextElm( pDb, pLFile, pStack)))
|
||||
{
|
||||
if (rc == FERR_BT_END_OF_DATA)
|
||||
{
|
||||
rc = RC_SET( FERR_DATA_ERROR);
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( uiLowestTransId > FB2UD( &pStack->pBlk[ BH_TRANS_ID]))
|
||||
{
|
||||
uiLowestTransId = FB2UD( &pStack->pBlk[ BH_TRANS_ID]);
|
||||
}
|
||||
|
||||
if( !bMostCurrent)
|
||||
{
|
||||
bMostCurrent = (pStack->pSCache->uiHighTransID ==
|
||||
0xFFFFFFFF) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
#ifdef FLM_DBG_LOG
|
||||
f_sprintf( szTmpBuf, "Rd3:L%X,H%X",
|
||||
(unsigned)FB2UD( &pStack->pBlk[ BH_TRANS_ID]),
|
||||
(unsigned)pStack->pSCache->uiHighTransID);
|
||||
|
||||
flmDbgLogWrite( pDb->pFile->uiFFileId,
|
||||
pStack->pSCache->uiBlkAddress, uiDrn,
|
||||
pDb->LogHdr.uiCurrTransID, szTmpBuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Corruption Check.
|
||||
|
||||
pCurElm = CURRENT_ELM( pStack );
|
||||
if( BBE_IS_FIRST( pCurElm))
|
||||
{
|
||||
rc = RC_SET( FERR_DATA_ERROR);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
if( pRecord)
|
||||
{
|
||||
void * pvField;
|
||||
|
||||
if( bOkToPreallocSpace)
|
||||
{
|
||||
if( RC_BAD( rc = pRecord->preallocSpace( uiFieldCount, uiTrueDataSpace)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
pFldGroup = pFirstFldGroup;
|
||||
|
||||
for( uiFieldPos = 0; uiFieldCount--; uiFieldPos++)
|
||||
{
|
||||
|
||||
if( uiFieldPos >= NUM_FIELDS_IN_ARRAY)
|
||||
{
|
||||
uiFieldPos = 0;
|
||||
if( (pFldGroup = pFldGroup->pNext) == NULL)
|
||||
break;
|
||||
}
|
||||
pField = &pFldGroup->pFields[ uiFieldPos];
|
||||
|
||||
if( RC_BAD( rc = pRecord->insertLast( pField->uiLevel,
|
||||
pField->uiFieldID, pField->uiFieldType, &pvField)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( pField->uiFieldLen)
|
||||
{
|
||||
FLMBYTE * pDataPtr;
|
||||
FLMBYTE * pEncDataPtr;
|
||||
|
||||
pDataPiece = &pField->DataPiece;
|
||||
if (RC_BAD( rc = pRecord->allocStorageSpace(
|
||||
pvField,
|
||||
pField->uiFieldType,
|
||||
pField->uiFieldLen,
|
||||
pField->uiEncFieldLen,
|
||||
pField->uiEncId,
|
||||
(pField->uiEncId
|
||||
? FLD_HAVE_ENCRYPTED_DATA
|
||||
: 0),
|
||||
&pDataPtr,
|
||||
&pEncDataPtr)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (pField->uiEncId)
|
||||
{
|
||||
f_memcpy( pEncDataPtr, pDataPiece->pData, pDataPiece->uiLength);
|
||||
pEncDataPtr += pDataPiece->uiLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
f_memcpy( pDataPtr, pDataPiece->pData, pDataPiece->uiLength);
|
||||
pDataPtr += pDataPiece->uiLength;
|
||||
}
|
||||
pDataPiece = pDataPiece->pNext;
|
||||
} while( pDataPiece);
|
||||
|
||||
// If the field is encrypted, then we must decrypt it here.
|
||||
if (pField->uiEncId && !pDb->pFile->bInLimitedMode)
|
||||
{
|
||||
if (RC_BAD( rc = flmDecryptField( pDb->pDict,
|
||||
pRecord,
|
||||
pvField,
|
||||
pField->uiEncId,
|
||||
&pDb->TempPool)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( puiRecTransId)
|
||||
{
|
||||
*puiRecTransId = uiLowestTransId;
|
||||
}
|
||||
|
||||
if( pbMostCurrent)
|
||||
{
|
||||
*pbMostCurrent = bMostCurrent;
|
||||
}
|
||||
|
||||
if( *ppRecord)
|
||||
{
|
||||
// We shouldn't hit this case, but in case we do we will deal
|
||||
// with it.
|
||||
|
||||
flmAssert( 0);
|
||||
(*ppRecord)->Release();
|
||||
}
|
||||
|
||||
*ppRecord = pRecord;
|
||||
pRecord = NULL;
|
||||
|
||||
Exit:
|
||||
|
||||
// Release all locked down blocks except the current block.
|
||||
|
||||
while( pLockedBlock)
|
||||
{
|
||||
ScaReleaseCache( pLockedBlock->pSCache, FALSE);
|
||||
pLockedBlock = pLockedBlock->pNext;
|
||||
}
|
||||
|
||||
GedPoolReset( pPool, pvPoolMark);
|
||||
|
||||
if( pRecord)
|
||||
{
|
||||
pRecord->Release();
|
||||
}
|
||||
|
||||
// You are now positioned to the last element in the record
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Desc: Read field overhead (level, field drn, and length information.
|
||||
This isolates the complexity of the storage formats.
|
||||
Out: fstate updated according to data
|
||||
Ret: FERR_OK or FERR_NOT_FOUND if the field is not found
|
||||
Notes:The entire field overhead MUST always be together (not split).
|
||||
The data may be in another element.
|
||||
**************************************************************************/
|
||||
FSTATIC RCODE FSGetFldOverhead(
|
||||
FDB_p pDb,
|
||||
FSTATE * fState)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
FLMBYTE * pFieldOvhd = &fState->pElement[ fState->uiPosInElm ];
|
||||
FLMBYTE * pElement = fState->pElement;
|
||||
FLMBOOL bDoesntHaveFieldDef = TRUE;
|
||||
FLMUINT uiFieldLen;
|
||||
FLMUINT uiFieldType = 0;
|
||||
FLMUINT uiTagNum;
|
||||
FLMBYTE byTemp;
|
||||
FLMUINT uiEncId = 0;
|
||||
FLMUINT uiEncFieldLen = 0;
|
||||
|
||||
/**
|
||||
*** See FO_xxx_FLD definitions in FS.H
|
||||
*** If maintaining, see also FSRecUpd.c to see how codes were written.
|
||||
**/
|
||||
|
||||
if( FOP_IS_STANDARD( pFieldOvhd))
|
||||
{
|
||||
if( FSTA_LEVEL( pFieldOvhd))
|
||||
{
|
||||
fState->uiLevel++;
|
||||
}
|
||||
|
||||
uiFieldLen = FSTA_FLD_LEN( pFieldOvhd );
|
||||
uiTagNum = FSTA_FLD_NUM( pFieldOvhd );
|
||||
pFieldOvhd += FSTA_OVHD;
|
||||
}
|
||||
else if( FOP_IS_OPEN( pFieldOvhd))
|
||||
{
|
||||
if( FOPE_LEVEL( pFieldOvhd))
|
||||
{
|
||||
fState->uiLevel++;
|
||||
}
|
||||
|
||||
byTemp = (FLMBYTE)(FOP_GET_FLD_FLAGS( pFieldOvhd++ ));
|
||||
|
||||
uiTagNum = (FLMUINT) *pFieldOvhd++;
|
||||
if( FOP_2BYTE_FLDNUM(byTemp))
|
||||
{
|
||||
uiTagNum += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
|
||||
uiFieldLen = (FLMUINT) *pFieldOvhd++;
|
||||
if( FOP_2BYTE_FLDLEN( byTemp ))
|
||||
{
|
||||
uiFieldLen += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
}
|
||||
else if( FOP_IS_NO_VALUE( pFieldOvhd))
|
||||
{
|
||||
if( FNOV_LEVEL( pFieldOvhd ))
|
||||
{
|
||||
fState->uiLevel++;
|
||||
}
|
||||
|
||||
byTemp = (FLMBYTE)(FOP_GET_FLD_FLAGS( pFieldOvhd++ ));
|
||||
uiTagNum = (FLMUINT) *pFieldOvhd++;
|
||||
if( FOP_2BYTE_FLDNUM(byTemp))
|
||||
{
|
||||
uiTagNum += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
uiFieldLen= uiFieldType = 0;
|
||||
}
|
||||
else if( FOP_IS_SET_LEVEL( pFieldOvhd))
|
||||
{
|
||||
// SET THE LEVEL
|
||||
//
|
||||
// Must be continuous with the next field
|
||||
|
||||
fState->uiLevel -= FSLEV_GET( pFieldOvhd++);
|
||||
fState->uiPosInElm = (FLMUINT)(pFieldOvhd - pElement);
|
||||
|
||||
rc = FSGetFldOverhead( pDb, fState);
|
||||
goto Exit;
|
||||
}
|
||||
else if( FOP_IS_TAGGED( pFieldOvhd))
|
||||
{
|
||||
bDoesntHaveFieldDef = FALSE;
|
||||
|
||||
if( FTAG_LEVEL( pFieldOvhd))
|
||||
{
|
||||
fState->uiLevel++;
|
||||
}
|
||||
|
||||
byTemp = (FLMBYTE)(FOP_GET_FLD_FLAGS( pFieldOvhd));
|
||||
uiFieldType = (FLMUINT)(FTAG_FLD_TYPE( pFieldOvhd ));
|
||||
pFieldOvhd += FTAG_OVHD;
|
||||
uiTagNum = (FLMUINT) *pFieldOvhd++;
|
||||
|
||||
if( FOP_2BYTE_FLDNUM(byTemp))
|
||||
{
|
||||
uiTagNum += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
|
||||
// When storing the unregistered fields we cleared the high bit
|
||||
// to save on storage for VER11. The problem is that if a tag that is
|
||||
// not in the unregistered range (FLAIM TAGS) cannot be represented.
|
||||
// SO, we will XOR the high bit so 0x0111 is stored as 0x8111 and
|
||||
// 0x8222 is stored as 0x0222.
|
||||
|
||||
uiTagNum ^= 0x8000;
|
||||
uiFieldLen = (FLMUINT) *pFieldOvhd++;
|
||||
if( FOP_2BYTE_FLDLEN( byTemp))
|
||||
{
|
||||
uiFieldLen += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
}
|
||||
else if( FOP_IS_RECORD_INFO( pFieldOvhd))
|
||||
{
|
||||
bDoesntHaveFieldDef = FALSE;
|
||||
byTemp = *pFieldOvhd++;
|
||||
uiFieldLen = *pFieldOvhd++;
|
||||
if( FOP_2BYTE_FLDLEN( byTemp ))
|
||||
uiFieldLen += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
uiTagNum = 0;
|
||||
}
|
||||
else if (FOP_IS_ENCRYPTED( pFieldOvhd))
|
||||
{
|
||||
FLMBOOL bTagSz;
|
||||
FLMBOOL bLenSz;
|
||||
FLMBOOL bENumSz;
|
||||
FLMBOOL bELenSz;
|
||||
|
||||
bDoesntHaveFieldDef = FALSE;
|
||||
|
||||
if( FENC_LEVEL( pFieldOvhd ))
|
||||
{
|
||||
fState->uiLevel++;
|
||||
}
|
||||
|
||||
uiFieldType = (FLMUINT)(FENC_FLD_TYPE( pFieldOvhd ));
|
||||
bTagSz = FENC_TAG_SZ( pFieldOvhd);
|
||||
bLenSz = FENC_LEN_SZ( pFieldOvhd);
|
||||
bENumSz = FENC_ETAG_SZ( pFieldOvhd);
|
||||
bELenSz = FENC_ELEN_SZ( pFieldOvhd);
|
||||
|
||||
pFieldOvhd += 2;
|
||||
|
||||
uiTagNum = (FLMUINT) *pFieldOvhd++;
|
||||
if ( bTagSz)
|
||||
{
|
||||
uiTagNum += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
|
||||
uiFieldLen = (FLMUINT)*pFieldOvhd++;
|
||||
if (bLenSz)
|
||||
{
|
||||
uiFieldLen += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
|
||||
uiEncId = (FLMUINT) *pFieldOvhd++;
|
||||
if (bENumSz)
|
||||
{
|
||||
uiEncId += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
|
||||
uiEncFieldLen = (FLMUINT) *pFieldOvhd++;
|
||||
if (bELenSz)
|
||||
{
|
||||
uiEncFieldLen += ((FLMUINT) *pFieldOvhd++) << 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flmAssert( 0);
|
||||
rc = RC_SET( FERR_DATA_ERROR);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( bDoesntHaveFieldDef)
|
||||
{
|
||||
// Get the field's storage type.
|
||||
|
||||
if( RC_BAD( fdictGetField( pDb->pDict, uiTagNum, &uiFieldType,
|
||||
NULL, NULL)))
|
||||
{
|
||||
rc = RC_SET( FERR_DATA_ERROR);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the fState return values
|
||||
|
||||
fState->uiFieldType = uiFieldType;
|
||||
fState->uiFieldLen = uiFieldLen;
|
||||
fState->uiPosInElm = (FLMUINT) (pFieldOvhd - pElement);
|
||||
fState->uiTagNum = uiTagNum;
|
||||
fState->uiEncId = uiEncId;
|
||||
fState->uiEncFieldLen = uiEncFieldLen;
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
Reference in New Issue
Block a user