windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/irtl/svmap/svmap.cpp

305 lines
7 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995-1996 Microsoft Corporation
Module Name :
svmap.cpp
Abstract:
Provides name/id mapping for server variables. Used
to allow server variable values to be cached by out
of process applications.
Author:
Taylor Weiss ( TaylorW ) 19-Apr-1999
Environment:
Project:
w3svc.dll private\inet\iis\svcs\w3\server
wam.dll private\inet\iis\svcs\wam\object
Functions Exported:
Revision History:
--*/
#include <windows.h>
#include <dbgutil.h>
#include <svmap.h>
// Define a table of name, len pairs for each cachable server variable
#define DEFINE_SV( token ) { #token, sizeof(#token) - 1 },
SV_CACHE_MAP::SV_NAME
SV_CACHE_MAP::sm_rgNames[] =
{
ALL_SERVER_VARIABLES()
};
#undef DEFINE_SV
BOOL
SV_CACHE_MAP::Initialize( VOID )
/*++
Routine Description:
Fills our hash table with name, id pairs.
--*/
{
BOOL fInitialized = TRUE;
DWORD dwHashValue;
for( int i = 0; i < SV_COUNT; ++i )
{
dwHashValue = HashString( FindName(i) );
DBG_ASSERT( dwHashValue < TABLE_SIZE );
// It really isn't bad if we collide, it just means that
// this particular server variable will not be cachable
DBG_REQUIRE( m_rgHashTable[dwHashValue].InsertValue( i ) );
}
return fInitialized;
}
BOOL
SV_CACHE_MAP::FindOrdinal(
IN LPCSTR pszName,
IN INT cchName,
OUT DWORD * pdwOrdinal
) const
/*++
Routine Description:
Lookup the server variable specified by name and return it's
ordinal if found.
NOTE - We should provide method that doesn't require the
length!
Return Value
FALSE == Not found
TRUE == Found - pdwOrdinal contains the server variable id.
--*/
{
BOOL fFoundIt = FALSE;
DBG_ASSERT( pdwOrdinal );
DWORD dwHashValue = HashString(pszName);
const HASH_TABLE_ENTRY &hte = m_rgHashTable[dwHashValue];
if( !hte.IsSlotEmpty(0) )
{
// Hashed to a non empty entry
if( hte.IsSlotEmpty(1) )
{
// It's the only one.
*pdwOrdinal = hte.GetSlotValue(0);
fFoundIt = StringMatches( pszName, cchName, *pdwOrdinal );
}
else
{
// Collision, need to compare strings with all
// the non empty slots or until we get a hit
DBG_ASSERT( !hte.IsSlotEmpty(0) );
DBG_ASSERT( !hte.IsSlotEmpty(1) );
if( StringMatches(pszName, cchName, hte.GetSlotValue(0)) )
{
*pdwOrdinal = hte.GetSlotValue(0);
fFoundIt = TRUE;
}
else if( StringMatches(pszName, cchName, hte.GetSlotValue(1)) )
{
*pdwOrdinal = hte.GetSlotValue(1);
fFoundIt = TRUE;
}
else if( !hte.IsSlotEmpty(2) &&
StringMatches( pszName, cchName, hte.GetSlotValue(2) )
)
{
*pdwOrdinal = hte.GetSlotValue(2);
fFoundIt = TRUE;
}
else if( !hte.IsSlotEmpty(3) &&
StringMatches( pszName, cchName, hte.GetSlotValue(3) )
)
{
*pdwOrdinal = hte.GetSlotValue(3);
fFoundIt = TRUE;
}
}
}
return fFoundIt;
}
VOID
SV_CACHE_MAP::PrintToBuffer(
IN CHAR * pchBuffer,
IN OUT LPDWORD pcch
) const
/*++
Routine Description:
Dump the hash table to pchBuffer.
Note: We really aren't checking pcch as an in parameter. If
the buffer is too small we will overwrite it.
--*/
{
DWORD cb = 0;
DBG_ASSERT( NULL != pchBuffer);
cb += wsprintfA( pchBuffer + cb,
"SV_CACHE_MAP(%p): sizeof(SV_CACHE_MAP)=%08x\n",
this,
sizeof(SV_CACHE_MAP)
);
DBG_ASSERT( cb < *pcch );
// Gather some stats on the hash table
DWORD dwEmptyEntries = 0;
DWORD dwFilledEntries = 0;
DWORD dwCollisions = 0;
for( int i = 0; i < TABLE_SIZE; ++i )
{
if( m_rgHashTable[i].IsSlotEmpty(0) )
{
++dwEmptyEntries;
}
else
{
++dwFilledEntries;
if( !m_rgHashTable[i].IsSlotEmpty(1) )
{
++dwCollisions;
}
if( !m_rgHashTable[i].IsSlotEmpty(2) )
{
++dwCollisions;
}
if( !m_rgHashTable[i].IsSlotEmpty(3) )
{
++dwCollisions;
}
}
}
cb += wsprintfA( pchBuffer + cb,
"Table Size = %d; Hashed Items = %d; Empty Entries = %d; "
"Filled Entries = %d; Collisions = %d;\n",
TABLE_SIZE, SV_COUNT, dwEmptyEntries, dwFilledEntries,
dwCollisions
);
DBG_ASSERT( cb < *pcch );
for( int j = 0; j < TABLE_SIZE; ++j )
{
if( !m_rgHashTable[j].IsSlotEmpty(0) )
{
cb += wsprintfA( pchBuffer + cb, "%03d", j );
DBG_ASSERT( cb < *pcch );
int k = 0;
while( k < HASH_TABLE_ENTRY::MAX_ITEMS && !m_rgHashTable[j].IsSlotEmpty(k) )
{
cb += wsprintfA( pchBuffer + cb,
" - %d (%s)",
m_rgHashTable[j].GetSlotValue(k),
sm_rgNames[m_rgHashTable[j].GetSlotValue(k)]
);
DBG_ASSERT( cb < *pcch );
k++;
}
cb += wsprintfA( pchBuffer + cb, "\n" );
DBG_ASSERT( cb < *pcch );
}
}
*pcch = cb;
return;
}
VOID
SV_CACHE_MAP::Print( VOID ) const
/*++
Routine Description:
--*/
{
// DANGER - This buffer size is much larger then necessary, but
// changes to the PrintToBuffer or the underlying size of the
// SV_CACHE_MAP may make this buffer insufficient.
CHAR pchBuffer[ 10000 ];
DWORD cb = sizeof( pchBuffer );
PrintToBuffer( pchBuffer, &cb );
DBG_ASSERT( cb < sizeof(pchBuffer) );
DBGDUMP(( DBG_CONTEXT, pchBuffer ));
}
VOID
SV_CACHE_LIST::GetBufferItems
(
IN OUT BUFFER_ITEM * pBufferItems,
IN OUT DWORD * pdwBufferItemCount
)
/*++
Routine Description:
Initialize pBufferItems with the server variable ids that
should be cached.
--*/
{
DBG_ASSERT( pdwBufferItemCount && *pdwBufferItemCount >= SVID_COUNT );
DWORD dwCount = 0;
for( DWORD svid = 0; svid < SVID_COUNT; ++svid )
{
if( m_rgItems[svid].fCached )
{
if( dwCount < *pdwBufferItemCount )
{
pBufferItems[dwCount].svid = svid;
pBufferItems[dwCount].dwOffset = 0;
}
++dwCount;
}
}
*pdwBufferItemCount = dwCount;
}