/*
* Time moved backwards, if was less than three seconds, spin to let it catch up
* otherwise calculate an offset to add to the system clock in order to use it to
* continue moving forward
*/
VoltLogger log = new VoltLogger("HOST");
double diffSeconds = (lastUsedTime - currentTime) / 1000.0;
String msg = String.format("UniqueIdGenerator time moved backwards from: %d to %d, a difference of %.2f seconds.",
lastUsedTime, currentTime, diffSeconds);
log.error(msg);
System.err.println(msg);
// if the diff is less than some specified amount of time, wait a bit
if ((lastUsedTime - currentTime) < BACKWARD_TIME_FORGIVENESS_WINDOW_MS) {
log.info("This node will delay any stored procedures sent to it.");
log.info(String.format("This node will resume full operation in %.2f seconds.", diffSeconds));
long count = BACKWARD_TIME_FORGIVENESS_WINDOW_MS;
// note, the loop should stop once lastUsedTime is PASSED, not current
while ((currentTime <= lastUsedTime) && (count-- > 0)) {
try {
m_clock.sleep(1);
} catch (InterruptedException e) {}
currentTime = m_clock.get();
}
// if the loop above ended because it ran too much, time is pretty darn wonky.
// Going to let it crash in this instance
if (count < 0) {
VoltDB.crashLocalVoltDB("VoltDB was unable to recover after the system time was externally negatively adusted. " +
"It is possible that there is a serious system time or NTP error. ", false, null);
}
}
// Calculate an offset that will keep time moving forward at the rate of the system clock
// but at the current time, not the time the system clock shifted back too.
else {
m_backwardsTimeAdjustmentOffset = lastUsedTime - currentTime + 1;
//Since we calculated a new offset, recalculate the current time + the offset
currentTimePlusOffset = currentTime + m_backwardsTimeAdjustmentOffset;
//Should satisfy this constraint now
assert(currentTimePlusOffset > lastUsedTime);
double offsetSeconds = m_backwardsTimeAdjustmentOffset / 1000.0;
msg = String.format(
"Continuing operation by adding an offset of %.2f to system time. " +
"This means the time and unique IDs provided by VoltProcedure " +
" (getUniqueId, getTransactionId, getTransactionTime) " +
"will not correctly reflect wall clock time as reported by the system clock." +
" For severe shifts you could see duplicate " +
"IDs or time moving backwards when the server is" +
" restarted causing the offset to be discarded.",
offsetSeconds);
log.error(msg);
System.err.println(msg);
}
} else if (currentTime > lastUsedTime && m_backwardsTimeAdjustmentOffset != 0) {
//Actual wall clock time is correct, blast away the offset
//and switch to current time
m_backwardsTimeAdjustmentOffset = 0;
currentTimePlusOffset = currentTime;
VoltLogger log = new VoltLogger("HOST");
log.error("Host clock seems to have adjusted again to make the offset unecessary");
System.err.println("Host clock seems to have adjusted again to make the offset unecessary");
}
currentTime = currentTimePlusOffset;
lastUsedTime = currentTime;
counterValue = 0;