Added F_DynSearchSet class and supporting classes.
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@566 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
1202
ftk/src/ftkdynbtree.cpp
Normal file
1202
ftk/src/ftkdynbtree.cpp
Normal file
File diff suppressed because it is too large
Load Diff
328
ftk/src/ftkdynrset.cpp
Normal file
328
ftk/src/ftkdynrset.cpp
Normal file
@@ -0,0 +1,328 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Desc: Contains the methods for F_DynSearchSet class.
|
||||
//
|
||||
// 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$
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "ftk.h"
|
||||
#include "ftkdynrset.h"
|
||||
|
||||
#define HASH_POS(vp) \
|
||||
(((FLMUINT)(FB2UD((FLMBYTE*)vp)) % m_uiNumSlots) * m_uiEntrySize)
|
||||
|
||||
static const FLMBYTE ucZeros [ DYNSSET_MAX_FIXED_ENTRY_SIZE ] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Setup the result set with input values. This method must be
|
||||
called and only called once.
|
||||
****************************************************************************/
|
||||
RCODE F_DynSearchSet::setup(
|
||||
char * pszTmpDir,
|
||||
FLMUINT uiEntrySize)
|
||||
{
|
||||
RCODE rc = NE_FLM_OK;
|
||||
F_HashBlk * pHashBlk;
|
||||
|
||||
// Set the input variables.
|
||||
|
||||
if( pszTmpDir )
|
||||
{
|
||||
f_strcpy( m_szFileName, pszTmpDir); // Dest <- src
|
||||
}
|
||||
else
|
||||
{
|
||||
f_memset( m_szFileName, 0, F_PATH_MAX_SIZE);
|
||||
}
|
||||
m_uiEntrySize = uiEntrySize;
|
||||
|
||||
if ((pHashBlk = f_new F_HashBlk) == NULL)
|
||||
{
|
||||
rc = RC_SET( NE_FLM_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
pHashBlk->setup( uiEntrySize);
|
||||
m_pAccess = (F_FixedBlk *) pHashBlk;
|
||||
m_pvUserData = (void *) uiEntrySize;
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Add a fixed length entry to the dynamic search result set.
|
||||
****************************************************************************/
|
||||
RCODE F_DynSearchSet::addEntry(
|
||||
void * pvEntry)
|
||||
{
|
||||
RCODE rc = NE_FLM_OK;
|
||||
|
||||
Add_Again:
|
||||
|
||||
if (RC_OK( rc = m_pAccess->search( pvEntry)))
|
||||
{
|
||||
rc = RC_SET( NE_FLM_EXISTS);
|
||||
}
|
||||
else if (rc == NE_FLM_NOT_FOUND)
|
||||
{
|
||||
|
||||
// Insert the entry.
|
||||
|
||||
if ((rc = m_pAccess->insert( pvEntry)) == NE_FLM_FAILURE)
|
||||
{
|
||||
// Find the type of access method implemented
|
||||
|
||||
if (m_pAccess->blkType() == ACCESS_HASH)
|
||||
{
|
||||
F_BtreeLeaf * pBtreeBlk;
|
||||
FLMBYTE ucEntryBuffer[ DYNSSET_MAX_FIXED_ENTRY_SIZE];
|
||||
|
||||
// Go from a hash to a b-tree object. Alloc and move stuff over.
|
||||
|
||||
if ((pBtreeBlk = f_new F_BtreeLeaf) == NULL)
|
||||
{
|
||||
rc = RC_SET( NE_FLM_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
pBtreeBlk->setup( m_uiEntrySize);
|
||||
pBtreeBlk->setCompareFunc( m_fnCompare, m_pvUserData);
|
||||
for( rc = m_pAccess->getFirst( ucEntryBuffer );
|
||||
RC_OK(rc);
|
||||
rc = m_pAccess->getNext( ucEntryBuffer) )
|
||||
{
|
||||
// Call search to setup for insert.
|
||||
(void) pBtreeBlk->search( ucEntryBuffer);
|
||||
if (RC_BAD( rc = pBtreeBlk->insert( ucEntryBuffer)))
|
||||
{
|
||||
pBtreeBlk->Release();
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
rc = NE_FLM_OK;
|
||||
m_pAccess->Release();
|
||||
m_pAccess = pBtreeBlk;
|
||||
goto Add_Again;
|
||||
}
|
||||
else if( m_pAccess->blkType() == ACCESS_BTREE_LEAF)
|
||||
{
|
||||
F_BtreeRoot * pFullBtree;
|
||||
|
||||
// Go from 1 block to 3 changing root blocks and free m_pAccess
|
||||
// All new splits will be taken care of automatically.
|
||||
|
||||
if ((pFullBtree = f_new F_BtreeRoot) == NULL)
|
||||
{
|
||||
rc = RC_SET( NE_FLM_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
if( RC_BAD( rc = pFullBtree->setup( m_uiEntrySize, m_szFileName)))
|
||||
{
|
||||
pFullBtree->Release();
|
||||
goto Exit;
|
||||
}
|
||||
pFullBtree->setCompareFunc( m_fnCompare, m_pvUserData);
|
||||
if (RC_BAD( rc = ((F_BtreeLeaf *)m_pAccess)->split( pFullBtree)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
m_pAccess->Release();
|
||||
m_pAccess = pFullBtree;
|
||||
goto Add_Again;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Find matching entry. Position for Get* or for insert.
|
||||
****************************************************************************/
|
||||
RCODE F_HashBlk::search(
|
||||
void * pvEntry,
|
||||
void * pvFoundEntry)
|
||||
{
|
||||
RCODE rc = NE_FLM_OK;
|
||||
FLMUINT uiHashPos = HASH_POS( pvEntry);
|
||||
FLMINT iCompare;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
// If all zeros then setup to insert at this position.
|
||||
|
||||
if (!f_memcmp( &m_pucBlkBuf[ uiHashPos], ucZeros, m_uiEntrySize))
|
||||
{
|
||||
rc = RC_SET( NE_FLM_NOT_FOUND);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (m_fnCompare)
|
||||
{
|
||||
iCompare = m_fnCompare( pvEntry, &m_pucBlkBuf[ uiHashPos],
|
||||
m_pvUserData);
|
||||
}
|
||||
else
|
||||
{
|
||||
iCompare = f_memcmp( pvEntry, &m_pucBlkBuf[ uiHashPos],
|
||||
m_uiEntrySize);
|
||||
}
|
||||
|
||||
if (iCompare == 0)
|
||||
{
|
||||
|
||||
// Found match.
|
||||
|
||||
if (pvFoundEntry)
|
||||
{
|
||||
f_memcpy( pvFoundEntry, &m_pucBlkBuf[ uiHashPos], m_uiEntrySize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Go to the next entry
|
||||
|
||||
uiHashPos += m_uiEntrySize;
|
||||
if (uiHashPos >= DYNSSET_HASH_BUFFER_SIZE)
|
||||
{
|
||||
uiHashPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
m_uiPosition = uiHashPos;
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Insert the entry into the buffer.
|
||||
****************************************************************************/
|
||||
RCODE F_HashBlk::insert(
|
||||
void * pvEntry)
|
||||
{
|
||||
RCODE rc = NE_FLM_OK;
|
||||
|
||||
if( getTotalEntries() > ((m_uiNumSlots * 7) / 10))
|
||||
{
|
||||
rc = RC_SET( NE_FLM_FAILURE);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
f_memcpy( &m_pucBlkBuf[ m_uiPosition], pvEntry, m_uiEntrySize);
|
||||
m_uiTotalEntries++;
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Return the next entry in the result set. If the result set
|
||||
is not positioned then the first entry will be returned.
|
||||
****************************************************************************/
|
||||
RCODE F_HashBlk::getNext(
|
||||
void * pvEntryBuffer)
|
||||
{
|
||||
RCODE rc = NE_FLM_OK;
|
||||
FLMUINT uiHashPos;
|
||||
|
||||
// Position to the next/first entry.
|
||||
|
||||
if (m_uiPosition == DYNSSET_POSITION_NOT_SET)
|
||||
{
|
||||
uiHashPos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uiHashPos = m_uiPosition + m_uiEntrySize;
|
||||
}
|
||||
|
||||
for ( ; ; uiHashPos += m_uiEntrySize)
|
||||
{
|
||||
if (uiHashPos >= DYNSSET_HASH_BUFFER_SIZE)
|
||||
{
|
||||
rc = RC_SET( NE_FLM_EOF_HIT);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// If all zeros then setup to insert at this position.
|
||||
|
||||
if (f_memcmp( &m_pucBlkBuf[ uiHashPos], ucZeros, m_uiEntrySize))
|
||||
{
|
||||
f_memcpy( pvEntryBuffer, &m_pucBlkBuf[ uiHashPos], m_uiEntrySize);
|
||||
m_uiPosition = uiHashPos;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Returns the last entry in the result set.
|
||||
****************************************************************************/
|
||||
RCODE F_HashBlk::getLast(
|
||||
void * pvEntryBuffer)
|
||||
{
|
||||
RCODE rc = NE_FLM_OK;
|
||||
FLMUINT uiHashPos;
|
||||
|
||||
// Position to the next/first entry.
|
||||
|
||||
uiHashPos = DYNSSET_HASH_BUFFER_SIZE;
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
uiHashPos -= m_uiEntrySize;
|
||||
|
||||
// If all zeros then setup to insert at this position.
|
||||
|
||||
if (f_memcmp( &m_pucBlkBuf[ uiHashPos], ucZeros, m_uiEntrySize))
|
||||
{
|
||||
f_memcpy( pvEntryBuffer, &m_pucBlkBuf[ uiHashPos], m_uiEntrySize);
|
||||
m_uiPosition = uiHashPos;
|
||||
goto Exit;
|
||||
}
|
||||
if (uiHashPos == 0)
|
||||
{
|
||||
rc = RC_SET( NE_FLM_EOF_HIT);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
514
ftk/src/ftkdynrset.h
Normal file
514
ftk/src/ftkdynrset.h
Normal file
@@ -0,0 +1,514 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Desc: FLAIM Dynamic search result set class.
|
||||
//
|
||||
// Tabs: 3
|
||||
//
|
||||
// Copyright (c) 1998-2000, 2002-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$
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef FTKDYNRSET_H
|
||||
#define FTKDYNRSET_H
|
||||
|
||||
/*****************************************************************************
|
||||
*****
|
||||
** Definitions
|
||||
*****
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
A block size of 8K will perform well in minimizing the number of reads
|
||||
to obtain a block. A 6K may perform better if the file is located
|
||||
across the network.
|
||||
*/
|
||||
|
||||
#define DYNSSET_BLOCK_SIZE 0x4000
|
||||
#define DYNSSET_HASH_BUFFER_SIZE 0x2000
|
||||
#define DYNSSET_MIN_FIXED_ENTRY_SIZE 4
|
||||
// Change ucZeros in fdynsset.cpp if this changes.
|
||||
#define DYNSSET_MAX_FIXED_ENTRY_SIZE 32
|
||||
#define DYNSSET_POSITION_NOT_SET 0xFFFFFFFF
|
||||
|
||||
#define FBTREE_CACHE_BLKS 32
|
||||
#define FBTREE_END 0xFFFFFFFF
|
||||
#define FBTREE_MAX_LEVELS 4
|
||||
|
||||
/*****************************************************************************
|
||||
*****
|
||||
** Forward References
|
||||
*****
|
||||
*****************************************************************************/
|
||||
|
||||
class F_HashBlk;
|
||||
class F_BtreeBlk;
|
||||
class F_BtreeRoot;
|
||||
class F_BtreeNonLeaf;
|
||||
class F_BtreeLeaf;
|
||||
|
||||
/*===========================================================================
|
||||
Block Header Definition
|
||||
|
||||
Desc: Actually stored as the first section of each block.
|
||||
We can write this structure because the same process will
|
||||
read the block header i.e. portability is not a problem.
|
||||
===========================================================================*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FLMUINT uiBlkAddr;
|
||||
FLMUINT uiPrevBlkAddr;
|
||||
FLMUINT uiNextBlkAddr;
|
||||
FLMUINT uiLEMAddr;
|
||||
FLMUINT uiNumEntries;
|
||||
} FixedBlkHdr;
|
||||
|
||||
/*===========================================================================
|
||||
Fixed Length HASH Access Method
|
||||
===========================================================================*/
|
||||
class F_HashBlk : public F_FixedBlk
|
||||
{
|
||||
public:
|
||||
|
||||
F_HashBlk()
|
||||
{
|
||||
// Base class constructors are called before this constructor is.
|
||||
|
||||
m_eBlkType = ACCESS_HASH;
|
||||
m_pucBlkBuf = m_ucHashBlk;
|
||||
f_memset( m_ucHashBlk, 0, sizeof( m_ucHashBlk));
|
||||
m_uiTotalEntries = 0;
|
||||
}
|
||||
|
||||
~F_HashBlk()
|
||||
{
|
||||
// Set to NULL so we don't free the block
|
||||
m_pucBlkBuf = NULL;
|
||||
}
|
||||
|
||||
FINLINE RCODE setup(
|
||||
FLMUINT uiEntrySize
|
||||
)
|
||||
{
|
||||
m_uiEntrySize = uiEntrySize;
|
||||
m_uiNumSlots = DYNSSET_HASH_BUFFER_SIZE / uiEntrySize;
|
||||
return( NE_FLM_OK);
|
||||
}
|
||||
|
||||
FINLINE RCODE getCurrent(
|
||||
void * pvEntryBuffer
|
||||
)
|
||||
{
|
||||
|
||||
// Position to the next/first entry.
|
||||
|
||||
if (m_uiPosition == DYNSSET_POSITION_NOT_SET)
|
||||
{
|
||||
return RC_SET( NE_FLM_NOT_FOUND);
|
||||
}
|
||||
|
||||
f_memcpy( pvEntryBuffer, &m_pucBlkBuf[ m_uiPosition], m_uiEntrySize);
|
||||
return( NE_FLM_OK);
|
||||
}
|
||||
|
||||
FINLINE RCODE getFirst(
|
||||
void * pvEntryBuffer
|
||||
)
|
||||
{
|
||||
m_uiPosition = DYNSSET_POSITION_NOT_SET;
|
||||
return( getNext( pvEntryBuffer));
|
||||
}
|
||||
|
||||
RCODE getLast(
|
||||
void * pvEntryBuffer);
|
||||
|
||||
RCODE getNext(
|
||||
void * pvEntryBuffer);
|
||||
|
||||
FINLINE FLMUINT getTotalEntries( void)
|
||||
{
|
||||
return m_uiTotalEntries;
|
||||
}
|
||||
|
||||
RCODE insert(
|
||||
void * pvEntry);
|
||||
|
||||
RCODE search(
|
||||
void * pvEntry,
|
||||
void * pvFoundEntry = NULL);
|
||||
|
||||
private:
|
||||
|
||||
FLMUINT m_uiTotalEntries;
|
||||
// Allocate the hash block to save 1 allocation.
|
||||
// We need to make the hash as fast as possible.
|
||||
FLMBYTE m_ucHashBlk[ DYNSSET_HASH_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
Virtual F_BtreeBlk
|
||||
===========================================================================*/
|
||||
|
||||
// Leaf and non-leaf entry position. Don't do any ++ or -- ! ! ! !
|
||||
|
||||
#define ENTRY_POS(uiPos) (m_pucBlkBuf + sizeof( FixedBlkHdr) + \
|
||||
(uiPos * (m_uiEntrySize+m_uiEntryOvhd)))
|
||||
|
||||
class F_BtreeBlk : public F_FixedBlk
|
||||
{
|
||||
public:
|
||||
|
||||
F_BtreeBlk()
|
||||
{
|
||||
}
|
||||
|
||||
~F_BtreeBlk()
|
||||
{
|
||||
if (m_pucBlkBuf)
|
||||
{
|
||||
f_free( &m_pucBlkBuf);
|
||||
}
|
||||
}
|
||||
|
||||
// virtual methods that must be implemented
|
||||
|
||||
FINLINE RCODE getCurrent(
|
||||
void * pvEntryBuffer
|
||||
)
|
||||
{
|
||||
// Position to the next/first entry.
|
||||
|
||||
if (m_uiPosition == DYNSSET_POSITION_NOT_SET)
|
||||
{
|
||||
return RC_SET( NE_FLM_NOT_FOUND);
|
||||
}
|
||||
|
||||
f_memcpy( pvEntryBuffer, ENTRY_POS( m_uiPosition), m_uiEntrySize);
|
||||
return( NE_FLM_OK);
|
||||
}
|
||||
|
||||
FINLINE RCODE getFirst(
|
||||
void * pvEntryBuffer
|
||||
)
|
||||
{
|
||||
m_uiPosition = DYNSSET_POSITION_NOT_SET;
|
||||
return( getNext( pvEntryBuffer));
|
||||
}
|
||||
|
||||
RCODE getLast(
|
||||
void * pvEntryBuffer);
|
||||
|
||||
RCODE getNext(
|
||||
void * pvEntryBuffer);
|
||||
|
||||
RCODE readBlk(
|
||||
IF_FileHdl * pFileHdl,
|
||||
FLMUINT uiBlkAddr);
|
||||
|
||||
void reset(
|
||||
eDynRSetBlkTypes eBlkType);
|
||||
|
||||
RCODE split(
|
||||
F_BtreeRoot * pParent,
|
||||
FLMBYTE * pucCurEntry,
|
||||
FLMUINT uiCurBlkAddr,
|
||||
FLMBYTE * pucParentEntry,
|
||||
FLMUINT * puiNewBlkAddr);
|
||||
|
||||
RCODE writeBlk(
|
||||
IF_FileHdl * pFileHdl);
|
||||
|
||||
// Virtual methods
|
||||
|
||||
virtual FLMUINT getTotalEntries( void) = 0;
|
||||
|
||||
virtual RCODE insert(
|
||||
void * pvEntry) = 0;
|
||||
|
||||
virtual RCODE search(
|
||||
void * pvEntry,
|
||||
void * pvFoundEntry = NULL) = 0;
|
||||
|
||||
virtual RCODE searchEntry(
|
||||
void * pvEntry,
|
||||
FLMUINT * puiChildAddr = NULL,
|
||||
void * pvFoundEntry = NULL);
|
||||
|
||||
// Implemented as inline functions.
|
||||
// Even though these are b-tree specific - keep them here to
|
||||
// avoid having a b-tree block class. Most are not used for hash.
|
||||
|
||||
FINLINE FLMUINT blkAddr( void)
|
||||
{
|
||||
return( ((FixedBlkHdr *)m_pucBlkBuf)->uiBlkAddr);
|
||||
}
|
||||
|
||||
FINLINE void blkAddr(
|
||||
FLMUINT uiBlkAddr)
|
||||
{
|
||||
((FixedBlkHdr *)m_pucBlkBuf)->uiBlkAddr = uiBlkAddr;
|
||||
m_bDirty = TRUE;
|
||||
}
|
||||
|
||||
// Get and set the number of entries in the block
|
||||
|
||||
FINLINE FLMUINT entryCount( void)
|
||||
{
|
||||
return( ((FixedBlkHdr *)m_pucBlkBuf)->uiNumEntries);
|
||||
}
|
||||
|
||||
FINLINE void entryCount(
|
||||
FLMUINT uiNumEntries)
|
||||
{
|
||||
((FixedBlkHdr *)m_pucBlkBuf)->uiNumEntries = uiNumEntries;
|
||||
m_bDirty = TRUE;
|
||||
}
|
||||
|
||||
RCODE insertEntry(
|
||||
void * pvEntry,
|
||||
FLMUINT uiChildAddr = FBTREE_END);
|
||||
|
||||
|
||||
// Get and set the last element marker in the block.
|
||||
|
||||
FINLINE FLMUINT lemBlk( void)
|
||||
{
|
||||
return( ((FixedBlkHdr *)m_pucBlkBuf)->uiLEMAddr);
|
||||
}
|
||||
|
||||
FINLINE void lemBlk(
|
||||
FLMUINT uiLEMAddr)
|
||||
{
|
||||
((FixedBlkHdr *)m_pucBlkBuf)->uiLEMAddr = uiLEMAddr;
|
||||
m_bDirty = TRUE;
|
||||
}
|
||||
|
||||
// Get and set the next block address element
|
||||
|
||||
FINLINE FLMUINT nextBlk( void)
|
||||
{
|
||||
return( ((FixedBlkHdr *)m_pucBlkBuf)->uiNextBlkAddr);
|
||||
}
|
||||
|
||||
FINLINE void nextBlk(
|
||||
FLMUINT uiBlkAddr)
|
||||
{
|
||||
((FixedBlkHdr *)m_pucBlkBuf)->uiNextBlkAddr = uiBlkAddr;
|
||||
m_bDirty = TRUE;
|
||||
}
|
||||
|
||||
// Get and set the previous block address element
|
||||
|
||||
FINLINE FLMUINT prevBlk( void)
|
||||
{
|
||||
return( ((FixedBlkHdr *)m_pucBlkBuf)->uiPrevBlkAddr);
|
||||
}
|
||||
|
||||
FINLINE void prevBlk(
|
||||
FLMUINT uiBlkAddr)
|
||||
{
|
||||
((FixedBlkHdr *)m_pucBlkBuf)->uiPrevBlkAddr = uiBlkAddr;
|
||||
m_bDirty = TRUE;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// Variables
|
||||
|
||||
FLMUINT m_uiEntryOvhd; // Overhead in the entry.
|
||||
};
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
Fixed Length B-tree Leaf - may be a root
|
||||
===========================================================================*/
|
||||
|
||||
class F_BtreeLeaf : public F_BtreeBlk
|
||||
{
|
||||
public:
|
||||
|
||||
F_BtreeLeaf()
|
||||
{
|
||||
m_eBlkType = ACCESS_BTREE_LEAF;
|
||||
m_uiEntryOvhd = 0;
|
||||
}
|
||||
|
||||
~F_BtreeLeaf()
|
||||
{
|
||||
}
|
||||
|
||||
RCODE setup(
|
||||
FLMUINT uiEntrySize);
|
||||
|
||||
FINLINE FLMUINT getTotalEntries( void)
|
||||
{
|
||||
return( (FLMUINT)entryCount());
|
||||
}
|
||||
|
||||
FINLINE RCODE insert(
|
||||
void * pvEntry)
|
||||
{
|
||||
return( insertEntry( pvEntry, FBTREE_END));
|
||||
}
|
||||
|
||||
FINLINE RCODE search(
|
||||
void * pvEntry,
|
||||
void * pvFoundEntry = NULL)
|
||||
{
|
||||
return( searchEntry( pvEntry, NULL, pvFoundEntry));
|
||||
}
|
||||
|
||||
RCODE split(
|
||||
F_BtreeRoot * pNewRoot);
|
||||
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FLMUINT uiBlkAddr;
|
||||
FLMUINT uiLRUValue;
|
||||
F_BtreeBlk * pBlk; // Points to leaf or non-leaf block
|
||||
} FBTREE_CACHE;
|
||||
|
||||
/*===========================================================================
|
||||
Fixed Length B-tree non-leaf block
|
||||
===========================================================================*/
|
||||
|
||||
class F_BtreeNonLeaf : public F_BtreeBlk
|
||||
{
|
||||
public:
|
||||
|
||||
F_BtreeNonLeaf()
|
||||
{
|
||||
m_eBlkType = ACCESS_BTREE_NON_LEAF;
|
||||
m_uiEntryOvhd = sizeof( FLMUINT32);
|
||||
}
|
||||
|
||||
~F_BtreeNonLeaf()
|
||||
{
|
||||
}
|
||||
|
||||
RCODE setup(
|
||||
FLMUINT uiEntrySize);
|
||||
|
||||
FINLINE FLMUINT getTotalEntries( void)
|
||||
{
|
||||
return( (FLMUINT) entryCount());
|
||||
}
|
||||
|
||||
FINLINE RCODE insert(
|
||||
void * // pvEntry
|
||||
)
|
||||
{
|
||||
return( NE_FLM_OK);
|
||||
}
|
||||
|
||||
FINLINE RCODE search(
|
||||
void *, // pvEntry,
|
||||
void * pvFoundEntry = NULL
|
||||
)
|
||||
{
|
||||
F_UNREFERENCED_PARM( pvFoundEntry);
|
||||
flmAssert( 0);
|
||||
return( NE_FLM_OK);
|
||||
}
|
||||
};
|
||||
|
||||
/*===========================================================================
|
||||
Fixed Length B-tree Non-Leaf Root
|
||||
===========================================================================*/
|
||||
class F_BtreeRoot : public F_BtreeNonLeaf
|
||||
{
|
||||
public:
|
||||
F_BtreeRoot();
|
||||
~F_BtreeRoot();
|
||||
|
||||
RCODE setup(
|
||||
FLMUINT uiEntrySize,
|
||||
char * pszFileName);
|
||||
|
||||
|
||||
void closeFile( void);
|
||||
|
||||
FINLINE FLMUINT getTotalEntries( void)
|
||||
{
|
||||
return( m_uiTotalEntries);
|
||||
}
|
||||
|
||||
RCODE insert(
|
||||
void * pvEntry);
|
||||
|
||||
RCODE newBlk(
|
||||
F_BtreeBlk ** ppBlk,
|
||||
eDynRSetBlkTypes eBlkType);
|
||||
|
||||
FINLINE FLMUINT newBlkAddr( void)
|
||||
{
|
||||
return( m_uiNewBlkAddr++);
|
||||
}
|
||||
|
||||
RCODE newCacheBlk(
|
||||
FLMUINT uiCachePos,
|
||||
F_BtreeBlk ** ppBlk,
|
||||
eDynRSetBlkTypes eBlkType);
|
||||
|
||||
RCODE openFile( void);
|
||||
|
||||
RCODE readBlk(
|
||||
FLMUINT uiBlkAddr,
|
||||
eDynRSetBlkTypes eBlkType,
|
||||
F_BtreeBlk ** ppBlk);
|
||||
|
||||
RCODE search(
|
||||
void * pvEntry,
|
||||
void * pvFoundEntry = NULL);
|
||||
|
||||
RCODE setupTree(
|
||||
FLMBYTE * pucMidEntry, // If !NULL entry to insert into root.
|
||||
eDynRSetBlkTypes eBlkType, // Leaf or non-leaf
|
||||
F_BtreeBlk ** ppLeftBlk, // (out)
|
||||
F_BtreeBlk ** ppRightBlk); // (out)
|
||||
|
||||
RCODE split(
|
||||
void * pvCurEntry,
|
||||
FLMUINT uiCurChildAddr);
|
||||
|
||||
RCODE writeBlk(
|
||||
FLMUINT uiWritePos);
|
||||
|
||||
private:
|
||||
|
||||
FLMUINT m_uiLevels; // Number of levels in the b-tree
|
||||
FLMUINT m_uiTotalEntries; // Count of total entries
|
||||
FLMUINT m_uiNewBlkAddr; // Next new blk addr.
|
||||
FLMUINT m_uiHighestWrittenBlkAddr;
|
||||
|
||||
IF_FileHdl * m_pFileHdl; // File handle or NULL if not open.
|
||||
char * m_pszFileName; // File created for result set or default.
|
||||
|
||||
// Cache of 'n' blocks to apply LRU algorithm.
|
||||
|
||||
FLMUINT m_uiLRUCount; // Count to find least rec. used.
|
||||
FBTREE_CACHE m_CacheBlks[ FBTREE_CACHE_BLKS];
|
||||
|
||||
// B-tree stack.
|
||||
F_BtreeBlk * m_BTStack[ FBTREE_MAX_LEVELS];
|
||||
};
|
||||
|
||||
#endif // ifndef FTKDYNRSET_H
|
||||
Reference in New Issue
Block a user