You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2006/01/28 23:40:36 UTC

svn commit: r373254 - in /directory/trunks/apacheds/standalone: daemon/src/main/java/org/apache/directory/server/standalone/daemon/ simple/main/src/main/java/org/apache/ldap/server/

Author: akarasulu
Date: Sat Jan 28 14:40:26 2006
New Revision: 373254

URL: http://svn.apache.org/viewcvs?rev=373254&view=rev
Log:
got shutdown socket working with procrun

Modified:
    directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/Bootstrapper.java
    directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/ProcrunBootstrapper.java
    directory/trunks/apacheds/standalone/simple/main/src/main/java/org/apache/ldap/server/DirectoryServer.java

Modified: directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/Bootstrapper.java
URL: http://svn.apache.org/viewcvs/directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/Bootstrapper.java?rev=373254&r1=373253&r2=373254&view=diff
==============================================================================
--- directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/Bootstrapper.java (original)
+++ directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/Bootstrapper.java Sat Jan 28 14:40:26 2006
@@ -17,10 +17,22 @@
 package org.apache.directory.server.standalone.daemon;
 
 
+import java.io.BufferedReader;
+import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.security.AccessControlException;
 import java.util.Properties;
+import java.util.Random;
 
 import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
@@ -39,6 +51,16 @@
     private static final Logger log = LoggerFactory.getLogger( Bootstrapper.class );
     private static final String START_CLASS_PROP = "bootstrap.start.class";
     private static final String STOP_CLASS_PROP = "bootstrap.stop.class";
+
+    /** Shutdown command to use for await() */
+    private static final String SHUTDOWN = "SHUTDOWN";
+
+    private static final String SHUTDOWN_FILE = "shutdownPort";
+    /** The Port to Listen on for Shutdown commands */
+    private int shutdownPort = -1;
+    /** Random number generator */
+    private Random random;
+    
     
     private InstallationLayout layout;
     private ClassLoader application;
@@ -222,5 +244,179 @@
         }
         
         return EMPTY_STRARRAY;
+    }
+
+    
+    public void sendShutdownCommand() throws IOException
+    {
+        Socket socket = null;
+        OutputStream stream = null;
+        
+        if ( shutdownPort == -1 )
+        {
+            File shutdownPortFile = new File( layout.getRunDirectory(), SHUTDOWN_FILE );
+            if ( shutdownPortFile.exists() )
+            {
+                BufferedReader in = new BufferedReader( new FileReader( shutdownPortFile ) );
+                shutdownPort = Integer.parseInt( in.readLine() );
+                in.close();
+            }
+        }
+        
+        // this stops the main thread listening for shutdown requests
+        try {
+            socket = new Socket( "127.0.0.1", shutdownPort );
+            stream = socket.getOutputStream();
+
+            for (int i = 0; i < SHUTDOWN.length(); i++ )
+            {
+                stream.write( SHUTDOWN.charAt(i) );
+            }
+
+            stream.flush();
+        }
+        finally
+        {
+            if ( stream != null ) stream.close();
+            if ( socket != null ) socket.close();
+        }
+    }
+    
+
+    /**
+     * Wait until a proper shutdown command is received, then return.
+     */
+    public void waitForShutdown()
+    {
+        try
+        {
+            shutdownPort = AvailablePortFinder.getNextAvailable( 30003 );
+            File shutdownPortFile = new File( layout.getRunDirectory(), SHUTDOWN_FILE );
+            if ( shutdownPortFile.exists() )
+            {
+                String msg = "Shutdown port file " + shutdownPortFile + " exists. ";
+                msg += "\nEither the server is already running or a previous run existed abruptly.";
+                msg += "\nIf the server is not running remove this file and try again.";
+                log.error( msg );
+                throw new IllegalStateException( msg );
+            }
+            FileWriter writer = new FileWriter( shutdownPortFile );
+            writer.write( shutdownPort + "\n" );
+            writer.close();
+        }
+        catch ( IOException e )
+        {
+            log.error( "Failed to setup shutdown port", e );
+            System.exit( ExitCodes.START );
+        }
+
+        // Set up a server socket to wait on
+        ServerSocket serverSocket = null;
+        try
+        {
+            serverSocket = new ServerSocket( shutdownPort, 1, InetAddress.getByName( "127.0.0.1" ) );
+            log.debug( "waiting for shutdown command on port = " + shutdownPort );
+        }
+        catch ( IOException e )
+        {
+            log.error( "server waitForShutdown: create[" + shutdownPort + "]: ", e );
+            System.exit( 1 );
+        }
+
+        // Loop waiting for a connection and a valid command
+        while ( true )
+        {
+            // Wait for the next connection
+            Socket socket = null;
+            InputStream stream = null;
+
+            try
+            {
+                socket = serverSocket.accept();
+                socket.setSoTimeout(10 * 1000);  // Ten seconds
+                stream = socket.getInputStream();
+            }
+            catch ( AccessControlException ace )
+            {
+                log.warn( "Standard Server.accept security exception: " + ace.getMessage(), ace );
+                continue;
+            }
+            catch ( IOException e )
+            {
+                log.error( "Server.await: accept: ", e );
+                System.exit( 5 );
+            }
+
+            // Read a set of characters from the socket
+            StringBuffer command = new StringBuffer();
+            int expected = 1024; // Cut off to avoid DoS attack
+
+            while ( expected < SHUTDOWN.length() )
+            {
+                if ( random == null )
+                {
+                    random = new Random(System.currentTimeMillis());
+                }
+                expected += ( random.nextInt() % 1024 );
+            }
+            while ( expected > 0 )
+            {
+                int ch;
+                try
+                {
+                    ch = stream.read();
+                }
+                catch ( IOException e )
+                {
+                    log.warn( "StandardServer.await: read: ", e );
+                    ch = -1;
+                }
+
+                if ( ch < 32 )  // Control character or EOF terminates loop
+                {
+                    break;
+                }
+
+                command.append( ( char ) ch );
+                expected--;
+            }
+
+            // Close the socket now that we are done with it
+            try
+            {
+                socket.close();
+            }
+            catch ( IOException e )
+            {
+                log.debug( "Failed on socket close", e );
+            }
+
+            // Match against our command string
+            boolean match = command.toString().equals( SHUTDOWN );
+            if ( match )
+            {
+                break;
+            }
+            else
+            {
+                log.warn( "Server.await: Invalid command '" + command.toString() + "' received" );
+            }
+        }
+
+        // Close the server socket and return
+        try
+        {
+            serverSocket.close();
+        }
+        catch ( IOException e )
+        {
+            log.debug( "Failed on socket close", e );
+        }
+        
+        File shutdownPortFile = new File( layout.getRunDirectory(), SHUTDOWN_FILE );
+        if ( shutdownPortFile.exists() )
+        {
+            shutdownPortFile.delete();
+        }
     }
 }

