// now, on best effort.
// Run the calibration loop and collect data.
for (int i = 0, tooLong = 0; i < iterations;) {
if (tooLong > limit) // prevent infinite loops.
throw new FatalException("Cannot establish clock offset " +
"(ms->ns), retries " + i + "," +
tooLong);
long nanos;
long millis;
long millisBefore = System.currentTimeMillis();
do {
nanos = System.nanoTime();
millis = System.currentTimeMillis();
} while (millis == millisBefore);
// Now we're on the edge of a new ms value
// Find the ms clock step for this system
// by iterating down the min step value.
clockStep[i] = (int) (millis - millisBefore);
if (clockStep[i] < msStep)
msStep = clockStep[i];
// If we discover any step bigger than the best recorded step,
// ignore the iteration.
if (msStep != Integer.MAX_VALUE && clockStep[i] > msStep) {
++tooLong;
continue;
}
diffms[i] = millis - nanos / Utilities.TO_NANOS;
diffns[i] = (int) (nanos % Utilities.TO_NANOS);
logger.finer("iter: " + i + ", millis: " + millis +
", nanos: " + nanos + ", diffms: " + diffms[i] +
", diffns: " + diffns[i] + ", stepms: " + clockStep[i]);
tooLong = 0; // Reset retry counters on success.
++i;
}
logger.fine("System.currentTimeMillis() granularity is " + msStep +
"ms");
// There might still be some records left at the beginning before
// that have the step > minstep. This happens before the minstep
// is established. We must not use these records. Count them and
// report. If more than 25% are bad, don't continue.
int badRecords = 0;
for (int i = 0; i < clockStep.length; i++) {
if (clockStep[i] > msStep) {
logger.finer("Rejected bad record " + i +
"Edge mis-detection. Clock step of " +
clockStep[i] + "ms higher than granularity.");
++badRecords;
}
}
if (badRecords > iterations / 4) {
throw new FatalException("Cannot establish clock offset " +
"(ms->ns), edge mis-detections beyond threshold - " +
badRecords + " out of " + iterations +
". Perhaps system is too busy.");
} else {
logger.fine("Rejected " + badRecords + " bad records.");