JSWINDOW.CPP
// --jswindow.cpp--------------------------------------------------------------- 
// 
//  Implements a Jump Sliding window (jswindow) object.  The window collects 
//  events and can return either an estimate or actual number of events 
//  collected during the most recent window period. 
// 
//  The window contains a current register and a FIFO buffer. 
// 
// 
//    |___|    |___|___|___|___|___|___| ... |___|___| 
//   Current     1   2   3   4   5   6        i-1  i 
//                      FIFO Buffer 
// 
//  The current register will collect events until the current interval has 
//  passed. The this interval defines the resolution of the JSWindow. 
//  A typical interval resolution is 10 seconds. 
// 
//  When the current register's interval has elapsed, it dumps its contents 
//  into the FIFO buffer. In doing so it pushes the oldest contents out of 
//  the end of the buffer.  The length of the FIFO buffer is called the 
//  "duration" of the window and is expressed as the number of intervals. 
// 
//  A running total of all of the events contained within the FIFO buffer 
//  is kept. Whenever new events are added to the buffer, they are also 
//  added to the running total. When the old events are pushed out of the 
//  end of the buffer, they are subtracted from the running total. 
// 
//  The running total is the number of events recorded in the last 
//  "duration" of time.  ie.  If the duration time is 60 resolution 
//  units, each resolution unit being 60 seconds long, then the 
//  running total is the number of events per hour (60 * 60 = 3600 seconds). 
// 
//  You can query the window value using the GetValue() member function. 
//  If the interval hasn't had time to fill (ie. if the interval is 1 hour and 
//  you query it after 1 minute) then the ratio of dwFractionCompleteNum / 
//  dwFractionCompleteDen will represent the fraction of the window 
//  period that was filled when the GetValue request was made. 
// 
//  This code is NOT multithread safe. 
//  
// Copyright (C) Microsoft Corp. 1986-1996.  All Rights Reserved. 
// ----------------------------------------------------------------------------- 
 
#include "edk.h" 
#include "jswindow.h" 
#include "jswindow.chk" 
 
 
//$--CJSWindow::CJSWindow------------------------------------------------------- 
//  Constructor 
// ----------------------------------------------------------------------------- 
CJSWindow::CJSWindow() 
{ 
    DEBUGPRIVATE("CJSWindow::CJSWindow\n"); 
 
} 
 
//$--CJSWindow::~CJSWindow------------------------------------------------------ 
//  Destructor 
// ----------------------------------------------------------------------------- 
CJSWindow::~CJSWindow() 
{ 
    DEBUGPRIVATE("CJSWindow::~CJSWindow\n"); 
 
} 
 
