/**
* 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.InputStream;
import org.appwork.utils.speedmeter.SpeedMeterInterface;
/**
* @author daniel
*
*/
public class MeteredInputStream extends InputStream implements SpeedMeterInterface {
private InputStream in;
private SpeedMeterInterface speedmeter = null;
private long transfered = 0;
private long transfered2 = 0;
private long time = 0;
private int readTmp1;
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 todo;
private int lastRead;
private int rest;
private int lastRead2;
private long lastTime;
private long lastTrans;
private long timeForCheckStep = 0;
private int timeCheck = 0;
/**
* constructor for MeterdInputStream
*
* @param in
*/
public MeteredInputStream(InputStream in) {
this.in = in;
}
/**
* constructor for MeteredInputStream with custom SpeedMeter
*
* @param in
* @param speedmeter
*/
public MeteredInputStream(InputStream in, SpeedMeterInterface speedmeter) {
this.in = in;
this.speedmeter = speedmeter;
}
@Override
public int read() throws IOException {
readTmp1 = in.read();
if (readTmp1 != -1) transfered++;
return readTmp1;
}
public int getCheckStepSize() {
return checkStep;
}
public void setCheckStepSize(int step) {
checkStep = Math.min(LOWStep, checkStep);
}
@Override
public int read(byte b[], int off, int len) throws IOException {
offset = off;
rest = len;
lastRead2 = 0;
while (rest != 0) {
todo = rest;
if (todo > checkStep) todo = checkStep;
timeForCheckStep = System.currentTimeMillis();
lastRead = in.read(b, offset, todo);
timeCheck = (int) (System.currentTimeMillis() - timeForCheckStep);
if (lastRead == -1) break;
if (timeCheck > 1000) {
/* we want 5 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);
}
lastRead2 += lastRead;
transfered += lastRead;
rest -= lastRead;
offset += lastRead;
}
if (lastRead == -1 && lastRead2 == 0) {
return -1;
} else {
return lastRead2;
}
}
@Override
public int available() throws IOException {
return in.available();
}
@Override
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
in.reset();
}
@Override
public boolean markSupported() {
return in.markSupported();
}
@Override
public long skip(long n) throws IOException {
return in.skip(n);
}
@Override
public void close() throws IOException {
in.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);
speed = speedmeter.getSpeedMeter();
return speed;
} 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();
}
}