/* 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.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import xxl.core.collections.MapEntry;
import xxl.core.collections.containers.recordManager.RecordManager.PageInformation;
/**
* This class provides a last-to-first-fit-strategy for the record-manager.
* It inserts a new record into the first block with enough free space it
* finds in linear search starting from the end of the record manager going
* to the beginning.
* <p>
* This class does not have a state. So no information is written when
* calling write.
*
* @see RecordManager
* @see Strategy
*/
public class LastToFirstFitStrategy extends AbstractStrategy {
/**
* ArrayList for storing the pages a second time. This is
* necessary, because no reverse iterator is implemented inside
* the Java API.
*/
protected ArrayList pageList;
/**
* Creates a new FirstFitStrategy object.
*/
public LastToFirstFitStrategy() {
pageList = null;
}
/**
* Initializes the strategy. This call must be made, before the
* first real (other) operation is performed. The call can also
* be made multiple times.
* @param pages SortedMap with key pageId and value of type PageInformation.
* @param pageSize size of each page in bytes.
* @param maxObjectSize Size of the largest record which can be stored
* inside the RecordManager.
*/
public void init(SortedMap pages, int pageSize, int maxObjectSize) {
super.init(pages, pageSize, maxObjectSize);
pageList = new ArrayList();
Iterator it = pages.entrySet().iterator();
while (it.hasNext()) {
Map.Entry me = (Map.Entry) it.next();
pageList.add(new MapEntry(me.getKey(), me.getValue()));
}
}
/**
* Informs the strategy, that a new page has been inserted by the RecordManager.
* @param pageId identifyer of the page which has been inserted.
* @param pi PageInformation for the page.
*/
public void pageInserted(Object pageId, PageInformation pi) {
pageList.add(new MapEntry(pageId, pi));
}
/**
* Informs the strategy, that a page has been deleted by the RecordManager.
* @param pageId identifyer of the page which has been removed.
* @param pi PageInformation for the page.
*/
public void pageRemoved(Object pageId, PageInformation pi) {
pageList.remove(new MapEntry(pageId, pi));
}
/**
* 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) {
int size = pageList.size();
Object pageId=null;
PageInformation pi;
for (int i = size-1; i>=0; i--) {
MapEntry me = (MapEntry) pageList.get(i);
pageId = me.getKey();
pi = (PageInformation) me.getValue();
if (pi.bytesFreeAfterPossibleReservation(bytesRequired)>=0)
return pageId;
}
return null;
}
}