Modified: directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/ProcrunBootstrapper.java
URL: http://svn.apache.org/viewcvs/directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/ProcrunBootstrapper.java?rev=373254&r1=373253&r2=373254&view=diff
==============================================================================
--- directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/ProcrunBootstrapper.java (original)
+++ directory/trunks/apacheds/standalone/daemon/src/main/java/org/apache/directory/server/standalone/daemon/ProcrunBootstrapper.java Sat Jan 28 14:40:26 2006
@@ -25,6 +25,7 @@
  * The bootstrapper used for procrun services on windows platforms.  This
  * class contains static methods invoked by the prunsrv service manager.
  * 
+ * @todo explain procrun behavoir
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
@@ -63,23 +64,19 @@
             log.debug( "prunsrvStart(String[]) calling callStart()" );
             instance.callStart( false );
 
-            // This is only needed for procrun 
-            while( true )
-            {
-                try
-                {
-                    Thread.sleep( 2000 );
-                }
-                catch ( InterruptedException e )
-                {
-                    e.printStackTrace();
-                }
-            }
+            log.debug( "prunsrvStart(String[]) block waitForShutdown()" );
+            instance.waitForShutdown();
+            log.debug( "prunsrvStart(String[]) returned from waitForShutdown()" );
+
+            log.debug( "prunsrvStart(String[]) calling callStop()" );
+            instance.callStop( shift( args, 1 ) );
+            log.debug( "prunsrvStart(String[]) calling callDestroy()" );
+            instance.callDestroy();
         }
         catch ( Throwable t )
         {
             log.error( "Encountered error in prunsrvStart(String[])", t );
-            System.exit( 4 );
+            System.exit( ExitCodes.UNKNOWN );
         }
     }
 
@@ -102,16 +99,12 @@
             ProcrunBootstrapper instance = new ProcrunBootstrapper();
             instance.setInstallationLayout( args[0] );
             instance.setParentLoader( Bootstrapper.class.getClassLoader() );
-
-            log.debug( "prunsrvStop(String[]) calling callStop()" );
-            instance.callStop( shift( args, 1 ) );
-            log.debug( "prunsrvStop(String[]) calling callDestroy()" );
-            instance.callDestroy();
+            instance.sendShutdownCommand();
         }
         catch ( Throwable t )
         {
             log.error( "Encountered error in prunsrvStop(String[])", t );
-            System.exit( 4 );
+            System.exit( ExitCodes.UNKNOWN );
         }
     }
 }

Modified: directory/trunks/apacheds/standalone/simple/main/src/main/java/org/apache/ldap/server/DirectoryServer.java
URL: http://svn.apache.org/viewcvs/directory/trunks/apacheds/standalone/simple/main/src/main/java/org/apache/ldap/server/DirectoryServer.java?rev=373254&r1=373253&r2=373254&view=diff
==============================================================================
--- directory/trunks/apacheds/standalone/simple/main/src/main/java/org/apache/ldap/server/DirectoryServer.java (original)
+++ directory/trunks/apacheds/standalone/simple/main/src/main/java/org/apache/ldap/server/DirectoryServer.java Sat Jan 28 14:40:26 2006
@@ -97,6 +97,8 @@
     }
     
 
+    // @todo don't think this nowait is needed here if the procrun bootstrapper
+    // handles the creation of the socket and the blocking.
     public void start( boolean nowait ) 
     {
         startNoWait = nowait;
@@ -109,7 +111,7 @@
         }
 
         started = true;
-        worker.run();  // - blocks here 
+//        worker.run();  // - blocks here 
     }