/*
* Copyright [2012-2015] PayPal Software Foundation
*
* Licensed 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 ml.shifu.guagua.util;
import java.util.Iterator;
import java.util.List;
import ml.shifu.guagua.GuaguaRuntimeException;
/**
* A simple wrapper list with limited byte size.
*
* <p>
* Only two stages support in such kind of list. The first one is WRITE, the next is read. So far random WRITE and READ
* are not supported in this list.
*
* <p>
* If current size is over limited size, a GuaguaRuntimeException is added when {@link #add(Object)}.
*
* @author Zhang David (pengzhang@paypal.com)
*/
public class MemoryLimitedList<T> implements AppendList<T> {
/**
* Limited size setting
*/
private long maxByteSize = Long.MAX_VALUE;
/**
* Current size of delegated list.
*/
private long byteSize = 0L;
/**
* A delegation list, TODO if LinkedList, current size should be changed.
*/
private List<T> delegationList;
/**
* Internal state.
*/
private State state = State.WRITE;
/**
* Number of element in this list
*/
private long count;
/**
* Constructor with max bytes size limit and delegation list.
*/
public MemoryLimitedList(long maxSize, List<T> delegationList) {
super();
this.maxByteSize = maxSize;
this.delegationList = delegationList;
}
/**
* Constructor with delegation list
*/
public MemoryLimitedList(List<T> delegationList) {
super();
this.delegationList = delegationList;
}
@Override
public boolean append(T t) {
if(this.state != State.WRITE) {
throw new IllegalStateException();
}
this.count += 1;
long current = SizeEstimator.estimate(t);
if(byteSize + current > maxByteSize) {
throw new GuaguaRuntimeException("List over size limit.");
} else {
this.byteSize += current;
return this.delegationList.add(t);
}
}
/**
* Retrieve record given index. This function is only provided in {@link MemoryLimitedList}.
*
* @param index
* the index of record to be returned
* @return the record in that index
*/
public T get(int index) {
return this.delegationList.get(index);
}
@Override
public Iterator<T> iterator() {
if(this.state != State.READ) {
throw new IllegalStateException();
}
return new Iterator<T>() {
private Iterator<T> iter = MemoryLimitedList.this.delegationList.iterator();
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public T next() {
return iter.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/*
* (non-Javadoc)
*
* @see ml.shifu.guagua.util.AppendList#switchState()
*/
@Override
public void switchState() {
this.state = State.READ;
}
/*
* (non-Javadoc)
*
* @see ml.shifu.guagua.util.AppendList#size()
*/
@Override
public int size() {
return (int) this.count;
}
/*
* (non-Javadoc)
*
* @see ml.shifu.guagua.util.AppendList#clear()
*/
@Override
public void clear() {
this.delegationList.clear();
}
}