//--------------------------------------------------------------------
// Microsoft OLE DB Sample Provider
// (C) Copyright 1994 - 1996 Microsoft Corporation. All Rights Reserved.
//
// @module hashtbl.cpp | Hashing routines for row manipulation.
//
//
#include "headers.h"
#include "hashtbl.h"
//--------------------------------------------------------------------
// GetNextSlots
//
// @func Allocates a contiguous block of the required number of slots.
//
// @rdesc Returns one of the following values:
// @flag S_OK | slot allocate succeeded
// @flag E_OUTOFMEMORY | slot allocation failed because of memory allocation
// problem
///
HRESULT GetNextSlots
(
PLSTSLOT plstslot, //@parm IN | slot list
ULONG cslot, //@parm IN | needed block size (in slots)
ULONG* pislot //@parm IN | handle of the first slot in the returned block
)
{
ULONG islot, dslot;
PSLOT pslot, pslotTmp;
ULONG cbCommit;
HRESULT hr;
if (plstslot->islotRov)
plstslot->islotRov = ((PSLOT) & plstslot->rgslot[plstslot->islotRov *plstslot->cbSlot])->islotNext;
else
plstslot->islotRov = plstslot->islotFirst;
islot = plstslot->islotRov;
while (islot)
{
if (((PSLOT) & plstslot->rgslot[islot *plstslot->cbSlot])->cslot >= cslot)
break;
islot = ((PSLOT) & plstslot->rgslot[islot *plstslot->cbSlot])->islotNext;
}
if (islot == 0)
{
islot = plstslot->islotFirst;
while (islot != plstslot->islotRov)
{
if (((PSLOT) & plstslot->rgslot[islot *plstslot->cbSlot])->cslot >= cslot)
break;
islot = ((PSLOT) & plstslot->rgslot[islot *plstslot->cbSlot])->islotNext;
}
if (islot == plstslot->islotRov)
islot = 0;
}
if (islot == 0)
{
cbCommit = ((cslot *plstslot->cbSlot) / plstslot->cbPage + 1) *plstslot->cbPage;
if ((plstslot->cbCommitCurrent + cbCommit) > plstslot->cbCommitMax
|| VirtualAlloc((VOID *) ((BYTE *) plstslot + plstslot->cbCommitCurrent),
cbCommit,
MEM_COMMIT,
PAGE_READWRITE ) == NULL)
return ResultFromScode( E_OUTOFMEMORY );
islot = (ULONG) ((plstslot->cbCommitCurrent + plstslot->cbExtra) / plstslot->cbSlot);
dslot = ((cbCommit + plstslot->cbslotLeftOver) / plstslot->cbSlot);
if ((plstslot->pbitsSlot)->IsSlotSet( islot - 1 ) != NOERROR)
{
if ((plstslot->pbitsSlot)->FindSet( islot - 1, plstslot->islotMin, &islot ) == NOERROR)
islot++;
else
islot = plstslot->islotMin;
pslot = (PSLOT) & plstslot->rgslot[islot *plstslot->cbSlot];
pslot->cslot += dslot;
DecoupleSlot( plstslot, islot, pslot );
}
else
{
pslot = (PSLOT) ((BYTE *) plstslot + plstslot->cbCommitCurrent - plstslot->cbslotLeftOver);
pslot->cslot = dslot;
}
pslot->islotNext = plstslot->islotFirst;
pslot->islotPrev = 0;
plstslot->islotMax += dslot;
plstslot->islotFirst = islot;
plstslot->cbslotLeftOver = (cbCommit + plstslot->cbslotLeftOver) % plstslot->cbSlot;
plstslot->cbCommitCurrent += cbCommit;
if (pslot->islotNext)
((PSLOT) & plstslot->rgslot[pslot->islotNext *plstslot->cbSlot])->islotPrev = islot;
islot = plstslot->islotFirst;
}
pslot = (PSLOT) & plstslot->rgslot[islot *plstslot->cbSlot];
DecoupleSlot( plstslot, islot, pslot );
if (pslot->cslot > cslot)
{
pslotTmp = (PSLOT) & plstslot->rgslot[ (islot + cslot) *plstslot->cbSlot];
pslotTmp->cslot = pslot->cslot - cslot;
AddSlotToList( plstslot, islot + cslot, pslotTmp );
}
if (FAILED( hr = (plstslot->pbitsSlot)->SetSlots( islot, islot + cslot - 1 )))
return hr;
if (pislot)
*pislot = islot;
return ResultFromScode( S_OK );
}
//--------------------------------------------------------------------
// DecoupleSlot
//
// @func Decouples a slot from the list of free slots
//
// @rdesc NONE
//
VOID DecoupleSlot
(
PLSTSLOT plstslot, //@parm IN | slot list
ULONG islot, //@parm IN | slot handle to decouple
PSLOT pslot //@parm IN | pointer to the slot header
)
{
if (pslot->islotNext)
((PSLOT) & plstslot->rgslot[pslot->islotNext *plstslot->cbSlot])->islotPrev = pslot->islotPrev;
if (pslot->islotPrev)
((PSLOT) & plstslot->rgslot[pslot->islotPrev *plstslot->cbSlot])->islotNext = pslot->islotNext;
else
plstslot->islotFirst = pslot->islotNext;
if (islot == plstslot->islotRov)
plstslot->islotRov = pslot->islotNext;
}
//--------------------------------------------------------------------
// AddSlotToList
//
// @func Adds a slot to the list of free slots
//
// @rdesc NONE
//
VOID AddSlotToList
(
PLSTSLOT plstslot, //@parm IN | slot list
ULONG islot, //@parm IN | slot handle
PSLOT pslot //@parm IN | pointer to the slot header
)
{
pslot->islotPrev = 0;
pslot->islotNext = plstslot->islotFirst;
plstslot->islotFirst = islot;
if (pslot->islotNext)
((PSLOT) & plstslot->rgslot[pslot->islotNext *plstslot->cbSlot])->islotPrev = islot;
}
//--------------------------------------------------------------------
// ReleaseSlots
//
// @func Releases a contiguous block of slots.
//
// @rdesc Returns one of the following values:
// @flag S_OK | method succeeded
//
HRESULT ReleaseSlots
(
PLSTSLOT plstslot, //@parm IN | slot list
ULONG islot, //@parm IN | handle of first slot to release
ULONG cslot //@parm IN | count of slots to release
)
{
PSLOT pslot, pslotTmp;
(plstslot->pbitsSlot)->ResetSlots( islot, islot + cslot - 1 );
pslot = (PSLOT) & plstslot->rgslot[islot *plstslot->cbSlot];
pslot->cslot = cslot;
if (islot > plstslot->islotMin && (plstslot->pbitsSlot)->IsSlotSet( islot - 1 ) != NOERROR)
{
if ((plstslot->pbitsSlot)->FindSet( islot - 1, plstslot->islotMin, &islot ) == NOERROR)
islot++;
else
islot = plstslot->islotMin;
pslot = (PSLOT) & plstslot->rgslot[islot *plstslot->cbSlot];
pslot->cslot += cslot;
DecoupleSlot( plstslot, islot, pslot );
}
if ((islot + cslot) <= plstslot->islotMax && (plstslot->pbitsSlot)->IsSlotSet( islot + cslot ) != NOERROR)
{
pslotTmp = (PSLOT) & plstslot->rgslot[ (islot + cslot) *plstslot->cbSlot];
pslot->cslot += pslotTmp->cslot;
DecoupleSlot( plstslot, (islot + cslot), pslotTmp );
}
AddSlotToList( plstslot, islot, pslot );
return ResultFromScode( S_OK );
}
//--------------------------------------------------------------------
// InitializeSlotList
//
// @func Initializes the Slot List object
//
// @rdesc Did the initialization succeed
// @flag S_OK | method succeeded
// @flag E_OUTOFMEMORY | failed, out of memory
//
//
HRESULT InitializeSlotList
(
ULONG cslotMax, //@parm IN | max number of slots
ULONG cbSlot, //@parm IN | slot size (row buffer size)
ULONG cbPage, //@parm IN | page size
LPBITARRAY pbits, //@parm IN |
PLSTSLOT* pplstslot, //@parm OUT | pointer to slot list
BYTE** prgslot //@parm OUT |
)
{
ULONG cbReserve;
BYTE *pbAlloc;
ULONG cbCommitFirst;
PLSTSLOT plstslot;
ULONG cslot, islotFirst;
PSLOT pslot;
if (cbPage == 0)
{
SYSTEM_INFO sysinfo;
GetSystemInfo( &sysinfo );
cbPage = sysinfo.dwPageSize;
}
cbReserve = ((cslotMax *cbSlot + sizeof( LSTSLOT )) / cbPage + 1) *cbPage;
pbAlloc = (BYTE *) VirtualAlloc( NULL, cbReserve, MEM_RESERVE, PAGE_READWRITE );
if (pbAlloc == NULL)
return ResultFromScode( E_OUTOFMEMORY );
cbCommitFirst = (sizeof( LSTSLOT ) / cbPage + 1) * cbPage;
plstslot = (PLSTSLOT) VirtualAlloc( pbAlloc, cbCommitFirst, MEM_COMMIT, PAGE_READWRITE );
if (plstslot == NULL)
{
VirtualFree((VOID *) pbAlloc, 0, MEM_RELEASE );
return ResultFromScode( E_OUTOFMEMORY );
}
plstslot->cbSlot = cbSlot;
plstslot->cbPage = cbPage;
plstslot->cbCommitCurrent = cbCommitFirst;
plstslot->cbCommitMax = cbReserve;
plstslot->pbitsSlot = pbits;
if (cbSlot <= 2*sizeof( LSTSLOT ))
{
islotFirst = sizeof( LSTSLOT ) / cbSlot + ((sizeof( LSTSLOT ) % cbSlot) ? 1 : 0);
plstslot->cbExtra = 0;
cslot = (ULONG) ((cbCommitFirst / cbSlot) - islotFirst);
plstslot->cbslotLeftOver = cbCommitFirst - cbSlot * (cslot + islotFirst);
}
else
{
islotFirst = 1;
plstslot->cbExtra = cbSlot - sizeof( LSTSLOT );
cslot = (cbCommitFirst - sizeof( LSTSLOT )) / cbSlot;
plstslot->cbslotLeftOver = cbCommitFirst - sizeof( LSTSLOT ) - cslot*cbSlot;
}
plstslot->rgslot = ((BYTE *) plstslot - plstslot->cbExtra);
if (cslot)
{
plstslot->islotFirst = islotFirst;
pslot = (PSLOT) & plstslot->rgslot[islotFirst *plstslot->cbSlot];
pslot->cslot = cslot;
pslot->islotNext = 0;
pslot->islotPrev = 0;
}
else
plstslot->islotFirst = 0;
plstslot->islotMin = islotFirst;
plstslot->islotMax = islotFirst + cslot - 1;
plstslot->islotRov = plstslot->islotFirst;
*pplstslot = plstslot;
*prgslot = plstslot->rgslot;
return ResultFromScode( S_OK );
}
//--------------------------------------------------------------------
// ResetSlotList
//
// @func Restore slot list to newly-initiated state
//
// @rdesc
// @flag S_OK | method succeeded
//
HRESULT ResetSlotList
(
PLSTSLOT plstslot //@parm IN | slot list
)
{
ULONG cslot;
PSLOT pslot;
cslot = (plstslot->islotMax >= plstslot->islotMin) ? (plstslot->islotMax - plstslot->islotMin + 1) : 0;
if (cslot)
{
plstslot->islotFirst = plstslot->islotMin;
pslot = (PSLOT) & plstslot->rgslot[plstslot->islotFirst *plstslot->cbSlot];
pslot->cslot = cslot;
pslot->islotNext = 0;
pslot->islotPrev = 0;
}
else
plstslot->islotFirst = 0;
plstslot->islotRov = plstslot->islotFirst;
return ResultFromScode( S_OK );
}
//--------------------------------------------------------------------
// ReleaseSlotList
//
// @func Free slot list's memory
//
// @rdesc
// @flag S_OK | method succeeded
//
HRESULT ReleaseSlotList
(
PLSTSLOT plstslot //@parm IN | slot list
)
{
if (plstslot == NULL)
return NOERROR;
if (plstslot->cbCommitCurrent)
VirtualFree((VOID *) plstslot, plstslot->cbCommitCurrent, MEM_DECOMMIT );
VirtualFree((VOID *) plstslot, 0, MEM_RELEASE );
return ResultFromScode( S_OK );
}