mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
5.2 KiB
226 lines
5.2 KiB
/*****************************************************************************
|
|
* *
|
|
* BTMAPRD.C *
|
|
* *
|
|
* Copyright (C) Microsoft Corporation 1989, 1990-1994 *
|
|
* All Rights reserved. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Module Intent *
|
|
* *
|
|
* Routines to read btree map files. *
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "help.h"
|
|
#pragma hdrstop
|
|
|
|
// #include "inc\btpriv.h"
|
|
|
|
/***************************************************************************\
|
|
*
|
|
- Function: HmapbtOpenHfs( hfs, szName )
|
|
-
|
|
* Purpose: Returns an HMAPBT for the btree map named szName.
|
|
*
|
|
* ASSUMES
|
|
* args IN: hfs - file system wherein lives the btree map file
|
|
* szName - name of the btree map file
|
|
*
|
|
* PROMISES
|
|
* returns: NULL on error (call RcGetBtreeError()); or a valid HMAPBT.
|
|
* +++
|
|
*
|
|
* Method: Opens the file, allocates a hunk of memory, reads the
|
|
* file into the memory, and closes the file.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HMAPBT STDCALL HmapbtOpenHfs(HFS hfs, LPCSTR szName)
|
|
{
|
|
HF hf;
|
|
HMAPBT hmapbt;
|
|
QMAPBT qmapbt;
|
|
LONG lcb;
|
|
|
|
if (hfs == NULL) {
|
|
rcBtreeError = rcBadHandle;
|
|
return NULL;
|
|
}
|
|
|
|
hf = HfOpenHfs(hfs, (LPSTR) szName, fFSOpenReadOnly);
|
|
if (hf == NULL) {
|
|
rcBtreeError = RcGetFSError();
|
|
return NULL;
|
|
}
|
|
lcb = LcbSizeHf(hf);
|
|
#ifdef _X86_
|
|
hmapbt = GhAlloc(GPTR, lcb);
|
|
#else
|
|
hmapbt = GhAlloc(GPTR, (lcb+2)*2); // MIPS, word padding inserted
|
|
#endif
|
|
if (hmapbt != NULL) {
|
|
qmapbt = (QMAPBT) PtrFromGh(hmapbt);
|
|
LSeekHf(hf, 0L, wFSSeekSet);
|
|
if (LcbReadHf(hf, qmapbt, lcb) != lcb) {
|
|
rcBtreeError = RcGetFSError();
|
|
FreeGh(hmapbt);
|
|
hmapbt = NULL;
|
|
}
|
|
#ifndef _X86_
|
|
else { // SDFF translation:
|
|
LcbMapSDFF( ISdffFileIdHf( hf) , SE_MAPBT, qmapbt, qmapbt);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
rcBtreeError = rcOutOfMemory;
|
|
|
|
RcCloseHf(hf);
|
|
return hmapbt;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
- Function: RcCloseHmapbt( hmapbt )
|
|
-
|
|
* Purpose: Get rid of a btree map.
|
|
*
|
|
* ASSUMES
|
|
* args IN: hmapbt - handle to the btree map
|
|
*
|
|
* PROMISES
|
|
* returns: rc
|
|
* args OUT: hmapbt - no longer valid
|
|
* +++
|
|
*
|
|
* Method: Free the memory.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
RC STDCALL RcCloseHmapbt(HMAPBT hmapbt)
|
|
{
|
|
if (hmapbt != NULL) {
|
|
FreeGh(hmapbt);
|
|
return rcSuccess;
|
|
}
|
|
else
|
|
return rcBtreeError = rcBadHandle;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
- Function: RcIndexFromKeyHbt( hbt, hmapbt, ql, key )
|
|
-
|
|
* Purpose:
|
|
*
|
|
* ASSUMES
|
|
* args IN: hbt - a btree handle
|
|
* hmapbt - map to hbt
|
|
* key - key
|
|
* globals IN:
|
|
* state IN:
|
|
*
|
|
* PROMISES
|
|
* returns: rc
|
|
* args OUT: ql - gives you the ordinal of the key in the btree
|
|
* (i.e. key is the (*ql)th in the btree)
|
|
* +++
|
|
*
|
|
* Method: Looks up the key, uses the btpos and the hmapbt to
|
|
* determine the ordinal.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
RC STDCALL RcIndexFromKeyHbt(HBT hbt, HMAPBT hmapbt, QL ql, KEY key)
|
|
{
|
|
BTPOS btpos;
|
|
QMAPBT qmapbt;
|
|
int i;
|
|
|
|
if ((hbt == NULL) || (hmapbt == NULL))
|
|
return rcBtreeError = rcBadHandle;
|
|
|
|
qmapbt = (QMAPBT) PtrFromGh(hmapbt);
|
|
if (qmapbt->cTotalBk == 0) {
|
|
return rcBtreeError = rcFailure;
|
|
}
|
|
|
|
RcLookupByKey(hbt, key, &btpos, NULL); //???? return code ????*/
|
|
|
|
for (i = 0; i < qmapbt->cTotalBk; i++) {
|
|
if (qmapbt->table[i].bk == btpos.bk) break;
|
|
}
|
|
if (i == qmapbt->cTotalBk) {
|
|
|
|
// Something is terribly wrong, if we are here
|
|
|
|
return rcBtreeError = rcFailure;
|
|
}
|
|
|
|
*ql = qmapbt->table[i].cPreviousKeys + btpos.cKey;
|
|
return rcBtreeError = rcSuccess;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
- Function: RcKeyFromIndexHbt( hbt, hmapbt, key, li )
|
|
-
|
|
* Purpose: Gets the (li)th key from a btree.
|
|
*
|
|
* ASSUMES
|
|
* args IN: hbt - btree handle
|
|
* hmapbt - map to the btree
|
|
* li - ordinal
|
|
*
|
|
* PROMISES
|
|
* returns: rc
|
|
* args OUT: key - (li)th key copied here on success
|
|
* +++
|
|
*
|
|
* Method: We roll our own btpos using the hmapbt, then use
|
|
* RcLookupByPos() to get the key.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
RC STDCALL RcKeyFromIndexHbt(HBT hbt, HMAPBT hmapbt, KEY key, LONG li)
|
|
{
|
|
BTPOS btpos;
|
|
BTPOS btposNew;
|
|
QMAPBT qmapbt;
|
|
int i;
|
|
LONG liDummy;
|
|
|
|
if ((hbt == NULL) || (hmapbt == NULL))
|
|
return rcBtreeError = rcBadHandle;
|
|
|
|
/*
|
|
* Given index N, get block having greatest PreviousKeys < N. Use
|
|
* linear search for now.
|
|
*/
|
|
|
|
qmapbt = (QMAPBT) PtrFromGh( hmapbt );
|
|
if (qmapbt->cTotalBk == 0)
|
|
return rcBtreeError = rcFailure;
|
|
|
|
for (i = 0;; i++) {
|
|
if (i + 1 >= qmapbt->cTotalBk)
|
|
break;
|
|
if (qmapbt->table[i + 1].cPreviousKeys >= li)
|
|
break;
|
|
}
|
|
|
|
btpos.bk = qmapbt->table[i].bk;
|
|
btpos.cKey = 0;
|
|
btpos.iKey = 2 * sizeof(BK); // start at the zero-th key
|
|
|
|
// Scan the block for the n-th key
|
|
|
|
if (RcOffsetPos(hbt, &btpos, (LONG) (li - qmapbt->table[i].cPreviousKeys),
|
|
&liDummy, &btposNew) != rcSuccess)
|
|
return rcBtreeError = rcNoExists;
|
|
|
|
return RcLookupByPos(hbt, &btposNew, key, NULL);
|
|
}
|