Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]
    1   /*
    2    * Copyright 2000-2006 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    * An implementation of SocketChannels
   38    */
   39   
   40   class SocketChannelImpl
   41       extends SocketChannel
   42       implements SelChImpl
   43   {
   44   
   45       // Used to make native read and write calls
   46       private static NativeDispatcher nd;
   47   
   48       // Our file descriptor object
   49       private final FileDescriptor fd;
   50   
   51       // fd value needed for dev/poll. This value will remain valid
   52       // even after the value in the file descriptor object has been set to -1
   53       private final int fdVal;
   54   
   55       // IDs of native threads doing reads and writes, for signalling
   56       private volatile long readerThread = 0;
   57       private volatile long writerThread = 0;
   58   
   59       // Lock held by current reading or connecting thread
   60       private final Object readLock = new Object();
   61   
   62       // Lock held by current writing or connecting thread
   63       private final Object writeLock = new Object();
   64   
   65       // Lock held by any thread that modifies the state fields declared below
   66       // DO NOT invoke a blocking I/O operation while holding this lock!
   67       private final Object stateLock = new Object();
   68   
   69       // -- The following fields are protected by stateLock
   70   
   71       // State, increases monotonically
   72       private static final int ST_UNINITIALIZED = -1;
   73       private static final int ST_UNCONNECTED = 0;
   74       private static final int ST_PENDING = 1;
   75       private static final int ST_CONNECTED = 2;
   76       private static final int ST_KILLPENDING = 3;
   77       private static final int ST_KILLED = 4;
   78       private int state = ST_UNINITIALIZED;
   79   
   80       // Binding
   81       private SocketAddress localAddress = null;
   82       private SocketAddress remoteAddress = null;
   83   
   84       // Input/Output open
   85       private boolean isInputOpen = true;
   86       private boolean isOutputOpen = true;
   87       private boolean readyToConnect = false;
   88   
   89       // Options, created on demand
   90       private SocketOpts.IP.TCP options = null;
   91   
   92       // Socket adaptor, created on demand
   93       private Socket socket = null;
   94   
   95       // -- End of fields protected by stateLock
   96   
   97   
   98       // Constructor for normal connecting sockets
   99       //
  100       SocketChannelImpl(SelectorProvider sp) throws IOException {
  101           super(sp);
  102           this.fd = Net.socket(true);
  103           this.fdVal = IOUtil.fdVal(fd);
  104           this.state = ST_UNCONNECTED;
  105       }
  106   
  107       // Constructor for sockets obtained from server sockets
  108       //
  109       SocketChannelImpl(SelectorProvider sp,
  110                         FileDescriptor fd, InetSocketAddress remote)
  111           throws IOException
  112       {
  113           super(sp);
  114           this.fd = fd;
  115           this.fdVal = IOUtil.fdVal(fd);
  116           this.state = ST_CONNECTED;
  117           this.remoteAddress = remote;
  118       }
  119   
  120       public Socket socket() {
  121           synchronized (stateLock) {
  122               if (socket == null)
  123                   socket = SocketAdaptor.create(this);
  124               return socket;
  125           }
  126       }
  127   
  128       private boolean ensureReadOpen() throws ClosedChannelException {
  129           synchronized (stateLock) {
  130               if (!isOpen())
  131                   throw new ClosedChannelException();
  132               if (!isConnected())
  133                   throw new NotYetConnectedException();
  134               if (!isInputOpen)
  135                   return false;
  136               else
  137                   return true;
  138           }
  139       }
  140   
  141       private void ensureWriteOpen() throws ClosedChannelException {
  142           synchronized (stateLock) {
  143               if (!isOpen())
  144                   throw new ClosedChannelException();
  145               if (!isOutputOpen)
  146                   throw new ClosedChannelException();
  147               if (!isConnected())
  148                   throw new NotYetConnectedException();
  149           }
  150       }
  151   
  152       private void readerCleanup() throws IOException {
  153           synchronized (stateLock) {
  154               readerThread = 0;
  155               if (state == ST_KILLPENDING)
  156                   kill();
  157           }
  158       }
  159   
  160       private void writerCleanup() throws IOException {
  161           synchronized (stateLock) {
  162               writerThread = 0;
  163               if (state == ST_KILLPENDING)
  164                   kill();
  165           }
  166       }
  167   
  168       public int read(ByteBuffer buf) throws IOException {
  169   
  170           if (buf == null)
  171               throw new NullPointerException();
  172   
  173           synchronized (readLock) {
  174               if (!ensureReadOpen())
  175                   return -1;
  176               int n = 0;
  177               try {
  178   
  179                   // Set up the interruption machinery; see
  180                   // AbstractInterruptibleChannel for details
  181                   //
  182                   begin();
  183   
  184                   synchronized (stateLock) {
  185                       if (!isOpen()) {
  186                       // Either the current thread is already interrupted, so
  187                       // begin() closed the channel, or another thread closed the
  188                       // channel since we checked it a few bytecodes ago.  In
  189                       // either case the value returned here is irrelevant since
  190                       // the invocation of end() in the finally block will throw
  191                       // an appropriate exception.
  192                       //
  193                           return 0;
  194   
  195                       }
  196   
  197                       // Save this thread so that it can be signalled on those
  198                       // platforms that require it
  199                       //
  200                       readerThread = NativeThread.current();
  201                   }
  202   
  203                   // Between the previous test of isOpen() and the return of the
  204                   // IOUtil.read invocation below, this channel might be closed
  205                   // or this thread might be interrupted.  We rely upon the
  206                   // implicit synchronization point in the kernel read() call to
  207                   // make sure that the right thing happens.  In either case the
  208                   // implCloseSelectableChannel method is ultimately invoked in
  209                   // some other thread, so there are three possibilities:
  210                   //
  211                   //   - implCloseSelectableChannel() invokes nd.preClose()
  212                   //     before this thread invokes read(), in which case the
  213                   //     read returns immediately with either EOF or an error,
  214                   //     the latter of which will cause an IOException to be
  215                   //     thrown.
  216                   //
  217                   //   - implCloseSelectableChannel() invokes nd.preClose() after
  218                   //     this thread is blocked in read().  On some operating
  219                   //     systems (e.g., Solaris and Windows) this causes the read
  220                   //     to return immediately with either EOF or an error
  221                   //     indication.
  222                   //
  223                   //   - implCloseSelectableChannel() invokes nd.preClose() after
  224                   //     this thread is blocked in read() but the operating
  225                   //     system (e.g., Linux) doesn't support preemptive close,
  226                   //     so implCloseSelectableChannel() proceeds to signal this
  227                   //     thread, thereby causing the read to return immediately
  228                   //     with IOStatus.INTERRUPTED.
  229                   //
  230                   // In all three cases the invocation of end() in the finally
  231                   // clause will notice that the channel has been closed and
  232                   // throw an appropriate exception (AsynchronousCloseException
  233                   // or ClosedByInterruptException) if necessary.
  234                   //
  235                   // *There is A fourth possibility. implCloseSelectableChannel()
  236                   // invokes nd.preClose(), signals reader/writer thred and quickly
  237                   // moves on to nd.close() in kill(), which does a real close.
  238                   // Then a third thread accepts a new connection, opens file or
  239                   // whatever that causes the released "fd" to be recycled. All
  240                   // above happens just between our last isOpen() check and the
  241                   // next kernel read reached, with the recycled "fd". The solution
  242                   // is to postpone the real kill() if there is a reader or/and
  243                   // writer thread(s) over there "waiting", leave the cleanup/kill
  244                   // to the reader or writer thread. (the preClose() still happens
  245                   // so the connection gets cut off as usual).
  246                   //
  247                   // For socket channels there is the additional wrinkle that
  248                   // asynchronous shutdown works much like asynchronous close,
  249                   // except that the channel is shutdown rather than completely
  250                   // closed.  This is analogous to the first two cases above,
  251                   // except that the shutdown operation plays the role of
  252                   // nd.preClose().
  253                   for (;;) {
  254                       n = IOUtil.read(fd, buf, -1, nd, readLock);
  255                       if ((n == IOStatus.INTERRUPTED) && isOpen()) {
  256                           // The system call was interrupted but the channel
  257                           // is still open, so retry
  258                           continue;
  259                       }
  260                       return IOStatus.normalize(n);
  261                   }
  262   
  263               } finally {
  264                   readerCleanup();        // Clear reader thread
  265                   // The end method, which is defined in our superclass
  266                   // AbstractInterruptibleChannel, resets the interruption
  267                   // machinery.  If its argument is true then it returns
  268                   // normally; otherwise it checks the interrupt and open state
  269                   // of this channel and throws an appropriate exception if
  270                   // necessary.
  271                   //
  272                   // So, if we actually managed to do any I/O in the above try
  273                   // block then we pass true to the end method.  We also pass
  274                   // true if the channel was in non-blocking mode when the I/O
  275                   // operation was initiated but no data could be transferred;
  276                   // this prevents spurious exceptions from being thrown in the
  277                   // rare event that a channel is closed or a thread is
  278                   // interrupted at the exact moment that a non-blocking I/O
  279                   // request is made.
  280                   //
  281                   end(n > 0 || (n == IOStatus.UNAVAILABLE));
  282   
  283                   // Extra case for socket channels: Asynchronous shutdown
  284                   //
  285                   synchronized (stateLock) {
  286                       if ((n <= 0) && (!isInputOpen))
  287                           return IOStatus.EOF;
  288                   }
  289   
  290                   assert IOStatus.check(n);
  291   
  292               }
  293           }
  294       }
  295   
  296       private long read0(ByteBuffer[] bufs) throws IOException {
  297           if (bufs == null)
  298               throw new NullPointerException();
  299           synchronized (readLock) {
  300               if (!ensureReadOpen())
  301                   return -1;
  302               long n = 0;
  303               try {
  304                   begin();
  305                   synchronized (stateLock) {
  306                       if (!isOpen())
  307                           return 0;
  308                       readerThread = NativeThread.current();
  309                   }
  310   
  311                   for (;;) {
  312                       n = IOUtil.read(fd, bufs, nd);
  313                       if ((n == IOStatus.INTERRUPTED) && isOpen())
  314                           continue;
  315                       return IOStatus.normalize(n);
  316                   }
  317               } finally {
  318                   readerCleanup();
  319                   end(n > 0 || (n == IOStatus.UNAVAILABLE));
  320                   synchronized (stateLock) {
  321                       if ((n <= 0) && (!isInputOpen))
  322                           return IOStatus.EOF;
  323                   }
  324                   assert IOStatus.check(n);
  325               }
  326           }
  327       }
  328   
  329       public long read(ByteBuffer[] dsts, int offset, int length)
  330           throws IOException
  331       {
  332           if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
  333               throw new IndexOutOfBoundsException();
  334           // ## Fix IOUtil.write so that we can avoid this array copy
  335           return read0(Util.subsequence(dsts, offset, length));
  336       }
  337   
  338       public int write(ByteBuffer buf) throws IOException {
  339           if (buf == null)
  340               throw new NullPointerException();
  341           synchronized (writeLock) {
  342               ensureWriteOpen();
  343               int n = 0;
  344               try {
  345                   begin();
  346                   synchronized (stateLock) {
  347                       if (!isOpen())
  348                           return 0;
  349                       writerThread = NativeThread.current();
  350                   }
  351                   for (;;) {
  352                       n = IOUtil.write(fd, buf, -1, nd, writeLock);
  353                       if ((n == IOStatus.INTERRUPTED) && isOpen())
  354                           continue;
  355                       return IOStatus.normalize(n);
  356                   }
  357               } finally {
  358                   writerCleanup();
  359                   end(n > 0 || (n == IOStatus.UNAVAILABLE));
  360                   synchronized (stateLock) {
  361                       if ((n <= 0) && (!isOutputOpen))
  362                           throw new AsynchronousCloseException();
  363                   }
  364                   assert IOStatus.check(n);
  365               }
  366           }
  367       }
  368   
  369       public long write0(ByteBuffer[] bufs) throws IOException {
  370           if (bufs == null)
  371               throw new NullPointerException();
  372           synchronized (writeLock) {
  373               ensureWriteOpen();
  374               long n = 0;
  375               try {
  376                   begin();
  377                   synchronized (stateLock) {
  378                       if (!isOpen())
  379                           return 0;
  380                       writerThread = NativeThread.current();
  381                   }
  382                   for (;;) {
  383                       n = IOUtil.write(fd, bufs, nd);
  384                       if ((n == IOStatus.INTERRUPTED) && isOpen())
  385                           continue;
  386                       return IOStatus.normalize(n);
  387                   }
  388               } finally {
  389                   writerCleanup();
  390                   end((n > 0) || (n == IOStatus.UNAVAILABLE));
  391                   synchronized (stateLock) {
  392                       if ((n <= 0) && (!isOutputOpen))
  393                           throw new AsynchronousCloseException();
  394                   }
  395                   assert IOStatus.check(n);
  396               }
  397           }
  398       }
  399   
  400       public long write(ByteBuffer[] srcs, int offset, int length)
  401           throws IOException
  402       {
  403           if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
  404               throw new IndexOutOfBoundsException();
  405           // ## Fix IOUtil.write so that we can avoid this array copy
  406           return write0(Util.subsequence(srcs, offset, length));
  407       }
  408   
  409       protected void implConfigureBlocking(boolean block) throws IOException {
  410           IOUtil.configureBlocking(fd, block);
  411       }
  412   
  413       public SocketOpts options() {
  414           synchronized (stateLock) {
  415               if (options == null) {
  416                   SocketOptsImpl.Dispatcher d
  417                       = new SocketOptsImpl.Dispatcher() {
  418                               int getInt(int opt) throws IOException {
  419                                   return Net.getIntOption(fd, opt);
  420                               }
  421                               void setInt(int opt, int arg)
  422                                   throws IOException
  423                               {
  424                                   Net.setIntOption(fd, opt, arg);
  425                               }
  426                           };
  427                   options = new SocketOptsImpl.IP.TCP(d);
  428               }
  429               return options;
  430           }
  431       }
  432   
  433       public boolean isBound() {
  434           synchronized (stateLock) {
  435               if (state == ST_CONNECTED)
  436                   return true;
  437               return localAddress != null;
  438           }
  439       }
  440   
  441       public SocketAddress localAddress() {
  442           synchronized (stateLock) {
  443               if (state == ST_CONNECTED &&
  444                   (localAddress == null ||
  445                    ((InetSocketAddress)localAddress).getAddress().isAnyLocalAddress())) {
  446                       // Socket was not bound before connecting or
  447                       // Socket was bound with an "anyLocalAddress"
  448                       localAddress = Net.localAddress(fd);
  449               }
  450               return localAddress;
  451           }
  452       }
  453   
  454       public SocketAddress remoteAddress() {
  455           synchronized (stateLock) {
  456               return remoteAddress;
  457           }
  458       }
  459   
  460       public void bind(SocketAddress local) throws IOException {
  461           synchronized (readLock) {
  462               synchronized (writeLock) {
  463                   synchronized (stateLock) {
  464                       ensureOpenAndUnconnected();
  465                       if (localAddress != null)
  466                           throw new AlreadyBoundException();
  467                       InetSocketAddress isa = Net.checkAddress(local);
  468                       Net.bind(fd, isa.getAddress(), isa.getPort());
  469                       localAddress = Net.localAddress(fd);
  470                   }
  471               }
  472           }
  473       }
  474   
  475       public boolean isConnected() {
  476           synchronized (stateLock) {
  477               return (state == ST_CONNECTED);
  478           }
  479       }
  480   
  481       public boolean isConnectionPending() {
  482           synchronized (stateLock) {
  483               return (state == ST_PENDING);
  484           }
  485       }
  486   
  487       void ensureOpenAndUnconnected() throws IOException { // package-private
  488           synchronized (stateLock) {
  489               if (!isOpen())
  490                   throw new ClosedChannelException();
  491               if (state == ST_CONNECTED)
  492                   throw new AlreadyConnectedException();
  493               if (state == ST_PENDING)
  494                   throw new ConnectionPendingException();
  495           }
  496       }
  497   
  498       public boolean connect(SocketAddress sa) throws IOException {
  499           int trafficClass = 0;           // ## Pick up from options
  500           int localPort = 0;
  501   
  502           synchronized (readLock) {
  503               synchronized (writeLock) {
  504                   ensureOpenAndUnconnected();
  505                   InetSocketAddress isa = Net.checkAddress(sa);
  506                   SecurityManager sm = System.getSecurityManager();
  507                   if (sm != null)
  508                       sm.checkConnect(isa.getAddress().getHostAddress(),
  509                                       isa.getPort());
  510                   synchronized (blockingLock()) {
  511                       int n = 0;
  512                       try {
  513                           try {
  514                               begin();
  515                               synchronized (stateLock) {
  516                                   if (!isOpen()) {
  517                                       return false;
  518                                   }
  519                                   readerThread = NativeThread.current();
  520                               }
  521                               for (;;) {
  522                                   InetAddress ia = isa.getAddress();
  523                                   if (ia.isAnyLocalAddress())
  524                                       ia = InetAddress.getLocalHost();
  525                                   n = Net.connect(fd,
  526                                                   ia,
  527                                                   isa.getPort(),
  528                                                   trafficClass);
  529                                   if (  (n == IOStatus.INTERRUPTED)
  530                                         && isOpen())
  531                                       continue;
  532                                   break;
  533                               }
  534                           } finally {
  535                               readerCleanup();
  536                               end((n > 0) || (n == IOStatus.UNAVAILABLE));
  537                               assert IOStatus.check(n);
  538                           }
  539                       } catch (IOException x) {
  540                           // If an exception was thrown, close the channel after
  541                           // invoking end() so as to avoid bogus
  542                           // AsynchronousCloseExceptions
  543                           close();
  544                           throw x;
  545                       }
  546                       synchronized (stateLock) {
  547                           remoteAddress = isa;
  548                           if (n > 0) {
  549   
  550                               // Connection succeeded; disallow further
  551                               // invocation
  552                               state = ST_CONNECTED;
  553                               return true;
  554                           }
  555                           // If nonblocking and no exception then connection
  556                           // pending; disallow another invocation
  557                           if (!isBlocking())
  558                               state = ST_PENDING;
  559                           else
  560                               assert false;
  561                       }
  562                   }
  563                   return false;
  564               }
  565           }
  566       }
  567   
  568       public boolean finishConnect() throws IOException {
  569           synchronized (readLock) {
  570               synchronized (writeLock) {
  571                   synchronized (stateLock) {
  572                       if (!isOpen())
  573                           throw new ClosedChannelException();
  574                       if (state == ST_CONNECTED)
  575                           return true;
  576                       if (state != ST_PENDING)
  577                           throw new NoConnectionPendingException();
  578                   }
  579                   int n = 0;
  580                   try {
  581                       try {
  582                           begin();
  583                           synchronized (blockingLock()) {
  584                               synchronized (stateLock) {
  585                                   if (!isOpen()) {
  586                                       return false;
  587                                   }
  588                                   readerThread = NativeThread.current();
  589                               }
  590                               if (!isBlocking()) {
  591                                   for (;;) {
  592                                       n = checkConnect(fd, false,
  593                                                        readyToConnect);
  594                                       if (  (n == IOStatus.INTERRUPTED)
  595                                             && isOpen())
  596                                           continue;
  597                                       break;
  598                                   }
  599                               } else {
  600                                   for (;;) {
  601                                       n = checkConnect(fd, true,
  602                                                        readyToConnect);
  603                                       if (n == 0) {
  604                                           // Loop in case of
  605                                           // spurious notifications
  606                                           continue;
  607                                       }
  608                                       if (  (n == IOStatus.INTERRUPTED)
  609                                             && isOpen())
  610                                           continue;
  611                                       break;
  612                                   }
  613                               }
  614                           }
  615                       } finally {
  616                           synchronized (stateLock) {
  617                               readerThread = 0;
  618                               if (state == ST_KILLPENDING) {
  619                                   kill();
  620                                   // poll()/getsockopt() does not report
  621                                   // error (throws exception, with n = 0)
  622                                   // on Linux platform after dup2 and
  623                                   // signal-wakeup. Force n to 0 so the
  624                                   // end() can throw appropriate exception
  625                                   n = 0;
  626                               }
  627                           }
  628                           end((n > 0) || (n == IOStatus.UNAVAILABLE));
  629                           assert IOStatus.check(n);
  630                       }
  631                   } catch (IOException x) {
  632                       // If an exception was thrown, close the channel after
  633                       // invoking end() so as to avoid bogus
  634                       // AsynchronousCloseExceptions
  635                       close();
  636                       throw x;
  637                   }
  638                   if (n > 0) {
  639                       synchronized (stateLock) {
  640                           state = ST_CONNECTED;
  641                       }
  642                       return true;
  643                   }
  644                   return false;
  645               }
  646           }
  647       }
  648   
  649       public final static int SHUT_RD = 0;
  650       public final static int SHUT_WR = 1;
  651       public final static int SHUT_RDWR = 2;
  652   
  653       public void shutdownInput() throws IOException {
  654           synchronized (stateLock) {
  655               if (!isOpen())
  656                   throw new ClosedChannelException();
  657               isInputOpen = false;
  658               shutdown(fd, SHUT_RD);
  659               if (readerThread != 0)
  660                   NativeThread.signal(readerThread);
  661           }
  662       }
  663   
  664       public void shutdownOutput() throws IOException {
  665           synchronized (stateLock) {
  666               if (!isOpen())
  667                   throw new ClosedChannelException();
  668               isOutputOpen = false;
  669               shutdown(fd, SHUT_WR);
  670               if (writerThread != 0)
  671                   NativeThread.signal(writerThread);
  672           }
  673       }
  674   
  675       public boolean isInputOpen() {
  676           synchronized (stateLock) {
  677               return isInputOpen;
  678           }
  679       }
  680   
  681       public boolean isOutputOpen() {
  682           synchronized (stateLock) {
  683               return isOutputOpen;
  684           }
  685       }
  686   
  687       // AbstractInterruptibleChannel synchronizes invocations of this method
  688       // using AbstractInterruptibleChannel.closeLock, and also ensures that this
  689       // method is only ever invoked once.  Before we get to this method, isOpen
  690       // (which is volatile) will have been set to false.
  691       //
  692       protected void implCloseSelectableChannel() throws IOException {
  693           synchronized (stateLock) {
  694               isInputOpen = false;
  695               isOutputOpen = false;
  696   
  697               // Close the underlying file descriptor and dup it to a known fd
  698               // that's already closed.  This prevents other operations on this
  699               // channel from using the old fd, which might be recycled in the
  700               // meantime and allocated to an entirely different channel.
  701               //
  702               nd.preClose(fd);
  703   
  704               // Signal native threads, if needed.  If a target thread is not
  705               // currently blocked in an I/O operation then no harm is done since
  706               // the signal handler doesn't actually do anything.
  707               //
  708               if (readerThread != 0)
  709                   NativeThread.signal(readerThread);
  710   
  711               if (writerThread != 0)
  712                   NativeThread.signal(writerThread);
  713   
  714               // If this channel is not registered then it's safe to close the fd
  715               // immediately since we know at this point that no thread is
  716               // blocked in an I/O operation upon the channel and, since the
  717               // channel is marked closed, no thread will start another such
  718               // operation.  If this channel is registered then we don't close
  719               // the fd since it might be in use by a selector.  In that case
  720               // closing this channel caused its keys to be cancelled, so the
  721               // last selector to deregister a key for this channel will invoke
  722               // kill() to close the fd.
  723               //
  724               if (!isRegistered())
  725                   kill();
  726           }
  727       }
  728   
  729       public void kill() throws IOException {
  730           synchronized (stateLock) {
  731               if (state == ST_KILLED)
  732                   return;
  733               if (state == ST_UNINITIALIZED) {
  734                   state = ST_KILLED;
  735                   return;
  736               }
  737               assert !isOpen() && !isRegistered();
  738   
  739               // Postpone the kill if there is a waiting reader
  740               // or writer thread. See the comments in read() for
  741               // more detailed explanation.
  742               if (readerThread == 0 && writerThread == 0) {
  743                   nd.close(fd);
  744                   state = ST_KILLED;
  745               } else {
  746                   state = ST_KILLPENDING;
  747               }
  748           }
  749       }
  750   
  751       /**
  752        * Translates native poll revent ops into a ready operation ops
  753        */
  754       public boolean translateReadyOps(int ops, int initialOps,
  755                                        SelectionKeyImpl sk) {
  756           int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
  757           int oldOps = sk.nioReadyOps();
  758           int newOps = initialOps;
  759   
  760           if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
  761               // This should only happen if this channel is pre-closed while a
  762               // selection operation is in progress
  763               // ## Throw an error if this channel has not been pre-closed
  764               return false;
  765           }
  766   
  767           if ((ops & (PollArrayWrapper.POLLERR
  768                       | PollArrayWrapper.POLLHUP)) != 0) {
  769               newOps = intOps;
  770               sk.nioReadyOps(newOps);
  771               // No need to poll again in checkConnect,
  772               // the error will be detected there
  773               readyToConnect = true;
  774               return (newOps & ~oldOps) != 0;
  775           }
  776   
  777           if (((ops & PollArrayWrapper.POLLIN) != 0) &&
  778               ((intOps & SelectionKey.OP_READ) != 0) &&
  779               (state == ST_CONNECTED))
  780               newOps |= SelectionKey.OP_READ;
  781   
  782           if (((ops & PollArrayWrapper.POLLCONN) != 0) &&
  783               ((intOps & SelectionKey.OP_CONNECT) != 0) &&
  784               ((state == ST_UNCONNECTED) || (state == ST_PENDING))) {
  785               newOps |= SelectionKey.OP_CONNECT;
  786               readyToConnect = true;
  787           }
  788   
  789           if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
  790               ((intOps & SelectionKey.OP_WRITE) != 0) &&
  791               (state == ST_CONNECTED))
  792               newOps |= SelectionKey.OP_WRITE;
  793   
  794           sk.nioReadyOps(newOps);
  795           return (newOps & ~oldOps) != 0;
  796       }
  797   
  798       public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
  799           return translateReadyOps(ops, sk.nioReadyOps(), sk);
  800       }
  801   
  802       public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
  803           return translateReadyOps(ops, 0, sk);
  804       }
  805   
  806       /**
  807        * Translates an interest operation set into a native poll event set
  808        */
  809       public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
  810           int newOps = 0;
  811           if ((ops & SelectionKey.OP_READ) != 0)
  812               newOps |= PollArrayWrapper.POLLIN;
  813           if ((ops & SelectionKey.OP_WRITE) != 0)
  814               newOps |= PollArrayWrapper.POLLOUT;
  815           if ((ops & SelectionKey.OP_CONNECT) != 0)
  816               newOps |= PollArrayWrapper.POLLCONN;
  817           sk.selector.putEventOps(sk, newOps);
  818       }
  819   
  820       public FileDescriptor getFD() {
  821           return fd;
  822       }
  823   
  824       public int getFDVal() {
  825           return fdVal;
  826       }
  827   
  828       public String toString() {
  829           StringBuffer sb = new StringBuffer();
  830           sb.append(this.getClass().getSuperclass().getName());
  831           sb.append('[');
  832           if (!isOpen())
  833               sb.append("closed");
  834           else {
  835               synchronized (stateLock) {
  836                   switch (state) {
  837                   case ST_UNCONNECTED:
  838                       sb.append("unconnected");
  839                       break;
  840                   case ST_PENDING:
  841                       sb.append("connection-pending");
  842                       break;
  843                   case ST_CONNECTED:
  844                       sb.append("connected");
  845                       if (!isInputOpen)
  846                           sb.append(" ishut");
  847                       if (!isOutputOpen)
  848                           sb.append(" oshut");
  849                       break;
  850                   }
  851                   if (localAddress() != null) {
  852                       sb.append(" local=");
  853                       sb.append(localAddress().toString());
  854                   }
  855                   if (remoteAddress() != null) {
  856                       sb.append(" remote=");
  857                       sb.append(remoteAddress().toString());
  858                   }
  859               }
  860           }
  861           sb.append(']');
  862           return sb.toString();
  863       }
  864   
  865   
  866       // -- Native methods --
  867   
  868       private static native int checkConnect(FileDescriptor fd,
  869                                              boolean block, boolean ready)
  870           throws IOException;
  871   
  872       private static native void shutdown(FileDescriptor fd, int how)
  873           throws IOException;
  874   
  875       static {
  876           Util.load();
  877           nd = new SocketDispatcher();
  878       }
  879   
  880   }

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