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

1370 lines
31 KiB
C++

//-------------------------------------------------------------------------
// Desc: Build dicitionary tables.
// Tabs: 3
//
// Copyright (c) 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: fdictbld.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
//-------------------------------------------------------------------------
#include "flaimsys.h"
FSTATIC POOL_STATS g_TDictPoolStats = {0,0};
FSTATIC void fdictFixupPointers(
FDICT * pNewDict,
FDICT * pOldDict);
FSTATIC RCODE fdictReallocAllTables(
TDICT * pTDict);
FSTATIC RCODE fdictReallocTbl(
FLMUINT uiElementSize,
FLMUINT uiTblSize,
FLMUINT uiAddElements,
void ** ppvTblRV);
FSTATIC void fdictAddItem(
TDICT * pTDict,
FLMUINT uiFieldNum,
FLMUINT uiFieldType);
FSTATIC RCODE fdictAddIndex(
TDICT * pTDict,
DDENTRY * pEntry);
FSTATIC RCODE fdictFixupIfdPointers(
FDICT * pDict,
FLMUINT uiIfdStartOffset);
FSTATIC RCODE fdictAddNewCCS(
TDICT * pTDict,
TENCDEF * pTEncDef,
FLMUINT uiRecNum);
/****************************************************************************
Desc: Rebuild the dictionary tables reading in all dictionary
records.
****************************************************************************/
RCODE fdictRebuild(
FDB * pDb)
{
RCODE rc = FERR_OK;
TDICT tDict;
FLMUINT uiCount;
IXD_p pIxd;
FLMBOOL bTDictInitialized = FALSE;
FLMBOOL bSuspended;
FLMUINT uiOnlineTransId;
// Allocate a new FDICT structure for reading the local dictionary
// into memory.
// At this point, pDb better not be pointing to a dictionary.
flmAssert( pDb->pDict == NULL);
if( RC_BAD( rc = flmAllocDict( &pDb->pDict)))
{
goto Exit;
}
if( !pDb->pDict->pLFileTbl)
{
// Read the local dictionary into memory.
if( RC_BAD(rc = fdictReadLFiles( pDb, pDb->pDict)))
{
goto Exit;
}
// For a database create the LFiles still are not created.
if( pDb->pDict->pLFileTbl->uiLfNum == 0)
{
goto Exit;
}
}
bTDictInitialized = TRUE;
if( RC_BAD( rc = fdictInitTDict( pDb, &tDict)))
{
goto Exit;
}
if( RC_BAD( rc = fdictProcessAllDictRecs( pDb, &tDict)))
{
goto Exit;
}
if( RC_BAD( rc = fdictBuildTables( &tDict, FALSE, FALSE)))
{
goto Exit;
}
// Loop through the IXD and set the uiLastDrnIndexed value.
uiCount = pDb->pDict->uiIxdCnt;
for( pIxd = pDb->pDict->pIxdTbl; uiCount--; pIxd++)
{
// Ignore any errors in case we are rebuilding.
if( RC_BAD( flmGetIxTrackerInfo( pDb, pIxd->uiIndexNum,
&pIxd->uiLastContainerIndexed,
&pIxd->uiLastDrnIndexed, &uiOnlineTransId, &bSuspended)))
{
goto Exit;
}
if( bSuspended)
{
pIxd->uiFlags |= (IXD_SUSPENDED | IXD_OFFLINE);
}
else if( uiOnlineTransId == TRANS_ID_OFFLINE)
{
pIxd->uiFlags |= IXD_OFFLINE;
}
}
Exit:
if( bTDictInitialized)
{
GedPoolFree( &tDict.pool);
}
return( rc );
}
/****************************************************************************
Desc: Initializes and sets up a TDICT structure.
****************************************************************************/
RCODE fdictInitTDict(
FDB * pDb,
TDICT * pTDict)
{
RCODE rc = FERR_OK;
f_memset( pTDict, 0, sizeof( TDICT)); // Set elements to zeros.
GedSmartPoolInit( &pTDict->pool, &g_TDictPoolStats);
pTDict->pDb = pDb;
pTDict->uiVersionNum = pDb->pFile->FileHdr.uiVersionNum;
pTDict->uiDefaultLanguage =
pDb->pFile->FileHdr.uiDefaultLanguage;
pTDict->pDict = pDb->pDict;
if( RC_BAD(rc = fdictGetContainer( pDb->pDict, FLM_DICT_CONTAINER,
&pTDict->pLFile )))
goto Exit;
Exit:
return( rc);
}
/****************************************************************************
Desc: Build all of the dictionary tables given the temporary dictionary
(pTDict) that was built in ddprep.
Note: There are two ways this will be called. The first is when
we are building a dictionary from scratch. The second is ONLY
when a new field definition or container is added, or an index's
state is changed.
****************************************************************************/
RCODE fdictBuildTables(
TDICT * pTDict,
FLMBOOL bRereadLFiles,
FLMBOOL bNewDict)
{
RCODE rc = FERR_OK;
DDENTRY * pEntry;
TFIELD * pTField;
FLMUINT uiEntryNum;
TENCDEF * pTEncDef;
if( RC_BAD( rc = fdictReallocAllTables( pTDict)))
{
goto Exit;
}
// Go through and add each new item to the dictionary.
for( pEntry = pTDict->pFirstEntry
; pEntry
; pEntry = pEntry->pNextEntry )
{
uiEntryNum = pEntry->uiEntryNum;
switch( pEntry->uiType)
{
case 0: // Field
{
pTField = (TFIELD *) pEntry->vpDef;
fdictAddItem( pTDict, uiEntryNum, pTField->uiFldInfo);
break;
}
case ITT_INDEX_TYPE:
{
fdictAddItem( pTDict, uiEntryNum, ITT_INDEX_TYPE);
if( RC_BAD( rc = fdictAddIndex( pTDict, pEntry )))
{
goto Exit;
}
break;
}
case ITT_CONTAINER_TYPE:
{
fdictAddItem( pTDict, uiEntryNum, ITT_CONTAINER_TYPE);
// rc = fdictAddLFile( pTDict, pEntry ); Already done.
break;
}
case ITT_ENCDEF_TYPE:
{
if (!pTDict->pDb->pFile)
{
flmAssert( 0);
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
else
{
fdictAddItem( pTDict, uiEntryNum, ITT_ENCDEF_TYPE);
pTEncDef = (TENCDEF *) pEntry->vpDef;
// Need to add a new CCS.
if (RC_BAD( rc = fdictAddNewCCS(pTDict, pTEncDef, uiEntryNum)))
{
goto Exit;
}
}
break;
}
default:
{
break;
}
}
}
if( pTDict->uiNewIfds || bNewDict)
{
if( RC_BAD( rc = fdictFixupIfdPointers( pTDict->pDict,
bNewDict ? 0 : (pTDict->uiTotalIfds - pTDict->uiNewIfds))))
{
goto Exit;
}
}
if( bRereadLFiles)
{
if( RC_BAD( rc = fdictReadLFiles( pTDict->pDb, pTDict->pDict)))
{
goto Exit;
}
}
if( RC_BAD( rc = fdictFixupLFileTbl( pTDict->pDict)))
{
goto Exit;
}
Exit:
return( rc );
}
/****************************************************************************
Desc: Fixup pointers in tables of copied dictionary. This is called after
a copy of one dictionary to another, or after a dictionary's tables
have been reallocated.
****************************************************************************/
FSTATIC void fdictFixupPointers(
FDICT * pNewDict,
FDICT * pOldDict
)
{
FLMUINT uiPos;
FLMUINT uiOffset;
LFILE * pOldLFile;
LFILE * pNewLFile;
IFD * pOldIfd;
IFD * pNewIfd;
IXD * pOldIxd;
IXD * pNewIxd;
ITT * pOldItt;
ITT * pNewItt;
// Fixup anything that points to LFILE entries.
if (pNewDict->pLFileTbl && pNewDict->pLFileTbl != pOldDict->pLFileTbl)
{
// Fixup pItt->pvItem pointers for indexes and containers
for (uiPos = 0, pOldItt = pOldDict->pIttTbl,
pNewItt = pNewDict->pIttTbl;
uiPos < pOldDict->uiIttCnt;
uiPos++, pOldItt++, pNewItt++)
{
if (ITT_IS_CONTAINER( pOldItt) || ITT_IS_INDEX( pOldItt))
{
if (pOldItt->pvItem)
{
LFILE * pTmpLFile;
pTmpLFile = (LFILE *)(pOldItt->pvItem);
uiOffset = (FLMUINT)(pTmpLFile - pOldDict->pLFileTbl);
pTmpLFile = pNewDict->pLFileTbl + uiOffset;
pNewItt->pvItem = (void *)pTmpLFile;
}
else
{
flmAssert( pNewItt->pvItem == NULL);
}
}
else if (ITT_IS_ENCDEF( pOldItt))
{
if (pOldItt->pvItem)
{
pNewItt->pvItem = pOldItt->pvItem;
((F_CCS *)pNewItt->pvItem)->AddRef();
}
else
{
flmAssert( pNewItt->pvItem == NULL);
}
}
}
}
// Fixup anything that points to IXD entries
if (pNewDict->pIxdTbl && pNewDict->pIxdTbl != pOldDict->pIxdTbl)
{
// Fixup pLFile->pIxd pointers
for (uiPos = 0, pOldLFile = pOldDict->pLFileTbl,
pNewLFile = pNewDict->pLFileTbl;
uiPos < pOldDict->uiLFileCnt;
uiPos++, pOldLFile++, pNewLFile++)
{
if (pOldLFile->pIxd)
{
uiOffset = (FLMUINT)(pOldLFile->pIxd - pOldDict->pIxdTbl);
pNewLFile->pIxd = pNewDict->pIxdTbl + uiOffset;
}
else
{
flmAssert( pNewLFile->pIxd == NULL);
}
}
// Fixup pIfd->pIxd pointers
for (uiPos = 0, pOldIfd = pOldDict->pIfdTbl,
pNewIfd = pNewDict->pIfdTbl;
uiPos < pOldDict->uiIfdCnt;
uiPos++, pOldIfd++, pNewIfd++)
{
if (pOldIfd->pIxd)
{
uiOffset = (FLMUINT)(pOldIfd->pIxd - pOldDict->pIxdTbl);
pNewIfd->pIxd = pNewDict->pIxdTbl + uiOffset;
}
else
{
flmAssert( pNewIfd->pIxd == NULL);
}
}
}
// Fixup anything that points to IFD entries
if (pNewDict->pIfdTbl && pNewDict->pIfdTbl != pOldDict->pIfdTbl)
{
// Fixup pIfd->pNextInChain pointers
for (uiPos = 0, pOldIfd = pOldDict->pIfdTbl,
pNewIfd = pNewDict->pIfdTbl;
uiPos < pOldDict->uiIfdCnt;
uiPos++, pOldIfd++, pNewIfd++)
{
if (pOldIfd->pNextInChain)
{
uiOffset = (FLMUINT)(pOldIfd->pNextInChain - pOldDict->pIfdTbl);
pNewIfd->pNextInChain = pNewDict->pIfdTbl + uiOffset;
}
else
{
flmAssert( pNewIfd->pNextInChain == NULL);
}
}
// Fixup pIxd->pFirstIfd pointers
for (uiPos = 0, pOldIxd = pOldDict->pIxdTbl,
pNewIxd = pNewDict->pIxdTbl;
uiPos < pOldDict->uiIxdCnt;
uiPos++, pOldIxd++, pNewIxd++)
{
if (pOldIxd->pFirstIfd)
{
uiOffset = (FLMUINT)(pOldIxd->pFirstIfd - pOldDict->pIfdTbl);
pNewIxd->pFirstIfd = pNewDict->pIfdTbl + uiOffset;
}
else
{
flmAssert( pNewIxd->pFirstIfd == NULL);
}
}
// Fixup pItt->pvItem pointers
for (uiPos = 0, pOldItt = pOldDict->pIttTbl,
pNewItt = pNewDict->pIttTbl;
uiPos < pOldDict->uiIttCnt;
uiPos++, pOldItt++, pNewItt++)
{
if (ITT_IS_FIELD( pOldItt))
{
if (pOldItt->pvItem)
{
IFD * pTmpIfd;
pTmpIfd = (IFD *)(pOldItt->pvItem);
uiOffset = (FLMUINT)(pTmpIfd - pOldDict->pIfdTbl);
pTmpIfd = pNewDict->pIfdTbl + uiOffset;
pNewItt->pvItem = (void *)pTmpIfd;
}
else
{
flmAssert( pNewItt->pvItem == NULL);
}
}
}
}
// Fixup anything that points to field path entries
if (pNewDict->pFldPathsTbl && pNewDict->pFldPathsTbl != pOldDict->pFldPathsTbl)
{
// Fixup pIfd->pFieldPathCToP and pIfd->pFieldPathPToC pointers
for (uiPos = 0, pOldIfd = pOldDict->pIfdTbl,
pNewIfd = pNewDict->pIfdTbl;
uiPos < pOldDict->uiIfdCnt;
uiPos++, pOldIfd++, pNewIfd++)
{
if (pOldIfd->pFieldPathCToP)
{
uiOffset = (FLMUINT)(pOldIfd->pFieldPathCToP - pOldDict->pFldPathsTbl);
pNewIfd->pFieldPathCToP = pNewDict->pFldPathsTbl + uiOffset;
}
else
{
flmAssert( pNewIfd->pFieldPathCToP == NULL);
}
if (pOldIfd->pFieldPathPToC)
{
uiOffset = (FLMUINT)(pOldIfd->pFieldPathPToC - pOldDict->pFldPathsTbl);
pNewIfd->pFieldPathPToC = pNewDict->pFldPathsTbl + uiOffset;
}
else
{
flmAssert( pNewIfd->pFieldPathPToC == NULL);
}
}
}
}
/****************************************************************************
Desc: Allocate all of the dictionary tables based on the counts that
were incremented in pTDict. Coded to add new fields, indexes or
container, but not to modify or delete anything!
****************************************************************************/
FSTATIC RCODE fdictReallocAllTables(
TDICT * pTDict)
{
RCODE rc = FERR_OK;
FDICT OldDict;
FDICT * pDict = pTDict->pDict;
// Save a copy of the old dictionary's pointers and counters
// Easiest way to do this is to simply copy the structure.
f_memcpy( &OldDict, pDict, sizeof( FDICT));
if( pTDict->pLastEntry
&& pTDict->pLastEntry->uiEntryNum >= pDict->uiIttCnt
&& pTDict->pLastEntry->uiEntryNum < FLM_RESERVED_TAG_NUMS)
{
ITT * pItt;
FLMUINT uiNewCount;
uiNewCount = pTDict->pLastEntry->uiEntryNum + 1 - pDict->uiIttCnt;
if (uiNewCount)
{
// Must fake out so that we don't lose the old table.
pDict->pIttTbl = NULL;
if( RC_BAD( rc = fdictReallocTbl( sizeof( ITT), pDict->uiIttCnt,
uiNewCount, (void **) &pDict->pIttTbl)))
{
goto Exit;
}
pTDict->uiTotalItts = pDict->uiIttCnt + uiNewCount;
// Copy the table to the new location (because of fake out above)
if( OldDict.uiIttCnt)
{
f_memcpy( pDict->pIttTbl, OldDict.pIttTbl,
sizeof( ITT) * OldDict.uiIttCnt);
}
// Initialize the new items to empty.
pItt = pDict->pIttTbl + pDict->uiIttCnt;
for( ;uiNewCount--; pItt++)
{
pItt->uiType = ITT_EMPTY_SLOT;
pItt->pvItem = NULL;
}
}
}
if (pTDict->uiNewIxds)
{
// Must fake out so that we don't lose the old table.
pDict->pIxdTbl = NULL;
if( RC_BAD( rc = fdictReallocTbl( sizeof( IXD), pDict->uiIxdCnt,
pTDict->uiNewIxds, (void **)&pDict->pIxdTbl)))
{
goto Exit;
}
pTDict->uiTotalIxds = pDict->uiIxdCnt + pTDict->uiNewIxds;
// Copy the table to the new location (because of fake out above)
if( OldDict.uiIxdCnt)
{
f_memcpy( pDict->pIxdTbl, OldDict.pIxdTbl,
sizeof( IXD) * OldDict.uiIxdCnt);
}
}
if (pTDict->uiNewIfds)
{
// Must fake out so that we don't lose the old table.
pDict->pIfdTbl = NULL;
if( RC_BAD( rc = fdictReallocTbl( sizeof( IFD), pDict->uiIfdCnt,
pTDict->uiNewIfds, (void **)&pDict->pIfdTbl)))
{
goto Exit;
}
pTDict->uiTotalIfds = pDict->uiIfdCnt + pTDict->uiNewIfds;
// Copy the table to the new location (because of fake out above)
if( OldDict.uiIfdCnt)
{
f_memcpy( pDict->pIfdTbl, OldDict.pIfdTbl,
sizeof( IFD) * OldDict.uiIfdCnt);
}
}
if (pTDict->uiNewFldPaths)
{
// Must fake out so that we don't lose the old table.
pDict->pFldPathsTbl = NULL;
if( RC_BAD( rc = fdictReallocTbl( sizeof( FLMUINT), pDict->uiFldPathsCnt,
pTDict->uiNewFldPaths, (void **)&pDict->pFldPathsTbl)))
{
goto Exit;
}
pTDict->uiTotalFldPaths = pDict->uiFldPathsCnt + pTDict->uiNewFldPaths;
// Copy the table to the new location (because of fake out above)
if( OldDict.uiFldPathsCnt)
{
f_memcpy( pDict->pFldPathsTbl, OldDict.pFldPathsTbl,
sizeof( FLMUINT) * OldDict.uiFldPathsCnt);
}
}
fdictFixupPointers( pDict, &OldDict);
Exit:
// Free any old tables where a new table was allocated.
if (OldDict.pLFileTbl != pDict->pLFileTbl)
{
f_free( &OldDict.pLFileTbl);
}
if (OldDict.pIttTbl != pDict->pIttTbl)
{
f_free( &OldDict.pIttTbl);
}
if (OldDict.pIxdTbl != pDict->pIxdTbl)
{
f_free( &OldDict.pIxdTbl);
}
if (OldDict.pIfdTbl != pDict->pIfdTbl)
{
f_free( &OldDict.pIfdTbl);
}
if (OldDict.pFldPathsTbl != pDict->pFldPathsTbl)
{
f_free( &OldDict.pFldPathsTbl);
}
return( rc );
}
/****************************************************************************
Desc: Allocate or reallocate a table.
****************************************************************************/
FSTATIC RCODE fdictReallocTbl(
FLMUINT uiElementSize,
FLMUINT uiTblSize,
FLMUINT uiAddElements,
void ** ppvTblRV)
{
RCODE rc = FERR_OK;
// Does the table need to grow?
if( uiAddElements)
{
if( *ppvTblRV)
{
if( RC_BAD( rc = f_recalloc(
uiElementSize * (uiTblSize + uiAddElements),
ppvTblRV)))
{
goto Exit;
}
}
else
{
if( RC_BAD( rc = f_calloc(
uiElementSize * (uiTblSize + uiAddElements),
ppvTblRV)))
{
goto Exit;
}
}
}
Exit:
return( rc );
}
/****************************************************************************
Desc: Add a new item to the item type table.
****************************************************************************/
FSTATIC void fdictAddItem(
TDICT * pTDict,
FLMUINT uiFieldNum,
FLMUINT uiFieldType)
{
FDICT * pDict = pTDict->pDict;
ITT * pItt;
if( uiFieldNum < FLM_RESERVED_TAG_NUMS)
{
pItt = pDict->pIttTbl + uiFieldNum;
pItt->uiType = uiFieldType;
pItt->pvItem = NULL;
if( uiFieldNum >= pDict->uiIttCnt)
{
pDict->uiIttCnt = uiFieldNum + 1;
}
}
}
/****************************************************************************
Desc: Add the new IXD, IFD, field paths and LFILE for the index.
****************************************************************************/
FSTATIC RCODE fdictAddIndex(
TDICT * pTDict,
DDENTRY * pEntry)
{
RCODE rc = FERR_OK;
FDICT * pDict = pTDict->pDict;
FLMUINT uiIndexNum = pEntry->uiEntryNum;
IXD * pIxd;
IFD * pIfd;
FLMUINT * pFirstPToCFld;
FLMUINT * pFirstCToPFld;
FLMUINT * pCurFld;
FLMUINT * pTempFld;
TIXD * pTIxd;
TIFD * pTIfd;
TIFP * pTIfp;
// The index numbers in the IXD array do not need to be in any order.
// Just add all of the index information to the end of the table.
pIxd = pDict->pIxdTbl + pDict->uiIxdCnt++;
pIxd->uiIndexNum = uiIndexNum;
pTIxd = (TIXD *) pEntry->vpDef;
pIxd->uiContainerNum = pTIxd->uiContainerNum;
pIxd->uiNumFlds = pTIxd->uiNumFlds;
pIxd->uiFlags = pTIxd->uiFlags;
pIxd->uiLanguage = pTIxd->uiLanguage;
pIxd->uiLastContainerIndexed = 0xFFFFFFFF;
pIxd->uiLastDrnIndexed = DRN_LAST_MARKER;
pIxd->uiEncId = pTIxd->uiEncId;
// Setup the IFD elements and the field paths.
pIxd->pFirstIfd = pIfd = pDict->pIfdTbl + pDict->uiIfdCnt;
pDict->uiIfdCnt += pIxd->uiNumFlds;
for( pTIfd = pTIxd->pNextTIfd; pTIfd; pIfd++, pTIfd = pTIfd->pNextTIfd)
{
// This is a good place to set the IFD_LAST flag.
// Could/Should be done in ddprep.c
if( pTIfd->pNextTIfd == NULL)
pTIfd->uiFlags |= IFD_LAST;
pIfd->uiIndexNum = uiIndexNum;
pIfd->pIxd = pIxd;
pIfd->uiFlags = pTIfd->uiFlags;
pIfd->uiLimit = pTIfd->uiLimit;
pIfd->uiCompoundPos = pTIfd->uiCompoundPos;
// The pTIfp->pNextTIfp are linked from parent to child.
pTIfp = pTIfd->pTIfp;
pCurFld = pDict->pFldPathsTbl + pDict->uiFldPathsCnt;
pFirstPToCFld = pFirstCToPFld = pCurFld;
pIfd->pFieldPathPToC = pFirstPToCFld;
do
{
*pCurFld++ = pTIfp->uiFldNum;
pTIfp = pTIfp->pNextTIfp;
} while( pTIfp);
pIfd->uiFldNum = *(pCurFld-1);
pTempFld = pCurFld - 1;
// Null Terminate
*pCurFld++ = 0;
pTIfp = pTIfd->pTIfp;
if( pTIfp->pNextTIfp) // If more than one field make the CToP path.
{
pFirstCToPFld = pCurFld;
while( pTempFld != pFirstPToCFld)
{
*pCurFld++ = *pTempFld--;
}
*pCurFld++ = *pTempFld;
*pCurFld++ = 0;
}
pIfd->pFieldPathCToP = pFirstCToPFld;
pDict->uiFldPathsCnt += pCurFld - pFirstPToCFld;
}
return( rc );
}
/****************************************************************************
Desc: Fixup the IFD chain and the pIfd->pIxd pointers.
****************************************************************************/
FSTATIC RCODE fdictFixupIfdPointers(
FDICT * pDict,
FLMUINT uiIfdStartOffset)
{
RCODE rc = FERR_OK;
FLMUINT uiCount;
IFD * pIfd;
ITT * pItt;
ITT * pIttTbl = pDict->pIttTbl;
// Go through the IFD list and setup the pNextInChain pointers
// making sure that the required fields are first.
for( uiCount = pDict->uiIfdCnt - uiIfdStartOffset,
pIfd = pDict->pIfdTbl + uiIfdStartOffset;
uiCount; uiCount--, pIfd++)
{
IFD * pPrevInChain;
IFD * pTempIfd;
if( pIfd->uiFldNum >= pDict->uiIttCnt)
{
if( pIfd->uiFldNum < FLM_RESERVED_TAG_NUMS)
{
rc = RC_SET( FERR_BAD_REFERENCE);
goto Exit;
}
continue;
}
else
{
pItt = pIttTbl + pIfd->uiFldNum;
if( !ITT_IS_FIELD( pItt))
{
rc = RC_SET( FERR_BAD_REFERENCE);
goto Exit;
}
}
// Move the field type to the pIfd->uiFlags
IFD_SET_FIELD_TYPE( pIfd, ITT_FLD_GET_TYPE( pItt));
// Visit: We could verify all of the fields in the field path.
// Need to include 'any', 'use', 'parent' tags as valid tags.
if( !pItt->pvItem)
{
pItt->pvItem = (void *) pIfd;
}
else
{
// Follow the chain and index at the front or rear depending on
// if the field is required within the set.
pTempIfd = (IFD *) pItt->pvItem;
if( (pIfd->uiFlags & IFD_REQUIRED_IN_SET)
|| !(pTempIfd->uiFlags & IFD_REQUIRED_IN_SET))
{
pIfd->pNextInChain = pTempIfd;
pItt->pvItem = (void *) pIfd;
}
else
{
// Not required in set and first IFD is required in set.
// Look for first not required IFD in the chain.
pPrevInChain = pTempIfd;
pTempIfd = pTempIfd->pNextInChain;
for( ; pTempIfd; pTempIfd = pTempIfd->pNextInChain)
{
if( !(pTempIfd->uiFlags & IFD_REQUIRED_IN_SET))
break;
pPrevInChain = pTempIfd;
}
pIfd->pNextInChain = pPrevInChain->pNextInChain;
pPrevInChain->pNextInChain = pIfd;
}
}
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Fixup the ITT pointers into the LFILE elements and all of
the IXD pointers in the LDICT.
****************************************************************************/
RCODE fdictFixupLFileTbl(
FDICT * pDict)
{
RCODE rc = FERR_OK;
FLMUINT uiCount;
LFILE * pLFile;
IXD * pIxd;
ITT * pItt;
ITT * pIttTbl = pDict->pIttTbl;
FLMUINT uiIttCnt = pDict->uiIttCnt;
for( uiCount = pDict->uiLFileCnt, pLFile = pDict->pLFileTbl
; uiCount; uiCount--, pLFile++)
{
if( pLFile->uiLfNum != FLM_DATA_CONTAINER
&& pLFile->uiLfNum != FLM_DICT_CONTAINER
&& pLFile->uiLfNum != FLM_DICT_INDEX
&& pLFile->uiLfNum != FLM_TRACKER_CONTAINER)
{
pItt = pIttTbl + pLFile->uiLfNum;
if( uiIttCnt <= pLFile->uiLfNum ||
(pLFile->uiLfType == LF_CONTAINER && !ITT_IS_CONTAINER( pItt)))
{
rc = RC_SET( FERR_BAD_REFERENCE);
goto Exit;
}
if( pLFile->uiLfType == LF_INDEX && !ITT_IS_INDEX( pItt))
{
rc = RC_SET( FERR_BAD_REFERENCE);
goto Exit;
}
pItt->pvItem = pLFile;
}
else if( pLFile->uiLfNum == FLM_DICT_INDEX)
{
// The first IXD should be the dictionary index.
if( pDict->pIxdTbl && pDict->pIxdTbl->uiIndexNum == FLM_DICT_INDEX)
{
pLFile->pIxd = pDict->pIxdTbl;
}
}
}
// Now that all of the indexes/containers in the ITT table point
// to the LFILE entries, fixup the LFILE to point to the IXD entries.
for( uiCount = pDict->uiIxdCnt, pIxd = pDict->pIxdTbl;
uiCount; uiCount--, pIxd++)
{
if( uiIttCnt <= pIxd->uiIndexNum)
{
if( pIxd->uiIndexNum != FLM_DICT_INDEX)
{
rc = RC_SET( FERR_BAD_REFERENCE);
goto Exit;
}
}
else
{
pItt = pIttTbl + pIxd->uiIndexNum;
pLFile = (LFILE *) pItt->pvItem;
if( !pLFile)
{
rc = RC_SET( FERR_BAD_REFERENCE);
goto Exit;
}
pLFile->pIxd = pIxd;
}
// Verify that the pIxd->uiContainerNum is actually a container.
// A value of 0 means that the index is on ALL containers.
if (pIxd->uiContainerNum)
{
if( uiIttCnt <= pIxd->uiContainerNum)
{
if( pIxd->uiContainerNum != FLM_DATA_CONTAINER
&& pIxd->uiContainerNum != FLM_DICT_CONTAINER
&& pIxd->uiContainerNum != FLM_TRACKER_CONTAINER)
{
rc = RC_SET( FERR_BAD_REFERENCE);
goto Exit;
}
}
else
{
pItt = pIttTbl + pIxd->uiContainerNum;
if( !ITT_IS_CONTAINER( pItt))
{
rc = RC_SET( FERR_BAD_REFERENCE);
goto Exit;
}
}
}
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Add a new CCS reference to the item type table. If a key is included
we can use it, otherwise we will have to generate one.
****************************************************************************/
FSTATIC RCODE fdictAddNewCCS(
TDICT * pTDict,
TENCDEF * pTEncDef,
FLMUINT uiRecNum)
{
RCODE rc = FERR_OK;
FDICT * pDict = pTDict->pDict;
ITT * pItt;
F_CCS * pCcs = NULL;
FDB * pDb = pTDict->pDb;
F_CCS * pDbWrappingKey;
if( uiRecNum >= FLM_RESERVED_TAG_NUMS)
{
goto Exit;
}
if (!pDb->pFile->bInLimitedMode)
{
pDbWrappingKey = pDb->pFile->pDbWrappingKey;
flmAssert( pTEncDef);
if ((pCcs = f_new F_CCS) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
// Setup the F_CCS.
if (RC_BAD( rc = pCcs->init( FALSE, pTEncDef->uiAlgType )))
{
goto Exit;
}
if (!pTEncDef->uiLength)
{
flmAssert( 0);
rc = RC_SET( FERR_MISSING_ENC_KEY);
goto Exit;
}
// We need to set the key information. This also unwraps the key and stores the
// handle.
if( RC_BAD( rc = pCcs->setKeyFromStore( pTEncDef->pucKeyInfo,
(FLMUINT32)pTEncDef->uiLength, NULL, pDbWrappingKey)))
{
goto Exit;
}
}
// Save the CCS object in the ITT table.
pItt = pDict->pIttTbl + uiRecNum;
pItt->pvItem = (void *)pCcs;
pCcs = NULL;
if( uiRecNum >= pDict->uiIttCnt)
{
pDict->uiIttCnt = uiRecNum + 1;
}
Exit:
if (pCcs)
{
delete pCcs;
}
return( rc);
}
/****************************************************************************
Desc: Copies an existing dictionary to a new dictionary. This does not
fix up all of the ITT's pvItem pointers (including the
pFirstIfd pointer of fields in the ITT table). To clone the
dictionary, call fdictCloneDict.
****************************************************************************/
RCODE fdictCopySkeletonDict(
FDB * pDb)
{
RCODE rc = FERR_OK;
FDICT * pNewDict = NULL;
FDICT * pOldDict = pDb->pDict;
FLMUINT uiTblSize;
FLMUINT uiPos;
LFILE * pLFile;
IXD * pIxd;
ITT * pItt;
ITT * pNewIttTbl = NULL;
FLMUINT uiNewIttTblLen = 0;
LFILE * pNewDictIndexLFile = NULL;
FLMUINT * pOldFieldPathsTbl = NULL;
FLMUINT * pNewFieldPathsTbl = NULL;
if( RC_BAD( rc = f_calloc( (FLMUINT)sizeof( FDICT), &pNewDict)))
{
goto Exit;
}
pNewDict->pNext = pNewDict->pPrev = NULL;
pNewDict->pFile = NULL;
pNewDict->uiUseCount = 1;
// Nothing to do is not a legal state.
if( !pOldDict)
{
flmAssert( pOldDict != NULL);
pDb->pDict = pNewDict;
goto Exit;
}
// ITT Table
if( (uiTblSize = pNewDict->uiIttCnt = pOldDict->uiIttCnt) != 0)
{
if( RC_BAD( rc = f_alloc( uiTblSize * sizeof( ITT), &pNewDict->pIttTbl)))
{
goto Exit;
}
pNewIttTbl = pNewDict->pIttTbl;
uiNewIttTblLen = uiTblSize;
f_memcpy( pNewDict->pIttTbl, pOldDict->pIttTbl,
uiTblSize * sizeof( ITT));
// Clear out all of the pointer values.
pItt = pNewDict->pIttTbl;
for( uiPos = 0; uiPos < uiTblSize; uiPos++, pItt++)
{
if ( pItt->uiType == ITT_ENCDEF_TYPE && !pDb->pFile->bInLimitedMode)
{
flmAssert( pItt->pvItem);
((F_CCS *)pItt->pvItem)->AddRef();
}
else
{
pItt->pvItem = NULL;
}
}
}
// LFILE Table
if( (uiTblSize = pNewDict->uiLFileCnt = pOldDict->uiLFileCnt) != 0)
{
if( RC_BAD( rc = f_alloc( uiTblSize * sizeof( LFILE),
&pNewDict->pLFileTbl)))
{
goto Exit;
}
f_memcpy( pNewDict->pLFileTbl, pOldDict->pLFileTbl,
uiTblSize * sizeof( LFILE));
for( pLFile = pNewDict->pLFileTbl; uiTblSize--; pLFile++)
{
if( pLFile->uiLfNum < FLM_RESERVED_TAG_NUMS)
{
// WARNING: The code must make a new LFILE
// before the dictionary is aware of it.
if( pLFile->uiLfNum < uiNewIttTblLen)
{
pItt = pNewIttTbl + pLFile->uiLfNum;
pItt->pvItem = (void *) pLFile;
}
}
else if( pLFile->uiLfNum == FLM_DICT_INDEX)
{
pNewDictIndexLFile = pLFile;
}
}
}
// IXD Table
if( (uiTblSize = pNewDict->uiIxdCnt = pOldDict->uiIxdCnt) != 0)
{
if( RC_BAD( rc = f_alloc(
uiTblSize * sizeof( IXD), &pNewDict->pIxdTbl)))
{
goto Exit;
}
f_memcpy( pNewDict->pIxdTbl, pOldDict->pIxdTbl,
uiTblSize * sizeof( IXD));
// Fixup all of the pointers to the IXD.
for( pIxd = pNewDict->pIxdTbl; uiTblSize--; pIxd++)
{
if( pIxd->uiIndexNum != FLM_DICT_INDEX)
{
pItt = pNewIttTbl + pIxd->uiIndexNum;
pLFile = (LFILE *) pItt->pvItem;
pLFile->pIxd = pIxd;
}
else if( pNewDictIndexLFile)
{
pNewDictIndexLFile->pIxd = pIxd;
}
}
}
// Field Paths Table
if( (uiTblSize = pNewDict->uiFldPathsCnt = pOldDict->uiFldPathsCnt) != 0)
{
if( RC_BAD( rc = f_alloc( uiTblSize * sizeof( FLMUINT),
&pNewDict->pFldPathsTbl)))
{
goto Exit;
}
f_memcpy( pNewDict->pFldPathsTbl, pOldDict->pFldPathsTbl,
uiTblSize * sizeof( FLMUINT));
pOldFieldPathsTbl = pOldDict->pFldPathsTbl;
pNewFieldPathsTbl = pNewDict->pFldPathsTbl;
}
// IFD Table
if( (uiTblSize = pNewDict->uiIfdCnt = pOldDict->uiIfdCnt) != 0)
{
IFD * pIfd;
FLMUINT uiLastIndexNum;
FLMUINT uiOffset;
if( RC_BAD( rc = f_alloc( uiTblSize * sizeof( IFD),
&pNewDict->pIfdTbl)))
{
goto Exit;
}
f_memcpy( pNewDict->pIfdTbl, pOldDict->pIfdTbl,
uiTblSize * sizeof( IFD));
// Fixup all pFirstIfd pointers, backlinks to the pIxd and fldPathTbls.
// Set all of the IfdChain values to NULL to be fixed up later.
pIfd = pNewDict->pIfdTbl;
uiLastIndexNum = 0;
for( uiPos = 0; uiPos < uiTblSize; uiPos++, pIfd++)
{
pIfd->pNextInChain = NULL;
if( pIfd->uiIndexNum != FLM_DICT_INDEX)
{
pItt = pNewIttTbl + pIfd->uiIndexNum;
pLFile = (LFILE *) pItt->pvItem;
pIxd = pLFile->pIxd;
}
else
{
pIxd = pNewDictIndexLFile->pIxd;
}
pIfd->pIxd = pIxd;
if( uiLastIndexNum != pIfd->uiIndexNum)
{
pIxd->pFirstIfd = pIfd;
uiLastIndexNum = pIfd->uiIndexNum;
}
// Fixup the field paths.
flmAssert( pNewFieldPathsTbl != NULL);
uiOffset = pIfd->pFieldPathCToP - pOldFieldPathsTbl;
pIfd->pFieldPathCToP = pNewFieldPathsTbl + uiOffset;
uiOffset = pIfd->pFieldPathPToC - pOldFieldPathsTbl;
pIfd->pFieldPathPToC = pNewFieldPathsTbl + uiOffset;
}
}
f_mutexLock( gv_FlmSysData.hShareMutex);
flmUnlinkFdbFromDict( pDb);
f_mutexUnlock( gv_FlmSysData.hShareMutex);
pDb->pDict = pNewDict;
pNewDict = NULL;
Exit:
if( RC_BAD( rc) && pNewDict)
{
// Undo all of the allocations on the new table.
if( pNewDict->pLFileTbl)
{
f_free( &pNewDict->pLFileTbl);
}
if( pNewDict->pIttTbl)
{
f_free( &pNewDict->pIttTbl);
}
if( pNewDict->pIxdTbl)
{
f_free( &pNewDict->pIxdTbl);
}
if( pNewDict->pIfdTbl)
{
f_free( &pNewDict->pIfdTbl);
}
if( pNewDict->pFldPathsTbl)
{
f_free( &pNewDict->pFldPathsTbl);
}
f_free( &pNewDict);
}
return( rc);
}
/****************************************************************************
Desc: Creates a new version of the current dictionary and fixes up all
pointers
****************************************************************************/
RCODE fdictCloneDict(
FDB * pDb)
{
RCODE rc = FERR_OK;
TDICT tDict;
FLMBOOL bTDictInitialized = FALSE;
if( RC_BAD( rc = fdictCopySkeletonDict( pDb)))
{
goto Exit;
}
bTDictInitialized = TRUE;
if( RC_BAD( rc = fdictInitTDict( pDb, &tDict)))
{
goto Exit;
}
if( RC_BAD( rc = fdictBuildTables( &tDict, FALSE, TRUE)))
{
goto Exit;
}
pDb->uiFlags |= FDB_UPDATED_DICTIONARY;
Exit:
if( bTDictInitialized)
{
GedPoolFree( &tDict.pool);
}
// If we allocated an FDICT and there was an error, free the FDICT.
if( (RC_BAD( rc)) && (pDb->pDict))
{
flmFreeDict( pDb->pDict);
pDb->pDict = NULL;
}
return( rc);
}