//$--CJSWindow::HrReset--------------------------------------------------------- 
//  Sets up the parameters of the JSWindow. This function must be called 
//  after creating and before using the interval. 
// ----------------------------------------------------------------------------- 
HRESULT CJSWindow::HrReset(        // RETURNS: HRESULT 
    IN __int64 liNow,              // The current time in arbitrary units. 
    IN __int64 liResolution,       // The resolution of the interval in arbitrary units. 
    IN DWORD dwWindowDuration)     // The interval duration expressed in multiples of 
                                   // resolution. 
{ 
    HRESULT hr = NOERROR; 
 
    DEBUGPRIVATE("CJSWindow::rcReset\n"); 
 
    hr = m_FIFO.HrReset(dwWindowDuration); 
 
    m_liCurrentIntervalTimeStart = liNow; 
    m_liResolution = liResolution; 
    m_dwIntervalValue = 0; 
 
    RETURN(hr); 
} 
 
 
//$--CJSWindow::AdvanceToNow---------------------------------------------------- 
//  Advances the JSWindow so that liNow is within the current active interval. 
// ----------------------------------------------------------------------------- 
VOID CJSWindow::AdvanceToNow(       // RETURNS: nothing 
    IN __int64 liNow,               // Current time. 
    OUT DWORD &dwFIFOOut,           // Data pushed out of the FIFO buffer 
OUT BOOL &fAdvanced)            // returns TRUE if a jump happened 
{ 
 
    HRESULT hr = NOERROR; 
    DWORD dwFIFOOut1    = 0; 
    DWORD dwFIFOOut2    = 0; 
    DWORD iDelta        = 0; 
    __int64 liDeltaTime = 0; 
 
    DEBUGPRIVATE("CJSWindow::AdvanceToNow\n"); 
 
fAdvanced = FALSE; 
 
hr = CHK_CJSWindow_AdvanceToNow(liNow, dwFIFOOut, fAdvanced); 
if (FAILED(hr)) 
return; 
 
    ASSERTERROR(m_liResolution!=0,"CJSWindow::AdvanceToNow() member m_liResolution == 0"); 
 
    // Calculate the number of intervals that have passed since 
    // the window was last updated and liNow.  
    // 
    // Find the difference between liNow and the last interval and divide 
    // by the resolution. 
    // 
    // ----------------------------------------------------------------------------- 
 
    liDeltaTime = liNow - m_liCurrentIntervalTimeStart; 
    iDelta = (DWORD)(liDeltaTime / m_liResolution); 
 
    if (iDelta > 0) 
    { 
        fAdvanced = TRUE; 
        m_FIFO.PushElement(m_dwIntervalValue, dwFIFOOut1); 
        m_dwIntervalValue = 0; 
 
 
        m_FIFO.PushNNulls(iDelta-1, dwFIFOOut2); 
        m_liCurrentIntervalTimeStart = (m_liResolution * iDelta) + m_liCurrentIntervalTimeStart; 
    } 
 
    dwFIFOOut = dwFIFOOut1 + dwFIFOOut2; 
 
    return; 
} 
 
 
//$--CJSWindowTotal::HrReset---------------------------------------------------- 
//  Sets up the parameters of the JSWindow. This function must be called 
//  after creating and before using the interval. 
// ----------------------------------------------------------------------------- 
HRESULT CJSWindowTotal::HrReset(   // RETURNS: HRESULT 
    IN __int64 liNow,              // The current time in arbitrary units. 
    IN __int64 liResolution,       // The resolution of the interval in arbitrary units. 
    IN DWORD dwWindowDuration)     // The interval duration expressed in multiples of 
                                   // resolution. 
{ 
    HRESULT hr = NOERROR; 
 
    DEBUGPRIVATE("CJSWindowTotal::HrReset()\n"); 
 
hr = CHK_CJSWindowTotal_HrReset(liNow, liResolution, dwWindowDuration); 
if (FAILED(hr)) 
RETURN(hr); 
 
    hr = CJSWindow::HrReset(liNow,liResolution,dwWindowDuration); 
 
    m_dwWindowTotal = 0; 
 
    RETURN(hr); 
} 
 
