/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.cache.lru;
import org.apache.geode.cache.Region;
import org.apache.geode.internal.cache.InternalRegionArguments;
import org.apache.geode.internal.cache.AbstractRegionEntry;
/**
* NewLIFOClockHand holds the behavior for LIFO logic , Overwriting getLRUEntry() to return most
* recently added Entry
*
* @since GemFire 5.7
*/
public class NewLIFOClockHand extends NewLRUClockHand {
/*
* constructor
*/
public NewLIFOClockHand(Object region, EnableLRU ccHelper,
InternalRegionArguments internalRegionArgs) {
super(region, ccHelper, internalRegionArgs);
}
public NewLIFOClockHand(Region region, EnableLRU ccHelper, NewLRUClockHand oldList) {
super(region, ccHelper, oldList);
}
/*
* Fetch the tail member which should be the last added value and remove it from the list
*/
protected LRUClockNode getTailEntry() {
LRUClockNode aNode = null;
synchronized (this.lock) {
aNode = this.tail.prevLRUNode();
if (aNode == this.head) {
return null; // end of lru list
}
// remove entry from list
LRUClockNode prev = aNode.prevLRUNode();
prev.setNextLRUNode(this.tail);
this.tail.setPrevLRUNode(prev);
aNode.setNextLRUNode(null);
aNode.setPrevLRUNode(null);
super.size--;
}
return aNode;
}
/*
* return the Entry that is considered most recently used and available to be evicted to overflow
*/
@Override
public LRUClockNode getLRUEntry() {
long numEvals = 0;
LRUClockNode aNode = null;
// search for entry to return from list
for (;;) {
aNode = getTailEntry();
// end of Lifo list stop searching
if (aNode == null) {
break;
}
numEvals++;
synchronized (aNode) {
// look for another entry if in transaction
boolean inUseByTransaction = false;
if (aNode instanceof AbstractRegionEntry) {
if (((AbstractRegionEntry) aNode).isInUseByTransaction()) {
inUseByTransaction = true;
}
}
// if entry NOT used by transaction and NOT evicted return entry
if (!inUseByTransaction && !aNode.testEvicted()) {
break;
}
}
}
this.stats().incEvaluations(numEvals);
return aNode;
}
}