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

    1   /*
    2    * Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package sun.nio.ch;
   27   
   28   import java.io.FileDescriptor;
   29   import java.io.IOException;
   30   import java.nio.ByteBuffer;
   31   
   32   
   33   /**
   34    * File-descriptor based I/O utilities that are shared by NIO classes.
   35    */
   36   
   37   class IOUtil {
   38   
   39       private IOUtil() { }                // No instantiation
   40   
   41       static int write(FileDescriptor fd, ByteBuffer src, long position,
   42                        NativeDispatcher nd, Object lock)
   43           throws IOException
   44       {
   45           if (src instanceof DirectBuffer)
   46               return writeFromNativeBuffer(fd, src, position, nd, lock);
   47   
   48           // Substitute a native buffer
   49           int pos = src.position();
   50           int lim = src.limit();
   51           assert (pos <= lim);
   52           int rem = (pos <= lim ? lim - pos : 0);
   53           ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
   54           try {
   55               bb.put(src);
   56               bb.flip();
   57               // Do not update src until we see how many bytes were written
   58               src.position(pos);
   59   
   60               int n = writeFromNativeBuffer(fd, bb, position, nd, lock);
   61               if (n > 0) {
   62                   // now update src
   63                   src.position(pos + n);
   64               }
   65               return n;
   66           } finally {
   67               Util.offerFirstTemporaryDirectBuffer(bb);
   68           }
   69       }
   70   
   71       private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
   72                                              long position, NativeDispatcher nd,
   73                                                Object lock)
   74           throws IOException
   75       {
   76           int pos = bb.position();
   77           int lim = bb.limit();
   78           assert (pos <= lim);
   79           int rem = (pos <= lim ? lim - pos : 0);
   80   
   81           int written = 0;
   82           if (rem == 0)
   83               return 0;
   84           if (position != -1) {
   85               written = nd.pwrite(fd,
   86                                   ((DirectBuffer)bb).address() + pos,
   87                                   rem, position, lock);
   88           } else {
   89               written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
   90           }
   91           if (written > 0)
   92               bb.position(pos + written);
   93           return written;
   94       }
   95   
   96       static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
   97           throws IOException
   98       {
   99           return write(fd, bufs, 0, bufs.length, nd);
  100       }
  101   
  102       static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
  103                         NativeDispatcher nd)
  104           throws IOException
  105       {
  106           IOVecWrapper vec = IOVecWrapper.get(length);
  107   
  108           boolean completed = false;
  109           int iov_len = 0;
  110           try {
  111   
  112               // Iterate over buffers to populate native iovec array.
  113               int count = offset + length;
  114               for (int i=offset; i<count; i++) {
  115                   ByteBuffer buf = bufs[i];
  116                   int pos = buf.position();
  117                   int lim = buf.limit();
  118                   assert (pos <= lim);
  119                   int rem = (pos <= lim ? lim - pos : 0);
  120                   if (rem > 0) {
  121                       vec.setBuffer(iov_len, buf, pos, rem);
  122   
  123                       // allocate shadow buffer to ensure I/O is done with direct buffer
  124                       if (!(buf instanceof DirectBuffer)) {
  125                           ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
  126                           shadow.put(buf);
  127                           shadow.flip();
  128                           vec.setShadow(iov_len, shadow);
  129                           buf.position(pos);  // temporarily restore position in user buffer
  130                           buf = shadow;
  131                           pos = shadow.position();
  132                       }
  133   
  134                       vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
  135                       vec.putLen(iov_len, rem);
  136                       iov_len++;
  137                   }
  138               }
  139               if (iov_len == 0)
  140                   return 0L;
  141   
  142               long bytesWritten = nd.writev(fd, vec.address, iov_len);
  143   
  144               // Notify the buffers how many bytes were taken
  145               long left = bytesWritten;
  146               for (int j=0; j<iov_len; j++) {
  147                   if (left > 0) {
  148                       ByteBuffer buf = vec.getBuffer(j);
  149                       int pos = vec.getPosition(j);
  150                       int rem = vec.getRemaining(j);
  151                       int n = (left > rem) ? rem : (int)left;
  152                       buf.position(pos + n);
  153                       left -= n;
  154                   }
  155                   // return shadow buffers to buffer pool
  156                   ByteBuffer shadow = vec.getShadow(j);
  157                   if (shadow != null)
  158                       Util.offerLastTemporaryDirectBuffer(shadow);
  159                   vec.clearRefs(j);
  160               }
  161   
  162               completed = true;
  163               return bytesWritten;
  164   
  165           } finally {
  166               // if an error occurred then clear refs to buffers and return any shadow
  167               // buffers to cache
  168               if (!completed) {
  169                   for (int j=0; j<iov_len; j++) {
  170                       ByteBuffer shadow = vec.getShadow(j);
  171                       if (shadow != null)
  172                           Util.offerLastTemporaryDirectBuffer(shadow);
  173                       vec.clearRefs(j);
  174                   }
  175               }
  176           }
  177       }
  178   
  179       static int read(FileDescriptor fd, ByteBuffer dst, long position,
  180                       NativeDispatcher nd, Object lock)
  181           throws IOException
  182       {
  183           if (dst.isReadOnly())
  184               throw new IllegalArgumentException("Read-only buffer");
  185           if (dst instanceof DirectBuffer)
  186               return readIntoNativeBuffer(fd, dst, position, nd, lock);
  187   
  188           // Substitute a native buffer
  189           ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());
  190           try {
  191               int n = readIntoNativeBuffer(fd, bb, position, nd, lock);
  192               bb.flip();
  193               if (n > 0)
  194                   dst.put(bb);
  195               return n;
  196           } finally {
  197               Util.offerFirstTemporaryDirectBuffer(bb);
  198           }
  199       }
  200   
  201       private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
  202                                               long position, NativeDispatcher nd,
  203                                               Object lock)
  204           throws IOException
  205       {
  206           int pos = bb.position();
  207           int lim = bb.limit();
  208           assert (pos <= lim);
  209           int rem = (pos <= lim ? lim - pos : 0);
  210   
  211           if (rem == 0)
  212               return 0;
  213           int n = 0;
  214           if (position != -1) {
  215               n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
  216                            rem, position, lock);
  217           } else {
  218               n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
  219           }
  220           if (n > 0)
  221               bb.position(pos + n);
  222           return n;
  223       }
  224   
  225       static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
  226           throws IOException
  227       {
  228           return read(fd, bufs, 0, bufs.length, nd);
  229       }
  230   
  231       static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
  232                        NativeDispatcher nd)
  233           throws IOException
  234       {
  235           IOVecWrapper vec = IOVecWrapper.get(length);
  236   
  237           boolean completed = false;
  238           int iov_len = 0;
  239           try {
  240   
  241               // Iterate over buffers to populate native iovec array.
  242               int count = offset + length;
  243               for (int i=offset; i<count; i++) {
  244                   ByteBuffer buf = bufs[i];
  245                   if (buf.isReadOnly())
  246                       throw new IllegalArgumentException("Read-only buffer");
  247                   int pos = buf.position();
  248                   int lim = buf.limit();
  249                   assert (pos <= lim);
  250                   int rem = (pos <= lim ? lim - pos : 0);
  251   
  252                   if (rem > 0) {
  253                       vec.setBuffer(iov_len, buf, pos, rem);
  254   
  255                       // allocate shadow buffer to ensure I/O is done with direct buffer
  256                       if (!(buf instanceof DirectBuffer)) {
  257                           ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
  258                           vec.setShadow(iov_len, shadow);
  259                           buf = shadow;
  260                           pos = shadow.position();
  261                       }
  262   
  263                       vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
  264                       vec.putLen(iov_len, rem);
  265                       iov_len++;
  266                   }
  267               }
  268               if (iov_len == 0)
  269                   return 0L;
  270   
  271               long bytesRead = nd.readv(fd, vec.address, iov_len);
  272   
  273               // Notify the buffers how many bytes were read
  274               long left = bytesRead;
  275               for (int j=0; j<iov_len; j++) {
  276                   ByteBuffer shadow = vec.getShadow(j);
  277                   if (left > 0) {
  278                       ByteBuffer buf = vec.getBuffer(j);
  279                       int rem = vec.getRemaining(j);
  280                       int n = (left > rem) ? rem : (int)left;
  281                       if (shadow == null) {
  282                           int pos = vec.getPosition(j);
  283                           buf.position(pos + n);
  284                       } else {
  285                           shadow.limit(shadow.position() + n);
  286                           buf.put(shadow);
  287                       }
  288                       left -= n;
  289                   }
  290                   if (shadow != null)
  291                       Util.offerLastTemporaryDirectBuffer(shadow);
  292                   vec.clearRefs(j);
  293               }
  294   
  295               completed = true;
  296               return bytesRead;
  297   
  298           } finally {
  299               // if an error occurred then clear refs to buffers and return any shadow
  300               // buffers to cache
  301               if (!completed) {
  302                   for (int j=0; j<iov_len; j++) {
  303                       ByteBuffer shadow = vec.getShadow(j);
  304                       if (shadow != null)
  305                           Util.offerLastTemporaryDirectBuffer(shadow);
  306                       vec.clearRefs(j);
  307                   }
  308               }
  309           }
  310       }
  311   
  312       static FileDescriptor newFD(int i) {
  313           FileDescriptor fd = new FileDescriptor();
  314           setfdVal(fd, i);
  315           return fd;
  316       }
  317   
  318       static native boolean randomBytes(byte[] someBytes);
  319   
  320       /**
  321        * Returns two file descriptors for a pipe encoded in a long.
  322        * The read end of the pipe is returned in the high 32 bits,
  323        * while the write end is returned in the low 32 bits.
  324        */
  325       static native long makePipe(boolean blocking);
  326   
  327       static native boolean drain(int fd) throws IOException;
  328   
  329       static native void configureBlocking(FileDescriptor fd, boolean blocking)
  330           throws IOException;
  331   
  332       static native int fdVal(FileDescriptor fd);
  333   
  334       static native void setfdVal(FileDescriptor fd, int value);
  335   
  336       static native void initIDs();
  337   
  338       static {
  339           // Note that IOUtil.initIDs is called from within Util.load.
  340           Util.load();
  341       }
  342   
  343   }

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