//$--CJSWindowTotal::DataPoint-------------------------------------------------- 
//  Used to add a count of events to the total window. 
// ----------------------------------------------------------------------------- 
VOID CJSWindowTotal::DataPoint( 
    IN __int64 liNow,           // Event time in arbitrary units. 
    IN DWORD dwValue)           // Number of events to add for this time. 
{ 
    HRESULT hr = NOERROR; 
    DWORD dwFIFOIn  = 0; 
    DWORD dwFIFOOut  = 0; 
    BOOL fAdvanced = FALSE; 
 
    DEBUGPRIVATE("CJSWindowTotal::DataPoint()\n"); 
 
hr = CHK_CJSWindowTotal_DataPoint(liNow, dwValue); 
if (FAILED(hr)) 
return; 
 
    dwFIFOIn = m_dwIntervalValue; 
 
    AdvanceToNow(liNow, dwFIFOOut, fAdvanced); 
    if (fAdvanced) 
    { 
        m_dwWindowTotal += dwFIFOIn; 
        m_dwWindowTotal -= dwFIFOOut; 
    } 
 
    m_dwIntervalValue += dwValue; 
} 
 
 
//$--CJSWindowTotal::HrGetValue------------------------------------------------- 
//  Returns the total number of events in the window period. Also returns 
//  the number of intervals that have been entered. 
// ----------------------------------------------------------------------------- 
HRESULT CJSWindowTotal::HrGetValue( 
    IN __int64 liNow,                   // Current time expressed as FILETIME. 
    OUT DWORD &dwValue,                 // Receives window value. 
    OUT DWORD &dwFractionCompleteNum,   // numerator 
    OUT DWORD &dwFractionCompleteDen)   // denominator 
{ 
    HRESULT hr          = NOERROR; 
    DWORD dwFIFOOut     = 0; 
    DWORD dwFIFOIn      = 0; 
    BOOL fAdvanced      = FALSE; 
 
    DEBUGPRIVATE("CJSWindowTotal::HrGetValue()\n"); 
 
hr = CHK_CJSWindowTotal_HrGetValue( 
liNow,  
dwValue,  
dwFractionCompleteNum,  
dwFractionCompleteDen); 
if (FAILED(hr)) 
RETURN(hr); 
 
    dwValue = 0; 
    dwFractionCompleteNum = 0; 
    dwFractionCompleteDen = 1; 
 
    dwFIFOIn = m_dwIntervalValue; 
    AdvanceToNow(liNow, dwFIFOOut, fAdvanced); 
    if (fAdvanced) 
    { 
        m_dwWindowTotal += dwFIFOIn; 
        m_dwWindowTotal -= dwFIFOOut; 
    } 
 
    if (m_FIFO.dwNumberElements() != 0 ) 
    { 
        dwValue =  m_dwWindowTotal; 
        dwFractionCompleteNum = m_FIFO.dwNumberElements(); 
        dwFractionCompleteDen = m_FIFO.dwMaxNumberElements(); 
    } 
 
    RETURN(hr); 
} 
 
 
//$--CJSWindowMin::DataPoint---------------------------------------------------- 
//  Used to add a count of events to the total window. 
// ----------------------------------------------------------------------------- 
VOID CJSWindowMin::DataPoint( 
    IN __int64 liNow,           // Event time in arbirary units. 
    IN DWORD dwValue)           // Number of events to add for this time. 
{ 
    HRESULT hr = NOERROR; 
    DWORD dwFIFOOut; 
    BOOL fAdvanced = FALSE; 
 
    DEBUGPRIVATE("CJSWindow::DataPoint()\n"); 
 
hr = CHK_CJSWindowMin_DataPoint(liNow, dwValue); 
if (FAILED(hr)) 
return; 
 
    AdvanceToNow(liNow, dwFIFOOut, fAdvanced); 
 
    if (m_dwIntervalValue > dwValue) 
        m_dwIntervalValue = dwValue; 
} 
 
 
//$--CJSWindowMin::HrGetValue--------------------------------------------------- 
//  Returns the total number of events in the window period. Also returns 
//  the number of intervals that have been entered. 
// ----------------------------------------------------------------------------- 
HRESULT CJSWindowMin::HrGetValue( 
    IN __int64 liNow,                   // Current time expressed as FILETIME. 
    OUT DWORD &dwValue,                 // Receives window value. 
    OUT DWORD &dwFractionCompleteNum,   // numerator 
    OUT DWORD &dwFractionCompleteDen)   // denominator 
{ 
    HRESULT hr = NOERROR; 
    DWORD i = 0; 
    DWORD dwFIFOOut =0; 
    BOOL fAdvanced = FALSE; 
 
    DEBUGPRIVATE("CJSWindowMin::HrGetValue()\n"); 
 
hr = CHK_CJSWindowMin_HrGetValue( 
liNow,  
dwValue,  
dwFractionCompleteNum,  
dwFractionCompleteDen); 
if (FAILED(hr)) 
RETURN(hr); 
 
    dwValue = 0; 
    dwFractionCompleteNum = 0; 
    dwFractionCompleteDen = 1; 
 
    AdvanceToNow(liNow, dwFIFOOut, fAdvanced); 
    m_FIFO.Min(dwValue); 
 
    dwFractionCompleteNum = m_FIFO.dwNumberElements(); 
    dwFractionCompleteDen = m_FIFO.dwMaxNumberElements(); 
 
    RETURN(hr); 
} 
 
 
//$--CJSWindowMax::DataPoint---------------------------------------------------- 
//  Used to add a count of events to the total window. 
// ----------------------------------------------------------------------------- 
VOID CJSWindowMax::DataPoint( 
    IN __int64 liNow,           // Event time in arbirary units. 
    IN DWORD dwValue)           // Number of events to add for this time. 
{ 
    HRESULT hr = NOERROR; 
    DWORD dwFIFOOut = 0; 
    BOOL fAdvanced = FALSE; 
 
    DEBUGPRIVATE("CJSWindowMax::DataPoint()\n"); 
 
hr = CHK_CJSWindowMax_DataPoint(liNow, dwValue); 
if (FAILED(hr)) 
return; 
 
    AdvanceToNow(liNow, dwFIFOOut, fAdvanced); 
 
    if (m_dwIntervalValue < dwValue) 
        m_dwIntervalValue = dwValue; 
} 
 
 
//$--CJSWindowMax::HrGetValue--------------------------------------------------- 
//  Returns the total number of events in the window period. Also returns 
//  the number of intervals that have been entered. 
// ----------------------------------------------------------------------------- 
HRESULT CJSWindowMax::HrGetValue( 
    IN __int64 liNow,                  // Current time expressed as FILETIME. 
    OUT DWORD &dwValue,                // Receives window value. 
    OUT DWORD &dwFractionCompleteNum,  // Numerator of fraction completed. 
    OUT DWORD &dwFractionCompleteDen)  // Denominator of fraction completed. 
{ 
    HRESULT hr = NOERROR; 
    DWORD i = 0; 
    DWORD dwFIFOOut = 0; 
    BOOL fAdvanced = FALSE; 
 
    DEBUGPRIVATE("CJSWindowMax::HrGetValue()\n"); 
 
hr = CHK_CJSWindowMax_HrGetValue( 
liNow,  
dwValue,  
dwFractionCompleteNum,  
dwFractionCompleteDen); 
if (FAILED(hr)) 
RETURN(hr); 
 
    dwValue = 0; 
    dwFractionCompleteNum = 0; 
    dwFractionCompleteDen = 1; 
 
    AdvanceToNow(liNow,dwFIFOOut, fAdvanced); 
 
    m_FIFO.Max(dwValue); 
    dwFractionCompleteNum = m_FIFO.dwNumberElements(); 
    dwFractionCompleteDen = m_FIFO.dwMaxNumberElements(); 
 
    RETURN(hr); 
} 
 
 
//$--CJSWindowAverage::HrReset---------------------------------------------------- 
//  Sets up the parameters of the JSWindow. This function must be called 
//  after creating and before using the interval. 
// ----------------------------------------------------------------------------- 
HRESULT CJSWindowAverage::HrReset( // RETURNS: HRESULT 
    IN __int64 liNow,              // The current time in arbitrary units. 
    IN __int64 liResolution,       // The resolution of the interval in arbitrary units. 
    IN DWORD dwWindowDuration)     // The interval duration expressed in multiples of 
                                   // resolution. 
{ 
    HRESULT hr = NOERROR; 
 
    DEBUGPRIVATE("CJSWindowAverage::HrReset\n"); 
 
hr = CHK_CJSWindowAverage_HrReset(liNow, liResolution, dwWindowDuration); 
if (FAILED(hr)) 
RETURN(hr); 
 
    m_cIntervalValues = 0; 
    m_dwIntervalTotal = 0; 
 
    hr = CJSWindow::HrReset(liNow, liResolution, dwWindowDuration); 
    RETURN(hr); 
} 
 
 
//$--CJSWindowAverage::DataPoint---------------------------------------------------- 
//  Used to add a count of events to the total window. 
// ----------------------------------------------------------------------------- 
VOID CJSWindowAverage::DataPoint( 
    IN __int64 liNow,             // Event time in arbirary units. 
    IN DWORD dwValue)             // Number of events to add for this time. 
{ 
    HRESULT hr = NOERROR; 
    DWORD dwFIFOOut = 0; 
    BOOL  fAdvanced = FALSE; 
 
    DEBUGPRIVATE("CJSWindowAverage::DataPoint()\n"); 
 
hr = CHK_CJSWindowAverage_DataPoint(liNow, dwValue); 
if (FAILED(hr)) 
return; 
 
    AdvanceToNow(liNow, dwFIFOOut, fAdvanced); 
 
    if (fAdvanced) 
    { 
        m_dwIntervalTotal = 0; 
        m_cIntervalValues = 0; 
    } 
 
    m_dwIntervalTotal += dwValue; 
    m_cIntervalValues ++; 
    if (m_cIntervalValues > 0) 
        m_dwIntervalValue = m_dwIntervalTotal / m_cIntervalValues; 
    else 
        m_dwIntervalValue = 0; 
 
} 
 
