/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.collections.containers.recordManager; import java.util.Iterator; import java.util.LinkedList; import java.util.SortedMap; import xxl.core.collections.containers.recordManager.RecordManager.PageInformation; public class LRUStrategy extends AbstractStrategy { /** * Information which is stored for each of the last n * allocated pages. This class implements the method equal * (important for removal from a list). */ protected class PageEntry { /** * The identifyer of a page. */ protected Object pageId; /** * The additional information used for a page. */ protected PageInformation pi; /** * Constructs a new entry. * @param pageId The identifyer of a page. * @param pi The additional information used for a page. */ protected PageEntry(Object pageId, PageInformation pi) { this.pageId = pageId; this.pi = pi; } /** * Returns true iff the page identifyers are identical. * @param o Object of type PageEntry with which the current * Object is compared. * @return true iff the page identifyers are identical. */ public boolean equals(Object o) { return pageId.equals(((PageEntry) o).pageId); } } /** * Pages with the most free space. */ protected LinkedList lastPages; /** * Number of pages inside the queue (at most). */ protected int n; /** * Creates a BestFitOnNEmptiestPagesStrategy object. * @param n Number of pages which are stored inside. */ public LRUStrategy(int n) { this.n = n; lastPages = new LinkedList(); } /** * Returns the number of pages inside the queue (at most). * @return Returns the number of pages inside the queue (at most). */ public int getN() { return n; } /** * At the time of initialization, the data of the * n emptiest pages are taken. Computation is * done via a heap. * @see xxl.core.collections.containers.recordManager.Strategy#init(java.util.SortedMap, int, int) */ public void init(SortedMap pages, int pageSize, int maxObjectSize) { super.init(pages, pageSize, maxObjectSize); lastPages.clear(); } /** * Finds a block with enough free space to hold the given number * of bytes. * @param bytesRequired The free space needed, in bytes. * @return Id of the Page or null, if no such page exists. */ public Object getPageForRecord(int bytesRequired) { Object pageId=null; int bytesFree=Integer.MAX_VALUE; Iterator it = lastPages.iterator(); while (it.hasNext()) { PageEntry sp = (PageEntry) it.next(); int currentBytesFree = sp.pi.bytesFreeAfterPossibleReservation(bytesRequired); if (currentBytesFree>=0) { if (currentBytesFree<bytesFree) { pageId = sp.pageId; bytesFree = currentBytesFree; } } } return pageId; } /** * @see xxl.core.collections.containers.recordManager.Strategy#pageRemoved(java.lang.Object, xxl.core.collections.containers.recordManager.RecordManager.PageInformation) */ public void pageRemoved(Object pageId, PageInformation pi) { // if it is inside the structures, remove it. lastPages.remove(new PageEntry(pageId, pi)); } /** * @see xxl.core.collections.containers.recordManager.Strategy#recordUpdated(java.lang.Object, xxl.core.collections.containers.recordManager.RecordManager.PageInformation, short, int, int, int) */ public void recordUpdated(Object pageId, PageInformation pi, short recordNumber, int recordsAdded, int bytesAdded, int linkRecordsAdded) { PageEntry peNew = new PageEntry(pageId, pi); lastPages.remove(peNew); // Remove and insert at the beginning! lastPages.addLast(peNew); if (lastPages.size()>=n) // If there has not been removed a page... lastPages.removeFirst(); } }