mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-03-05 15:05:48 +02:00
Add Wait object and time module.
This commit is contained in:
parent
721d1127a0
commit
d633417e5d
@ -54,7 +54,11 @@
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add <code>Buffer</code>, <code>Ini</code>, <code>KeyValue</code>, <code>List</code>, <code>RegExp</code>, <code>Storage</code>, <code>String</code>, <code>StringList</code>, <code>Variant</code>, and <code>VariantList</code> objects.</p>
|
||||
<p>Add <code>Buffer</code>, <code>Ini</code>, <code>KeyValue</code>, <code>List</code>, <code>RegExp</code>, <code>Storage</code>, <code>String</code>, <code>StringList</code>, <code>Variant</code>, <code>VariantList</code>, and <code>Wait</code> objects.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add <code>time</code> module.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
|
@ -8,6 +8,7 @@ pgbackrest: \
|
||||
common/ini.o \
|
||||
common/memContext.o \
|
||||
common/regExp.o \
|
||||
common/time.o \
|
||||
common/type/buffer.o \
|
||||
common/type/keyValue.o \
|
||||
common/type/list.o \
|
||||
@ -15,6 +16,7 @@ pgbackrest: \
|
||||
common/type/stringList.o \
|
||||
common/type/variant.o \
|
||||
common/type/variantList.o \
|
||||
common/wait.o \
|
||||
config/config.o \
|
||||
config/define.o \
|
||||
config/parse.o \
|
||||
@ -27,6 +29,7 @@ pgbackrest: \
|
||||
common/ini.o \
|
||||
common/memContext.o \
|
||||
common/regExp.o \
|
||||
common/time.o \
|
||||
common/type/buffer.o \
|
||||
common/type/keyValue.o \
|
||||
common/type/list.o \
|
||||
@ -34,6 +37,7 @@ pgbackrest: \
|
||||
common/type/stringList.o \
|
||||
common/type/variant.o \
|
||||
common/type/variantList.o \
|
||||
common/wait.o \
|
||||
config/config.o \
|
||||
config/define.o \
|
||||
config/parse.o \
|
||||
|
30
src/common/time.c
Normal file
30
src/common/time.c
Normal file
@ -0,0 +1,30 @@
|
||||
/***********************************************************************************************************************************
|
||||
Time Management
|
||||
***********************************************************************************************************************************/
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "common/time.h"
|
||||
#include "common/type.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Epoch time in microseconds
|
||||
***********************************************************************************************************************************/
|
||||
TimeUSec
|
||||
timeUSec()
|
||||
{
|
||||
struct timeval currentTime;
|
||||
gettimeofday(¤tTime, NULL);
|
||||
return ((TimeUSec)currentTime.tv_sec * USEC_PER_SEC) + (TimeUSec)currentTime.tv_usec;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Sleep for specified microseconds
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
sleepUSec(TimeUSec sleepUSec)
|
||||
{
|
||||
struct timeval delay;
|
||||
delay.tv_sec = sleepUSec / USEC_PER_SEC;
|
||||
delay.tv_usec = sleepUSec % USEC_PER_SEC;
|
||||
select(0, NULL, NULL, NULL, &delay);
|
||||
}
|
25
src/common/time.h
Normal file
25
src/common/time.h
Normal file
@ -0,0 +1,25 @@
|
||||
/***********************************************************************************************************************************
|
||||
Time Management
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMON_TIME_H
|
||||
#define COMMON_TIME_H
|
||||
|
||||
#include "common/type.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Time types
|
||||
***********************************************************************************************************************************/
|
||||
typedef uint64 TimeUSec;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Constants describing number if sub-units in a second
|
||||
***********************************************************************************************************************************/
|
||||
#define USEC_PER_SEC ((TimeUSec)1000000)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
void sleepUSec(TimeUSec);
|
||||
TimeUSec timeUSec();
|
||||
|
||||
#endif
|
106
src/common/wait.c
Normal file
106
src/common/wait.c
Normal file
@ -0,0 +1,106 @@
|
||||
/***********************************************************************************************************************************
|
||||
Wait Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/memContext.h"
|
||||
#include "common/time.h"
|
||||
#include "common/wait.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Contains information about the wait handler
|
||||
***********************************************************************************************************************************/
|
||||
struct Wait
|
||||
{
|
||||
MemContext *memContext; // Context that contains the wait handler
|
||||
TimeUSec waitTime; // Total time to wait (in usec)
|
||||
TimeUSec sleepTime; // Next sleep time (in usec)
|
||||
TimeUSec sleepPrevTime; // Previous time slept (in usec)
|
||||
TimeUSec beginTime; // Time the wait began (in epoch usec)
|
||||
};
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
New wait handler
|
||||
***********************************************************************************************************************************/
|
||||
Wait *
|
||||
waitNew(double waitTime)
|
||||
{
|
||||
// Make sure wait time is valid
|
||||
if (waitTime < 0.1 || waitTime > 999999.0)
|
||||
THROW(AssertError, "waitTime must be >= 0.1 and <= 999999.0");
|
||||
|
||||
// Allocate wait object
|
||||
Wait *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("wait")
|
||||
{
|
||||
// Create object
|
||||
this = memNew(sizeof(Wait));
|
||||
this->memContext = MEM_CONTEXT_NEW();
|
||||
|
||||
// Store time
|
||||
this->waitTime = (TimeUSec)(waitTime * USEC_PER_SEC);
|
||||
|
||||
// Calculate first sleep time -- start with 1/10th of a second for anything >= 1 second
|
||||
if (this->waitTime >= USEC_PER_SEC)
|
||||
this->sleepTime = USEC_PER_SEC / 10;
|
||||
// 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 = timeUSec();
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Wait and return whether the caller has more time left
|
||||
***********************************************************************************************************************************/
|
||||
bool
|
||||
waitMore(Wait *this)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// If sleep is 0 then the wait time has already ended
|
||||
if (this->sleepTime > 0)
|
||||
{
|
||||
// Sleep required amount
|
||||
sleepUSec(this->sleepTime);
|
||||
|
||||
// Get the end time
|
||||
TimeUSec elapsedTime = timeUSec() - this->beginTime;
|
||||
|
||||
// Is there more time to go?
|
||||
if (elapsedTime < this->waitTime)
|
||||
{
|
||||
// Calculate sleep time as a sum of current and last (a Fibonacci-type sequence)
|
||||
TimeUSec sleepNextTime = this->sleepTime + this->sleepPrevTime;
|
||||
|
||||
// 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;
|
||||
}
|
||||
// Else set sleep to zero so next call will return false
|
||||
else
|
||||
this->sleepTime = 0;
|
||||
|
||||
// Need to wait more
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Free the wait
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
waitFree(Wait *this)
|
||||
{
|
||||
memContextFree(this->memContext);
|
||||
}
|
19
src/common/wait.h
Normal file
19
src/common/wait.h
Normal file
@ -0,0 +1,19 @@
|
||||
/***********************************************************************************************************************************
|
||||
Wait Handler
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMON_WAIT_H
|
||||
#define COMMON_WAIT_H
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Ini object
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct Wait Wait;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
Wait *waitNew(double waitTime);
|
||||
bool waitMore(Wait *this);
|
||||
void waitFree(Wait *this);
|
||||
|
||||
#endif
|
@ -131,6 +131,26 @@ my $oTestDef =
|
||||
'common/memContext' => TESTDEF_COVERAGE_FULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
&TESTDEF_NAME => 'time',
|
||||
&TESTDEF_TOTAL => 2,
|
||||
&TESTDEF_C => true,
|
||||
|
||||
&TESTDEF_COVERAGE =>
|
||||
{
|
||||
'common/time' => TESTDEF_COVERAGE_FULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
&TESTDEF_NAME => 'wait',
|
||||
&TESTDEF_TOTAL => 1,
|
||||
&TESTDEF_C => true,
|
||||
|
||||
&TESTDEF_COVERAGE =>
|
||||
{
|
||||
'common/wait' => TESTDEF_COVERAGE_FULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
&TESTDEF_NAME => 'type-list',
|
||||
&TESTDEF_TOTAL => 2,
|
||||
|
30
test/src/module/common/timeTest.c
Normal file
30
test/src/module/common/timeTest.c
Normal file
@ -0,0 +1,30 @@
|
||||
/***********************************************************************************************************************************
|
||||
Test Time Management
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test Run
|
||||
***********************************************************************************************************************************/
|
||||
void testRun()
|
||||
{
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("timeUSec()"))
|
||||
{
|
||||
// Make sure the time returned is between 2017 and 2100
|
||||
TEST_RESULT_BOOL(timeUSec() > (TimeUSec)1483228800000000, true, "lower range check");
|
||||
TEST_RESULT_BOOL(timeUSec() < (TimeUSec)4102444800000000, true, "upper range check");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("sleepUSec()"))
|
||||
{
|
||||
// Sleep and measure time slept
|
||||
TimeUSec begin = timeUSec();
|
||||
sleepUSec(1400000);
|
||||
TimeUSec end = timeUSec();
|
||||
|
||||
// Check bounds for time slept (within a range of .1 seconds)
|
||||
TEST_RESULT_BOOL(end - begin > (TimeUSec)1400000, true, "lower range check");
|
||||
TEST_RESULT_BOOL(end - begin < (TimeUSec)1500000, true, "upper range check");
|
||||
}
|
||||
}
|
54
test/src/module/common/waitTest.c
Normal file
54
test/src/module/common/waitTest.c
Normal file
@ -0,0 +1,54 @@
|
||||
/***********************************************************************************************************************************
|
||||
Test Wait Handler
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test Run
|
||||
***********************************************************************************************************************************/
|
||||
void testRun()
|
||||
{
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("waitNew(), waitMore, and waitFree()"))
|
||||
{
|
||||
Wait *wait = NULL;
|
||||
|
||||
TEST_ERROR(waitNew(0.01), AssertError, "waitTime must be >= 0.1 and <= 999999.0");
|
||||
TEST_ERROR(waitNew(9999999), AssertError, "waitTime must be >= 0.1 and <= 999999.0");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
unsigned long begin = timeUSec();
|
||||
|
||||
TEST_ASSIGN(wait, waitNew(0.2), "new wait = 0.2 sec");
|
||||
TEST_RESULT_DOUBLE(wait->waitTime, 200000, " check wait time");
|
||||
TEST_RESULT_DOUBLE(wait->sleepTime, 20000, " check sleep time");
|
||||
TEST_RESULT_DOUBLE(wait->sleepPrevTime, 0, " check sleep prev time");
|
||||
TEST_RESULT_BOOL(wait->beginTime > (unsigned long)1483228800000000, true, " check begin time");
|
||||
|
||||
while (waitMore(wait));
|
||||
unsigned long end = timeUSec();
|
||||
|
||||
// Check bounds for time slept (within a range of .1 seconds)
|
||||
TEST_RESULT_BOOL(end - begin >= wait->waitTime, true, " lower range check");
|
||||
TEST_RESULT_BOOL(end - begin < wait->waitTime + 100000, true, " upper range check");
|
||||
|
||||
TEST_RESULT_VOID(waitFree(wait), " free wait");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
begin = timeUSec();
|
||||
|
||||
TEST_ASSIGN(wait, waitNew(1.1), "new wait = 1.1 sec");
|
||||
TEST_RESULT_DOUBLE(wait->waitTime, 1100000, " check wait time");
|
||||
TEST_RESULT_DOUBLE(wait->sleepTime, 100000, " check sleep time");
|
||||
TEST_RESULT_DOUBLE(wait->sleepPrevTime, 0, " check sleep prev time");
|
||||
TEST_RESULT_BOOL(wait->beginTime > (unsigned long)1483228800000000, true, " check begin time");
|
||||
|
||||
while (waitMore(wait));
|
||||
end = timeUSec();
|
||||
|
||||
// Check bounds for time slept (within a range of .1 seconds)
|
||||
TEST_RESULT_BOOL(end - begin >= wait->waitTime, true, " lower range check");
|
||||
TEST_RESULT_BOOL(end - begin < wait->waitTime + 1200000, true, " upper range check");
|
||||
|
||||
TEST_RESULT_VOID(waitFree(wait), " free wait");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user