162 lines
3.7 KiB
C
162 lines
3.7 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
backpack.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the package for pseudo polling. When a caller
|
|||
|
requests the same operation and gets the same error return the rdr
|
|||
|
must prevent flooding the network by backing off requests. Examples
|
|||
|
of when this is desirable are receiving 0 bytes on consequtive reads
|
|||
|
and consequtive fails on a file lock.
|
|||
|
|
|||
|
If the caller is flooding the network, the rdr will return the 0 bytes
|
|||
|
for a pipe read or lock fail to the user until NextTime is reached.
|
|||
|
When NextTime is reached BackOff will indicate that the network should
|
|||
|
be used.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Colin Watson (colinw) 02-Jan-1991
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
Typical usage would be demonstrated by fsctrl.c on the peek request.
|
|||
|
|
|||
|
1) Each time peek is called it calls RxShouldRequestBeThrottled.
|
|||
|
When the result is true, the wrapper returns to the caller a response
|
|||
|
indicating there is no data at the other end of the pipe.
|
|||
|
|
|||
|
When the result is false, a request is made to the network.
|
|||
|
|
|||
|
2) If the reply from the server to the peek in step 1 indicates that
|
|||
|
there is no data in the pipe then the wrapper calls RxInitiateOrContinueThrottling.
|
|||
|
|
|||
|
3) Whenever there is data in the pipe or when this workstation may
|
|||
|
unblock the pipe (eg. the workstation writing to the pipe)
|
|||
|
RxTerminateThrottling is called.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
ColinWatson [ColinW] 24-Dec-1990 Created
|
|||
|
Joe Linn [JoeLinn] 10-Oct-1996 Lifted from rdr1 and massaged for rdr2
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
//#pragma alloc_text(PAGE3FILE, RxBackOff) spinlock
|
|||
|
//#pragma alloc_text(PAGE3FILE, RxBackPackFailure) spinlock
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxShouldRequestBeThrottled (
|
|||
|
IN PTHROTTLING_STATE pBP
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called each time a request is made to find out if a the
|
|||
|
request should be sent to the network or a standard reply should be
|
|||
|
returned to the caller.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pBP - supplies back pack data for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE when caller should not access the network.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LARGE_INTEGER CurrentTime,SavedThrottlingTime;
|
|||
|
BOOLEAN result;
|
|||
|
|
|||
|
|
|||
|
// If the previous request worked then we should access the network.
|
|||
|
|
|||
|
if (( pBP->CurrentIncrement == 0 ) ||
|
|||
|
( pBP->MaximumDelay == 0 )) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// If the delay has expired then access the network.
|
|||
|
|
|||
|
KeQuerySystemTime(&CurrentTime);
|
|||
|
|
|||
|
InterlockedIncrement(&pBP->NumberOfQueries);
|
|||
|
|
|||
|
SavedThrottlingTime.QuadPart = 0;
|
|||
|
|
|||
|
RxAcquireSerializationMutex();
|
|||
|
|
|||
|
SavedThrottlingTime.QuadPart = pBP->NextTime.QuadPart;
|
|||
|
|
|||
|
RxReleaseSerializationMutex();
|
|||
|
|
|||
|
result = (CurrentTime.QuadPart < SavedThrottlingTime.QuadPart);
|
|||
|
|
|||
|
RxLog(("shouldthrttle=%x (%x)\n",result,pBP));
|
|||
|
|
|||
|
return(result);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RxInitiateOrContinueThrottling (
|
|||
|
IN PTHROTTLING_STATE pBP
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called each time a request fails.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pBP - supplies back pack data for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LARGE_INTEGER CurrentTime,NextTime;
|
|||
|
|
|||
|
KeQuerySystemTime(&CurrentTime);
|
|||
|
|
|||
|
if (pBP->CurrentIncrement < pBP->MaximumDelay ) {
|
|||
|
|
|||
|
//
|
|||
|
// We have reached NextTime but not our maximum delay limit.
|
|||
|
//
|
|||
|
|
|||
|
InterlockedIncrement(&pBP->CurrentIncrement);
|
|||
|
}
|
|||
|
|
|||
|
// NextTime = CurrentTime + (Interval * CurrentIncrement )
|
|||
|
|
|||
|
NextTime.QuadPart = CurrentTime.QuadPart +
|
|||
|
(pBP->Increment.QuadPart * pBP->CurrentIncrement);
|
|||
|
|
|||
|
RxAcquireSerializationMutex();
|
|||
|
|
|||
|
pBP->NextTime.QuadPart = NextTime.QuadPart;
|
|||
|
|
|||
|
RxReleaseSerializationMutex();
|
|||
|
}
|
|||
|
|
|||
|
|