|
|
/*++
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; }
|