git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@226 0109f412-320b-0410-ab79-c3e0c5ffbbe6
332 lines
7.4 KiB
C++
332 lines
7.4 KiB
C++
//------------------------------------------------------------------------------
|
|
// Desc: This file contains the F_Db::keyRetrieve method.
|
|
//
|
|
// Tabs: 3
|
|
//
|
|
// Copyright (c) 1998-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: flkeyret.cpp 3113 2006-01-19 13:20:35 -0700 (Thu, 19 Jan 2006) dsanders $
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include "flaimsys.h"
|
|
|
|
/*API~***********************************************************************
|
|
Area : RETRIEVAL
|
|
Desc: Retrieves a key from an index based on a passed-in GEDCOM tree and DRN.
|
|
*END************************************************************************/
|
|
RCODE F_Db::keyRetrieve(
|
|
FLMUINT uiIndex,
|
|
// [IN] Index number.
|
|
IF_DataVector * ifpSearchKey,
|
|
// [IN] Pointer to the search key.
|
|
FLMUINT uiFlags,
|
|
// [IN] Flag (XFLM_FIRST, XFLM_LAST, XFLM_EXCL, XFLM_INCL,
|
|
// XFLM_EXACT, XFLM_KEY_EXACT
|
|
IF_DataVector * ifpFoundKey
|
|
// [OUT] Returns key that was found - may also have data components.
|
|
)
|
|
{
|
|
RCODE rc = NE_XFLM_OK;
|
|
IXD * pIxd = NULL;
|
|
LFILE * pLFile;
|
|
FLMBYTE * pucSearchKey = NULL;
|
|
FLMBYTE * pucFoundKey = NULL;
|
|
void * pvMark = m_TempPool.poolMark();
|
|
FLMUINT uiSearchKeyLen = 0;
|
|
FLMUINT uiFoundKeyLen;
|
|
FLMUINT uiOriginalFlags;
|
|
F_Btree * pbtree = NULL;
|
|
FLMUINT uiDataLen;
|
|
FLMBOOL bStartedTrans = FALSE;
|
|
FLMUINT uiIdMatchFlags = uiFlags & (XFLM_MATCH_IDS | XFLM_MATCH_DOC_ID);
|
|
IXKeyCompare compareObject;
|
|
FLMBOOL bCompareDocId = FALSE;
|
|
FLMBOOL bCompareNodeIds = FALSE;
|
|
F_DataVector * pSearchKey = (F_DataVector *)ifpSearchKey;
|
|
F_DataVector * pFoundKey = (F_DataVector *)ifpFoundKey;
|
|
|
|
// See if the database is being forced to close
|
|
|
|
if (RC_BAD( rc = checkState( __FILE__, __LINE__)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If we are not in a transaction, we cannot read.
|
|
|
|
if (m_eTransType == XFLM_NO_TRANS)
|
|
{
|
|
if( RC_BAD( rc = transBegin( XFLM_READ_TRANS)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
bStartedTrans = TRUE;
|
|
}
|
|
|
|
// See if we have a transaction going which should be aborted.
|
|
|
|
if( RC_BAD( m_AbortRc))
|
|
{
|
|
rc = RC_SET( NE_XFLM_ABORT_TRANS);
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate key buffers.
|
|
|
|
if (pSearchKey)
|
|
{
|
|
if (RC_BAD( rc = m_TempPool.poolAlloc( XFLM_MAX_KEY_SIZE,
|
|
(void **)&pucSearchKey)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = m_TempPool.poolAlloc( XFLM_MAX_KEY_SIZE, (void **)&pucFoundKey)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Make sure it is a valid index definition
|
|
|
|
if (RC_BAD( rc = m_pDict->getIndex( uiIndex, &pLFile, &pIxd)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = flushKeys()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (uiFlags & XFLM_FIRST || (!pSearchKey &&
|
|
!(uiFlags & XFLM_FIRST) && !(uiFlags & XFLM_LAST)))
|
|
{
|
|
uiOriginalFlags = uiFlags = XFLM_FIRST;
|
|
}
|
|
else if (uiFlags & XFLM_LAST)
|
|
{
|
|
uiOriginalFlags = uiFlags = XFLM_LAST;
|
|
}
|
|
else
|
|
{
|
|
uiOriginalFlags = uiFlags;
|
|
if( !(uiIdMatchFlags & XFLM_MATCH_IDS))
|
|
{
|
|
flmAssert( !(uiFlags & XFLM_KEY_EXACT));
|
|
if (uiFlags & XFLM_EXCL)
|
|
{
|
|
uiFlags = XFLM_EXCL;
|
|
}
|
|
else if (uiFlags & XFLM_EXACT)
|
|
{
|
|
uiOriginalFlags = XFLM_EXACT | XFLM_KEY_EXACT;
|
|
uiFlags = XFLM_INCL;
|
|
}
|
|
else
|
|
{
|
|
uiFlags = XFLM_INCL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (uiFlags & XFLM_EXACT)
|
|
{
|
|
flmAssert( !(uiFlags & XFLM_KEY_EXACT));
|
|
uiFlags = XFLM_EXACT;
|
|
}
|
|
else if (uiFlags & XFLM_EXCL)
|
|
{
|
|
uiFlags = XFLM_EXCL;
|
|
}
|
|
else
|
|
{
|
|
uiFlags = XFLM_INCL;
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pSearchKey->outputKey( pIxd, uiIdMatchFlags,
|
|
pucSearchKey, XFLM_MAX_KEY_SIZE, &uiSearchKeyLen, SEARCH_KEY_FLAG)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If we are not matching on the IDs and this is an XFLM_EXCL
|
|
// search, tack on a 0xFF for the IDs, which should get us past
|
|
// all keys that match. We need to turn on the match IDs flags
|
|
// in this case so that the comparison routine will match on the
|
|
// 0xFF.
|
|
|
|
if (!uiIdMatchFlags && (uiFlags & XFLM_EXCL))
|
|
{
|
|
pucSearchKey [uiSearchKeyLen++] = 0xFF;
|
|
bCompareDocId = TRUE;
|
|
bCompareNodeIds = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (uiIdMatchFlags & XFLM_MATCH_IDS)
|
|
{
|
|
bCompareNodeIds = TRUE;
|
|
bCompareDocId = TRUE;
|
|
}
|
|
else if (uiIdMatchFlags & XFLM_MATCH_DOC_ID)
|
|
{
|
|
bCompareDocId = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
compareObject.setIxInfo( this, pIxd);
|
|
compareObject.setCompareNodeIds( bCompareNodeIds);
|
|
compareObject.setCompareDocId( bCompareDocId);
|
|
compareObject.setSearchKey( pSearchKey);
|
|
|
|
// Get a btree
|
|
|
|
if (RC_BAD( rc = gv_XFlmSysData.pBtPool->btpReserveBtree( &pbtree)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( RC_BAD( rc = pbtree->btOpen( this, pLFile,
|
|
(pIxd->uiFlags & IXD_ABS_POS)
|
|
? TRUE
|
|
: FALSE,
|
|
(pIxd->pFirstData)
|
|
? TRUE
|
|
: FALSE, &compareObject)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Search the for the key
|
|
|
|
if (uiSearchKeyLen)
|
|
{
|
|
f_memcpy( pucFoundKey, pucSearchKey, uiSearchKeyLen);
|
|
}
|
|
uiFoundKeyLen = uiSearchKeyLen;
|
|
|
|
if( RC_BAD( rc = pbtree->btLocateEntry(
|
|
pucFoundKey, XFLM_MAX_KEY_SIZE, &uiFoundKeyLen, uiFlags, NULL,
|
|
&uiDataLen)))
|
|
{
|
|
if (rc == NE_XFLM_EOF_HIT && uiOriginalFlags & XFLM_EXACT)
|
|
{
|
|
rc = RC_SET( NE_XFLM_NOT_FOUND);
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
// See if we are in the same key
|
|
|
|
if (uiOriginalFlags & XFLM_KEY_EXACT)
|
|
{
|
|
FLMINT iTmpCmp;
|
|
|
|
if (RC_BAD( rc = ixKeyCompare( this, pIxd,
|
|
(F_DataVector *)pSearchKey, NULL, NULL,
|
|
(uiIdMatchFlags == XFLM_MATCH_DOC_ID) ? TRUE : FALSE,
|
|
FALSE, pucFoundKey, uiFoundKeyLen,
|
|
pucSearchKey, uiSearchKeyLen, &iTmpCmp)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (iTmpCmp != 0)
|
|
{
|
|
rc = (uiOriginalFlags & (XFLM_INCL | XFLM_EXCL))
|
|
? RC_SET( NE_XFLM_EOF_HIT)
|
|
: RC_SET( NE_XFLM_NOT_FOUND);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Parse the found key into its individual components
|
|
|
|
if (pFoundKey)
|
|
{
|
|
pFoundKey->reset();
|
|
if (RC_BAD( rc = pFoundKey->inputKey( pIxd, pucFoundKey, uiFoundKeyLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// See if there is a data part
|
|
|
|
if (pIxd->pFirstData)
|
|
{
|
|
FLMUINT uiDataBufSize;
|
|
FLMBYTE * pucData;
|
|
|
|
// If the data will fit in the search key buffer, just
|
|
// reuse it since we are not going to do anything with
|
|
// it after this. Otherwise, allocate a new buffer.
|
|
|
|
if (uiDataLen <= XFLM_MAX_KEY_SIZE && pucSearchKey)
|
|
{
|
|
uiDataBufSize = XFLM_MAX_KEY_SIZE;
|
|
pucData = pucSearchKey;
|
|
}
|
|
else
|
|
{
|
|
uiDataBufSize = uiDataLen;
|
|
if (RC_BAD( rc = m_TempPool.poolAlloc( uiDataBufSize,
|
|
(void **)&pucData)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Retrieve the data
|
|
|
|
if (RC_BAD( rc = pbtree->btGetEntry(
|
|
pucFoundKey, XFLM_MAX_KEY_SIZE, uiFoundKeyLen,
|
|
pucData, uiDataBufSize, &uiDataLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Parse the data
|
|
|
|
if (RC_BAD( rc = pFoundKey->inputData( pIxd, pucData, uiDataLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
m_TempPool.poolReset( pvMark);
|
|
|
|
if (pbtree)
|
|
{
|
|
gv_XFlmSysData.pBtPool->btpReturnBtree( &pbtree);
|
|
}
|
|
|
|
if( bStartedTrans)
|
|
{
|
|
transAbort();
|
|
}
|
|
|
|
return( rc);
|
|
}
|