diff --git a/core/src/main/groovy/com/muwire/core/upload/ContentUploader.groovy b/core/src/main/groovy/com/muwire/core/upload/ContentUploader.groovy index 05a287a9..a2457df2 100644 --- a/core/src/main/groovy/com/muwire/core/upload/ContentUploader.groovy +++ b/core/src/main/groovy/com/muwire/core/upload/ContentUploader.groovy @@ -62,11 +62,13 @@ class ContentUploader extends Uploader { mapped = channel.map(FileChannel.MapMode.READ_ONLY, range.start, range.end - range.start + 1) byte [] tmp = new byte[0x1 << 13] while(mapped.hasRemaining()) { - int start = mapped.position() + int read synchronized(this) { + int start = mapped.position() mapped.get(tmp, 0, Math.min(tmp.length, mapped.remaining())) + read = mapped.position() - start + dataSinceLastRead += read } - int read = mapped.position() - start endpoint.getOutputStream().write(tmp, 0, read) } } finally { diff --git a/core/src/main/groovy/com/muwire/core/upload/HashListUploader.groovy b/core/src/main/groovy/com/muwire/core/upload/HashListUploader.groovy index 4be57da2..e344a29a 100644 --- a/core/src/main/groovy/com/muwire/core/upload/HashListUploader.groovy +++ b/core/src/main/groovy/com/muwire/core/upload/HashListUploader.groovy @@ -26,11 +26,13 @@ class HashListUploader extends Uploader { byte[]tmp = new byte[0x1 << 13] while(mapped.hasRemaining()) { - int start = mapped.position() + int read synchronized(this) { + int start = mapped.position() mapped.get(tmp, 0, Math.min(tmp.length, mapped.remaining())) + read = mapped.position() - start + dataSinceLastRead += read } - int read = mapped.position() - start endpoint.getOutputStream().write(tmp, 0, read) } endpoint.getOutputStream().flush() diff --git a/core/src/main/groovy/com/muwire/core/upload/Uploader.groovy b/core/src/main/groovy/com/muwire/core/upload/Uploader.groovy index c065383a..559aaa44 100644 --- a/core/src/main/groovy/com/muwire/core/upload/Uploader.groovy +++ b/core/src/main/groovy/com/muwire/core/upload/Uploader.groovy @@ -11,7 +11,13 @@ import com.muwire.core.connection.Endpoint abstract class Uploader { protected final Endpoint endpoint protected ByteBuffer mapped + + private long lastSpeedRead + protected int dataSinceLastRead + private final ArrayList speedArr = [0,0,0,0,0] + private int speedPos, speedAvg + Uploader(Endpoint endpoint) { this.endpoint = endpoint } @@ -38,4 +44,34 @@ abstract class Uploader { abstract int getTotalPieces(); abstract long getTotalSize(); + + synchronized int speed() { + final long now = System.currentTimeMillis() + long interval = Math.max(1000, now - lastSpeedRead) + lastSpeedRead = now; + int currSpeed = (int) (dataSinceLastRead * 1000.0 / interval) + dataSinceLastRead = 0 + + // normalize to speedArr.size + currSpeed /= speedArr.size() + + // compute new speedAvg and update speedArr + if ( speedArr[speedPos] > speedAvg ) { + speedAvg = 0 + } else { + speedAvg -= speedArr[speedPos] + } + speedAvg += currSpeed + speedArr[speedPos] = currSpeed + // this might be necessary due to rounding errors + if (speedAvg < 0) + speedAvg = 0 + + // rolling index over the speedArr + speedPos++ + if (speedPos >= speedArr.size()) + speedPos=0 + + speedAvg + } } diff --git a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy index 0093490a..0d0144cd 100644 --- a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy @@ -293,6 +293,10 @@ class MainFrameView { } String.format("%02d", percent) + "% ${totalSize} ($done/$pieces pcs)".toString() }) + closureColumn(header : "Speed", type : String, read : { row -> + int speed = row.uploader.speed() + DataHelper.formatSize2Decimal(speed, false) + "B/sec" + }) } } }