int onReadable() {
    spitPending();
    // even if the socket is paused,
    // it may end up getting a queued readable event if it is
    // already in the selector's ready queue.
    if (mPaused) return 0;
    int total = 0;
    try {
      boolean closed = false;

      //            ByteBufferList.obtainArray(buffers, Math.min(Math.max(mToAlloc, 2 << 11),
      // maxAlloc));
      ByteBuffer b = allocator.allocate();
      // keep track of the max mount read during this read cycle
      // so we can be quicker about allocations during the next
      // time this socket reads.
      long read = mChannel.read(b);
      if (read < 0) {
        closeInternal();
        closed = true;
      } else {
        total += read;
      }
      if (read > 0) {
        allocator.track(read);
        b.flip();
        //                for (int i = 0; i < buffers.length; i++) {
        //                    ByteBuffer b = buffers[i];
        //                    buffers[i] = null;
        //                    b.flip();
        //                    pending.add(b);
        //                }
        pending.add(b);
        Util.emitAllData(this, pending);
      } else {
        ByteBufferList.reclaim(b);
      }

      if (closed) {
        reportEndPending(null);
        reportClose(null);
      }
    } catch (Exception e) {
      closeInternal();
      reportEndPending(e);
      reportClose(e);
    }

    return total;
  }
  @Override
  public void write(ByteBufferList bb) {
    if (mPendingWrites == null) mDataSink.write(bb);
    //        else
    //            Assert.assertTrue(mPendingWrites.remaining() <= mMaxBuffer);

    if (bb.remaining() > 0) {
      int toRead = Math.min(bb.remaining(), mMaxBuffer);
      if (toRead > 0) {
        if (mPendingWrites == null) mPendingWrites = new ByteBufferList();
        mPendingWrites.add(bb.get(toRead));
      }
    }
  }
 @Override
 public void run() {
   try {
     if (channel == null) channel = new FileInputStream(file).getChannel();
     if (!pending.isEmpty()) {
       Util.emitAllData(FileDataEmitter.this, pending);
       if (!pending.isEmpty()) return;
     }
     ByteBuffer b;
     do {
       b = ByteBufferList.obtain(8192);
       if (-1 == channel.read(b)) {
         report(null);
         return;
       }
       b.flip();
       pending.add(b);
       Util.emitAllData(FileDataEmitter.this, pending);
     } while (pending.remaining() == 0 && !isPaused());
   } catch (Exception e) {
     report(e);
   }
 }
 @Override
 public void write(ByteBuffer bb) {
   ByteBufferList bbl = new ByteBufferList();
   bbl.add(bb);
   write(bbl);
 }