home *** CD-ROM | disk | FTP | other *** search
- /*++
-
- Copyright (c) 1997 Microsoft Corporation
-
- Module Name: WorkerThread.c
-
- Abstract:
-
- IIS maintains a pool of threads to handle incoming HTTP requests. When all of
- these threads are in use, new requests will be rejected. If all the pool threads
- are in a wait state (for instance, running ISAPI dlls that are waiting for a query
- on a remote database to complete), IIS may reject incoming requests even if there
- is plenty of CPU power to handle them.
-
- One way of avoiding this situation is to offload processing of these types of
- requests to a worker thread, releasing the IIS thread back to the pool so that it
- can be used for another request. This basic sample demonstrates how to implement
- this in an ISAPI dll.
-
- */
-
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <httpext.h>
- #include <stdio.h>
-
- //
- // global variables
- //
-
- DWORD g_dwThreadCount = 0;
-
- //
- // local functions prototypes
- //
-
- DWORD WINAPI WorkerFunction( LPVOID );
- BOOL SendHttpHeaders(EXTENSION_CONTROL_BLOCK *, LPCSTR , LPCSTR, BOOL );
-
-
-
- BOOL WINAPI
- GetExtensionVersion(
- OUT HSE_VERSION_INFO *pVer
- )
- /*++
-
- Purpose:
-
- This is required ISAPI Extension DLL entry point.
-
- Arguments:
-
- pVer - poins to extension version info structure
-
- Returns:
-
- always returns TRUE
-
- --*/
- {
-
- //
- // tell the server our version number and extension description
- //
-
- pVer->dwExtensionVersion =
- MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
-
- lstrcpyn(
- pVer->lpszExtensionDesc,
- "ISAPI Worker Thread Extension Sample",
- HSE_MAX_EXT_DLL_NAME_LEN
- );
-
- return TRUE;
- }
-
-
- DWORD WINAPI
- HttpExtensionProc(
- IN EXTENSION_CONTROL_BLOCK *pECB
- )
- /*++
-
- Purpose:
-
- Create a thread to handle extended processing. It will be passed
- the address of a function ("WorkerFunction") to run, and the address
- of the ECB associated with this session.
-
- Arguments:
-
- pECB - pointer to the extenstion control block
-
- Returns:
-
- HSE_STATUS_PENDING to mark this request as pending
-
- --*/
- {
- DWORD dwThreadID;
-
-
- // (NOTE: in production environment you'd probably
- // wanted to limit the number of threads created)
-
- CreateThread(NULL, // Pointer to thread security attributes
- 0, // Initial thread stack size, in bytes
- WorkerFunction, // Pointer to thread function
- pECB, // The ECB is the argument for the new thread
- 0, // Creation flags
- &dwThreadID // Pointer to returned thread identifier
- );
-
- //
- // update global thread count
- //
-
- InterlockedIncrement( &g_dwThreadCount );
-
- // Return HSE_STATUS_PENDING to release IIS pool thread without losing connection
-
- return HSE_STATUS_PENDING;
- }
-
-
- DWORD WINAPI
- WorkerFunction(
- IN LPVOID vECB
- )
- /*++
-
- Purpose:
-
- Show how to perform extended processing in ISAPI DLL without
- tying IIS threads.
-
- Arguments:
-
- vECB - points to current extension control block
-
- Returns:
-
- returns 0
-
- --*/
- {
- char szHeader[] = "Content-type: text/html\r\n\r\n";
- char szContent[]= "<html> <form method=get action=WorkerThread.dll><h1>Worker Thread Sample</h1><hr>"
- "<input type=submit value=\"Send Request\"> </form></html>";
- EXTENSION_CONTROL_BLOCK *pECB;
- DWORD dwSize;
-
- //
- // Initialize local ECB pointer to void pointer passed to thread
- //
-
- pECB = vECB;
-
-
- //
- // Send outgoing header
- //
-
- SendHttpHeaders( pECB, "200 OK", szHeader, FALSE );
-
- //
- // Simulate extended processing for 5 seconds
- //
-
- Sleep(5000);
-
-
- //
- // Send content
- //
-
- dwSize = strlen( szContent );
- pECB->WriteClient( pECB->ConnID, szContent, &dwSize, 0 );
-
-
- //
- // Inform server that the request has been satisfied,
- // and the connection may now be dropped
- //
-
- pECB->ServerSupportFunction(
- pECB->ConnID,
- HSE_REQ_DONE_WITH_SESSION,
- NULL,
- NULL,
- NULL
- );
-
- //
- // update global thread count
- //
-
- InterlockedDecrement( &g_dwThreadCount );
-
- return 0;
- }
-
-
- BOOL
- SendHttpHeaders(
- EXTENSION_CONTROL_BLOCK *pECB,
- LPCSTR pszStatus,
- LPCSTR pszHeaders,
- BOOL fKeepConnection
- )
- /*++
-
- Purpose:
- Send specified HTTP status string and any additional header strings
- using new ServerSupportFunction() request HSE_SEND_HEADER_EX_INFO
-
- Arguments:
-
- pECB - pointer to the extension control block
- pszStatus - HTTP status string (e.g. "200 OK")
- pszHeaders - any additional headers, separated by CRLFs and
- terminated by empty line
-
- Returns:
-
- TRUE if headers were successfully sent
- FALSE otherwise
-
- --*/
- {
- HSE_SEND_HEADER_EX_INFO header_ex_info;
- BOOL success;
-
- header_ex_info.pszStatus = pszStatus;
- header_ex_info.pszHeader = pszHeaders;
- header_ex_info.cchStatus = strlen( pszStatus );
- header_ex_info.cchHeader = strlen( pszHeaders );
- header_ex_info.fKeepConn = fKeepConnection;
-
-
- success = pECB->ServerSupportFunction(
- pECB->ConnID,
- HSE_REQ_SEND_RESPONSE_HEADER_EX,
- &header_ex_info,
- NULL,
- NULL
- );
-
- return success;
- }
-
-
- BOOL WINAPI
- TerminateExtension(
- IN DWORD dwFlags
- )
- /*++
-
- Routine Description:
-
- This function is called when the WWW service is shutdown.
-
- Arguments:
-
- dwFlags - HSE_TERM_ADVISORY_UNLOAD or HSE_TERM_MUST_UNLOAD
-
- Return Value:
-
- TRUE when extension is ready to be unloaded,
-
- --*/
- {
-
- // (Our threads are deterministic and will complete
- // not much later than 5 seconds from now)
-
- //
- // wait for all threads to terminate, sleeping for 1 sec
- //
-
- while( g_dwThreadCount > 0 ) {
- SleepEx( 1000, FALSE );
- }
-
- //
- // make sure the last thread indeed exited
- //
-
- SleepEx( 1000, FALSE );
-
- return TRUE;
- }
-
-
-
-