/** * @param entry Entry to touch. * @return {@code True} if queue has been changed by this call. */ private boolean touch(GridCacheEntry<K, V> entry) { Node<GridCacheEntry<K, V>> node = entry.meta(meta); // Entry has not been enqueued yet. if (node == null) { while (true) { node = queue.offerLastx(entry); if (entry.putMetaIfAbsent(meta, node) != null) { // Was concurrently added, need to clear it from queue. queue.unlinkx(node); // Queue has not been changed. return false; } else if (node.item() != null) { if (!entry.isCached()) { // Was concurrently evicted, need to clear it from queue. queue.unlinkx(node); return false; } return true; } // If node was unlinked by concurrent shrink() call, we must repeat the whole cycle. else if (!entry.removeMeta(meta, node)) return false; } } // Entry is already in queue. return false; }
/** {@inheritDoc} */ @Override public void onEntryAccessed(boolean rmv, GridCacheEntry<K, V> entry) { if (!rmv) { if (!entry.isCached()) return; // Shrink only if queue was changed. if (touch(entry)) shrink(); } else { Node<GridCacheEntry<K, V>> node = entry.removeMeta(meta); if (node != null) queue.unlinkx(node); } }
/** Shrinks FIFO queue to maximum allowed size. */ private void shrink() { int max = this.max; int startSize = queue.sizex(); for (int i = 0; i < startSize && queue.sizex() > max; i++) { GridCacheEntry<K, V> entry = queue.poll(); if (entry == null) break; if (!entry.evict()) { entry.removeMeta(meta); touch(entry); } } }