|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Motif
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* These libraries and programs are free software; you can
|
|
Packit |
b099d7 |
* redistribute them and/or modify them under the terms of the GNU
|
|
Packit |
b099d7 |
* Lesser General Public License as published by the Free Software
|
|
Packit |
b099d7 |
* Foundation; either version 2 of the License, or (at your option)
|
|
Packit |
b099d7 |
* any later version.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* These libraries and programs are distributed in the hope that
|
|
Packit |
b099d7 |
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
Packit |
b099d7 |
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
Packit |
b099d7 |
* PURPOSE. See the GNU Lesser General Public License for more
|
|
Packit |
b099d7 |
* details.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
b099d7 |
* License along with these librararies and programs; if not, write
|
|
Packit |
b099d7 |
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
Packit |
b099d7 |
* Floor, Boston, MA 02110-1301 USA
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* HISTORY
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
b099d7 |
#include <config.h>
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#ifdef REV_INFO
|
|
Packit |
b099d7 |
#ifndef lint
|
|
Packit |
b099d7 |
static char rcsid[] = "$XConsortium: MrmIindexw.c /main/12 1996/11/13 13:57:54 drk $"
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
* FACILITY:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* UIL Resource Manager (URM): IDB Facility
|
|
Packit |
b099d7 |
* Index management routines
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* ABSTRACT:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* These routines manage the index of an IDB file, including
|
|
Packit |
b099d7 |
* retrieving data entries accessed by index, and maintaing the
|
|
Packit |
b099d7 |
* index structure, particularly index splitting
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* INCLUDE FILES
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#include <Mrm/MrmAppl.h>
|
|
Packit |
b099d7 |
#include <Mrm/Mrm.h>
|
|
Packit |
b099d7 |
#include <Mrm/IDB.h>
|
|
Packit |
b099d7 |
#include "MrmMsgI.h"
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* TABLE OF CONTENTS
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_EnterItem - Enter a data entry under an index
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_EnterLeafIndex - Add an entry to a leaf record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_EnterNodeIndex - Add an entry to a node record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_SplitLeafRecord - Split a leaf index record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_SplitNodeRecord - Split a node index record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_InitRootLeafRecord - Init a (root) leaf index record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_InitRootNodeRecord - Init a (root) node index record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_CopyLeafRecord - Copy a leaf record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_CopyNodeRecord - Copy a node record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_CollapseLeafRecord - Collapse a leaf record (truncate)
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_CollapseNodeRecord - Collapse a node record (truncate)
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_ConfirmNodeSpace - Confirm enough space in node
|
|
Packit |
b099d7 |
* record for new entry
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_SetParent - Set parent pointer in record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_FixNodeChildren - Reset parent pointers for all
|
|
Packit |
b099d7 |
* the children of some node
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* DEFINE and MACRO DEFINITIONS
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Macros which validate index records in buffers
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
#define Idb__INX_ValidLeaf(buffer) \
|
|
Packit |
b099d7 |
(_IdbBufferRecordType(buffer)==IDBrtIndexLeaf)
|
|
Packit |
b099d7 |
#define Idb__INX_ValidNode(buffer) \
|
|
Packit |
b099d7 |
(_IdbBufferRecordType(buffer)==IDBrtIndexNode)
|
|
Packit |
b099d7 |
#define Idb__INX_ValidRecord(buffer) \
|
|
Packit |
b099d7 |
(_IdbBufferRecordType(buffer)==IDBrtIndexLeaf || \
|
|
Packit |
b099d7 |
_IdbBufferRecordType(buffer)==IDBrtIndexNode)
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_EnterItem makes an entry in the file's index for a data
|
|
Packit |
b099d7 |
* entry which has been previously entered in the file.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file in which to write entry
|
|
Packit |
b099d7 |
* index The entry's case-sensitive index
|
|
Packit |
b099d7 |
* data_entry Data entry pointer for data
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS operation succeeded
|
|
Packit |
b099d7 |
* MrmEXISTS index already exists in file
|
|
Packit |
b099d7 |
* MrmFAILURE some other failure
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_EnterItem (IDBFile file_id ,
|
|
Packit |
b099d7 |
char *index ,
|
|
Packit |
b099d7 |
IDBDataHandle data_entry )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr bufptr ; /* buffer into which to stuff entry */
|
|
Packit |
b099d7 |
MrmCount entndx ; /* locates pivotal entry in buffer */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Initialize the index with this entry if this is the initial one.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if ( !file_id->index_root )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__INX_InitRootLeafRecord (file_id, &bufptr) ;
|
|
Packit |
b099d7 |
if (result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
result = Idb__INX_EnterLeafIndex
|
|
Packit |
b099d7 |
(file_id, bufptr, index, data_entry, 0, MrmINDEX_LT) ;
|
|
Packit |
b099d7 |
return result ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Find the (leaf) record in which to place this entry, and the
|
|
Packit |
b099d7 |
* position in the record. Place it in the record (which must be
|
|
Packit |
b099d7 |
* a leaf record). This process loops as long as record splitting
|
|
Packit |
b099d7 |
* forces retries.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
do {
|
|
Packit |
b099d7 |
result = Idb__INX_FindIndex (file_id, index, &bufptr, &entndx) ;
|
|
Packit |
b099d7 |
switch ( result )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
case MrmINDEX_GT:
|
|
Packit |
b099d7 |
case MrmINDEX_LT:
|
|
Packit |
b099d7 |
break ;
|
|
Packit |
b099d7 |
case MrmSUCCESS:
|
|
Packit |
b099d7 |
return MrmEXISTS ;
|
|
Packit |
b099d7 |
default:
|
|
Packit |
b099d7 |
return result ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
result = Idb__INX_EnterLeafIndex
|
|
Packit |
b099d7 |
(file_id, bufptr, index, data_entry, entndx, result) ;
|
|
Packit |
b099d7 |
} while ( result == MrmINDEX_RETRY ) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Return results of final attempt to stuff in a leaf record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
return result ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_EnterLeafIndex creates a new entry for a data entry in a
|
|
Packit |
b099d7 |
* leaf index record. If there isn't enough room in the record for
|
|
Packit |
b099d7 |
* the new entry, the record is split and the enter operation must
|
|
Packit |
b099d7 |
* be retried.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* buffer Buffer containing leaf index record
|
|
Packit |
b099d7 |
* index The entry's case-sensitive index
|
|
Packit |
b099d7 |
* data_entry Data entry pointer for data
|
|
Packit |
b099d7 |
* entry_index Entry in record at which to force new entry
|
|
Packit |
b099d7 |
* order Specifies how new entry orders WRT entry at
|
|
Packit |
b099d7 |
* entry_index; MrmINDEX_GT or MrmINDEX_LT.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS operation succeeded
|
|
Packit |
b099d7 |
* MrmINDEX_RETRY operation must be tried again.
|
|
Packit |
b099d7 |
* MrmFAILURE some other failure
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_EnterLeafIndex (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordBufferPtr buffer,
|
|
Packit |
b099d7 |
char *index,
|
|
Packit |
b099d7 |
IDBDataHandle data_entry,
|
|
Packit |
b099d7 |
MrmCount entry_index,
|
|
Packit |
b099d7 |
Cardinal order)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBIndexLeafRecordPtr recptr ; /* leaf record in buffer */
|
|
Packit |
b099d7 |
IDBIndexLeafHdrPtr hdrptr ; /* record header */
|
|
Packit |
b099d7 |
MrmCount entndx ; /* index for new entry */
|
|
Packit |
b099d7 |
Cardinal entsiz ; /* # bytes needed for new entry */
|
|
Packit |
b099d7 |
MrmCount ndxsiz ; /* # bytes needed for new string */
|
|
Packit |
b099d7 |
char *ndxstg ; /* location for new string */
|
|
Packit |
b099d7 |
int ndx ; /* loop index */
|
|
Packit |
b099d7 |
char *stgheap ; /* string heap beginning */
|
|
Packit |
b099d7 |
MrmCount nfree ; /* # free bytes */
|
|
Packit |
b099d7 |
IDBIndexLeafEntryPtr itemvec ; /* The vector of index entries */
|
|
Packit |
b099d7 |
MrmCount itemcnt ; /* # entries in vector */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Initialize pointers into the record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
recptr = (IDBIndexLeafRecordPtr) buffer->IDB_record ;
|
|
Packit |
b099d7 |
hdrptr = (IDBIndexLeafHdrPtr) &recptr->leaf_header ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Compute sizes for new entry. Split record and retry if required
|
|
Packit |
b099d7 |
* to get enough space.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
ndxsiz = MIN(strlen(index),IDBMaxIndexLength) + 1 ;
|
|
Packit |
b099d7 |
ndxsiz = _FULLWORD(ndxsiz);
|
|
Packit |
b099d7 |
entsiz = IDBIndexLeafEntrySize + ndxsiz ;
|
|
Packit |
b099d7 |
nfree = hdrptr->free_bytes ;
|
|
Packit |
b099d7 |
if ( entsiz > nfree )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__INX_SplitLeafRecord (file_id, buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
return MrmINDEX_RETRY ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Pick up values and pointers into the record.
|
|
Packit |
b099d7 |
* Adjust entry index based on ordering, then make room for the
|
|
Packit |
b099d7 |
* new entry.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
stgheap = (char *) &recptr->index[0] + hdrptr->heap_start ;
|
|
Packit |
b099d7 |
itemvec = recptr->index ;
|
|
Packit |
b099d7 |
itemcnt = hdrptr->index_count ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
entndx = (order==MrmINDEX_GT) ? entry_index+1 : entry_index ;
|
|
Packit |
b099d7 |
ndxstg = (char *) stgheap - ndxsiz ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for ( ndx=itemcnt ; ndx>entndx ; ndx--)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
itemvec[ndx].index_stg = itemvec[ndx-1].index_stg ;
|
|
Packit |
b099d7 |
itemvec[ndx].data = itemvec[ndx-1].data ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Move the string and set the values in the vector entry
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
strcpy (ndxstg, "") ;
|
|
Packit |
b099d7 |
strncat (ndxstg, index, IDBMaxIndexLength) ;
|
|
Packit |
b099d7 |
itemvec[entndx].index_stg = (MrmOffset) (ndxstg-(char *)itemvec) ;
|
|
Packit |
b099d7 |
itemvec[entndx].data.internal_id.rec_no = data_entry.rec_no ;
|
|
Packit |
b099d7 |
itemvec[entndx].data.internal_id.item_offs = data_entry.item_offs ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* update the header
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
hdrptr->index_count++ ;
|
|
Packit |
b099d7 |
hdrptr->heap_start -= ndxsiz ;
|
|
Packit |
b099d7 |
hdrptr->free_bytes -= entsiz ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* entry successfully added
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (buffer) ;
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_EnterNodeIndex creates a new entry for a data entry in a
|
|
Packit |
b099d7 |
* node index record. It differs from entering an item in a leaf record
|
|
Packit |
b099d7 |
* in that the position for the new entry is not known.
|
|
Packit |
b099d7 |
* If there isn't room for the new entry, the record is split, and
|
|
Packit |
b099d7 |
* the operation must be tried again.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* buffer Buffer containing node index record
|
|
Packit |
b099d7 |
* index The entry's case-sensitive index
|
|
Packit |
b099d7 |
* data_entry Data entry pointer for data
|
|
Packit |
b099d7 |
* lt_record Record number of the less-than record associated with
|
|
Packit |
b099d7 |
* this entry
|
|
Packit |
b099d7 |
* gt_record Record number of the greater-than record associated with
|
|
Packit |
b099d7 |
* this entry
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS operation succeeded
|
|
Packit |
b099d7 |
* MrmINDEX_RETRY operation must be tried again.
|
|
Packit |
b099d7 |
* MrmFAILURE some other failure
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_EnterNodeIndex (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordBufferPtr buffer,
|
|
Packit |
b099d7 |
char *index,
|
|
Packit |
b099d7 |
IDBDataHandle data_entry,
|
|
Packit |
b099d7 |
IDBRecordNumber lt_record,
|
|
Packit |
b099d7 |
IDBRecordNumber gt_record)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBIndexNodeRecordPtr recptr ; /* node record in buffer */
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr hdrptr ; /* record header */
|
|
Packit |
b099d7 |
MrmCount entry_index ; /* searched location for new entry */
|
|
Packit |
b099d7 |
Cardinal order ; /* order of index WRT location */
|
|
Packit |
b099d7 |
MrmCount entndx ; /* index for new entry */
|
|
Packit |
b099d7 |
Cardinal entsiz ; /* # bytes needed for new entry */
|
|
Packit |
b099d7 |
MrmCount ndxsiz ; /* # bytes needed for new string */
|
|
Packit |
b099d7 |
char *ndxstg ; /* location for new string */
|
|
Packit |
b099d7 |
int ndx ; /* loop index */
|
|
Packit |
b099d7 |
char *stgheap ; /* string heap beginning */
|
|
Packit |
b099d7 |
MrmCount nfree ; /* # free bytes */
|
|
Packit |
b099d7 |
IDBIndexNodeEntryPtr itemvec ; /* The vector of index entries */
|
|
Packit |
b099d7 |
MrmCount itemcnt ; /* # entries in vector */
|
|
Packit |
b099d7 |
MrmCount prvndx ; /* preceding entry index */
|
|
Packit |
b099d7 |
MrmCount nxtndx ; /* succeeding entry index */
|
|
Packit |
b099d7 |
IDBRecordNumber p_recno ; /* this node record number */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Initialize pointers into the record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
recptr = (IDBIndexNodeRecordPtr) buffer->IDB_record ;
|
|
Packit |
b099d7 |
hdrptr = (IDBIndexNodeHdrPtr) &recptr->node_header ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Compute sizes for new entry. Split record and retry if required
|
|
Packit |
b099d7 |
* to get enough space.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
ndxsiz = MIN(strlen(index),IDBMaxIndexLength) + 1 ;
|
|
Packit |
b099d7 |
ndxsiz = _FULLWORD(ndxsiz);
|
|
Packit |
b099d7 |
entsiz = IDBIndexNodeEntrySize + ndxsiz ;
|
|
Packit |
b099d7 |
nfree = hdrptr->free_bytes ;
|
|
Packit |
b099d7 |
if ( entsiz > nfree )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__INX_SplitNodeRecord (file_id, buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
return MrmINDEX_RETRY ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Pick up value and pointers into the record. Figure out the
|
|
Packit |
b099d7 |
* location at which to insert the record (0 for a new entry),
|
|
Packit |
b099d7 |
* and make room for the new entry.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
stgheap = (char *) &recptr->index[0] + hdrptr->heap_start ;
|
|
Packit |
b099d7 |
itemvec = recptr->index ;
|
|
Packit |
b099d7 |
itemcnt = hdrptr->index_count ;
|
|
Packit |
b099d7 |
if ( itemcnt == 0 )
|
|
Packit |
b099d7 |
entndx = 0 ;
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
order = Idb__INX_SearchIndex (file_id, index, buffer, &entry_index) ;
|
|
Packit |
b099d7 |
entndx = (order==MrmINDEX_GT) ? entry_index+1 : entry_index ;
|
|
Packit |
b099d7 |
for ( ndx=itemcnt ; ndx>entndx ; ndx--)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
itemvec[ndx].index_stg = itemvec[ndx-1].index_stg ;
|
|
Packit |
b099d7 |
itemvec[ndx].data = itemvec[ndx-1].data ;
|
|
Packit |
b099d7 |
itemvec[ndx].LT_record = itemvec[ndx-1].LT_record ;
|
|
Packit |
b099d7 |
itemvec[ndx].GT_record = itemvec[ndx-1].GT_record ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Move the string and set the values in the vector entry and record vector
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
ndxstg = (char *) stgheap - ndxsiz ;
|
|
Packit |
b099d7 |
strcpy (ndxstg, "") ;
|
|
Packit |
b099d7 |
strncat (ndxstg, index, IDBMaxIndexLength) ;
|
|
Packit |
b099d7 |
itemvec[entndx].index_stg = (MrmOffset) (ndxstg-(char *)itemvec) ;
|
|
Packit |
b099d7 |
itemvec[entndx].data.internal_id.rec_no = data_entry.rec_no ;
|
|
Packit |
b099d7 |
itemvec[entndx].data.internal_id.item_offs = data_entry.item_offs ;
|
|
Packit |
b099d7 |
itemvec[entndx].LT_record = lt_record ;
|
|
Packit |
b099d7 |
itemvec[entndx].GT_record = gt_record ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* update the header
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
hdrptr->index_count = ++itemcnt ;
|
|
Packit |
b099d7 |
hdrptr->heap_start -= ndxsiz ;
|
|
Packit |
b099d7 |
hdrptr->free_bytes -= entsiz ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Now the entries to either side of the new index must have their LT
|
|
Packit |
b099d7 |
* and LT pointers verified and changed. By practice, the GT record of the
|
|
Packit |
b099d7 |
* new entry is a previous record which should occur as the GT record of
|
|
Packit |
b099d7 |
* the preceding entry and the LT record of the succeeding entry.
|
|
Packit |
b099d7 |
* These entries must be modified to have LT and GT pointers matching the
|
|
Packit |
b099d7 |
* records given here as arguments.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if ( entndx > 0 )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
prvndx = entndx - 1 ;
|
|
Packit |
b099d7 |
if ( itemvec[prvndx].GT_record != gt_record )
|
|
Packit |
b099d7 |
return Urm__UT_Error ("Idb__INX_EnterNodeIndex", _MrmMMsg_0016,
|
|
Packit |
b099d7 |
file_id, NULL, MrmBAD_BTREE) ;
|
|
Packit |
b099d7 |
itemvec[prvndx].GT_record = lt_record ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
if ( entndx < (itemcnt-1) )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
nxtndx = entndx + 1 ;
|
|
Packit |
b099d7 |
if ( itemvec[nxtndx].LT_record != gt_record )
|
|
Packit |
b099d7 |
return Urm__UT_Error ("Idb__INX_EnterNodeIndex", _MrmMMsg_0017,
|
|
Packit |
b099d7 |
file_id, NULL, MrmBAD_BTREE) ;
|
|
Packit |
b099d7 |
itemvec[nxtndx].LT_record = gt_record ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* entry successfully added
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (buffer) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Set the parent pointer in the LT and GT records
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
p_recno = _IdbBufferRecordNumber (buffer) ;
|
|
Packit |
b099d7 |
result = Idb__INX_SetParent (file_id, p_recno, lt_record) ;
|
|
Packit |
b099d7 |
result = Idb__INX_SetParent (file_id, p_recno, gt_record) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_SplitRecord splits an index record in order to make room
|
|
Packit |
b099d7 |
* for new entries. This is the crucial routine in causing the B-tree
|
|
Packit |
b099d7 |
* to grow. It splits leaf records only.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* The split process takes place as follows:
|
|
Packit |
b099d7 |
* - extract the middle entry from the record and save it.
|
|
Packit |
b099d7 |
* - create a new leaf record and move all the less-than
|
|
Packit |
b099d7 |
* ordered entries into it.
|
|
Packit |
b099d7 |
* - reorganize the current record to contain only the greater-than
|
|
Packit |
b099d7 |
* ordered entries (garbage collecting the string heap).
|
|
Packit |
b099d7 |
* - Enter the extracted entry in the parent (creating a new
|
|
Packit |
b099d7 |
* parent if required). This entry takes the less-than
|
|
Packit |
b099d7 |
* record with it to the parent, thus entering the new leaf
|
|
Packit |
b099d7 |
* record in the B-tree. The old record is retained as a
|
|
Packit |
b099d7 |
* greater-than record for the extracted index.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* The trickiest aspect of splitting nodes is maintaining parent
|
|
Packit |
b099d7 |
* pointers when splitting may cause parents to change. IDB deals
|
|
Packit |
b099d7 |
* this by splitting from the top of the tree down, so that a node's
|
|
Packit |
b099d7 |
* parent pointer is guaranteed correct when the node is split.
|
|
Packit |
b099d7 |
* This is done by:
|
|
Packit |
b099d7 |
* - Before splitting, check that parent has enough room
|
|
Packit |
b099d7 |
* for a new entry. If not, the parent will split and
|
|
Packit |
b099d7 |
* inform the caller to retry.
|
|
Packit |
b099d7 |
* - Splitting the root node is always safe
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* gt_buffer Buffer containing leaf index record to be split
|
|
Packit |
b099d7 |
* This will become the new GT buffer
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS operation succeeded
|
|
Packit |
b099d7 |
* MrmBAD_RECORD not a leaf index record
|
|
Packit |
b099d7 |
* MrmFAILURE some other failure
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_SplitLeafRecord (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordBufferPtr gt_buffer)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBRecordNumber p_recno ; /* parent record number */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr p_buffer ; /* parent buffer */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr lt_buffer ; /* buffer for LT leaf record */
|
|
Packit |
b099d7 |
IDBIndexLeafRecordPtr lt_recptr ; /* LT leaf record in buffer */
|
|
Packit |
b099d7 |
IDBIndexLeafRecordPtr gt_recptr ; /* GT leaf record in buffer */
|
|
Packit |
b099d7 |
IDBIndexLeafHdrPtr gt_hdrptr ; /* GT record header */
|
|
Packit |
b099d7 |
MrmCount p_index ; /* index of hoisted entry */
|
|
Packit |
b099d7 |
char p_index_stg[IDBMaxIndexLength1] ; /* save hoisted idx */
|
|
Packit |
b099d7 |
char *p_index_stgadr ; /* Address of hoisted index string */
|
|
Packit |
b099d7 |
IDBDataHandle p_data ; /* saves hoisted entry data */
|
|
Packit |
b099d7 |
MrmCount lt_cnt ; /* number of LT items */
|
|
Packit |
b099d7 |
MrmCount gt_cnt ; /* number of GT items */
|
|
Packit |
b099d7 |
MrmCount old_cnt ; /* original number of items */
|
|
Packit |
b099d7 |
IDBIndexLeafEntryPtr old_itmvec ; /* Original vector */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Initialize pointers into the record and sanity check. This record
|
|
Packit |
b099d7 |
* will become the GT leaf record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if ( ! Idb__INX_ValidLeaf(gt_buffer) )
|
|
Packit |
b099d7 |
return Urm__UT_Error ("Idb__INX_SplitLeafRecord", _MrmMMsg_0010,
|
|
Packit |
b099d7 |
file_id, NULL, MrmBAD_RECORD) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
gt_recptr = (IDBIndexLeafRecordPtr) gt_buffer->IDB_record ;
|
|
Packit |
b099d7 |
gt_hdrptr = (IDBIndexLeafHdrPtr) >_recptr->leaf_header ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* If this node has a parent, make sure it can hold a new entry.
|
|
Packit |
b099d7 |
* If not, it will split, and we must retry. Note a parent must be
|
|
Packit |
b099d7 |
* a node record.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
p_recno = gt_hdrptr->parent ;
|
|
Packit |
b099d7 |
if ( gt_hdrptr->parent )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__BM_GetRecord (file_id, gt_hdrptr->parent, &p_buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
if ( ! Idb__INX_ValidNode(p_buffer) )
|
|
Packit |
b099d7 |
return Urm__UT_Error ("Idb__INX_SplitLeafRecord", _MrmMMsg_0018,
|
|
Packit |
b099d7 |
file_id, NULL, MrmBAD_RECORD) ;
|
|
Packit |
b099d7 |
result = Idb__INX_ConfirmNodeSpace (file_id, p_buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Pick up current parameters
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
old_cnt = gt_hdrptr->index_count ;
|
|
Packit |
b099d7 |
old_itmvec = gt_recptr->index ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Compute the indexes and counts for the split, and save the hoisted entry.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
lt_cnt = old_cnt / 2 ;
|
|
Packit |
b099d7 |
p_index = lt_cnt ;
|
|
Packit |
b099d7 |
gt_cnt = old_cnt - lt_cnt - 1;
|
|
Packit |
b099d7 |
p_index_stgadr = (char *) old_itmvec+old_itmvec[p_index].index_stg ;
|
|
Packit |
b099d7 |
strcpy (p_index_stg, p_index_stgadr) ;
|
|
Packit |
b099d7 |
p_data.rec_no = old_itmvec[p_index].data.internal_id.rec_no ;
|
|
Packit |
b099d7 |
p_data.item_offs = old_itmvec[p_index].data.internal_id.item_offs ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Acquire a new record to become the LT part. Copy the entire current
|
|
Packit |
b099d7 |
* record into it, then collapse both records into their final form.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__BM_InitRecord (file_id, 0, IDBrtIndexLeaf, <_buffer) ;
|
|
Packit |
b099d7 |
lt_recptr = (IDBIndexLeafRecordPtr) lt_buffer->IDB_record ;
|
|
Packit |
b099d7 |
Idb__INX_CopyLeafRecord (lt_recptr, gt_recptr) ;
|
|
Packit |
b099d7 |
Idb__INX_CollapseLeafRecord (lt_recptr, 0, lt_cnt-1) ;
|
|
Packit |
b099d7 |
Idb__INX_CollapseLeafRecord (gt_recptr, p_index+1, p_index+gt_cnt) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Both records now have their parent set correctly via the copy operation,
|
|
Packit |
b099d7 |
* since our check on space in the parent guarantees that the parent
|
|
Packit |
b099d7 |
* pointer present in the original buffer will remain the parent after
|
|
Packit |
b099d7 |
* we host the pivot index (unless we create a new root node, which
|
|
Packit |
b099d7 |
* is guaranteed safe anyway. So we we can mark the buffers and
|
|
Packit |
b099d7 |
* hoist the pivot index.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (lt_buffer) ;
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (gt_buffer) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Either enter the hoisted entry into the parent, or create
|
|
Packit |
b099d7 |
* a parent (which will be the root record).
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if ( !p_recno )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__INX_InitRootNodeRecord
|
|
Packit |
b099d7 |
(file_id, &p_buffer, p_index_stg, p_data,
|
|
Packit |
b099d7 |
_IdbBufferRecordNumber(lt_buffer), _IdbBufferRecordNumber(gt_buffer)) ;
|
|
Packit |
b099d7 |
return result ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Hoist the entry into the parent (we know there should be room).
|
|
Packit |
b099d7 |
* The parent is already loaded in its buffer as part of the space check.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__INX_EnterNodeIndex
|
|
Packit |
b099d7 |
(file_id, p_buffer, p_index_stg, p_data,
|
|
Packit |
b099d7 |
_IdbBufferRecordNumber(lt_buffer), _IdbBufferRecordNumber(gt_buffer)) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Successfully added.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_SplitRecord splits an index record in order to make room
|
|
Packit |
b099d7 |
* for new entries. This is the crucial routine in causing the B-tree
|
|
Packit |
b099d7 |
* to grow. It splits node records only.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* The split process takes place as follows:
|
|
Packit |
b099d7 |
* - extract the middle entry from the record and save it.
|
|
Packit |
b099d7 |
* - create a new node record and move all the less-than
|
|
Packit |
b099d7 |
* ordered entries into it.
|
|
Packit |
b099d7 |
* - reorganize the current record to contain only the greater-than
|
|
Packit |
b099d7 |
* ordered entries (garbage collecting the string heap).
|
|
Packit |
b099d7 |
* - Enter the extracted entry in the parent (creating a new
|
|
Packit |
b099d7 |
* parent if required). This entry takes the less-than
|
|
Packit |
b099d7 |
* record with it to the parent, thus entering the new node
|
|
Packit |
b099d7 |
* record in the B-tree. The old record is retained as a
|
|
Packit |
b099d7 |
* greater-than record for the extracted index.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* For node records, the record vectors are handled entirely by
|
|
Packit |
b099d7 |
* the collapse routines. No record number is saved for the hoisted
|
|
Packit |
b099d7 |
* index, since the associated record number is either new LT record
|
|
Packit |
b099d7 |
* or both records if a root node is created.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* gt_buffer Buffer containing node index record to be split. This
|
|
Packit |
b099d7 |
* will become the new GT buffer.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS operation succeeded
|
|
Packit |
b099d7 |
* MrmBAD_RECORD not a node index record
|
|
Packit |
b099d7 |
* MrmFAILURE some other failure
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_SplitNodeRecord (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordBufferPtr gt_buffer)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBRecordNumber p_recno ; /* parent record number */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr p_buffer ; /* parent buffer */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr lt_buffer ; /* buffer for LT node record */
|
|
Packit |
b099d7 |
IDBIndexNodeRecordPtr lt_recptr ; /* LT node record in buffer */
|
|
Packit |
b099d7 |
IDBIndexNodeRecordPtr gt_recptr ; /* GT node record in buffer */
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr gt_hdrptr ; /* GT record header */
|
|
Packit |
b099d7 |
IDBRecordNumber lt_recno ; /* LT node record number */
|
|
Packit |
b099d7 |
IDBRecordNumber gt_recno ; /* GT node record number */
|
|
Packit |
b099d7 |
MrmCount p_index ; /* index of hoisted entry */
|
|
Packit |
b099d7 |
char p_index_stg[IDBMaxIndexLength1]; /* save hoisted indx */
|
|
Packit |
b099d7 |
char *p_index_stgadr ; /* Address of hoisted index string */
|
|
Packit |
b099d7 |
IDBDataHandle p_data ; /* saves hoisted entry data */
|
|
Packit |
b099d7 |
MrmCount lt_cnt ; /* number of LT items */
|
|
Packit |
b099d7 |
MrmCount gt_cnt ; /* number of GT items */
|
|
Packit |
b099d7 |
MrmCount old_cnt ; /* original number of items */
|
|
Packit |
b099d7 |
IDBIndexNodeEntryPtr old_itmvec ; /* Original vector */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Initialize pointers into the record and sanity check. This record
|
|
Packit |
b099d7 |
* will become the GT node record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if ( ! Idb__INX_ValidNode(gt_buffer) )
|
|
Packit |
b099d7 |
return Urm__UT_Error ("Idb__INX_SplitNodeRecord", _MrmMMsg_0010,
|
|
Packit |
b099d7 |
file_id, NULL, MrmBAD_RECORD) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
gt_recptr = (IDBIndexNodeRecordPtr) gt_buffer->IDB_record ;
|
|
Packit |
b099d7 |
gt_hdrptr = (IDBIndexNodeHdrPtr) >_recptr->node_header ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* If this node has a parent, make sure it can hold a new entry.
|
|
Packit |
b099d7 |
* If not, it will split, and we must retry. Note a parent must be
|
|
Packit |
b099d7 |
* a node record.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
p_recno = gt_hdrptr->parent ;
|
|
Packit |
b099d7 |
if ( p_recno )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__BM_GetRecord (file_id, p_recno, &p_buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
if ( ! Idb__INX_ValidNode(p_buffer) )
|
|
Packit |
b099d7 |
return Urm__UT_Error ("Idb__INX_SplitNodeRecord", _MrmMMsg_0018,
|
|
Packit |
b099d7 |
file_id, NULL, MrmBAD_RECORD) ;
|
|
Packit |
b099d7 |
result = Idb__INX_ConfirmNodeSpace (file_id, p_buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Pick up current parameters
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
old_cnt = gt_hdrptr->index_count ;
|
|
Packit |
b099d7 |
old_itmvec = gt_recptr->index ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Compute the indexes and counts for the split, and save the hoisted entry.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
lt_cnt = old_cnt / 2 ;
|
|
Packit |
b099d7 |
p_index = lt_cnt ;
|
|
Packit |
b099d7 |
gt_cnt = old_cnt - lt_cnt - 1;
|
|
Packit |
b099d7 |
p_index_stgadr = (char *) old_itmvec+old_itmvec[p_index].index_stg ;
|
|
Packit |
b099d7 |
strcpy (p_index_stg, p_index_stgadr) ;
|
|
Packit |
b099d7 |
p_data.rec_no = old_itmvec[p_index].data.internal_id.rec_no ;
|
|
Packit |
b099d7 |
p_data.item_offs = old_itmvec[p_index].data.internal_id.item_offs ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Acquire a new record to become the LT part. Copy the entire current
|
|
Packit |
b099d7 |
* record into it, then collapse both records into their final form.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__BM_InitRecord (file_id, 0, IDBrtIndexNode, <_buffer) ;
|
|
Packit |
b099d7 |
lt_recptr = (IDBIndexNodeRecordPtr) lt_buffer->IDB_record ;
|
|
Packit |
b099d7 |
Idb__INX_CopyNodeRecord (lt_recptr, gt_recptr) ;
|
|
Packit |
b099d7 |
Idb__INX_CollapseNodeRecord (lt_recptr, 0, lt_cnt-1) ;
|
|
Packit |
b099d7 |
Idb__INX_CollapseNodeRecord (gt_recptr, p_index+1, p_index+gt_cnt) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Both records now have their parent set correctly via the copy operation,
|
|
Packit |
b099d7 |
* since our check on space in the parent guarantees that the parent
|
|
Packit |
b099d7 |
* pointer present in the original buffer will remain the parent after
|
|
Packit |
b099d7 |
* we host the pivot index (unless we create a new root node, which
|
|
Packit |
b099d7 |
* is guaranteed safe anyway. Thus we are done with all changes to these
|
|
Packit |
b099d7 |
* buffers, and can mark them. Then save their record numbers and child
|
|
Packit |
b099d7 |
* list for future operations.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (lt_buffer) ;
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (gt_buffer) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
lt_recno = _IdbBufferRecordNumber (lt_buffer) ;
|
|
Packit |
b099d7 |
gt_recno = _IdbBufferRecordNumber (gt_buffer) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Either enter the hoisted entry into the parent, or create
|
|
Packit |
b099d7 |
* a parent (which will be the root record).
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Otherwise, hoist the entry into the parent (we know there should be room).
|
|
Packit |
b099d7 |
* The parent should be already loaded in its buffer as part of the space
|
|
Packit |
b099d7 |
* check, but a reload is done to make sure buffer turning hasn't interfered.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if ( !p_recno )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__INX_InitRootNodeRecord
|
|
Packit |
b099d7 |
(file_id, &p_buffer, p_index_stg, p_data, lt_recno, gt_recno) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__BM_GetRecord (file_id, p_recno, &p_buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
result = Idb__INX_EnterNodeIndex
|
|
Packit |
b099d7 |
(file_id, p_buffer, p_index_stg, p_data, lt_recno, gt_recno) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Now all child nodes of the split record must have their parent
|
|
Packit |
b099d7 |
* pointers updated. The gt_buffer children should still have the same
|
|
Packit |
b099d7 |
* parent, but the update will be done to that buffer as well for
|
|
Packit |
b099d7 |
* completeness.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__INX_FixNodeChildren (file_id, lt_recno) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
result = Idb__INX_FixNodeChildren (file_id, gt_recno) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Successfully added.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_InitLeafRecord initializes a new leaf index record,
|
|
Packit |
b099d7 |
* resulting in an empty record with the maximum free space available.
|
|
Packit |
b099d7 |
* It may be immediately used to enter an index item. This routine
|
|
Packit |
b099d7 |
* is used just once, to create the initial root record. Thereafter,
|
|
Packit |
b099d7 |
* all leaf records are created by splitting and collapsing existing
|
|
Packit |
b099d7 |
* records.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* buffer_return To return pointer to buffer containing new record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS operation succeeded
|
|
Packit |
b099d7 |
* MrmFAILURE some other failure
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_InitRootLeafRecord (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordBufferPtr *buffer_return)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr bufptr ; /* leaf record buffer */
|
|
Packit |
b099d7 |
IDBIndexLeafRecordPtr recptr ; /* leaf record in buffer */
|
|
Packit |
b099d7 |
IDBIndexLeafHdrPtr hdrptr ; /* record header */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Acquire a record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__BM_InitRecord (file_id, 0, IDBrtIndexLeaf, &bufptr) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
recptr = (IDBIndexLeafRecordPtr) bufptr->IDB_record ;
|
|
Packit |
b099d7 |
hdrptr = (IDBIndexLeafHdrPtr) &recptr->leaf_header ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Initialize the record header
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
hdrptr->parent = 0 ;
|
|
Packit |
b099d7 |
hdrptr->index_count = 0 ;
|
|
Packit |
b099d7 |
hdrptr->heap_start = IDBIndexLeafFreeMax ;
|
|
Packit |
b099d7 |
hdrptr->free_bytes = IDBIndexLeafFreeMax ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Successfully initialized
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (bufptr) ;
|
|
Packit |
b099d7 |
*buffer_return = bufptr ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
file_id->index_root = hdrptr->header.record_num ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Idb__INX_InitNodeRecord initializes a new node index record. It
|
|
Packit |
b099d7 |
* creates the initial entry in the record, with its index, data pointer,
|
|
Packit |
b099d7 |
* and pointers to two children records in the B-tree. This entry always
|
|
Packit |
b099d7 |
* becomes the root of the B-tree, since the only occasion on which
|
|
Packit |
b099d7 |
* a node record is created in this way is when a new root is needed.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* buffer_return To return pointer to buffer containing new record
|
|
Packit |
b099d7 |
* index Index for single entry in record
|
|
Packit |
b099d7 |
* data_entry Data entry pointer for data
|
|
Packit |
b099d7 |
* lt_record Record number of B-tree record ordering < the index
|
|
Packit |
b099d7 |
* gt_record Record number of B-tree record ordering > the index
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS operation succeeded
|
|
Packit |
b099d7 |
* MrmFAILURE some other failure
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_InitRootNodeRecord (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordBufferPtr *buffer_return,
|
|
Packit |
b099d7 |
char *index,
|
|
Packit |
b099d7 |
IDBDataHandle data_entry,
|
|
Packit |
b099d7 |
IDBRecordNumber lt_record,
|
|
Packit |
b099d7 |
IDBRecordNumber gt_record)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr bufptr ; /* node record buffer */
|
|
Packit |
b099d7 |
IDBIndexNodeRecordPtr recptr ; /* node record in buffer */
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr hdrptr ; /* record header */
|
|
Packit |
b099d7 |
IDBRecordNumber recno ; /* this buffer's record number */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Acquire a record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__BM_InitRecord (file_id, 0, IDBrtIndexNode, &bufptr) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
recptr = (IDBIndexNodeRecordPtr) bufptr->IDB_record ;
|
|
Packit |
b099d7 |
hdrptr = (IDBIndexNodeHdrPtr) &recptr->node_header ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Initialize the record header
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
hdrptr->parent = 0 ;
|
|
Packit |
b099d7 |
hdrptr->index_count = 0 ;
|
|
Packit |
b099d7 |
hdrptr->heap_start = IDBIndexNodeFreeMax ;
|
|
Packit |
b099d7 |
hdrptr->free_bytes = IDBIndexNodeFreeMax ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Enter the initial entry
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__INX_EnterNodeIndex
|
|
Packit |
b099d7 |
(file_id, bufptr, index, data_entry, lt_record, gt_record) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Successfully initialized
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (bufptr) ;
|
|
Packit |
b099d7 |
*buffer_return = bufptr ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Set the parent pointers in the two child entries.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
recno = _IdbBufferRecordNumber (bufptr) ;
|
|
Packit |
b099d7 |
result = Idb__INX_SetParent (file_id, recno, lt_record) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
result = Idb__INX_SetParent (file_id, recno, gt_record) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Root node successfully created. Update file header.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
file_id->index_root = hdrptr->header.record_num ;
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This routines copies one leaf record into another.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* dst_recptr pointer to record into which to copy
|
|
Packit |
b099d7 |
* src_recptr source record pointer
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
void
|
|
Packit |
b099d7 |
Idb__INX_CopyLeafRecord (IDBIndexLeafRecordPtr dst_recptr,
|
|
Packit |
b099d7 |
IDBIndexLeafRecordPtr src_recptr)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
IDBIndexLeafHdrPtr dst_hdrptr ; /* destination record header */
|
|
Packit |
b099d7 |
IDBIndexLeafHdrPtr src_hdrptr ; /* source record header */
|
|
Packit |
b099d7 |
char *dst_data ; /* data part of dest record */
|
|
Packit |
b099d7 |
char *src_data ; /* data part of source record */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* copy the header, field by field
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
dst_hdrptr = (IDBIndexLeafHdrPtr) &dst_recptr->leaf_header ;
|
|
Packit |
b099d7 |
src_hdrptr = (IDBIndexLeafHdrPtr) &src_recptr->leaf_header ;
|
|
Packit |
b099d7 |
dst_hdrptr->parent = src_hdrptr->parent ;
|
|
Packit |
b099d7 |
dst_hdrptr->index_count = src_hdrptr->index_count ;
|
|
Packit |
b099d7 |
dst_hdrptr->heap_start = src_hdrptr->heap_start ;
|
|
Packit |
b099d7 |
dst_hdrptr->free_bytes = src_hdrptr->free_bytes ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* copy the data area in the record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
dst_data = (char *) dst_recptr->index ;
|
|
Packit |
b099d7 |
src_data = (char *) src_recptr->index ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
UrmBCopy (src_data, dst_data, IDBIndexLeafFreeMax) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This routines copies one node record into another.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* dst_recptr pointer to record into which to copy
|
|
Packit |
b099d7 |
* src_recptr source record pointer
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
void
|
|
Packit |
b099d7 |
Idb__INX_CopyNodeRecord (IDBIndexNodeRecordPtr dst_recptr,
|
|
Packit |
b099d7 |
IDBIndexNodeRecordPtr src_recptr)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr dst_hdrptr ; /* destination record header */
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr src_hdrptr ; /* source record header */
|
|
Packit |
b099d7 |
char *dst_data ; /* data part of dest record */
|
|
Packit |
b099d7 |
char *src_data ; /* data part of source record */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* copy the header, field by field
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
dst_hdrptr = (IDBIndexNodeHdrPtr) &dst_recptr->node_header ;
|
|
Packit |
b099d7 |
src_hdrptr = (IDBIndexNodeHdrPtr) &src_recptr->node_header ;
|
|
Packit |
b099d7 |
dst_hdrptr->parent = src_hdrptr->parent ;
|
|
Packit |
b099d7 |
dst_hdrptr->index_count = src_hdrptr->index_count ;
|
|
Packit |
b099d7 |
dst_hdrptr->heap_start = src_hdrptr->heap_start ;
|
|
Packit |
b099d7 |
dst_hdrptr->free_bytes = src_hdrptr->free_bytes ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* copy the data area in the record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
dst_data = (char *) dst_recptr->index ;
|
|
Packit |
b099d7 |
src_data = (char *) src_recptr->index ;
|
|
Packit |
b099d7 |
UrmBCopy (src_data, dst_data, IDBIndexNodeFreeMax) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This routine collapses a leaf index record as part of splitting
|
|
Packit |
b099d7 |
* a record. Collapsing the record truncates the record contents
|
|
Packit |
b099d7 |
* by removing part of the index vector, re-organizing the string
|
|
Packit |
b099d7 |
* heap to consume minimal space, resetting the heap parameters,
|
|
Packit |
b099d7 |
* and resetting the index count.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* recptr The leaf index record to collapse
|
|
Packit |
b099d7 |
* start First entry in the index vector to be preserved
|
|
Packit |
b099d7 |
* end Last entry in the index vector to be preserved
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
void
|
|
Packit |
b099d7 |
Idb__INX_CollapseLeafRecord (IDBIndexLeafRecordPtr recptr,
|
|
Packit |
b099d7 |
MrmCount start,
|
|
Packit |
b099d7 |
MrmCount end)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
IDBIndexLeafHdrPtr hdrptr ; /* record header */
|
|
Packit |
b099d7 |
int ndx ; /* loop index */
|
|
Packit |
b099d7 |
char *temp_heap ; /* temporary heap */
|
|
Packit |
b099d7 |
char *cur_heap ; /* current heap pointer */
|
|
Packit |
b099d7 |
MrmCount heap_size ; /* # bytes used in temp heap */
|
|
Packit |
b099d7 |
IDBIndexLeafEntryPtr srcvec ; /* source index vector */
|
|
Packit |
b099d7 |
IDBIndexLeafEntryPtr dstvec ; /* destination index vector */
|
|
Packit |
b099d7 |
char *stgbase ; /* base address for string offsets */
|
|
Packit |
b099d7 |
char *ndxstg ; /* current index string */
|
|
Packit |
b099d7 |
MrmCount stgsiz ; /* # bytes for current string */
|
|
Packit |
b099d7 |
MrmCount ndxcnt ; /* # entries in collapsed record */
|
|
Packit |
b099d7 |
MrmCount nfree ; /* # free bytes in collapsed record */
|
|
Packit |
b099d7 |
MrmOffset heap_start ; /* new heap start offset */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Allocate a temporary heap (big enough to hold data area). Copy each
|
|
Packit |
b099d7 |
* string which must be preserved into the temporary heap. The heap
|
|
Packit |
b099d7 |
* is allocated top-to-bottom, and the temporary offsets will be
|
|
Packit |
b099d7 |
* made permanent when the temporary heap is copied into the record.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Copy the surviving part of the index vector while saving the strings.
|
|
Packit |
b099d7 |
* The new offset is set as part of this operation.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
temp_heap = (char *) XtMalloc (IDBIndexLeafFreeMax) ;
|
|
Packit |
b099d7 |
cur_heap = temp_heap ;
|
|
Packit |
b099d7 |
heap_size = 0 ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
hdrptr = (IDBIndexLeafHdrPtr) &recptr->leaf_header ;
|
|
Packit |
b099d7 |
srcvec = &recptr->index[start] ;
|
|
Packit |
b099d7 |
dstvec = &recptr->index[0] ;
|
|
Packit |
b099d7 |
stgbase = (char *) recptr->index ;
|
|
Packit |
b099d7 |
ndxcnt = end - start + 1 ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for ( ndx=0 ; ndx
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
dstvec[ndx].data = srcvec[ndx].data ;
|
|
Packit |
b099d7 |
ndxstg = (char *) stgbase + srcvec[ndx].index_stg ;
|
|
Packit |
b099d7 |
strcpy (cur_heap, ndxstg) ;
|
|
Packit |
b099d7 |
dstvec[ndx].index_stg = (MrmOffset) (cur_heap - temp_heap) ;
|
|
Packit |
b099d7 |
stgsiz = strlen(cur_heap) + 1 ;
|
|
Packit |
b099d7 |
stgsiz = _FULLWORD(stgsiz);
|
|
Packit |
b099d7 |
cur_heap += stgsiz ;
|
|
Packit |
b099d7 |
heap_size += stgsiz ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Compute offsets and sizes, and copy heap into record. Then adjust the
|
|
Packit |
b099d7 |
* offset to allow for the free space.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
hdrptr->index_count = ndxcnt ;
|
|
Packit |
b099d7 |
heap_start = IDBIndexLeafFreeMax - heap_size ;
|
|
Packit |
b099d7 |
hdrptr->heap_start = heap_start ;
|
|
Packit |
b099d7 |
nfree = IDBIndexLeafFreeMax - heap_size - ndxcnt*IDBIndexLeafEntrySize ;
|
|
Packit |
b099d7 |
hdrptr->free_bytes = nfree ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
UrmBCopy (temp_heap, &stgbase[heap_start], heap_size) ;
|
|
Packit |
b099d7 |
for ( ndx=0 ; ndx
|
|
Packit |
b099d7 |
dstvec[ndx].index_stg += heap_start ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
XtFree (temp_heap) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This routine collapses a node index record as part of splitting
|
|
Packit |
b099d7 |
* a record. Collapsing the record truncates the record contents
|
|
Packit |
b099d7 |
* by removing part of the index vector, re-organizing the string
|
|
Packit |
b099d7 |
* heap to consume minimal space, resetting the heap parameters,
|
|
Packit |
b099d7 |
* and resetting the index count.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* The record vector is preserved by moving entires start to end+1.
|
|
Packit |
b099d7 |
* For both records being collapsed, these entries are the correct
|
|
Packit |
b099d7 |
* ones to associate with the collapsed record.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* recptr The node index record to collapse
|
|
Packit |
b099d7 |
* start First entry in the index vector to be preserved
|
|
Packit |
b099d7 |
* end Last entry in the index vector to be preserved
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
void
|
|
Packit |
b099d7 |
Idb__INX_CollapseNodeRecord (IDBIndexNodeRecordPtr recptr,
|
|
Packit |
b099d7 |
MrmCount start,
|
|
Packit |
b099d7 |
MrmCount end)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr hdrptr ; /* record header */
|
|
Packit |
b099d7 |
int ndx ; /* loop index */
|
|
Packit |
b099d7 |
char *temp_heap ; /* temporary heap */
|
|
Packit |
b099d7 |
char *cur_heap ; /* current heap pointer */
|
|
Packit |
b099d7 |
MrmCount heap_size ; /* # bytes used in temp heap */
|
|
Packit |
b099d7 |
IDBIndexNodeEntryPtr srcvec ; /* source index vector */
|
|
Packit |
b099d7 |
IDBIndexNodeEntryPtr dstvec ; /* destination index vector */
|
|
Packit |
b099d7 |
char *stgbase ; /* base address for string offsets */
|
|
Packit |
b099d7 |
char *ndxstg ; /* current index string */
|
|
Packit |
b099d7 |
MrmCount stgsiz ; /* # bytes for current string */
|
|
Packit |
b099d7 |
MrmCount ndxcnt ; /* # entries in collapsed record */
|
|
Packit |
b099d7 |
MrmCount nfree ; /* # free bytes in collapsed record */
|
|
Packit |
b099d7 |
MrmOffset heap_start ; /* new heap start offset */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Allocate a temporary heap (big enough to hold data area). Copy each
|
|
Packit |
b099d7 |
* string which must be preserved into the temporary heap. The heap
|
|
Packit |
b099d7 |
* is allocated top-to-bottom, and the temporary offsets will be
|
|
Packit |
b099d7 |
* made permanent when the temporary heap is copied into the record.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Copy the surviving part of the index vector while saving the strings.
|
|
Packit |
b099d7 |
* The new offset is set as part of this operation.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
temp_heap = (char *) XtMalloc (IDBIndexNodeFreeMax) ;
|
|
Packit |
b099d7 |
cur_heap = temp_heap ;
|
|
Packit |
b099d7 |
heap_size = 0 ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
hdrptr = (IDBIndexNodeHdrPtr) &recptr->node_header ;
|
|
Packit |
b099d7 |
srcvec = &recptr->index[start] ;
|
|
Packit |
b099d7 |
dstvec = &recptr->index[0] ;
|
|
Packit |
b099d7 |
stgbase = (char *) recptr->index ;
|
|
Packit |
b099d7 |
ndxcnt = end - start + 1 ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for ( ndx=0 ; ndx
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
dstvec[ndx].data = srcvec[ndx].data ;
|
|
Packit |
b099d7 |
dstvec[ndx].LT_record = srcvec[ndx].LT_record ;
|
|
Packit |
b099d7 |
dstvec[ndx].GT_record = srcvec[ndx].GT_record ;
|
|
Packit |
b099d7 |
ndxstg = (char *) stgbase + srcvec[ndx].index_stg ;
|
|
Packit |
b099d7 |
strcpy (cur_heap, ndxstg) ;
|
|
Packit |
b099d7 |
dstvec[ndx].index_stg = (MrmOffset) (cur_heap - temp_heap) ;
|
|
Packit |
b099d7 |
stgsiz = strlen(cur_heap) + 1 ;
|
|
Packit |
b099d7 |
stgsiz = _FULLWORD(stgsiz);
|
|
Packit |
b099d7 |
cur_heap += stgsiz ;
|
|
Packit |
b099d7 |
heap_size += stgsiz ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Compute offsets and sizes, and copy heap into record. Then adjust the
|
|
Packit |
b099d7 |
* offset to allow for the free space.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
hdrptr->index_count = ndxcnt ;
|
|
Packit |
b099d7 |
heap_start = IDBIndexNodeFreeMax - heap_size ;
|
|
Packit |
b099d7 |
hdrptr->heap_start = heap_start ;
|
|
Packit |
b099d7 |
nfree = IDBIndexNodeFreeMax - heap_size - ndxcnt*IDBIndexNodeEntrySize ;
|
|
Packit |
b099d7 |
hdrptr->free_bytes = nfree ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
UrmBCopy (temp_heap, &stgbase[heap_start], heap_size) ;
|
|
Packit |
b099d7 |
for ( ndx=0 ; ndx
|
|
Packit |
b099d7 |
dstvec[ndx].index_stg += heap_start ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
XtFree (temp_heap) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This routine confirms that there is enough space in an index
|
|
Packit |
b099d7 |
* node for a new entry. If there is not, it splits the entry
|
|
Packit |
b099d7 |
* and tells the caller to retry.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* buffer Buffer containing the node record to be checked.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS There is enough space
|
|
Packit |
b099d7 |
* MrmINDEX_RETRY Node was split, caller must retry
|
|
Packit |
b099d7 |
* MrmFAILURE Some other failure
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_ConfirmNodeSpace (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordBufferPtr buffer)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBIndexNodeRecordPtr recptr ; /* node record in buffer */
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr hdrptr ; /* record header */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Initialize pointers into the record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
recptr = (IDBIndexNodeRecordPtr) buffer->IDB_record ;
|
|
Packit |
b099d7 |
hdrptr = (IDBIndexNodeHdrPtr) &recptr->node_header ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Check the size. If there is enough, OK. Else split this record and
|
|
Packit |
b099d7 |
* return a retry.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if ( hdrptr->free_bytes >= IDBIndexNodeEntryMax ) return MrmSUCCESS ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
result = Idb__INX_SplitNodeRecord (file_id, buffer) ;
|
|
Packit |
b099d7 |
if ( result == MrmSUCCESS ) result = MrmINDEX_RETRY ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return result ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This routine sets the parent pointer in a child record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* parent_record Parent record number
|
|
Packit |
b099d7 |
* child_record Child record number
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* MrmSUCCESS operation succeeded
|
|
Packit |
b099d7 |
* MrmFAILURE some failure occurred
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_SetParent (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordNumber parent_record,
|
|
Packit |
b099d7 |
IDBRecordNumber child_record)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr buffer ; /* buffer for child record */
|
|
Packit |
b099d7 |
IDBIndexLeafRecordPtr leafrec ; /* index leaf record */
|
|
Packit |
b099d7 |
IDBIndexLeafHdrPtr leafhdr ; /* index leaf header */
|
|
Packit |
b099d7 |
IDBIndexNodeRecordPtr noderec ; /* index node record */
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr nodehdr ; /* index node header */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Get the child record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__BM_GetRecord (file_id, child_record, &buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
if ( ! Idb__INX_ValidRecord(buffer) )
|
|
Packit |
b099d7 |
return Urm__UT_Error ("Idb__INX_SetParent", _MrmMMsg_0010,
|
|
Packit |
b099d7 |
file_id, NULL, MrmBAD_RECORD) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Set up pointers and set parent based on record type
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
switch ( _IdbBufferRecordType (buffer) )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
case IDBrtIndexLeaf:
|
|
Packit |
b099d7 |
leafrec = (IDBIndexLeafRecordPtr) buffer->IDB_record ;
|
|
Packit |
b099d7 |
leafhdr = (IDBIndexLeafHdrPtr) &leafrec->leaf_header ;
|
|
Packit |
b099d7 |
if ( leafhdr->parent != parent_record )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
leafhdr->parent = parent_record ;
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (buffer) ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
case IDBrtIndexNode:
|
|
Packit |
b099d7 |
noderec = (IDBIndexNodeRecordPtr) buffer->IDB_record ;
|
|
Packit |
b099d7 |
nodehdr = (IDBIndexNodeHdrPtr) &noderec->node_header ;
|
|
Packit |
b099d7 |
if ( nodehdr->parent != parent_record )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
nodehdr->parent = parent_record ;
|
|
Packit |
b099d7 |
Idb__BM_MarkModified (buffer) ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
default:
|
|
Packit |
b099d7 |
return MrmBAD_RECORD ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
*++
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* PROCEDURE DESCRIPTION:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This routine guarantees that the children of a node record have
|
|
Packit |
b099d7 |
* a correct parent pointer.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FORMAL PARAMETERS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* file_id Open IDB file
|
|
Packit |
b099d7 |
* p_record Record number of parent record
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT INPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* IMPLICIT OUTPUTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* FUNCTION VALUE:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* SIDE EFFECTS:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This routine uses MarkActivity to guarantee that the parent
|
|
Packit |
b099d7 |
* record remains in memory.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*--
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
Cardinal
|
|
Packit |
b099d7 |
Idb__INX_FixNodeChildren (IDBFile file_id,
|
|
Packit |
b099d7 |
IDBRecordNumber p_record)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Local variables
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
Cardinal result ; /* function results */
|
|
Packit |
b099d7 |
IDBRecordBufferPtr buffer ; /* parent node buffer */
|
|
Packit |
b099d7 |
IDBIndexNodeRecordPtr recptr ; /* parent node record in buffer */
|
|
Packit |
b099d7 |
IDBIndexNodeHdrPtr hdrptr ; /* parent record header */
|
|
Packit |
b099d7 |
int ndx ; /* loop index */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Get the parent record
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
result = Idb__BM_GetRecord (file_id, p_record, &buffer) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
if ( ! Idb__INX_ValidNode(buffer) )
|
|
Packit |
b099d7 |
return Urm__UT_Error ("Idb__INX_FixNodeChildren", _MrmMMsg_0010,
|
|
Packit |
b099d7 |
file_id, NULL, MrmBAD_RECORD) ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Bind pointers into the record, and set each child's parent pointer
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
recptr = (IDBIndexNodeRecordPtr) buffer->IDB_record ;
|
|
Packit |
b099d7 |
hdrptr = (IDBIndexNodeHdrPtr) &recptr->node_header ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for ( ndx=0 ; ndx<hdrptr->index_count ; ndx++ )
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = Idb__INX_SetParent (file_id, p_record,
|
|
Packit |
b099d7 |
recptr->index[ndx].LT_record) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
result = Idb__INX_SetParent (file_id, p_record,
|
|
Packit |
b099d7 |
recptr->index[ndx].GT_record) ;
|
|
Packit |
b099d7 |
if ( result != MrmSUCCESS ) return result ;
|
|
Packit |
b099d7 |
Idb__BM_MarkActivity (buffer) ;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Successfully modified
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
return MrmSUCCESS ;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|