Ning Sun avatar Ning Sun committed ac4eff2

new shutdown request

Comments (0)

Files changed (4)

src/main/java/info/sunng/soldat/Client.java

 
 import info.sunng.soldat.engines.Transport;
 import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
 import java.util.HashMap;
 import java.util.Map;
 
     protected Object attachment;
     protected long createdTime;
     protected long lastActionTime;
+    protected SelectionKey key;
 
     private final Map<String, Object> attributes = new HashMap<String, Object>();
 
         return this.serverPort;
     }
 
+    /**
+     * @return the key
+     */
+    public SelectionKey getKey() {
+        return key;
+    }
+
+    /**
+     * @param key the key to set
+     */
+    public void setKey(SelectionKey key) {
+        this.key = key;
+    }
+
 }

src/main/java/info/sunng/soldat/engines/AbstractAcceptorEngine.java

 import info.sunng.soldat.Protocol;
 import info.sunng.soldat.SoldatException;
 import info.sunng.soldat.util.NIOUtils;
-import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.SelectionKey;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicInteger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
     TransportType _type;
 
-    boolean _running ;
+    long maxIdle;
 
-    long maxIdle;
+    AtomicInteger managedChannels = new AtomicInteger();
 
     List<Client> connectedClients = new ArrayList<Client>();
 
         this._handler.onAccept(client);
 
         if (client.getTransport().getChannel().isOpen()) {
-            registerQ.offer(new RegistrationRequest(
+            registerQ.offer(new RegistrationRequest(this,
                     clientChannel, SelectionKey.OP_READ, client));
             
             if (logger.isDebugEnabled()) {
         _serverTransport.openAcceptor(_addr);
         _selector = Selector.open();
         if (this._type == TransportType.TCP){
-            RegistrationRequest request = new RegistrationRequest(
+            RegistrationRequest request = new RegistrationRequest(this,
                     _serverTransport.getChannel(), SelectionKey.OP_ACCEPT);
             registerQ.offer(request);
         } else {
-            RegistrationRequest request = new RegistrationRequest(
+            RegistrationRequest request = new RegistrationRequest(this,
                     _serverTransport.getChannel(), SelectionKey.OP_READ);
             registerQ.offer(request);
         }
 
     @Override
     public void shutdown() throws SoldatException {
-        _running = false;
-        logger.info("Server about to shutdown");
-        try {
-            for (SelectionKey key : _selector.keys()) {
-                key.cancel();
-                key.channel().close();
-            }
-            _selector.close();
-        } catch (IOException ex) {
-            throw new SoldatException(ex);
-        }
-        logger.info("Server down");
+        ShutdownRequest request = new ShutdownRequest(this);
+        registerQ.offer(request);
     }
 
     private void executeQueue() {
             throw new SoldatException(ex);
         }
 
-        _running = true;
-        while (_running) {
+        // start server channel
+        executeQueue();
+        
+        while( managedChannels.get() > 0 ) {
             checkClients();
 
             executeQueue();
 
             if (now - client.getLastActionTime() > getMaxIdle()) {
                 _handler.onIdle(client);
-                freeClient(client);
-                connectedClients.remove(client);
+                if (client.getKey() == null){
+                    freeClient(client);
+                    connectedClients.remove(client);
+                } else {
+                    cancelClient(client.getKey());
+                }
             }
         }
     }
     protected void cancelClient(SelectionKey key) {
         NIOUtils.cancelKey(key);
         connectedClients.remove((Client)key.attachment());
+        managedChannels.decrementAndGet();
     }
-
+    
 }

src/main/java/info/sunng/soldat/engines/RegistrationRequest.java

 
 package info.sunng.soldat.engines;
 
+import info.sunng.soldat.Client;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
 
 /**
 
     private Object attachment;
 
-    public RegistrationRequest(SelectableChannel channel, int registerOp){
+    private AbstractAcceptorEngine engine;
+
+    public RegistrationRequest(AbstractAcceptorEngine engine,
+            SelectableChannel channel, int registerOp){
+        this.engine = engine;
         this.channel = channel;
         this.registerOp = registerOp;
         this.attachment = null;
     }
 
-    public RegistrationRequest(SelectableChannel channel, int registerOp,
-            Object attachment){
+    public RegistrationRequest(AbstractAcceptorEngine engine,
+            SelectableChannel channel, int registerOp, Object attachment){
+        this.engine = engine;
         this.channel = channel;
         this.registerOp = registerOp;
         this.attachment = attachment;
     public boolean perform(Selector selector) {
         if (channel.isOpen()) {
             try {
-                channel.register(selector, registerOp, attachment);
+                SelectionKey key = channel.register(selector, registerOp,
+                        attachment);
+                if (attachment != null && attachment instanceof Client) {
+                    Client client = (Client)attachment;
+                    client.setKey(key);
+                }
+                engine.managedChannels.addAndGet(1);
                 selector.wakeup();
             } catch (ClosedChannelException e) {}
         } else {

src/main/java/info/sunng/soldat/engines/ShutdownRequest.java

+/*
+ *  Copyright (c) 2011 Sun Ning <classicning@gmail.com>
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of the project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL Sun Ning BE LIABLE FOR ANY
+ *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+
+package info.sunng.soldat.engines;
+
+import info.sunng.soldat.SoldatException;
+import java.io.IOException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author Sun Ning
+ *
+ */
+public class ShutdownRequest implements SelectRequest {
+
+    private static Logger logger = LoggerFactory.getLogger(ShutdownRequest.class);
+    
+    private AbstractAcceptorEngine engine;
+
+    public  ShutdownRequest(AbstractAcceptorEngine engine) {
+        this.engine = engine;
+    }
+
+    @Override
+    public boolean perform(Selector selector) {
+        logger.info("Server about to shutdown");
+        try {
+            for (SelectionKey key : selector.keys()) {
+                engine.cancelClient(key);
+            }
+            selector.close();
+        } catch (IOException ex) {
+            // just ignore exception here
+        }
+        logger.info("Server down");
+        return true;
+    }
+
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.