You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
7.3 KiB
304 lines
7.3 KiB
/*++
|
|
|
|
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;
|
|
}
|