diff --git a/Stats/src/main/java/io/deephaven/stats/StatsCPUCollector.java b/Stats/src/main/java/io/deephaven/stats/StatsCPUCollector.java index 7af2a416434..1f003b5fb1e 100644 --- a/Stats/src/main/java/io/deephaven/stats/StatsCPUCollector.java +++ b/Stats/src/main/java/io/deephaven/stats/StatsCPUCollector.java @@ -3,6 +3,7 @@ */ package io.deephaven.stats; +import io.deephaven.base.verify.Assert; import io.deephaven.configuration.Configuration; import io.deephaven.internal.log.LoggerFactory; import io.deephaven.io.logger.Logger; @@ -223,29 +224,27 @@ private boolean peekNextLong() { */ private void readToBuffer(FileChannel fileChannel, String fileName) throws IOException { statBuffer.clear(); - int nb = 0; fileChannel.position(0); + // Filesystem entries in /proc can only be read all at once to avoid races, so using too big of a buffer isn't a + // problem, but too small is. Attempt to read with the current buffer. If we filled the buffer we resize it and + // read again from start. while (true) { - final int thisNb = fileChannel.read(statBuffer); + final int nb = fileChannel.read(statBuffer); - if (thisNb == -1) { - break; + if (nb <= 0) { + // zero bytes read is an error, -1 is EOF + throw new IOException(fileName + " could not be read, or was empty"); } - nb += thisNb; - if (!statBuffer.hasRemaining()) { - // allocate larger read-buffer, and continue reading - ByteBuffer resized = ByteBuffer.allocate(statBuffer.capacity() * 2); - resized.put(statBuffer.flip()); - statBuffer = resized; + if (statBuffer.hasRemaining()) { + Assert.eq(statBuffer.position(), "statBuffer.position()", nb, "nb"); + statBuffer.flip(); + return; } - } - if (nb == 0) { - throw new IOException(fileName + " zero read"); - } else { - // Success, set position and limit to the data read - statBuffer.flip(); + // allocate larger read-buffer, and read again from start + statBuffer = ByteBuffer.allocate(statBuffer.capacity() * 2); + fileChannel.position(0); } }