//$--CJSWindowAverage::HrGetValue----------------------------------------------- 
//  Returns the total number of events in the window period. Also returns 
//  the number of intervals that have been entered. 
// ----------------------------------------------------------------------------- 
HRESULT CJSWindowAverage::HrGetValue( 
    IN __int64 liNow,                   // Current time expressed as FILETIME. 
    OUT DWORD &dwValue,                 // Receives window value. 
    OUT DWORD &dwFractionCompleteNum,   // numerator 
    OUT DWORD &dwFractionCompleteDen)   // denominator 
{ 
    HRESULT hr = NOERROR; 
    DWORD dwSum = 0; 
    DWORD i = 0; 
    DWORD dwFIFOOut = 0; 
    BOOL fAdvanced = FALSE; 
 
    DEBUGPRIVATE("CJSWindowAverage::HrGetValue()\n"); 
 
hr = CHK_CJSWindowAverage_HrGetValue( 
liNow,  
dwValue,  
dwFractionCompleteNum,  
dwFractionCompleteDen); 
if (FAILED(hr)) 
RETURN(hr); 
 
    dwValue = 0; 
    dwFractionCompleteNum = 0; 
    dwFractionCompleteDen = 1; 
 
    AdvanceToNow(liNow, dwFIFOOut, fAdvanced); 
 
    m_FIFO.Average(dwValue); 
    dwFractionCompleteNum = m_FIFO.dwNumberElements(); 
    dwFractionCompleteDen = m_FIFO.dwMaxNumberElements(); 
 
    RETURN(hr); 
}