in util/src/main/java/com/epam/deltix/util/time/TimeKeeper.java [246:334]
private void doAccurateTimeMaintenance () {
long sysNanoTime = nanoTime ();
long cpuTimeNanos = sysNanoTime + offset;
boolean sysClockChanged = getSystemTimeNoRollBack ();
if (!sysClockChanged && !isRunawayConfirmed ()) {
// Keep ticking
set (cpuTimeNanos);
return;
}
long cpuTimeMillis = cpuTimeNanos / M;
long keeperAhead = cpuTimeMillis - lastTimeMillis;
if (keeperAhead < 0) {
runawayAt = IN_SYNC;
//
// Assumption: system clock is never early. Therefore,
// adjust offset just enough so that model time catches up right away
//
cpuTimeNanos = lastTimeMillis * M;
if (DEBUG) {
System.out.printf (
"TK: + %,d ns\n",
cpuTimeNanos - sysNanoTime - offset
);
}
offset = cpuTimeNanos - sysNanoTime;
set (cpuTimeNanos);
return;
}
if (keeperAhead == 0) {
runawayAt = IN_SYNC;
set (cpuTimeNanos);
return;
}
//
// keeper is ahead by at least 1ms
//
if (runawayAt == IN_SYNC) {
if (DEBUG) {
System.out.print (
"TK: Ahead, raising runaway suspicion\n"
);
}
runawayAt = lastTimeMillis + RUNAWAY_THRESHOLD_MS;
}
if (lastTimeMillis >= runawayAt) {
//
// Keeper has been consistently ahead for RUNAWAY_THRESHOLD_MS.
// Keeper time can never go back, however.
//
long maxCompliantTimeNanos = lastTimeMillis * M + (M - 1);
long minPossibleOffset = currentTimeNanos - sysNanoTime;
long targetOffset = maxCompliantTimeNanos - sysNanoTime;
if (targetOffset >= minPossibleOffset) {
if (DEBUG) {
System.out.printf (
"TK: -%,d (FINAL)\n",
offset - targetOffset
);
}
offset = targetOffset;
runawayAt = IN_SYNC;
set (maxCompliantTimeNanos);
}
else {
if (DEBUG) {
System.out.printf (
"TK: STAYING PUT; -%,d (STILL RUNAWAY)\n",
offset - minPossibleOffset
);
}
offset = minPossibleOffset;
}
}
else
set (cpuTimeNanos);
}