package au.gov.amsa.geo.distance;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import org.apache.log4j.Logger;
import rx.Observable.Operator;
import rx.Observer;
import rx.Subscriber;
import rx.observers.Subscribers;
import au.gov.amsa.geo.model.CellValue;
import au.gov.amsa.geo.model.Position;
public class OperatorSumCellValues implements Operator<CellValue, CellValue> {
private static Logger log = Logger.getLogger(OperatorSumCellValues.class);
private static final int INITIAL_CAPACITY = 35000000;
/**
* This takes about 100 bytes per entry of memory;
*/
final Map<Position, Double> map;
public OperatorSumCellValues(boolean useDisk) {
if (useDisk)
map = MapDb.INSTANCE.getDb().getHashMap(UUID.randomUUID().toString());
else
map = new HashMap<Position, Double>(INITIAL_CAPACITY, 1.0f);
}
public OperatorSumCellValues() {
this(false);
}
// private final AtomicLong count = new AtomicLong();
@Override
public Subscriber<? super CellValue> call(final Subscriber<? super CellValue> child) {
Subscriber<CellValue> parent = Subscribers.from(new Observer<CellValue>() {
@Override
public void onCompleted() {
// MapDb.INSTANCE.getDb().commit();
try {
log.info("starting to emit map values");
synchronized (map) {
for (Entry<Position, Double> entry : map.entrySet()) {
CellValue cv = new CellValue(entry.getKey().lat(),
entry.getKey().lon(), entry.getValue().doubleValue());
child.onNext(cv);
}
}
child.onCompleted();
} catch (Throwable t) {
onError(t);
}
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onNext(CellValue cv) {
Position position = new Position((float) cv.getCentreLat(), (float) cv
.getCentreLon());
Double val = map.putIfAbsent(position, cv.getValue());
if (val != null)
map.put(position, val + cv.getValue());
}
});
child.add(parent);
return parent;
}
}