/***************************************************************************** * * * BTKTEXT.C * * * * Copyright (C) Microsoft Corporation 1997. * * All Rights reserved. * * * ****************************************************************************** * * * Module Intent * * * * Functions for external sort keys. * * * ****************************************************************************** * * * Current Owner: BillA * * * *****************************************************************************/ static char s_aszModule[] = __FILE__; /* For error report */ #include #ifdef _MAC #include #endif #include #include #include #include #include #include #include #include #include <_mvutil.h> #include "common.h" /*************************************************************************** * * @doc INTERNAL * * @func BK FAR PASCAL | BkScanExtSortInternal | * Scan an internal node for an external sort key and return child BK. * * @parm BK | bk | * BK of internal node to scan * * @parm KEY | key | * key to search for * * @parm SHORT | wLevel | * level of btree bk lives on * * @parm QBTHR | qbthr | * btree header containing cache, and btree specs * * @parm QW | qiKey | * address of an int or NULL to not get it * * @rdesc bk of subtree that might contain key; bkNil on error * args OUT: qbthr->qCache - bk's block will be cached * qiKey - index into rgbBlock of first key >= key * * Side Effects: bk's block will be cached * ***************************************************************************/ PUBLIC BK FAR PASCAL BkScanExtSortInternal(BK bk, KEY key, SHORT wLevel, QBTHR qbthr, QW qiKey, LPVOID lpv) { QCB qcb; // Pointer to cache block QB qb; // Pointer to block buffer SHORT cKeys; // Number of keys in the block if ((qcb = QFromBk(bk, wLevel, qbthr, (PHRESULT) lpv)) == NULL) { return bkNil; } qb = qcb->db.rgbBlock; // Block buffer cKeys = qcb->db.cKeys; // Number of keys in the block bk = (BK)GETLONG(qb); // Get leaf block number qb += sizeof(DWORD); while (cKeys-- > 0) { LONG lResult; // NOTE (billa): This won't work on the Mac unless a method is added // to IITSortKey to swap dwords and words if necessary. Mikkya // made an explicit decision to omit this from the initial // version of IITSortKey (6/4/97). if (qbthr->pITSortKey == NULL || FAILED(qbthr->pITSortKey->Compare((LPCVOID) key, (LPCVOID) qb, &lResult, NULL))) { return bkNil; } if (lResult >= 0) { DWORD cbKey; if (qbthr->pITSortKey == NULL || FAILED(qbthr->pITSortKey->GetSize((LPCVOID) qb, &cbKey))) { return bkNil; } qb += cbKey; bk = (BK)GETLONG(qb); qb += sizeof(DWORD); } else break; } if (qiKey != NULL) { *qiKey = (WORD)(qb - (QB)qcb->db.rgbBlock); } return bk; } /*************************************************************************** * * @doc INTERNAL * * @func HRESULT FAR PASCAL | RcScanExtSortLeaf | * Scan a leaf node for an external sort key and copy the associated data. * * @parm BK | bk | * the leaf block * * @parm KEY | key | * the key we're looking for * * @parm SHORT | wLevel | * the level of leaves (unnecessary) * * @parm QBTHR | qbthr | * the btree header * * @parm QV | qRec | * if found, record gets copied into this buffer * * @parm QTPOS | qbtpos | * pos of first key >= key goes here * * @rdesc ERR_SUCESS if found; ERR_NOTEXIST if not found * If we are scanning for a key greater than any key in this * block, the pos returned will be invalid and will point just * past the last valid key in this block. * ***************************************************************************/ PUBLIC HRESULT FAR PASCAL RcScanExtSortLeaf(BK bk, KEY key, SHORT wLevel, QBTHR qbthr, QV qRec, QBTPOS qbtpos) { QCB qcb; QB qb; HRESULT rc; SHORT i; SHORT cKeys; // Number of keys in the block QB qbSaved = NULL; DWORD cbLength, cbLengthSaved = 0; HRESULT errb; if ((qcb = QFromBk(bk, wLevel, qbthr, &errb)) == NULL) { return errb; } rc = E_NOTEXIST; qb = qcb->db.rgbBlock + 2 * sizeof(BK); cKeys = qcb->db.cKeys; for (i= 0; i < cKeys; i++) { LONG lResult; // NOTE (billa): This won't work on the Mac unless a method is added // to IITSortKey to swap dwords and words if necessary. Mikkya // made an explicit decision to omit this from the initial // version of IITSortKey (6/4/97). if (qbthr->pITSortKey == NULL || FAILED(qbthr->pITSortKey->GetSize((LPCVOID) qb, &cbLength)) || FAILED(qbthr->pITSortKey->Compare((LPCVOID) key, (LPCVOID) qb, &lResult, NULL))) { return rc; } if (lResult > 0) /* still looking for key */ { qb += cbLength; qb += CbSizeRec(qb, qbthr); } else if (lResult < 0) /* key not found */ { break; } else /* matched the key */ { if (qRec != NULL) { qb += cbLength; QVCOPY(qRec, qb, (LONG)CbSizeRec(qb, qbthr)); } rc = S_OK; break; } } if (qbtpos != NULL) { qbtpos->bk = bk; qbtpos->cKey = i; qbtpos->iKey = (int)(qb - (QB)qcb->db.rgbBlock); } return rc; } PUBLIC VOID EXPORT_API PASCAL FAR BtreeSetExtSort(HBT hbt, IITSortKey *pITSortKey) { if (hbt != NULL && pITSortKey != NULL) { QBTHR qbthr; qbthr = (QBTHR) _GLOBALLOCK(hbt); if (qbthr->pITSortKey != NULL) qbthr->pITSortKey->Release(); (qbthr->pITSortKey = pITSortKey)->AddRef(); _GLOBALUNLOCK(hbt); } else { ITASSERT(FALSE); } } PUBLIC VOID EXPORT_API PASCAL FAR BtreeGetExtSort(HBT hbt, IITSortKey **ppITSortKey) { if (ppITSortKey != NULL) { // Set to NULL in case we can't set it properly because the hbt is NULL. *ppITSortKey = NULL; if (hbt != NULL) { QBTHR qbthr; qbthr = (QBTHR) _GLOBALLOCK(hbt); if ((*ppITSortKey = qbthr->pITSortKey) != NULL) (*ppITSortKey)->AddRef(); _GLOBALUNLOCK(hbt); } else { ITASSERT(FALSE); } } else { ITASSERT(FALSE); } } /* EOF */