public long getExpensiveListCount() { synchronized (lock) { long count = 0; for (LRUClockNode aNode = this.head.nextLRUNode(); aNode != this.tail; aNode = aNode.nextLRUNode()) { count++; } return count; } }
public void dumpList() { final boolean isDebugEnabled = logger.isTraceEnabled(LogMarker.LRU_CLOCK); if (!isDebugEnabled) { return; } synchronized (lock) { int idx = 1; for (LRUClockNode aNode = this.head; aNode != null; aNode = aNode.nextLRUNode()) { if (isDebugEnabled) { logger.trace(LogMarker.LRU_CLOCK, " ({}) {}", (idx++), aNode); } } } }
/** * Adds a new lru node for the entry between the current tail and head of the list. * * @param aNode Description of the Parameter */ public final void appendEntry(final LRUClockNode aNode) { synchronized (this.lock) { if (aNode.nextLRUNode() != null || aNode.prevLRUNode() != null) { return; } if (logger.isTraceEnabled(LogMarker.LRU_CLOCK)) { logger.trace( LogMarker.LRU_CLOCK, LocalizedMessage.create( LocalizedStrings.NewLRUClockHand_ADDING_ANODE_TO_LRU_LIST, aNode)); } aNode.setNextLRUNode(this.tail); this.tail.prevLRUNode().setNextLRUNode(aNode); aNode.setPrevLRUNode(this.tail.prevLRUNode()); this.tail.setPrevLRUNode(aNode); this.size++; } }
public String getAuditReport() { LRUClockNode h = this.head; int totalNodes = 0; int evictedNodes = 0; int usedNodes = 0; while (h != null) { totalNodes++; if (h.testEvicted()) evictedNodes++; if (h.testRecentlyUsed()) usedNodes++; h = h.nextLRUNode(); } StringBuffer result = new StringBuffer(128); result .append("LRUList Audit: listEntries = ") .append(totalNodes) .append(" evicted = ") .append(evictedNodes) .append(" used = ") .append(usedNodes); return result.toString(); }
/** remove an entry from the pipe... (marks it evicted to be skipped later) */ public boolean unlinkEntry(LRUClockNode entry) { if (logger.isTraceEnabled(LogMarker.LRU_CLOCK)) { logger.trace( LogMarker.LRU_CLOCK, LocalizedMessage.create(LocalizedStrings.NewLRUClockHand_UNLINKENTRY_CALLED, entry)); } entry.setEvicted(); stats().incDestroys(); synchronized (lock) { LRUClockNode next = entry.nextLRUNode(); LRUClockNode prev = entry.prevLRUNode(); if (next == null || prev == null) { // not in the list anymore. return false; } next.setPrevLRUNode(prev); prev.setNextLRUNode(next); entry.setNextLRUNode(null); entry.setPrevLRUNode(null); } return true; }
/** * return the head entry in the list preserving the cupipe requirement of at least one entry left * in the list */ private LRUClockNode getHeadEntry() { synchronized (lock) { LRUClockNode aNode = NewLRUClockHand.this.head.nextLRUNode(); if (aNode == this.tail) { return null; } LRUClockNode next = aNode.nextLRUNode(); this.head.setNextLRUNode(next); next.setPrevLRUNode(this.head); aNode.setNextLRUNode(null); aNode.setPrevLRUNode(null); this.size++; return aNode; } }
/** * return the Entry that is considered least recently used. The entry will no longer be in the * pipe (unless it is the last empty marker). */ public LRUClockNode getLRUEntry() { long numEvals = 0; for (; ; ) { LRUClockNode aNode = null; aNode = getHeadEntry(); if (logger.isTraceEnabled(LogMarker.LRU_CLOCK)) { logger.trace(LogMarker.LRU_CLOCK, "lru considering {}", aNode); } if (aNode == null) { // hit the end of the list this.stats.incEvaluations(numEvals); return aNode; } // hit the end of the list numEvals++; // If this Entry is part of a transaction, skip it since // eviction should not cause commit conflicts synchronized (aNode) { if (aNode instanceof AbstractRegionEntry) { if (((AbstractRegionEntry) aNode).isInUseByTransaction()) { if (logger.isTraceEnabled(LogMarker.LRU_CLOCK)) { logger.trace( LogMarker.LRU_CLOCK, LocalizedMessage.create( LocalizedStrings .NewLRUClockHand_REMOVING_TRANSACTIONAL_ENTRY_FROM_CONSIDERATION)); } continue; } } if (aNode.testEvicted()) { if (logger.isTraceEnabled(LogMarker.LRU_CLOCK)) { logger.trace( LogMarker.LRU_CLOCK, LocalizedMessage.create(LocalizedStrings.NewLRUClockHand_DISCARDING_EVICTED_ENTRY)); } continue; } // At this point we have any acceptable entry. Now // use various criteria to determine if it's good enough // to return, or if we need to add it back to the list. if (maxEntries > 0 && numEvals > maxEntries) { if (logger.isTraceEnabled(LogMarker.LRU_CLOCK)) { logger.trace( LogMarker.LRU_CLOCK, LocalizedMessage.create( LocalizedStrings.NewLRUClockHand_GREEDILY_PICKING_AN_AVAILABLE_ENTRY)); } this.stats.incGreedyReturns(1); // fall through, return this node } else if (aNode.testRecentlyUsed()) { // Throw it back, it's in the working set aNode.unsetRecentlyUsed(); // aNode.setInList(); if (logger.isTraceEnabled(LogMarker.LRU_CLOCK)) { logger.trace( LogMarker.LRU_CLOCK, LocalizedMessage.create( LocalizedStrings.NewLRUClockHand_SKIPPING_RECENTLY_USED_ENTRY, aNode)); } appendEntry(aNode); continue; // keep looking } else { if (logger.isTraceEnabled(LogMarker.LRU_CLOCK)) { logger.trace( LogMarker.LRU_CLOCK, LocalizedMessage.create( LocalizedStrings.NewLRUClockHand_RETURNING_UNUSED_ENTRY, aNode)); } // fall through, return this node } // Return the current node. this.stats.incEvaluations(numEvals); return aNode; } // synchronized } // for }