333 lines
7.8 KiB
C++
333 lines
7.8 KiB
C++
/********************************************************************++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
wreqpool.cxx
|
|
|
|
Abstract:
|
|
This module implements the functions for managing the
|
|
pool of worker requests.
|
|
|
|
Author:
|
|
|
|
Murali R. Krishnan ( MuraliK ) 29-Oct-1998
|
|
|
|
Environment:
|
|
Win32 - User Mode
|
|
|
|
Project:
|
|
IIS Worker Process (web service)
|
|
|
|
--********************************************************************/
|
|
|
|
|
|
/************************************************************
|
|
* Include Headers
|
|
************************************************************/
|
|
|
|
#include "winbase.h"
|
|
#include "precomp.hxx"
|
|
#include "wreqpool.hxx"
|
|
|
|
extern WP_CONTEXT * g_pwpContext;
|
|
|
|
|
|
/************************************************************
|
|
* Functions
|
|
************************************************************/
|
|
|
|
/**
|
|
* UL_NATIVE_REQUEST_POOL::UL_NATIVE_REQUEST_POOL()
|
|
*
|
|
* o Construct a new worker requst pool object.
|
|
* This pool will maintain a list of all native request objects.
|
|
*
|
|
*/
|
|
UL_NATIVE_REQUEST_POOL::UL_NATIVE_REQUEST_POOL(void)
|
|
: m_nRequests ( 0),
|
|
m_nIdleRequests( 0),
|
|
m_fShutdown( FALSE),
|
|
m_fAddingItems( FALSE),
|
|
m_dwSignature( NREQ_POOL_SIGNATURE)
|
|
{
|
|
InitializeListHead( &m_lRequestList);
|
|
|
|
//
|
|
// Use spinned critical section.
|
|
// All operations using the CS are short lived and
|
|
// hence we keep the spins to a small amount.
|
|
//
|
|
//InitializeCriticalSection(&m_csRequestList);
|
|
|
|
InitializeCriticalSectionAndSpinCount(
|
|
&m_csRequestList,
|
|
UL_NATIVE_REQUEST_CS_SPINS
|
|
);
|
|
|
|
} // UL_NATIVE_REQUEST_POOL::UL_NATIVE_REQUEST_POOL()
|
|
|
|
|
|
/**
|
|
* ~UL_NATIVE_REQUEST_POOL
|
|
*
|
|
*/
|
|
|
|
UL_NATIVE_REQUEST_POOL::~UL_NATIVE_REQUEST_POOL(void)
|
|
{
|
|
if (m_nRequests > 0)
|
|
{
|
|
ReleaseAllWorkerRequests();
|
|
}
|
|
|
|
DeleteCriticalSection( &m_csRequestList);
|
|
InitializeListHead( &m_lRequestList);
|
|
|
|
m_dwSignature = ( NREQ_POOL_SIGNATURE_FREE);
|
|
|
|
} // UL_NATIVE_REQUEST_POOL::~UL_NATIVE_REQUEST_POOL()
|
|
|
|
|
|
/**
|
|
*
|
|
* UL_NATIVE_REQUEST_POOL::ReleaseAllWorkerRequests()
|
|
*
|
|
* o Walks the global list of all request objects and releases
|
|
* the requests
|
|
*
|
|
* NYI: For now it directly frees up the request. We need to post
|
|
* cancellations for the same as appropriate.
|
|
*/
|
|
|
|
HRESULT
|
|
UL_NATIVE_REQUEST_POOL::ReleaseAllWorkerRequests(void)
|
|
{
|
|
LIST_ENTRY * plScan;
|
|
|
|
// Wait for all requests's references drain away.
|
|
while(m_nRequests > 0)
|
|
{
|
|
PUL_NATIVE_REQUEST pwr;
|
|
|
|
// Should change to DEBUGGING CODE ONLY
|
|
// IF_DEBUG(DEBUG) {
|
|
DBGPRINTF((DBG_CONTEXT, "%d Requests still needs to be cleaned\n",
|
|
m_nRequests));
|
|
|
|
plScan = m_lRequestList.Flink;
|
|
pwr = CONTAINING_RECORD( plScan, UL_NATIVE_REQUEST, m_lRequestEntry);
|
|
|
|
DBGPRINTF((DBG_CONTEXT, "The unreleased request's ref count is %d\n",
|
|
pwr->ReferenceCount()));
|
|
// }
|
|
Sleep(2000);
|
|
}
|
|
|
|
DBG_ASSERT(m_nIdleRequests == 0);
|
|
|
|
DBGPRINTF((DBG_CONTEXT, "Released all native request objects\n"));
|
|
return (NOERROR);
|
|
} // UL_NATIVE_REQUEST_POOL::ReleaseAllWorkerRequests();
|
|
|
|
|
|
/**
|
|
* AddRequestToList
|
|
*
|
|
* Add an UL_NATIVE_REQUEST to the request list.
|
|
*
|
|
*/
|
|
|
|
void
|
|
UL_NATIVE_REQUEST_POOL::AddRequestToList(UL_NATIVE_REQUEST * pRequest)
|
|
{
|
|
EnterCriticalSection( &m_csRequestList);
|
|
InsertTailList( &m_lRequestList, &pRequest->m_lRequestEntry);
|
|
m_nRequests++;
|
|
LeaveCriticalSection( &m_csRequestList);
|
|
|
|
} // UL_NATIVE_REQUEST_POOL::AddRequestToList()
|
|
|
|
|
|
/**
|
|
* RemoveRequestFromList
|
|
*
|
|
* Remove an UL_NATIVE_REQUEST from the request list.
|
|
* This function is called within ~UL_NATIVE_REQUEST.
|
|
*
|
|
*/
|
|
|
|
void
|
|
UL_NATIVE_REQUEST_POOL::RemoveRequestFromList(UL_NATIVE_REQUEST * pRequest)
|
|
{
|
|
LONG nReqs;
|
|
|
|
EnterCriticalSection( &m_csRequestList);
|
|
RemoveEntryList( &pRequest->m_lRequestEntry);
|
|
nReqs = m_nRequests--;
|
|
LeaveCriticalSection( &m_csRequestList);
|
|
|
|
InitializeListHead( &pRequest->m_lRequestEntry);
|
|
|
|
} // UL_NATIVE_REQUEST_POOL::RemoveRequestFromList()
|
|
|
|
/**
|
|
* Description:
|
|
* UL_NATIVE_REQUEST_POOL::AddPoolItems()
|
|
*
|
|
* o Adds a fixed number of items to the pool and adds them to the
|
|
* current list of worker requests. After creating the object,
|
|
* an async read for request is posted on the worker request objects.
|
|
*
|
|
* Arguments:
|
|
* pContext - pointer to the CONTEXT object for IO operations
|
|
* nWorkerItemsToAdd - count of new worker requests to be added to the list
|
|
*
|
|
* Returns:
|
|
* ULONG
|
|
*
|
|
*/
|
|
|
|
ULONG
|
|
UL_NATIVE_REQUEST_POOL::AddPoolItems(
|
|
IN WP_CONTEXT * pContext,
|
|
IN int nWorkerItemsToAdd)
|
|
{
|
|
int i;
|
|
ULONG rc;
|
|
LONG nReqs;
|
|
BOOL fAdding;
|
|
|
|
PUL_NATIVE_REQUEST pwr;
|
|
|
|
EnterCriticalSection( &m_csRequestList);
|
|
if (nWorkerItemsToAdd + m_nRequests > REQUEST_POOL_MAX) {
|
|
nWorkerItemsToAdd = REQUEST_POOL_MAX - m_nRequests;
|
|
}
|
|
|
|
if (!m_fAddingItems) {
|
|
m_fAddingItems = TRUE;
|
|
fAdding = TRUE;
|
|
} else {
|
|
nWorkerItemsToAdd = 0;
|
|
fAdding = FALSE;
|
|
}
|
|
LeaveCriticalSection( &m_csRequestList);
|
|
|
|
|
|
//
|
|
// Loop through and create specified # of worker request objects
|
|
// Attach the current context to these objects
|
|
//
|
|
|
|
for (i = 0; i < nWorkerItemsToAdd; i++)
|
|
{
|
|
if (m_fShutdown) {
|
|
return i;
|
|
}
|
|
|
|
pwr = new UL_NATIVE_REQUEST( this);
|
|
|
|
if ( NULL == pwr)
|
|
{
|
|
rc = GetLastError();
|
|
|
|
if (NO_ERROR != rc)
|
|
{
|
|
IF_DEBUG( ERROR)
|
|
{
|
|
DPERROR(( DBG_CONTEXT, rc,
|
|
"Unable to create worker request %d.\n",
|
|
i));
|
|
}
|
|
}
|
|
|
|
//
|
|
// NYI: Log an event to the evnet log on this failure
|
|
//
|
|
|
|
//
|
|
// For now bail out of this loop on error
|
|
//
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
|
|
AddRequestToList( pwr);
|
|
|
|
//
|
|
// Initialize the Context for the object.
|
|
//
|
|
|
|
pwr->SetWPContext( pContext);
|
|
|
|
rc = pwr->DoWork( 0, 0, &pwr->m_overlapped);
|
|
|
|
// assume no failure in initial req. read operations
|
|
DBG_ASSERT( NO_ERROR == rc);
|
|
}
|
|
} // for
|
|
|
|
if (fAdding) {
|
|
EnterCriticalSection(&m_csRequestList);
|
|
DBG_ASSERT(m_fAddingItems);
|
|
m_fAddingItems = FALSE;
|
|
LeaveCriticalSection(&m_csRequestList);
|
|
}
|
|
|
|
return (NOERROR);
|
|
|
|
} // UL_NATIVE_REQUEST_POOL::AddPoolItems()
|
|
|
|
|
|
/**
|
|
* Description:
|
|
* UL_NATIVE_REQUEST_POOL::DecIdleRequests()
|
|
*
|
|
* Decrements the count of objects available to process new requests.
|
|
* If we fall below 1/4 the number of initial items, we add some more.
|
|
*
|
|
* Arguments:
|
|
* None.
|
|
*
|
|
* Returns:
|
|
* None.
|
|
*
|
|
*/
|
|
VOID
|
|
UL_NATIVE_REQUEST_POOL::DecIdleRequests()
|
|
{
|
|
LONG idle;
|
|
|
|
idle = InterlockedDecrement(&m_nIdleRequests);
|
|
DBG_ASSERT(idle >= 0);
|
|
|
|
if (idle < (NUM_INITIAL_REQUEST_POOL_ITEMS / 4)) {
|
|
AddPoolItems(g_pwpContext, REQUEST_POOL_INCREMENT);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Description:
|
|
* UL_NATIVE_REQUEST_POOL::IncIdleRequests()
|
|
*
|
|
* Increments the count of objects available to process new requests.
|
|
*
|
|
* Arguments:
|
|
* None.
|
|
*
|
|
* Returns:
|
|
* None.
|
|
*
|
|
*/
|
|
VOID
|
|
UL_NATIVE_REQUEST_POOL::IncIdleRequests()
|
|
{
|
|
InterlockedIncrement(&m_nIdleRequests);
|
|
}
|
|
|
|
|
|
/***************************** End of File ***************************/
|
|
|