/** * Returns an unmodifiable snapshot map roughly ordered by the expiration time. The wheels are * evaluated in order, but the timers that fall within the bucket's range are not sorted. Beware * that obtaining the mappings is <em>NOT</em> a constant-time operation. * * @param ascending the direction * @param limit the maximum number of entries * @param transformer a function that unwraps the value * @return an unmodifiable snapshot in the desired order */ Map<K, V> variableSnapshot(boolean ascending, int limit, Function<V, V> transformer) { evictionLock.lock(); try { maintenance(/* ignored */ null); return timerWheel().snapshot(ascending, limit, transformer); } finally { evictionLock.unlock(); } }
/** Expires entries in the timer wheel. */ @GuardedBy("evictionLock") void expireVariableEntries(long now) { if (expiresVariable()) { timerWheel().advance(now); } }
private void checkTimerWheel(BoundedLocalCache<K, V> cache) { if (!cache.expiresVariable()) { return; } Set<Node<K, V>> seen = Sets.newIdentityHashSet(); for (int i = 0; i < cache.timerWheel().wheel.length; i++) { for (int j = 0; j < cache.timerWheel().wheel[i].length; j++) { Node<K, V> sentinel = cache.timerWheel().wheel[i][j]; desc.expectThat("Wrong sentinel prev", sentinel.getPreviousInVariableOrder().getNextInVariableOrder(), sameInstance(sentinel)); desc.expectThat("Wrong sentinel next", sentinel.getNextInVariableOrder().getPreviousInVariableOrder(), sameInstance(sentinel)); desc.expectThat("Sentinel must be first element", sentinel, instanceOf(Sentinel.class)); for (Node<K, V> node = sentinel.getNextInVariableOrder(); node != sentinel; node = node.getNextInVariableOrder()) { Node<K, V> next = node.getNextInVariableOrder(); Node<K, V> prev = node.getPreviousInVariableOrder(); long duration = node.getVariableTime() - cache.timerWheel().nanos; desc.expectThat("Expired", duration, greaterThan(0L)); desc.expectThat("Loop detected", seen.add(node), is(true)); desc.expectThat("Wrong prev", prev.getNextInVariableOrder(), is(sameInstance(node))); desc.expectThat("Wrong next", next.getPreviousInVariableOrder(), is(sameInstance(node))); } } } desc.expectThat("Timers != Entries", seen, hasSize(cache.size())); }
/** Updates the node's location in the page replacement policy. */ @GuardedBy("evictionLock") void onAccess(Node<K, V> node) { if (evicts()) { K key = node.getKey(); if (key == null) { return; } frequencySketch().increment(key); if (node.inEden()) { reorder(accessOrderEdenDeque(), node); } else if (node.inMainProbation()) { reorderProbation(node); } else { reorder(accessOrderProtectedDeque(), node); } } else if (expiresAfterAccess()) { reorder(accessOrderEdenDeque(), node); } if (expiresVariable()) { timerWheel().reschedule(node); } }
/** Expires entries in the timer wheel. */ @GuardedBy("evictionLock") void expireVariableEntries(long now) { if (expiresVariable()) { timerWheel().advance(now); } }
/** * Returns an unmodifiable snapshot map roughly ordered by the expiration time. The wheels are * evaluated in order, but the timers that fall within the bucket's range are not sorted. Beware * that obtaining the mappings is <em>NOT</em> a constant-time operation. * * @param ascending the direction * @param limit the maximum number of entries * @param transformer a function that unwraps the value * @return an unmodifiable snapshot in the desired order */ Map<K, V> variableSnapshot(boolean ascending, int limit, Function<V, V> transformer) { evictionLock.lock(); try { maintenance(/* ignored */ null); return timerWheel().snapshot(ascending, limit, transformer); } finally { evictionLock.unlock(); } }
writeOrderDeque().remove(node); } else if (expiresVariable()) { timerWheel().deschedule(node);
writeOrderDeque().remove(node); } else if (expiresVariable()) { timerWheel().deschedule(node);
/** Updates the node's location in the page replacement policy. */ @GuardedBy("evictionLock") void onAccess(Node<K, V> node) { if (evicts()) { K key = node.getKey(); if (key == null) { return; } frequencySketch().increment(key); if (node.inEden()) { reorder(accessOrderEdenDeque(), node); } else if (node.inMainProbation()) { reorderProbation(node); } else { reorder(accessOrderProtectedDeque(), node); } } else if (expiresAfterAccess()) { reorder(accessOrderEdenDeque(), node); } if (expiresVariable()) { timerWheel().reschedule(node); } }
writeOrderDeque().remove(node); } else if (expiresVariable()) { timerWheel().deschedule(node);
writeOrderDeque().remove(node); } else if (expiresVariable()) { timerWheel().deschedule(node);