long now = System.currentTimeMillis();
// The cacheTimePostExpiry is not included here as this is our opportunity to inform the client to use a
// replacement nonce without a stale round trip.
long earliestAccepted = now - firstUseTimeOut;
if (value.timeStamp < earliestAccepted || value.timeStamp > now) {
XnioExecutor executor = exchange.getIoThread();
Nonce replacement = createNewNonce(holder);
if (value.executorKey != null) {
// The outcome doesn't matter - if we have the value we have all we need.
value.executorKey.remove();
}
nonce = replacement.nonce;
// Create a record of the forward mapping so if any requests do need to be marked stale they can be
// pointed towards the correct nonce to use.
forwardMapping.put(holder, nonce);
// Bring over any existing session key.
replacement.setSessionKey(value.getSessionKey());
// At this point we will not accept the nonce again so remove it from the list of known nonces but do
// register the replacement.
knownNonces.remove(holder.nonce);
// There are two reasons for registering the replacement 1 - to preserve any session key, 2 - To keep a
// reference to the now invalid key so it
// can be used as a key in a weak hash map.
knownNonces.put(nonce, replacement);
earliestAccepted = now - (overallTimeOut + cacheTimePostExpiry);
long timeTillExpiry = replacement.timeStamp - earliestAccepted;
replacement.executorKey = executor.executeAfter(new KnownNonceCleaner(nonce), timeTillExpiry,
TimeUnit.MILLISECONDS);
}
}
}