/* 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.sweepAreas;
import xxl.core.cursors.Cursors;
import xxl.core.cursors.filters.Filter;
import xxl.core.cursors.filters.Remover;
import xxl.core.functions.AbstractFunction;
import xxl.core.functions.Function;
import xxl.core.predicates.AbstractPredicate;
/**
* Default implementation for a memory manageable SweepArea.
* If this SweepArea reaches its limit of main memory,
* it randomly drops 20% of its content (load shedding).
*/
public class DefaultMemoryManageableSA<I,E> extends MemoryManageableSA<I,E> {
public static <I,E> Function<SweepArea<I,E>,DefaultMemoryManageableSA<I,E>> getMemoryManageableSA(final SweepArea<I,E> sweepArea, final int objectSize, final int preferredMemSize) {
return new AbstractFunction<SweepArea<I,E>,DefaultMemoryManageableSA<I,E>>() {
public DefaultMemoryManageableSA<I,E> invoke() {
return new DefaultMemoryManageableSA<I,E>(sweepArea, objectSize, preferredMemSize);
}
};
}
public static <I,E> DefaultMemoryManageableSA wrapSweepArea(SweepArea<I,E> sweepArea, final int objectSize, final int preferredMemSize) {
return new DefaultMemoryManageableSA<I,E>(sweepArea, objectSize, preferredMemSize);
}
/**
* This inner class provides a predicate for the remove filter for the
* load shedder.
* The method <code>invoke</code> returns <code>true</code> for every
* x-th method call on the average, where x is the ratio of
* <code>p/q</code>.
*/
public static class EveryQth<E> extends AbstractPredicate<E> {
// Fuer q=1 verhaelt sich EveryQth(p,q) identisch zu xxl.predicates.EveryNth(p).
// Ansonsten ist EveryQth die Verallgemeinerung von EveryNth auf rationale Zahlen p/q.
/**
* The counter how often the method <code>invoke</code> was called.
*/
protected long count = 0;
/**
* The counter how often the method <code>invoke</code> returned the
* value <code>true</code>.
*/
protected long applied = 0;
/**
* The numerator of the fraction <code>p/q</code>
*/
protected long p;
/**
* The denominator of the fraction <code>p/q</code>
*/
protected long q;
/**
* Constructs a new EveryQth object with <code>p/q</code> as its ratio.
*
* @param p The numerator of the fraction <code>p/q</code>
* @param q The denominator of the fraction <code>p/q</code>
*/
public EveryQth (int p, int q) {
if (q==0 || p/q<1)
throw new IllegalArgumentException("the fraction p/q must be greater or equal to 1");
this.p = p;
this.q = q;
}
/**
* Returns <code>true</code> or <code>false</code> according to
* the number of previous method calls.
* On the average the value <code>true</code> will be returned
* <code>q/p</code> times of the method calls,
* and accordingly the value <code>false</code> will be returned
* <code>(1 - q/p)</code> times of the method calls.
* The returned <code>true</code>-values are uniformly distributed
* among the several method calls.
*
* @param argument This argument is irrelevant, it may be <I>null</I>.
*/
public boolean invoke (E argument) {
count++;
if (p*applied<q*count) {
applied++;
return true;
}
return false;
}
} // END of inner class EveryQth
/**
* Creates a memory manageable SweepArea by decorating the underlying
* SweepArea.
*
* @param sweepArea The underlying SweepArea
* @param objectSize The size of the objects in this SweepArea (in bytes).
* @param memSize The preferred amount of memory (in bytes).
*/
public DefaultMemoryManageableSA(SweepArea<I,E> sweepArea, int objectSize, int memSize) {
super(sweepArea, objectSize, memSize);
}
/**
* This method handles an overflow.
* If there is an overflow, this method causes a dropping of tuples,
* until this SweepArea uses only 80% of its assigned memory amount.
* The dropping of tuples occurs uniformly distributed among the tuples
* in the SweepArea according to the order the
* <code>iterator()</code>-method supplies the tuples.
*/
public void handleOverflow() {
if (getCurrentMemUsage() <= assignedMemSize)
return;
int realNoOfObjects = size();
int maxAllowedNoOfObjects = 4*assignedMemSize/(5*objectSize);
int overage = realNoOfObjects - maxAllowedNoOfObjects;
//System.out.println("handleOverflow("+realNoOfObjects+", "+overage+")");
Cursors.consume(new Remover<E>(new Filter<E>(iterator(), new EveryQth<E>(realNoOfObjects, overage))));
}
public int getObjectSize() {
return objectSize;
}
}