305 lines
7 KiB
C++
305 lines
7 KiB
C++
|
/*++
|
||
|
|
||
|
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;
|
||
|
}
|