Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]
    1   /*
    2    * Copyright 2000-2002 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package sun.nio.ch;
   27   
   28   import java.io.FileDescriptor;
   29   import java.io.IOException;
   30   import java.net;
   31   import java.nio.ByteBuffer;
   32   import java.nio.channels;
   33   import java.nio.channels.spi;
   34   
   35   
   36   /**
   37    * File-descriptor based I/O utilities that are shared by NIO classes.
   38    */
   39   
   40   class IOUtil {
   41   
   42       private IOUtil() { }                // No instantiation
   43   
   44       /*
   45        * Returns the index of first buffer in bufs with remaining,
   46        * or -1 if there is nothing left
   47        */
   48       private static int remaining(ByteBuffer[] bufs) {
   49           int numBufs = bufs.length;
   50           boolean remaining = false;
   51           for (int i=0; i<numBufs; i++) {
   52               if (bufs[i].hasRemaining()) {
   53                   return i;
   54               }
   55           }
   56           return -1;
   57       }
   58   
   59       /*
   60        * Returns a new ByteBuffer array with only unfinished buffers in it
   61        */
   62       private static ByteBuffer[] skipBufs(ByteBuffer[] bufs,
   63                                            int nextWithRemaining)
   64       {
   65           int newSize = bufs.length - nextWithRemaining;
   66           ByteBuffer[] temp = new ByteBuffer[newSize];
   67           for (int i=0; i<newSize; i++) {
   68               temp[i] = bufs[i + nextWithRemaining];
   69           }
   70           return temp;
   71       }
   72   
   73       static int write(FileDescriptor fd, ByteBuffer src, long position,
   74                        NativeDispatcher nd, Object lock)
   75           throws IOException
   76       {
   77           if (src instanceof DirectBuffer)
   78               return writeFromNativeBuffer(fd, src, position, nd, lock);
   79   
   80           // Substitute a native buffer
   81           int pos = src.position();
   82           int lim = src.limit();
   83           assert (pos <= lim);
   84           int rem = (pos <= lim ? lim - pos : 0);
   85           ByteBuffer bb = null;
   86           try {
   87               bb = Util.getTemporaryDirectBuffer(rem);
   88               bb.put(src);
   89               bb.flip();
   90               // Do not update src until we see how many bytes were written
   91               src.position(pos);
   92   
   93               int n = writeFromNativeBuffer(fd, bb, position, nd, lock);
   94               if (n > 0) {
   95                   // now update src
   96                   src.position(pos + n);
   97               }
   98               return n;
   99           } finally {
  100               Util.releaseTemporaryDirectBuffer(bb);
  101           }
  102       }
  103   
  104       private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
  105                                              long position, NativeDispatcher nd,
  106                                                Object lock)
  107           throws IOException
  108       {
  109           int pos = bb.position();
  110           int lim = bb.limit();
  111           assert (pos <= lim);
  112           int rem = (pos <= lim ? lim - pos : 0);
  113   
  114           int written = 0;
  115           if (rem == 0)
  116               return 0;
  117           if (position != -1) {
  118               written = nd.pwrite(fd,
  119                                   ((DirectBuffer)bb).address() + pos,
  120                                   rem, position, lock);
  121           } else {
  122               written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
  123           }
  124           if (written > 0)
  125               bb.position(pos + written);
  126           return written;
  127       }
  128   
  129       static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
  130           throws IOException
  131       {
  132           int nextWithRemaining = remaining(bufs);
  133           // if all bufs are empty we should return immediately
  134           if (nextWithRemaining < 0)
  135               return 0;
  136           // If some bufs are empty we should skip them
  137           if (nextWithRemaining > 0)
  138               bufs = skipBufs(bufs, nextWithRemaining);
  139   
  140           int numBufs = bufs.length;
  141           int bytesReadyToWrite = 0;
  142   
  143           // Create shadow to ensure DirectByteBuffers are used
  144           ByteBuffer[] shadow = new ByteBuffer[numBufs];
  145           for (int i=0; i<numBufs; i++) {
  146               if (!(bufs[i] instanceof DirectBuffer)) {
  147                   int pos = bufs[i].position();
  148                   int lim = bufs[i].limit();
  149                   assert (pos <= lim);
  150                   int rem = (pos <= lim ? lim - pos : 0);
  151   
  152                   ByteBuffer bb = ByteBuffer.allocateDirect(rem);
  153                   shadow[i] = bb;
  154                   // Leave slow buffer position untouched; it will be updated
  155                   // after we see how many bytes were really written out
  156                   bb.put(bufs[i]);
  157                   bufs[i].position(pos);
  158                   bb.flip();
  159               } else {
  160                   shadow[i] = bufs[i];
  161               }
  162           }
  163   
  164           IOVecWrapper vec = null;
  165           long bytesWritten = 0;
  166           try {
  167               // Create a native iovec array
  168               vec= new IOVecWrapper(numBufs);
  169   
  170               // Fill in the iovec array with appropriate data
  171               for (int i=0; i<numBufs; i++) {
  172                   ByteBuffer nextBuffer = shadow[i];
  173                   // put in the buffer addresses
  174                   long pos = nextBuffer.position();
  175                   long len = nextBuffer.limit() - pos;
  176                   bytesReadyToWrite += len;
  177                   vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
  178                   vec.putLen(i, len);
  179               }
  180   
  181               // Invoke native call to fill the buffers
  182               bytesWritten = nd.writev(fd, vec.address, numBufs);
  183           } finally {
  184               vec.free();
  185           }
  186           long returnVal = bytesWritten;
  187   
  188           // Notify the buffers how many bytes were taken
  189           for (int i=0; i<numBufs; i++) {
  190               ByteBuffer nextBuffer = bufs[i];
  191               int pos = nextBuffer.position();
  192               int lim = nextBuffer.limit();
  193               assert (pos <= lim);
  194               int len = (pos <= lim ? lim - pos : lim);
  195               if (bytesWritten >= len) {
  196                   bytesWritten -= len;
  197                   int newPosition = pos + len;
  198                   nextBuffer.position(newPosition);
  199               } else { // Buffers not completely filled
  200                   if (bytesWritten > 0) {
  201                       assert(pos + bytesWritten < (long)Integer.MAX_VALUE);
  202                       int newPosition = (int)(pos + bytesWritten);
  203                       nextBuffer.position(newPosition);
  204                   }
  205                   break;
  206               }
  207           }
  208           return returnVal;
  209       }
  210   
  211       static int read(FileDescriptor fd, ByteBuffer dst, long position,
  212                       NativeDispatcher nd, Object lock)
  213           throws IOException
  214       {
  215           if (dst.isReadOnly())
  216               throw new IllegalArgumentException("Read-only buffer");
  217           if (dst instanceof DirectBuffer)
  218               return readIntoNativeBuffer(fd, dst, position, nd, lock);
  219   
  220           // Substitute a native buffer
  221           ByteBuffer bb = null;
  222           try {
  223               bb = Util.getTemporaryDirectBuffer(dst.remaining());
  224               int n = readIntoNativeBuffer(fd, bb, position, nd, lock);
  225               bb.flip();
  226               if (n > 0)
  227                   dst.put(bb);
  228               return n;
  229           } finally {
  230               Util.releaseTemporaryDirectBuffer(bb);
  231           }
  232       }
  233   
  234       private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
  235                                               long position, NativeDispatcher nd,
  236                                               Object lock)
  237           throws IOException
  238       {
  239           int pos = bb.position();
  240           int lim = bb.limit();
  241           assert (pos <= lim);
  242           int rem = (pos <= lim ? lim - pos : 0);
  243   
  244           if (rem == 0)
  245               return 0;
  246           int n = 0;
  247           if (position != -1) {
  248               n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
  249                            rem, position, lock);
  250           } else {
  251               n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
  252           }
  253           if (n > 0)
  254               bb.position(pos + n);
  255           return n;
  256       }
  257   
  258       static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
  259           throws IOException
  260       {
  261           int nextWithRemaining = remaining(bufs);
  262           // if all bufs are empty we should return immediately
  263           if (nextWithRemaining < 0)
  264               return 0;
  265           // If some bufs are empty we should skip them
  266           if (nextWithRemaining > 0)
  267               bufs = skipBufs(bufs, nextWithRemaining);
  268   
  269           int numBufs = bufs.length;
  270   
  271           // Read into the shadow to ensure DirectByteBuffers are used
  272           ByteBuffer[] shadow = new ByteBuffer[numBufs];
  273           for (int i=0; i<numBufs; i++) {
  274               if (bufs[i].isReadOnly())
  275                   throw new IllegalArgumentException("Read-only buffer");
  276               if (!(bufs[i] instanceof DirectBuffer)) {
  277                   shadow[i] = ByteBuffer.allocateDirect(bufs[i].remaining());
  278               } else {
  279                   shadow[i] = bufs[i];
  280               }
  281           }
  282   
  283           IOVecWrapper vec = null;
  284           long bytesRead = 0;
  285           try {
  286               // Create a native iovec array
  287               vec = new IOVecWrapper(numBufs);
  288   
  289               // Fill in the iovec array with appropriate data
  290               for (int i=0; i<numBufs; i++) {
  291                   ByteBuffer nextBuffer = shadow[i];
  292                   // put in the buffer addresses
  293                   long pos = nextBuffer.position();
  294                   long len = nextBuffer.remaining();
  295                   vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
  296                   vec.putLen(i, len);
  297               }
  298   
  299               // Invoke native call to fill the buffers
  300               bytesRead = nd.readv(fd, vec.address, numBufs);
  301           } finally {
  302               vec.free();
  303           }
  304           long returnVal = bytesRead;
  305   
  306           // Notify the buffers how many bytes were read
  307           for (int i=0; i<numBufs; i++) {
  308               ByteBuffer nextBuffer = shadow[i];
  309               // Note: should this have been cached from above?
  310               int pos = nextBuffer.position();
  311               int len = nextBuffer.remaining();
  312               if (bytesRead >= len) {
  313                   bytesRead -= len;
  314                   int newPosition = pos + len;
  315                   nextBuffer.position(newPosition);
  316               } else { // Buffers not completely filled
  317                   if (bytesRead > 0) {
  318                       assert(pos + bytesRead < (long)Integer.MAX_VALUE);
  319                       int newPosition = (int)(pos + bytesRead);
  320                       nextBuffer.position(newPosition);
  321                   }
  322                   break;
  323               }
  324           }
  325   
  326           // Put results from shadow into the slow buffers
  327           for (int i=0; i<numBufs; i++) {
  328               if (!(bufs[i] instanceof DirectBuffer)) {
  329                   shadow[i].flip();
  330                   bufs[i].put(shadow[i]);
  331               }
  332           }
  333   
  334           return returnVal;
  335       }
  336   
  337       static FileDescriptor newFD(int i) {
  338           FileDescriptor fd = new FileDescriptor();
  339           setfdVal(fd, i);
  340           return fd;
  341       }
  342   
  343       static native boolean randomBytes(byte[] someBytes);
  344   
  345       static native void initPipe(int[] fda, boolean blocking);
  346   
  347       static native boolean drain(int fd) throws IOException;
  348   
  349       static native void configureBlocking(FileDescriptor fd, boolean blocking)
  350           throws IOException;
  351   
  352       static native int fdVal(FileDescriptor fd);
  353   
  354       static native void setfdVal(FileDescriptor fd, int value);
  355   
  356       static native void initIDs();
  357   
  358       static {
  359           // Note that IOUtil.initIDs is called from within Util.load.
  360           Util.load();
  361       }
  362   
  363   }

Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]