|
|
/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corp., 1994-1997 **/ /**********************************************************************/
/*
atq.h
This module contains async thread queue (atq) for async IO and thread pool sharing among various services.
Brief Description of ATQ: For description, please see iis\spec\isatq.doc
*/
#ifndef _ATQ_H_
#define _ATQ_H_
#ifdef __cplusplus
extern "C" { #endif
// Include Standard headers
# include <nt.h>
# include <ntrtl.h>
# include <nturtl.h>
# include <windows.h>
# include <winsock2.h>
# include <mswsock.h>
#ifndef dllexp
#define dllexp __declspec( dllexport )
#endif
/*++
ATQ API Overview:
Global per module: AtqInitialize() AtqTerminate()
AtqGetInfo() AtqSetInfo()
ATQ Endpoint functions: AtqCreateEndpoint() AtqStartEndpoint() AtqEndpointGetInfo() AtqEndpointSetInfo() AtqStopCloseEndpoint() AtqCloseCloseEndpoint()
AtqStopAndCloseEndpoint() <-- soon to be killed Per ATQ Context Functions: AtqAddAsyncHandle() <-- for non AcceptEx() sockets
AtqGetAcceptExAddrs() <-- for AcceptEx() sockets
AtqContextSetInfo()
AtqCloseFileHandle() AtqCloseSocket() AtqFreeContext()
Bandwidth Throttler Functions: AtqCreateBandwidthInfo() AtqFreeBandwidthInfo() AtqBandwidthSetInfo() AtqBandwidthGetInfo()
IO Functions:
AtqReadFile() AtqWriteFile() AtqReadSocket() AtqWriteSocket() AtqTransmitFile() AtqTransmitFileAndRecv() AtqSendAndRecv()
Utility Functions:
AtqCreateFile() AtqCreateFileW() AtqOplockAcknowledge() AtqSpudInitialized() AtqReadDirChanges() AtqPostCompletionStatus()
--*/
/*----------------------------------------------------------
Registry Parameters used by ATQ during AtqInitialize() ATQ loads some of the parameters from HKLM\System\CurrentControlSet\Services\InetInfo\Parameters
Most of these parameters are for INTERNAL ANALYSIS and development/testing. Setup should not install values for the same. Setup can include values for items marked SETUP. ------------------------------------------------------------*/
// Names
#define ATQ_REG_PER_PROCESSOR_ATQ_THREADS TEXT("MaxPoolThreads")
#define ATQ_REG_POOL_THREAD_LIMIT TEXT("PoolThreadLimit") // SETUP
#define ATQ_REG_PER_PROCESSOR_CONCURRENCY TEXT("MaxConcurrency")
#define ATQ_REG_THREAD_TIMEOUT TEXT("ThreadTimeout")
#define ATQ_REG_USE_ACCEPTEX TEXT("UseAcceptEx")
#define ATQ_REG_MIN_KB_SEC TEXT("MinFileKbSec") // SETUP
#define ATQ_REG_LISTEN_BACKLOG TEXT("ListenBacklog") // SETUP
// Default Values
#define ATQ_REG_DEF_PER_PROCESSOR_ATQ_THREADS (4)
#define ATQ_REG_DEF_PER_PROCESSOR_CONCURRENCY (0)
// special value of 0 means that system will determine this dynamically.
//
// thread limit settings
//
#define ATQ_REG_MIN_POOL_THREAD_LIMIT (64)
#define ATQ_REG_DEF_POOL_THREAD_LIMIT (128)
#define ATQ_REG_MAX_POOL_THREAD_LIMIT (256)
//
// How often to check for thread progress.
//
#define ATQ_THREAD_MONITOR_PERIOD (2*60) // 2 Minutes
//
// How many IO's a temp thread should handle before
// exiting
//
#define ATQ_TEMP_THREAD_IO_COUNT (100)
//
// THREAD_TIMEOUTs are high to prevent async ios from being cancelled
// when the thread goes away.
//
#define ATQ_REG_DEF_THREAD_TIMEOUT (12*60*60) // 12 hours
#define ATQ_REG_DEF_USE_ACCEPTEX (TRUE)
#define ATQ_REG_DEF_MIN_KB_SEC (1000) // 1000 bytes
#define ATQ_REG_DEF_LISTEN_BACKLOG (25)
//
// fake xmit file buffer size
//
#define ATQ_REG_DEF_NONTF_BUFFER_SIZE (4096)
/*----------------------------------------------------------
Global Functions of ATQ module -----------------------------------------------------------*/
// Flags for AtqInitialize()
# define ATQ_INIT_SPUD_FLAG (0x00000001)
BOOL AtqInitialize( IN DWORD dwFlags );
BOOL AtqTerminate( VOID );
/*
* Sets various context information in Atq Module for global modifications * * * Bandwidth Throttle: Sets the throttle level in Bytes/Second. * If INFINITE, then it is assumed that * there is no throttle value (default) * * Max Pool Threads: Sets the maximum number of pool threads Atq will allow * to be created per processor * * MaxConcurrency: tells how many threads to permit per processor * * Thread Timeout: Indicates how long a thread should be kep alive * waiting on GetQueuedCompletionStatus() before commiting suicide * (in seconds) * * Inc/Dec max pool threads: If a server will be doing extended processing * in an ATQ pool thread, they should increase the max pool threads * while the extended processing is occurring. This prevents starvation * of other requests * * AtqMinKbSec: set the assumed minimum KB per second for AtqTransmitFile() * This value is used in calculating the timeout for file transfer * operation * */
typedef enum _ATQ_INFO {
AtqBandwidthThrottle = 0, AtqExitThreadCallback, AtqMaxPoolThreads, // per processor values
AtqMaxConcurrency, // per processor concurrency value
AtqThreadTimeout, AtqUseAcceptEx, // Use AcceptEx if available
AtqIncMaxPoolThreads, // Up the max thread count
AtqDecMaxPoolThreads, // Decrease the max thread count
AtqMinKbSec, // Minimum assumed transfer rate for AtqTransmitFile
AtqBandwidthThrottleMaxBlocked, // Max number of blocked requests
AtqUpdatePerfCounterCallback, AtqMaxDGramSend // Max bytes in a single datagram send
} ATQ_INFO;
//
// ATQ_THREAD_EXIT_CALLBACK
// Type of callback function to be called when an ATQ thread exits so
// that the user of ATQ may clen up thread specific data.
//
typedef VOID (*ATQ_THREAD_EXIT_CALLBACK) ( VOID );
//
// ATQ_PERF_UPDATE_CALLBACK
// Type of callback function to be called when ATQ needs to update
// PerfMon counters that do no reside within ATQ.
//
typedef VOID (*ATQ_UPDATE_PERF_CALLBACK) ( IN DWORD dwStat, IN DWORD dwOperation, IN DWORD dwChange );
dllexp DWORD_PTR AtqSetInfo( IN ATQ_INFO atqInfo, IN DWORD_PTR Data );
dllexp DWORD_PTR AtqGetInfo( IN ATQ_INFO atqInfo );
typedef struct _ATQ_STATISTICS {
DWORD cAllowedRequests; DWORD cBlockedRequests; DWORD cRejectedRequests; DWORD cCurrentBlockedRequests; DWORD MeasuredBandwidth;
} ATQ_STATISTICS;
dllexp BOOL AtqGetStatistics( IN OUT ATQ_STATISTICS * pAtqStats);
dllexp BOOL AtqClearStatistics(VOID);
/*----------------------------------------------------------
ATQ Endpoint functions -----------------------------------------------------------*/
//
// endpoint data
//
typedef enum _ATQ_ENDPOINT_INFO {
EndpointInfoListenPort, EndpointInfoListenSocket, EndpointInfoAcceptExOutstanding, EndpointInfoConsumerType
} ATQ_ENDPOINT_INFO;
//
// ATQ_COMPLETION
// This is the routine that is called upon IO completion (on
// error or success).
//
// Context is the context passed to AtqAddAsyncHandle
// BytesWritten is the number of bytes written to the file or
// bytes written to the client's buffer
// CompletionStatus is the WinError completion code
// lpOverLapped is the filled in overlap structure
//
// If the timeout thread times out an IO request, the completion routine
// will be called by the timeout thread with IOCompletion FALSE and
// CompletionStatus == ERROR_SEM_TIMEOUT. The IO request is *still*
// outstanding in this instance. Generally it will be completed when
// the file handle is closed.
//
typedef VOID (*ATQ_COMPLETION)( IN PVOID Context, IN DWORD BytesWritten, IN DWORD CompletionStatus, // Win32 Error code
IN OVERLAPPED * lpo );
//
// Type of callback function to be called when a new connection is established.
// This function should be defined before including conninfo.hxx
//
typedef VOID (*ATQ_CONNECT_CALLBACK) ( IN SOCKET sNew, IN LPSOCKADDR_IN pSockAddr, IN PVOID EndpointContext, IN PVOID EndpointObject );
typedef struct _ATQ_ENDPOINT_CONFIGURATION {
//
// Port to listen on. If 0, system will assign
//
USHORT ListenPort;
//
// Is connectionless
//
BOOL fDatagram; // The next two are datagram only.
BOOL fReverseQueuing; // If set then winsock will drop the oldest rather
// than the newest datagram buffers when winsock buffers
// overflow.
INT cbDatagramWSBufSize; // How much buffer space to tell winsock to reserve
// for this datagram socket.
//
// Prevent others from using this?
//
BOOL fLockDownPort;
//
// IP address to bind to. 0 (INADDR_ANY) == wildcard.
//
DWORD IpAddress;
DWORD cbAcceptExRecvBuffer; DWORD nAcceptExOutstanding; DWORD AcceptExTimeout;
//
// Callbacks
//
ATQ_CONNECT_CALLBACK pfnConnect; ATQ_COMPLETION pfnConnectEx; ATQ_COMPLETION pfnIoCompletion;
} ATQ_ENDPOINT_CONFIGURATION, *PATQ_ENDPOINT_CONFIGURATION;
dllexp PVOID AtqCreateEndpoint( IN PATQ_ENDPOINT_CONFIGURATION Configuration, IN PVOID EndpointContext );
dllexp BOOL AtqStartEndpoint( IN PVOID Endpoint );
dllexp DWORD_PTR AtqEndpointGetInfo( IN PVOID Endpoint, IN ATQ_ENDPOINT_INFO EndpointInfo );
dllexp DWORD_PTR AtqEndpointSetInfo( IN PVOID Endpoint, IN ATQ_ENDPOINT_INFO EndpointInfo, IN DWORD_PTR dwInfo );
dllexp BOOL AtqStopEndpoint( IN PVOID Endpoint );
dllexp BOOL AtqCloseEndpoint( IN PVOID Endpoint );
dllexp BOOL AtqStopAndCloseEndpoint( IN PVOID Endpoint, IN LPTHREAD_START_ROUTINE lpCompletion, IN PVOID lpCompletionContext );
/*----------------------------------------------------------
ATQ CONTEXT functions -----------------------------------------------------------*/
//
// This is the public portion of an ATQ Context. It should be treated
// as read only
//
// !!! Changes made to this structure should also be made to
// ATQ_CONTEXT in atqtypes.hxx !!!
//
typedef struct _ATQ_CONTEXT_PUBLIC {
HANDLE hAsyncIO; // handle for async i/o object: socket/file
OVERLAPPED Overlapped; // Overlapped structure used for IO
} ATQ_CONTEXT_PUBLIC, *PATQ_CONTEXT;
dllexp BOOL AtqAddAsyncHandle( OUT PATQ_CONTEXT * ppatqContext, IN PVOID EndpointObject, IN PVOID ClientContext, IN ATQ_COMPLETION pfnCompletion, IN DWORD TimeOut, IN HANDLE hAsyncIO );
dllexp VOID AtqGetAcceptExAddrs( IN PATQ_CONTEXT patqContext, OUT SOCKET * pSock, OUT PVOID * ppvBuff, OUT PVOID * pEndpointContext, OUT SOCKADDR * * ppsockaddrLocal, OUT SOCKADDR * * ppsockaddrRemote );
/*++
AtqCloseSocket()
Routine Description:
Closes the socket in this atq structure if it wasn't closed by transmitfile. This function should be called only if the embedded handle in AtqContext is a Socket.
Arguments:
patqContext - Context whose socket should be closed. fShutdown - If TRUE, means we call shutdown and always close the socket. Note that if TransmitFile closed the socket, it will have done the shutdown for us
Returns: TRUE on success and FALSE if there is a failure. --*/ dllexp BOOL AtqCloseSocket( PATQ_CONTEXT patqContext, BOOL fShutdown );
/*++
AtqCloseFileHandle()
Routine Description:
Closes the file handle in this atq structure. This function should be called only if the embedded handle in AtqContext is a file handle.
Arguments:
patqContext - Context whose file handle should be closed.
Returns: TRUE on success and FALSE if there is a failure. --*/ dllexp BOOL AtqCloseFileHandle( PATQ_CONTEXT patqContext );
/*++
AtqFreeContext()
Routine Description:
Frees the context created in AtqAddAsyncHandle. Call this after the async handle has been closed and all outstanding IO operations have been completed. The context is invalid after this call. Call AtqFreeContext() for same context only ONCE.
Arguments:
patqContext - Context to free fReuseContext - TRUE if this can context can be reused in the context of the calling thread. Should be FALSE if the calling thread will exit soon (i.e., isn't an AtqPoolThread).
Returns: None --*/ dllexp VOID AtqFreeContext( IN PATQ_CONTEXT patqContext, BOOL fReuseContext );
enum ATQ_CONTEXT_INFO { ATQ_INFO_TIMEOUT = 0, // Timeout rounded up to ATQ timeout interval
ATQ_INFO_RESUME_IO, // resumes IO as is after Timeout
ATQ_INFO_COMPLETION, // Completion routine
ATQ_INFO_COMPLETION_CONTEXT,// Completion context
ATQ_INFO_BANDWIDTH_INFO, // Bandwidth Throttling Descriptor
ATQ_INFO_ABORTIVE_CLOSE, // do abortive close on closesocket
ATQ_INFO_NEXT_TIMEOUT };
enum ATQ_CONSUMER_TYPE { AtqConsumerLDAP = 0, AtqConsumerOther, AtqConsumerAtq, AtqConsumerMax };
/*++
AtqContextSetInfo()
Routine Description:
Sets various bits of information for this context
Arguments:
patqContext - pointer to ATQ context atqInfo - Data item to set data - New value for item
Return Value:
The old value of the parameter
--*/
dllexp DWORD_PTR AtqContextSetInfo( IN PATQ_CONTEXT patqContext, IN enum ATQ_CONTEXT_INFO atqInfo, IN DWORD_PTR data );
dllexp DWORD_PTR AtqContextSetInfo2( IN PATQ_CONTEXT patqContext, IN enum ATQ_CONTEXT_INFO atqInfo, IN DWORD_PTR data );
VOID AtqUpdatePerfStats( IN ATQ_CONSUMER_TYPE ConsumerType, IN DWORD dwOperation, IN DWORD dwVal );
dllexp DWORD_PTR AtqEndpointSetInfo2( IN PVOID Endpoint, IN ATQ_ENDPOINT_INFO EndpointInfo, IN DWORD_PTR dwInfo );
dllexp DWORD_PTR AtqSetInfo2( IN ATQ_INFO atqInfo, IN DWORD_PTR Data );
/*----------------------------------------------------------
ATQ Context IO functions -----------------------------------------------------------*/
/*++
Routine Description:
Atq<Operation><Target>()
<Operation> := Read | Write | Transmit <Target> := File | Socket
These functions just setup ATQ context and then call the corresponding Win32/WinSock function for submitting an asynchronous IO operation. By default the Socket functions support scatter/gather using WSABUF
These functions are wrappers and should be called instead of the correpsonding Win32 API. The one difference from the Win32 API is TRUE is returned if the error ERROR_IO_PENDING occurred, thus clients do not need to check for this case.
The timeout time for the request is calculated by taking the maximum of the context's timeout time and bytes transferred based on 1k/second.
Arguments:
patqContext - pointer to ATQ context Everything else as in the Win32 API/WinSock APIs
NOTES: AtqTransmitFile takes an additional DWORD flags which may contain the winsock constants TF_DISCONNECT and TF_REUSE_SOCKET
AtqReadFile and AtqWriteFile take an optional overlapped structure if clients want to have multiple outstanding reads or writes. If the value is NULL, then the overlapped structure from the Atq context is used.
Return Value:
TRUE if successful, FALSE on error (call GetLastError) sets ERROR_NETWORK_BUSY as error when the request needs to be rejected.
--*/
dllexp BOOL AtqReadFile( IN PATQ_CONTEXT patqContext, IN LPVOID lpBuffer, IN DWORD BytesToRead, IN OVERLAPPED * lpo OPTIONAL );
dllexp BOOL AtqReadSocket( IN PATQ_CONTEXT patqContext, IN LPWSABUF pwsaBuffers, IN DWORD dwBufferCount, IN OVERLAPPED * lpo OPTIONAL );
/*
* Code for reading into single buffer will look like the following. * { * WSABUF wsaBuf = { (BytesToRead), (lpBuffer)}; * fRet = AtqReadSocket( patqContext, &wsaBuf, 1, lpo); * } */
dllexp BOOL AtqWriteFile( IN PATQ_CONTEXT patqContext, IN LPCVOID lpBuffer, IN DWORD BytesToWrite, IN OVERLAPPED * lpo OPTIONAL );
dllexp BOOL AtqWriteSocket( IN PATQ_CONTEXT patqContext, IN LPWSABUF pwsaBuffers, IN DWORD dwBufferCount, IN OVERLAPPED * lpo OPTIONAL );
dllexp BOOL AtqSyncWsaSend( IN PATQ_CONTEXT patqContext, IN LPWSABUF pwsaBuffers, IN DWORD dwBufferCount, OUT LPDWORD pcbWritten );
// Note: This API always causes the complete file to be sent.
// If you want to change the behaviour store the appropriate offsets
// in the ATQ_CONTEXT::Overlapped object.
dllexp BOOL AtqTransmitFile( IN PATQ_CONTEXT patqContext, IN HANDLE hFile, // File data comes from
IN DWORD dwBytesInFile, // what is the size of file?
IN LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, IN DWORD dwFlags // TF_DISCONNECT, TF_REUSE_SOCKET
);
dllexp BOOL AtqTransmitFileAndRecv( IN PATQ_CONTEXT patqContext, // pointer to ATQ context
IN HANDLE hFile, // handle of file to read
IN DWORD dwBytesInFile, // Bytes to transmit
IN LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, // transmit buffer structure
IN DWORD dwTFFlags, // TF Flags
IN LPWSABUF pwsaBuffers, // Buffers for recv
IN DWORD dwBufferCount );
dllexp BOOL AtqSendAndRecv( IN PATQ_CONTEXT patqContext, // pointer to ATQ context
IN LPWSABUF pwsaSendBuffers, // buffers for send
IN DWORD dwSendBufferCount, // count of buffers for send
IN LPWSABUF pwsaRecvBuffers, // Buffers for recv
IN DWORD dwRecvBufferCount // count of buffers for recv
);
/*----------------------------------------------------------
ATQ Utility Functions -----------------------------------------------------------*/
#define OPLOCK_BREAK_NO_OPLOCK 0x00000001
#define OPLOCK_BREAK_OPEN 0x00000007
#define OPLOCK_BREAK_CLOSE 0x00000008
typedef VOID (*ATQ_OPLOCK_COMPLETION)( IN PVOID Context, IN DWORD Status );
dllexp HANDLE AtqCreateFile( LPCSTR lpAFileName, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwFlagsAndAttributes, SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR sd, ULONG Length, PULONG LengthNeeded, ATQ_OPLOCK_COMPLETION pfnOplockCompletion, PVOID Context );
dllexp HANDLE AtqCreateFileW( LPCWSTR lpFileName, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwFlagsAndAttributes, SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR sd, ULONG Length, PULONG LengthNeeded, ATQ_OPLOCK_COMPLETION pfnOplockCompletion, PVOID Context );
dllexp BOOL AtqOplockAcknowledge( IN HANDLE FileHandle, ATQ_OPLOCK_COMPLETION pfnOplockCompletion, PVOID Context );
dllexp BOOL AtqSpudInitialized( VOID );
dllexp BOOL AtqReadDirChanges(PATQ_CONTEXT patqContext, LPVOID lpBuffer, DWORD BytesToRead, BOOL fWatchSubDir, DWORD dwNotifyFilter, OVERLAPPED * lpo );
/*++
AtqPostCompletionStatus()
Routine Description:
Posts a completion status on the completion port queue
An IO pending error code is treated as a success error code
Arguments:
patqContext - pointer to ATQ context Everything else as in the Win32 API
NOTES:
Return Value:
TRUE if successful, FALSE on error (call GetLastError)
--*/
dllexp BOOL AtqPostCompletionStatus( IN PATQ_CONTEXT patqContext, IN DWORD BytesTransferred );
/*----------------------------------------------------------
ATQ Utility Functions -----------------------------------------------------------*/
/*++
Bandwidth Throttling Support
The following items are used in the support for bandwidth throttling --*/
enum ATQ_BANDWIDTH_INFO { ATQ_BW_BANDWIDTH_LEVEL = 0, ATQ_BW_MAX_BLOCKED, ATQ_BW_STATISTICS, ATQ_BW_DESCRIPTION, };
/*++
AtqCreateBandwidthInfo()
Routine Description:
Allocate and opaque bandwidth descriptor
Arguments:
None
Return Value:
Pointer to descriptor. NULL if failed.
--*/ dllexp PVOID AtqCreateBandwidthInfo( VOID );
/*++
AtqFreeBandwidthInfo()
Routine Description:
Triggers the destruction of a bandwidth descriptor
Arguments:
pvBandwidthInfo - pointer to valid descriptor
Return Value:
TRUE if successful, else FALSE
--*/ dllexp BOOL AtqFreeBandwidthInfo( IN PVOID pvBandwidthInfo );
/*++
AtqBandwidthSetInfo()
Routine Description:
Set properties of bandwidth descriptor
Arguments:
pvBandwidthInfo - pointer to descriptor BWInfo - property to change Data - value of property
Return Value:
Old value of property
--*/ dllexp DWORD_PTR AtqBandwidthSetInfo( IN PVOID pvBandwidthInfo, IN ATQ_BANDWIDTH_INFO BwInfo, IN DWORD_PTR Data );
/*++
AtqBandwidthGetInfo()
Routine Description:
Get properties of bandwidth descriptor
Arguments:
pvBandwidthInfo - pointer to descriptor BWInfo - property to change pdwData - filled in with value of property
Return Value:
TRUE if successful, else FALSE
--*/ dllexp BOOL AtqBandwidthGetInfo( IN PVOID pvBandwidthInfo, IN ATQ_BANDWIDTH_INFO BwInfo, OUT DWORD_PTR * pdwData );
#include "atq2.h"
#ifdef __cplusplus
} #endif
#endif // !_ATQ_H_
|