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
  }