blob: 4aa7eb9aa7514fc41b4c88701c098ff01cfff107 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
* All Rights Reserved.
*=========================================================================
*/
#ifndef __PaceMeter_hpp__
#define __PaceMeter_hpp__
#include "fwklib/FwkLog.hpp"
#include <ace/Time_Value.h>
#include <ace/OS.h>
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#endif
namespace gemfire {
namespace testframework {
class Waiter {
public:
Waiter() {}
void waitUntil( ACE_Time_Value * until ) {
ACE_Time_Value now = ACE_OS::gettimeofday();
if ( *until < now ) {
return;
}
ACE_Time_Value interval = *until - now;
#ifdef WIN32
WaitForSingleObject( GetCurrentThread(), interval.msec() );
#else
struct timeval tv;
tv.tv_sec = interval.sec();
tv.tv_usec = interval.usec();
select( 1, NULL, NULL, NULL, &tv );
#endif
}
};
class PaceMeter {
private:
int32_t m_opsLimit;
int32_t m_current;
int32_t m_waitSeconds;
int32_t m_waitMicros;
ACE_Time_Value m_timeLimit;
public:
PaceMeter( int32_t ops, int32_t seconds = 1 ) :
m_opsLimit( 0 ),
m_current( 0 ),
m_waitSeconds( 0 ),
m_waitMicros( 0 ),
m_timeLimit( 0 ) {
if ( ( ops <= 0 ) || ( seconds <= 0 ) ) {
return;
}
double os = ( double )ops / ( double )seconds;
if ( ( ops / seconds ) < 1 ) { // This is for the "seconds per op" case
double dsec = 1 / os;
m_opsLimit = 1;
m_waitSeconds = ( int32_t )dsec;
dsec -= m_waitSeconds;
m_waitMicros = ( int32_t )( dsec * 1000000 );
}
else {
int32_t ios = ops / seconds;
m_waitSeconds = 0;
if ( ios < 4 ) {
m_opsLimit = ios;
m_waitSeconds = 1;
m_waitMicros = 0;
}
else {
if ( ( ios % 3 ) >= ( ios % 4 ) ) {
m_opsLimit = ios / 4;
m_waitMicros = 250000;
}
else {
m_opsLimit = ios / 3;
m_waitMicros = 333333;
}
}
}
// FWKINFO( "Args: " << ops << ", " << seconds << " Ops: " << m_opsLimit << " Seconds: " << m_waitSeconds << " Micros: " << m_waitMicros );
}
void checkPace() {
if ( m_opsLimit == 0 ) {
return;
}
if ( m_current == 0 ) {
// FWKINFO( "Setting time limit to Seconds: " << m_waitSeconds << " Micros: " << m_waitMicros );
m_timeLimit = ACE_OS::gettimeofday() + ACE_Time_Value( m_waitSeconds, m_waitMicros );
}
if ( ++m_current >= m_opsLimit ) {
// FWKINFO( "m_current is: " << m_current << " waiting." );
m_current = 0;
Waiter waiter;
waiter.waitUntil( &m_timeLimit );
}
}
};
} // namespace testframework
} // namespace gemfire
#endif // __PaceMeter_hpp__