I was having a problem with the TCP/IP socket communications in a web app where the server that the app was talking to would occasionally send bursts of data that would overflow the low level stream buffer, resulting in lost data.The solution I came up with is basically an unthreaded form of the StreamGobbler and I have been calling it a GreedyBufferedInputStream. The basic idea is that just about any call to this class will include draining the source InputStream.I'm still fairly new to Scala, so please let me know how this code could be improved. Also, is there anything in the code which could be done more efficiently? Performance is critically important.package edu.stsci.utilimport org.slf4j.Loggerimport java.io.InputStreamimport java.utilclass GreedyBufferedInputStream extends InputStream {  private var logger: Logger = null  private var source: InputStream = null  private val data: util.LinkedList[DataBlock] = new util.LinkedList[DataBlock]()  private var currentBlock: DataBlock = null  def this(logger: Logger, source: InputStream) {    this()    this.logger = logger    this.source = source    drainSource()  }  def this(source: InputStream) {    this(null, source)  }  def read() = {    prepareToRead()    if (currentBlock == null) -1    else currentBlock.read()  }  override def read(destination: Array[Byte], offset: Int, length: Int): Int = {    prepareToRead()    if (currentBlock == null) return -1    var bytesRead = currentBlock.read(offset, length, destination)    while (bytesRead < length) {      prepareToRead()      if (currentBlock == null) {// EOF        return bytesRead      }      else {        bytesRead += currentBlock.read((offset + bytesRead), (length - bytesRead), destination)      }    }    bytesRead  }  override def read(destination: Array[Byte]) = read(destination, 0, destination.length)  override def skip(length: Long): Long = {    prepareToRead()    if (currentBlock == null) return -1    var bytesSkipped = currentBlock.skip(length)    while (bytesSkipped < length) {      prepareToRead()      if (currentBlock == null) { // EOF        return bytesSkipped      }      else {        bytesSkipped += currentBlock.skip(length - bytesSkipped)      }    }    bytesSkipped  }  override def close() {    super.close()  }  override def available() = {    drainSource()    var result = 0    if (currentBlock != null) result += currentBlock.available    val it = data.iterator()    while (it.hasNext) {      val next = it.next()      result += next.available    }    result  }  private def drainSource() {    if (source == null) return // EOF    if (source.available() > 0) {      val raw = new Array[Byte](source.available())      val length = source.read(raw)      val block = new DataBlock(raw, length)      data.add(block)    }  }  private def prepareToRead() {    drainSource()    if (currentBlock != null) {      val done = currentBlock.isDone      if (done) currentBlock = null      else return // we have a current block    }    if (data.isEmpty) { // no choice but to block      if (source == null) return // have reached EOF      val raw = new Array[Byte](1024)      val length = source.read(raw)      if (length < 0) {        source = null        return      }      currentBlock = new DataBlock(raw, length)    }    else currentBlock = data.remove()  }}class DataBlock(data: Array[Byte], length: Int) {  var readPos = -1  def isDone: Boolean = (readPos >= length)  def available: Int = {    if (readPos < 0) length    else (length - readPos)  }  def read(): Int = {    if (readPos < 0) readPos = 0    val raw = data(readPos)    readPos += 1    raw & 0xff  }  def read(offset: Int, length: Int, destination: Array[Byte]): Int = {    if (readPos < 0) readPos = 0    var readCount = {      if (available >= length) length      else available    }    Array.copy(data, readPos, destination, offset, readCount)    readPos += readCount    readCount  }  def skip(length: Long): Long = {    if (readPos < 0) readPos = 0    var readCount = {      if (available >= length) length      else available    }    readPos += readCount.toInt    readCount  }}
Alternate form of BufferedInputStream
scala;networking
I think that the use of a LinkedList is not optimal. In every invocation of drainSource you potentially add a new DataBlock ant the end of the linked list; this has performance O(n) (length of the list). I propose to use a Vector instead of the LinkedList.Another point (but this is not Scala specific): Why do you initialize the field readPos in class DataBlock with -1? You have many special cases due to this choice. I would implement class DataBlock as follows:class DataBlock(data: Array[Byte], length: Int) {  require(length > 0)  private var readPos = 0  def isDone: Boolean = readPos >= length  def available: Int = length - readPos  def read(): Int = try { data(readPos) & 0xff } finally { readPos += 1 }  def read(offset: Int, length: Int, destination: Array[Byte]): Int = {    val readCount = length min available    Array.copy(data, readPos, destination, offset, readCount)    readPos += readCount    readCount  }  def skip(length: Long): Long = {    val readCount = length min available    readPos += readCount.toInt    readCount  }}