Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4670339

(ch) Channels.newChannel(OutputStream) should flush stream on every write

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Won't Fix
    • Icon: P4 P4
    • None
    • 1.4.0
    • core-libs
    • generic
    • generic



      Name: nt126004 Date: 04/17/2002


      FULL PRODUCT VERSION :
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
      Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)


      FULL OPERATING SYSTEM VERSION :

      Linux sicily 2.4.18-386 #2 Wed Mar 20 20:15:40 EST 2002 i686 unknown
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
      Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)


      A DESCRIPTION OF THE PROBLEM :
      The current bridge from Channels to OutputStream's
      does not call flush on the OutputStream when a
      WritableByteChannel.write( ) is called.

      This causes issues for me when writing data through
      OutputStreams that require flushes to push data
      to a network or display.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Since the NIO api's don't have a notion of flush,
      I think the OutputStream should be flushed on every
      write.


      This bug can be reproduced always.

      CUSTOMER WORKAROUND :
      Wrote my own bridge between OutputStream and GatheringByteChannel.

      I include the code below and assign the copyright to
      Sun Microsystem. As a return, I would love to have
      the mail address of somebody I could kvetch
      about ByteBuffers.

          private static class GatheringByteChannelImpl
              extends AbstractInterruptibleChannel // Not really interruptible
              implements GatheringByteChannel
          {
              OutputStream out;
              private static final int TRANSFER_SIZE = 8192;
              private byte buf[] = new byte[0];
              private boolean open = true;
              private Object writeLock = new Object();

              GatheringByteChannelImpl(OutputStream out) {
                  this.out = out;
              }

              public long write(ByteBuffer [] srcs,
                               int off,
                               int length)
                  throws IOException {
                  if (off < 0 || off >= srcs.length ||
                      length < 0 || (off + length) > srcs.length) {
                      throw new IndexOutOfBoundsException();
                  }

                  int srcIdx;
                  long len = 0;
                  for (srcIdx = off; srcIdx < (off + length); srcIdx++) {
                      len += srcs[srcIdx].remaining();
                  }

                  long totalWritten = 0;
                  int curSrcIdx = off;
                  synchronized (writeLock) {
                      while (totalWritten < len) {
                          int bytesToWrite = (int)Math.min((len - totalWritten),
                                                      (long)TRANSFER_SIZE);
                          if (buf.length < bytesToWrite)
                              buf = new byte[bytesToWrite];

                          {
                              int offset = 0;
                              int bytesToCopy = bytesToWrite;

                              do {
                                  ByteBuffer curSrc = srcs[curSrcIdx];

                                  // Try to copy all that's remaining from
                                  // current buffer
                                  int bytesToGet = bytesToCopy;

                                  // But that may not be possible if there
                                  // isn't enough in the current buffer,
                                  // so copy all we can
                                  if (curSrc.remaining() <= bytesToCopy) {
                                      curSrcIdx++;
                                      bytesToGet = curSrc.remaining();
                                  }

                                  // If there's nothing in this buffer,
                                  // don't bother calling curSrc.get
                                  if (bytesToGet == 0) continue;

                                  curSrc.get(buf, offset, bytesToGet);
                                  bytesToCopy -= bytesToGet;
                              } while (bytesToCopy > 0);
                          }

                          try {
                              begin();
                              out.write(buf, 0, bytesToWrite);
                          } finally {
                              end(bytesToWrite > 0);
                          }
                          totalWritten += bytesToWrite;
                      }

                      out.flush();

                      return totalWritten;
                  }
              }

              public long write(ByteBuffer [] srcs)
                  throws IOException
              {
                  return (write(srcs, 0, srcs.length));
              }

              public int write(ByteBuffer bb)
                  throws IOException
              {
                  return ((int)write(new ByteBuffer[] { bb }, 0, 1));
              }

              protected void implCloseChannel() throws IOException {
                  out.close();
                  open = false;
              }
          }
      (Review ID: 145187)
      ======================================================================

            bpb Brian Burkhalter
            nthompsosunw Nathanael Thompson (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: