Files
mars-flaim/xflaim/src/fdoclist.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

256 lines
5.5 KiB
C++

//------------------------------------------------------------------------------
// Desc: Document list object implementation
//
// Tabs: 3
//
// Copyright (c) 2003-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: fdoclist.cpp 3112 2006-01-19 13:12:40 -0700 (Thu, 19 Jan 2006) dsanders $
//------------------------------------------------------------------------------
#include "flaimsys.h"
#define MAX_PENDING_NODES 255
/****************************************************************************
Desc:
****************************************************************************/
FLMBOOL F_NodeList::findNode(
FLMUINT uiCollection,
FLMUINT64 ui64Document,
FLMUINT64 ui64NodeId,
FLMUINT * puiPos
)
{
FLMBOOL bFound = FALSE;
FLMUINT uiTblSize;
FLMUINT uiLow;
FLMUINT uiMid;
FLMUINT uiHigh;
FLMUINT uiTblCollection;
FLMUINT64 ui64TblDocument;
FLMUINT64 ui64TblNodeId;
FLMINT iCmp;
// Do binary search in the table
if ((uiTblSize = m_uiNumNodes) == 0)
{
*puiPos = 0;
goto Exit;
}
uiHigh = --uiTblSize;
uiLow = 0;
for (;;)
{
uiMid = (uiLow + uiHigh) / 2;
uiTblCollection = m_pNodeTbl[ uiMid].uiCollection;
ui64TblDocument = m_pNodeTbl[ uiMid].ui64Document;
ui64TblNodeId = m_pNodeTbl[ uiMid].ui64NodeId;
if( uiCollection == uiTblCollection)
{
if( ui64Document == ui64TblDocument)
{
if( ui64NodeId == ui64TblNodeId)
{
iCmp = 0;
}
else if( ui64NodeId < ui64TblNodeId)
{
iCmp = -1;
}
else
{
iCmp = 1;
}
}
else if( ui64Document < ui64TblDocument)
{
iCmp = -1;
}
else
{
iCmp = 1;
}
}
else if( uiCollection < uiTblCollection)
{
iCmp = -1;
}
else
{
iCmp = 1;
}
if (!iCmp)
{
// Found Match
bFound = TRUE;
*puiPos = uiMid;
goto Exit;
}
// Check if we are done
if (uiLow >= uiHigh)
{
// Done, item not found
*puiPos = (iCmp < 0
? uiMid
: uiMid + 1);
goto Exit;
}
if (iCmp < 0)
{
if (uiMid == 0)
{
*puiPos = 0;
goto Exit;
}
uiHigh = uiMid - 1;
}
else
{
if (uiMid == uiTblSize)
{
*puiPos = uiMid + 1;
goto Exit;
}
uiLow = uiMid + 1;
}
}
Exit:
return( bFound);
}
/*****************************************************************************
Desc: Add a node to the node list. If it is already there, it is ok.
******************************************************************************/
RCODE F_NodeList::addNode(
FLMUINT uiCollection,
FLMUINT64 ui64Document,
FLMUINT64 ui64NodeId)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiInsertPos;
// Cannot allow collection or document to be zero
flmAssert( uiCollection && ui64Document);
if( m_uiLastCollection == uiCollection &&
m_ui64LastDocument == ui64Document &&
m_ui64LastNodeId == ui64NodeId)
{
goto Exit;
}
if( !findNode( uiCollection, ui64Document, ui64NodeId, &uiInsertPos))
{
// Have we reached the limit of the number of documents we will
// keep pending in a transaction?
if( m_uiNumNodes == MAX_PENDING_NODES)
{
rc = RC_SET( NE_XFLM_TOO_MANY_PENDING_NODES);
goto Exit;
}
// See if we need to allocate the table
if( !m_pNodeTbl)
{
if (RC_BAD( rc = f_alloc(
sizeof( NODE_LIST_ITEM) * MAX_PENDING_NODES, &m_pNodeTbl)))
{
goto Exit;
}
m_uiNodeTblSize = MAX_PENDING_NODES;
}
flmAssert( uiInsertPos <= m_uiNumNodes);
// Make room for the new node ID
if( uiInsertPos < m_uiNumNodes)
{
f_memmove( &m_pNodeTbl[ uiInsertPos+1],
&m_pNodeTbl[ uiInsertPos],
sizeof( NODE_LIST_ITEM) * (m_uiNumNodes - uiInsertPos));
}
m_pNodeTbl[ uiInsertPos].uiCollection = uiCollection;
m_pNodeTbl[ uiInsertPos].ui64Document = ui64Document;
m_pNodeTbl[ uiInsertPos].ui64NodeId = ui64NodeId;
m_uiNumNodes++;
}
// Save collection and document id - this is an optimization
// that will keep us from calling findNode too much if
// we are working inside the same document.
m_uiLastPosition = uiInsertPos;
m_uiLastCollection = uiCollection;
m_ui64LastDocument = ui64Document;
m_ui64LastNodeId = ui64NodeId;
Exit:
return( rc);
}
/*****************************************************************************
Desc: Remove a node from the node list. If it is not there, it is ok.
******************************************************************************/
void F_NodeList::removeNode(
FLMUINT uiCollection,
FLMUINT64 ui64Document,
FLMUINT64 ui64NodeId)
{
FLMUINT uiPos;
// Cannot allow collection or document to be zero
flmAssert( uiCollection && ui64Document);
if( m_uiLastCollection == uiCollection &&
m_ui64LastDocument == ui64Document &&
m_ui64LastNodeId == ui64NodeId)
{
flmAssert( m_uiLastPosition < m_uiNumNodes);
removeNode( m_uiLastPosition);
}
else
{
if( findNode( uiCollection, ui64Document, ui64NodeId, &uiPos))
{
flmAssert( uiPos < m_uiNumNodes);
removeNode( uiPos);
}
}
}