home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / software / pelne / optionp / iis4_07.cab / WorkerThread.c < prev    next >
C/C++ Source or Header  |  1997-10-25  |  6KB  |  298 lines

  1. /*++
  2.  
  3. Copyright (c) 1997  Microsoft Corporation
  4.  
  5. Module Name:    WorkerThread.c
  6.  
  7. Abstract:
  8.  
  9.     IIS maintains a pool of threads to handle incoming HTTP requests.  When all of
  10.     these threads are in use, new requests will be rejected.  If all the pool threads
  11.     are in a wait state (for instance, running ISAPI dlls that are waiting for a query
  12.     on a remote database to complete), IIS may reject incoming requests even if there
  13.     is plenty of CPU power to handle them.
  14.     
  15.     One way of avoiding this situation is to offload processing of these types of
  16.     requests to a worker thread, releasing the IIS thread back to the pool so that it
  17.     can be used for another request.  This basic sample demonstrates how to implement
  18.     this in an ISAPI dll.
  19.  
  20. */
  21.  
  22. #define WIN32_LEAN_AND_MEAN
  23. #include <windows.h>
  24. #include <httpext.h>
  25. #include <stdio.h>
  26.  
  27. //
  28. // global variables
  29. //
  30.  
  31. DWORD g_dwThreadCount = 0;
  32.  
  33. //
  34. // local functions prototypes
  35. //
  36.  
  37. DWORD WINAPI WorkerFunction( LPVOID ); 
  38. BOOL SendHttpHeaders(EXTENSION_CONTROL_BLOCK *, LPCSTR , LPCSTR, BOOL );
  39.  
  40.  
  41.  
  42. BOOL WINAPI
  43. GetExtensionVersion(
  44.     OUT HSE_VERSION_INFO *pVer
  45. )
  46. /*++
  47.  
  48. Purpose:
  49.  
  50.     This is required ISAPI Extension DLL entry point.
  51.  
  52. Arguments:
  53.  
  54.     pVer - poins to extension version info structure 
  55.  
  56. Returns:
  57.  
  58.     always returns TRUE
  59.  
  60. --*/
  61. {
  62.  
  63.     //
  64.     // tell the server our version number and extension description
  65.     //
  66.  
  67.     pVer->dwExtensionVersion =
  68.         MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
  69.  
  70.     lstrcpyn(
  71.         pVer->lpszExtensionDesc, 
  72.         "ISAPI Worker Thread Extension Sample", 
  73.         HSE_MAX_EXT_DLL_NAME_LEN 
  74.         );
  75.  
  76.     return TRUE;
  77. }
  78.  
  79.  
  80. DWORD WINAPI
  81. HttpExtensionProc(
  82.     IN EXTENSION_CONTROL_BLOCK *pECB
  83. )
  84. /*++
  85.  
  86. Purpose:
  87.  
  88.     Create a thread to handle extended processing. It will be passed 
  89.     the address of a function ("WorkerFunction") to run, and the address 
  90.     of the ECB associated with this session.
  91.  
  92. Arguments:
  93.  
  94.     pECB - pointer to the extenstion control block 
  95.  
  96. Returns:
  97.  
  98.     HSE_STATUS_PENDING to mark this request as pending
  99.  
  100. --*/
  101. {
  102.     DWORD dwThreadID;
  103.  
  104.  
  105.     // (NOTE: in production environment you'd probably 
  106.     //  wanted to limit the number of threads created)
  107.  
  108.     CreateThread(NULL,              // Pointer to thread security attributes 
  109.                  0,                 // Initial thread stack size, in bytes 
  110.                  WorkerFunction,    // Pointer to thread function 
  111.                  pECB,              // The ECB is the argument for the new thread
  112.                  0,                 // Creation flags 
  113.                  &dwThreadID        // Pointer to returned thread identifier 
  114.                  );
  115.  
  116.     //
  117.     // update global thread count
  118.     //
  119.  
  120.     InterlockedIncrement( &g_dwThreadCount );
  121.  
  122.     // Return HSE_STATUS_PENDING to release IIS pool thread without losing connection
  123.  
  124.     return HSE_STATUS_PENDING;
  125. }
  126.  
  127.  
  128. DWORD WINAPI 
  129. WorkerFunction(
  130.     IN LPVOID vECB
  131. )
  132. /*++
  133.  
  134. Purpose:
  135.  
  136.     Show how to perform extended processing in ISAPI DLL without
  137.     tying IIS threads. 
  138.  
  139. Arguments:
  140.  
  141.     vECB - points to current extension control block
  142.  
  143. Returns:
  144.     
  145.     returns 0  
  146.  
  147. --*/
  148. {
  149.     char szHeader[] =   "Content-type: text/html\r\n\r\n";
  150.     char szContent[]=   "<html> <form method=get action=WorkerThread.dll><h1>Worker Thread Sample</h1><hr>"
  151.                         "<input type=submit value=\"Send Request\"> </form></html>";
  152.     EXTENSION_CONTROL_BLOCK *pECB;
  153.     DWORD dwSize;
  154.  
  155.     //
  156.     // Initialize local ECB pointer to void pointer passed to thread
  157.     //
  158.  
  159.     pECB = vECB;
  160.     
  161.  
  162.     //
  163.     // Send outgoing header
  164.     //
  165.     
  166.     SendHttpHeaders( pECB, "200 OK", szHeader, FALSE );
  167.  
  168.     //
  169.     // Simulate extended processing for 5 seconds
  170.     //
  171.     
  172.     Sleep(5000);
  173.  
  174.  
  175.     //
  176.     // Send content
  177.     //
  178.     
  179.     dwSize = strlen( szContent );
  180.     pECB->WriteClient( pECB->ConnID, szContent, &dwSize, 0 );
  181.  
  182.  
  183.     //
  184.     // Inform server that the request has been satisfied, 
  185.     // and the connection may now be dropped
  186.     //
  187.  
  188.     pECB->ServerSupportFunction( 
  189.         pECB->ConnID, 
  190.         HSE_REQ_DONE_WITH_SESSION, 
  191.         NULL, 
  192.         NULL, 
  193.         NULL 
  194.         );
  195.  
  196.     //
  197.     // update global thread count
  198.     //
  199.  
  200.     InterlockedDecrement( &g_dwThreadCount );
  201.  
  202.     return 0;
  203. }
  204.  
  205.  
  206. BOOL 
  207. SendHttpHeaders( 
  208.     EXTENSION_CONTROL_BLOCK *pECB, 
  209.     LPCSTR pszStatus,
  210.     LPCSTR pszHeaders,
  211.     BOOL fKeepConnection
  212. )
  213. /*++
  214.  
  215. Purpose:
  216.     Send specified HTTP status string and any additional header strings
  217.     using new ServerSupportFunction() request HSE_SEND_HEADER_EX_INFO
  218.  
  219. Arguments:
  220.  
  221.     pECB - pointer to the extension control block
  222.     pszStatus - HTTP status string (e.g. "200 OK")
  223.     pszHeaders - any additional headers, separated by CRLFs and 
  224.                  terminated by empty line
  225.  
  226. Returns:
  227.  
  228.     TRUE if headers were successfully sent
  229.     FALSE otherwise
  230.  
  231. --*/
  232. {
  233.     HSE_SEND_HEADER_EX_INFO header_ex_info;
  234.     BOOL success;
  235.  
  236.     header_ex_info.pszStatus = pszStatus;
  237.     header_ex_info.pszHeader = pszHeaders;
  238.     header_ex_info.cchStatus = strlen( pszStatus );
  239.     header_ex_info.cchHeader = strlen( pszHeaders );
  240.     header_ex_info.fKeepConn = fKeepConnection;
  241.  
  242.  
  243.     success = pECB->ServerSupportFunction(
  244.                   pECB->ConnID,
  245.                   HSE_REQ_SEND_RESPONSE_HEADER_EX,
  246.                   &header_ex_info,
  247.                   NULL,
  248.                   NULL
  249.                   );
  250.  
  251.     return success;
  252. }
  253.  
  254.  
  255. BOOL WINAPI
  256. TerminateExtension( 
  257.     IN DWORD dwFlags 
  258. )
  259. /*++
  260.  
  261. Routine Description:
  262.  
  263.     This function is called when the WWW service is shutdown.
  264.  
  265. Arguments:
  266.  
  267.     dwFlags - HSE_TERM_ADVISORY_UNLOAD or HSE_TERM_MUST_UNLOAD
  268.  
  269. Return Value:
  270.  
  271.     TRUE when extension is ready to be unloaded,
  272.  
  273. --*/
  274. {
  275.  
  276.     // (Our threads are deterministic and will complete 
  277.     //  not much later than 5 seconds from now)
  278.  
  279.     //
  280.     // wait for all threads to terminate, sleeping for 1 sec
  281.     //
  282.  
  283.     while( g_dwThreadCount > 0 ) {
  284.         SleepEx( 1000, FALSE );
  285.     }
  286.  
  287.     //
  288.     // make sure the last thread indeed exited
  289.     //
  290.  
  291.     SleepEx( 1000, FALSE );
  292.  
  293.     return TRUE;
  294. }
  295.  
  296.  
  297.  
  298.