1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-01 00:25:06 +02:00
Files
pgbackrest/src/common/wait.c

116 lines
4.0 KiB
C
Raw Normal View History

2018-01-16 13:05:00 -05:00
/***********************************************************************************************************************************
Wait Handler
***********************************************************************************************************************************/
#include "build.auto.h"
#include "common/debug.h"
#include "common/log.h"
2018-01-16 13:05:00 -05:00
#include "common/memContext.h"
#include "common/type/object.h"
2018-01-16 13:05:00 -05:00
#include "common/wait.h"
/***********************************************************************************************************************************
Object type
2018-01-16 13:05:00 -05:00
***********************************************************************************************************************************/
struct Wait
{
WaitPub pub; // Publicly accessible variables
2018-01-16 13:05:00 -05:00
MemContext *memContext; // Context that contains the wait handler
TimeMSec waitTime; // Total time to wait (in usec)
TimeMSec sleepTime; // Next sleep time (in usec)
TimeMSec sleepPrevTime; // Previous time slept (in usec)
TimeMSec beginTime; // Time the wait began (in epoch usec)
2018-01-16 13:05:00 -05:00
};
OBJECT_DEFINE_FREE(WAIT);
/**********************************************************************************************************************************/
2018-01-16 13:05:00 -05:00
Wait *
waitNew(TimeMSec waitTime)
2018-01-16 13:05:00 -05:00
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(TIMEMSEC, waitTime);
FUNCTION_LOG_END();
ASSERT(waitTime <= 999999000);
2018-01-16 13:05:00 -05:00
// Allocate wait object
Wait *this = NULL;
MEM_CONTEXT_NEW_BEGIN("wait")
{
// Create object
this = memNew(sizeof(Wait));
*this = (Wait)
{
.pub =
{
.remainTime = waitTime,
},
.memContext = MEM_CONTEXT_NEW(),
.waitTime = waitTime,
};
2018-01-16 13:05:00 -05:00
// Calculate first sleep time -- start with 1/10th of a second for anything >= 1 second
if (this->waitTime >= MSEC_PER_SEC)
this->sleepTime = MSEC_PER_SEC / 10;
2018-01-16 13:05:00 -05:00
// Unless the wait time is really small -- in that case divide wait time by 10
else
this->sleepTime = this->waitTime / 10;
// Get beginning time
this->beginTime = timeMSec();
2018-01-16 13:05:00 -05:00
}
MEM_CONTEXT_NEW_END();
FUNCTION_LOG_RETURN(WAIT, this);
2018-01-16 13:05:00 -05:00
}
/**********************************************************************************************************************************/
2018-01-16 13:05:00 -05:00
bool
waitMore(Wait *this)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(WAIT, this);
FUNCTION_LOG_END();
ASSERT(this != NULL);
2018-01-16 13:05:00 -05:00
bool result = false;
// If sleep is 0 then the wait time has already ended
if (this->sleepTime > 0)
{
// Sleep required amount
sleepMSec(this->sleepTime);
2018-01-16 13:05:00 -05:00
// Get the end time
TimeMSec elapsedTime = timeMSec() - this->beginTime;
2018-01-16 13:05:00 -05:00
// Is there more time to go?
if (elapsedTime < this->waitTime)
{
// Calculate sleep time as a sum of current and last (a Fibonacci-type sequence)
TimeMSec sleepNextTime = this->sleepTime + this->sleepPrevTime;
2018-01-16 13:05:00 -05:00
// Make sure sleep time does not go beyond end time (this won't be negative because of the if condition above)
if (sleepNextTime > this->waitTime - elapsedTime)
sleepNextTime = this->waitTime - elapsedTime;
// Store new sleep times
this->sleepPrevTime = this->sleepTime;
this->sleepTime = sleepNextTime;
this->pub.remainTime = this->waitTime - elapsedTime;
2018-01-16 13:05:00 -05:00
}
// Else set sleep to zero so next call will return false
else
this->sleepTime = 0;
// Need to wait more
result = true;
}
FUNCTION_LOG_RETURN(BOOL, result);
2018-01-16 13:05:00 -05:00
}