/**
* Copyright (c) 2009 - 2010 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org>
*
* This file is part of org.appwork.utils.net.meteredconnection
*
* This software is licensed under the Artistic License 2.0,
* see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php
* for details
*/
package org.appwork.utils.net.meteredconnection;
import java.io.IOException;
import java.io.OutputStream;
import org.appwork.utils.speedmeter.SpeedMeterInterface;
/**
* @author daniel
*
*/
public class MeteredOutputStream extends OutputStream implements SpeedMeterInterface {
private OutputStream out;
private SpeedMeterInterface speedmeter = null;
private long transfered = 0;
private long transfered2 = 0;
private long time = 0;
private long speed = 0;
private int offset;
private int checkStep = 1024;
// private final static int HIGHStep = 524288;
public final static int LOWStep = 1024;
private int rest;
private int todo;
private long lastTime;
private long lastTrans;
private long timeForCheckStep = 0;
private int timeCheck = 0;
/**
* constructor for MeteredOutputStream
*
* @param out
*/
public MeteredOutputStream(OutputStream out) {
this.out = out;
}
/**
* constructor for MeteredOutputStream with custom SpeedMeter
*
* @param out
* @param speedmeter
*/
public MeteredOutputStream(OutputStream out, SpeedMeterInterface speedmeter) {
this.out = out;
this.speedmeter = speedmeter;
}
@Override
public void write(int b) throws IOException {
out.write(b);
transfered++;
}
public int getCheckStepSize() {
return checkStep;
}
public void setCheckStepSize(int step) {
checkStep = Math.min(LOWStep, checkStep);
}
@Override
public void write(byte b[], int off, int len) throws IOException {
offset = off;
rest = len;
while (rest != 0) {
todo = rest;
if (todo > checkStep) todo = checkStep;
timeForCheckStep = System.currentTimeMillis();
out.write(b, offset, todo);
timeCheck = (int) (System.currentTimeMillis() - timeForCheckStep);
if (timeCheck > 1000) {
/* we want 2 update per second */
checkStep = Math.max(LOWStep, (todo / timeCheck) * 500);
} else if (timeCheck == 0) {
/* we increase in little steps */
checkStep += 1024;
// checkStep = Math.min(HIGHStep, checkStep + 1024);
}
transfered += todo;
rest -= todo;
offset += todo;
}
}
@Override
public void flush() throws IOException {
out.flush();
}
@Override
public void close() throws IOException {
out.close();
}
/*
* (non-Javadoc)
*
* @see org.appwork.utils.SpeedMeterInterface#getSpeedMeter()
*/
public synchronized long getSpeedMeter() {
if (time == 0) {
time = System.currentTimeMillis();
transfered2 = transfered;
return 0;
}
if (System.currentTimeMillis() - time < 1000) {
if (speedmeter != null) return speedmeter.getSpeedMeter();
return speed;
}
lastTime = System.currentTimeMillis() - time;
time = System.currentTimeMillis();
lastTrans = transfered - transfered2;
transfered2 = transfered;
if (speedmeter != null) {
speedmeter.putSpeedMeter(lastTrans, lastTime);
return speedmeter.getSpeedMeter();
} else {
speed = (lastTrans / lastTime) * 1000;
return speed;
}
}
/*
* (non-Javadoc)
*
* @see org.appwork.utils.SpeedMeterInterface#putSpeedMeter(long, long)
*/
public void putSpeedMeter(long bytes, long time) {
}
/*
* (non-Javadoc)
*
* @see org.appwork.utils.SpeedMeterInterface#resetSpeedMeter()
*/
public synchronized void resetSpeedMeter() {
if (speedmeter != null) speedmeter.resetSpeedMeter();
speed = 0;
transfered2 = transfered;
time = System.currentTimeMillis();
}
}