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/30 05:49:23 UTC

svn commit: r373434 - in /directory/trunks: apacheds/protocols/ldap/src/main/java/org/apache/ldap/server/protocol/support/extended/ apacheds/standalone/simple/jndi/src/main/java/org/apache/ldap/server/jndi/ apacheds/tools/src/main/java/org/apache/ldap/...

Author: akarasulu
Date: Sun Jan 29 20:49:12 2006
New Revision: 373434

URL: http://svn.apache.org/viewcvs?rev=373434&view=rev
Log:
changes ...

 o added a unsolicited notification listener which is graceful disconnect aware
 o added a bogus tool for now which just shows how to send a GracefulShutdown;
   i'll leave the setup of various command line parameters for laters
 o made it so the GracefulDisconnect message can initialize with payload bytes
 o fixed some issues in the Twix transform so it produces the correct values
 o corrected a bug in the server context factory where an already unbound ldap
   service with graceful shutdown is causing an exception that prevents proper
   receipt of the GracefulShutdownResponse
 o fixed several bugs in the handler for GracefulShutdown and tested it

 Oh and it all works !!!!!!


Added:
    directory/trunks/apacheds/tools/src/main/java/org/apache/ldap/server/dumptool/GracefulShutdown.java   (with props)
    directory/trunks/apacheds/tools/src/test/java/org/
    directory/trunks/apacheds/tools/src/test/java/org/apache/
    directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/
    directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/server/
    directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/server/dumptool/
    directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/server/dumptool/NotificationsExample.java   (with props)
Modified:
    directory/trunks/apacheds/protocols/ldap/src/main/java/org/apache/ldap/server/protocol/support/extended/GracefulShutdownHandler.java
    directory/trunks/apacheds/standalone/simple/jndi/src/main/java/org/apache/ldap/server/jndi/ServerContextFactory.java
    directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/codec/TwixTransformer.java
    directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulDisconnect.java
    directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownRequest.java
    directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownResponse.java

Modified: directory/trunks/apacheds/protocols/ldap/src/main/java/org/apache/ldap/server/protocol/support/extended/GracefulShutdownHandler.java
URL: http://svn.apache.org/viewcvs/directory/trunks/apacheds/protocols/ldap/src/main/java/org/apache/ldap/server/protocol/support/extended/GracefulShutdownHandler.java?rev=373434&r1=373433&r2=373434&view=diff
==============================================================================
--- directory/trunks/apacheds/protocols/ldap/src/main/java/org/apache/ldap/server/protocol/support/extended/GracefulShutdownHandler.java (original)
+++ directory/trunks/apacheds/protocols/ldap/src/main/java/org/apache/ldap/server/protocol/support/extended/GracefulShutdownHandler.java Sun Jan 29 20:49:12 2006
@@ -118,6 +118,8 @@
         // handle the body of this operation below here
         // -------------------------------------------------------------------
         
+        IoAcceptor acceptor = serviceRegistry.getAcceptor( ldapService.getTransportType() );
+        List sessions = new ArrayList( acceptor.getManagedSessions( ldapService.getAddress() ) );
         StartupConfiguration cfg = service.getConfiguration().getStartupConfiguration();
         GracefulShutdownRequest gsreq = ( GracefulShutdownRequest ) req;
 
@@ -133,7 +135,7 @@
 //        }
 
         // send (synch) the GracefulDisconnect to each client before unbinding
-        sendGracefulDisconnect( notice, requestor );
+        sendGracefulDisconnect( sessions, notice, requestor );
 
         // wait for the specified delay before we unbind the service 
         if ( gsreq.getDelay() > 0 )
@@ -169,7 +171,7 @@
         // after sending the NoD the client is disconnected if still connected
         // -------------------------------------------------------------------
 
-        sendNoticeOfDisconnect( requestor );
+        sendNoticeOfDisconnect( sessions, requestor );
 
         // -------------------------------------------------------------------
         // respond back to the client that requested the graceful shutdown w/
@@ -211,10 +213,8 @@
      * @param msg the graceful disconnec extended request to send
      * @param requestor the session of the graceful shutdown requestor
      */
-    private void sendGracefulDisconnect( GracefulDisconnect msg, IoSession requestor )
+    private void sendGracefulDisconnect( List sessions, GracefulDisconnect msg, IoSession requestor )
     {
-        IoAcceptor acceptor = serviceRegistry.getAcceptor( ldapService.getTransportType() );
-        List sessions = new ArrayList( acceptor.getManagedSessions( ldapService.getAddress() ) );
         List writeFutures = new ArrayList();
         
         // asynchronously send GracefulDisconnection messages to all connected
@@ -268,10 +268,8 @@
      * 
      * @param requestor the session of the graceful shutdown requestor
      */
-    private void sendNoticeOfDisconnect( IoSession requestor )
+    private void sendNoticeOfDisconnect( List sessions, IoSession requestor )
     {
-        IoAcceptor acceptor = serviceRegistry.getAcceptor( ldapService.getTransportType() );
-        List sessions = new ArrayList( acceptor.getManagedSessions( ldapService.getAddress() ) );
         List writeFutures = new ArrayList();
         
         // Send Notification of Disconnection messages to all connected clients.

Modified: directory/trunks/apacheds/standalone/simple/jndi/src/main/java/org/apache/ldap/server/jndi/ServerContextFactory.java
URL: http://svn.apache.org/viewcvs/directory/trunks/apacheds/standalone/simple/jndi/src/main/java/org/apache/ldap/server/jndi/ServerContextFactory.java?rev=373434&r1=373433&r2=373434&view=diff
==============================================================================
--- directory/trunks/apacheds/standalone/simple/jndi/src/main/java/org/apache/ldap/server/jndi/ServerContextFactory.java (original)
+++ directory/trunks/apacheds/standalone/simple/jndi/src/main/java/org/apache/ldap/server/jndi/ServerContextFactory.java Sun Jan 29 20:49:12 2006
@@ -494,11 +494,26 @@
             
             try
             {
-                // We should unbind the service before we begin sending the notice 
+                // we should unbind the service before we begin sending the notice 
                 // of disconnect so new connections are not formed while we process
                 List writeFutures = new ArrayList();
                 IoAcceptor acceptor = minaRegistry.getAcceptor( service.getTransportType() );
-                List sessions = new ArrayList( acceptor.getManagedSessions( service.getAddress() ) );
+                
+                // If the socket has already been unbound as with a successful 
+                // GracefulShutdownRequest then this will complain that the service
+                // is not bound - this is ok because the GracefulShutdown has already
+                // sent notices to to the existing active sessions
+                List sessions = null;
+                try
+                {
+                    sessions = new ArrayList( acceptor.getManagedSessions( service.getAddress() ) );
+                }
+                catch( IllegalArgumentException e )
+                {
+                    log.warn( "Seems like the LDAP service " + service + " has already been unbound." );
+                    return;
+                }
+                
                 minaRegistry.unbind( service );
                 if ( log.isInfoEnabled() )
                 {

Added: directory/trunks/apacheds/tools/src/main/java/org/apache/ldap/server/dumptool/GracefulShutdown.java
URL: http://svn.apache.org/viewcvs/directory/trunks/apacheds/tools/src/main/java/org/apache/ldap/server/dumptool/GracefulShutdown.java?rev=373434&view=auto
==============================================================================
--- directory/trunks/apacheds/tools/src/main/java/org/apache/ldap/server/dumptool/GracefulShutdown.java (added)
+++ directory/trunks/apacheds/tools/src/main/java/org/apache/ldap/server/dumptool/GracefulShutdown.java Sun Jan 29 20:49:12 2006
@@ -0,0 +1,60 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.dumptool;
+
+
+import java.util.Hashtable;
+import javax.naming.NamingException;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.ldap.common.message.extended.GracefulShutdownRequest;
+
+
+/**
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class GracefulShutdown
+{
+    private int port = 10389;
+    private String host = "localhost";
+    private String password = "secret";
+
+    
+    public void execute() throws NamingException
+    {
+        Hashtable env = new Hashtable();
+        env.put( "java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory" );
+        env.put( "java.naming.provider.url", "ldap://" + host + ":" + port );
+        env.put( "java.naming.security.principal", "uid=admin,ou=system" );
+        env.put( "java.naming.security.credentials", password );
+        env.put( "java.naming.security.authentication", "simple" );
+
+        LdapContext ctx = new InitialLdapContext( env, null );
+        ctx.extendedOperation( new GracefulShutdownRequest( 0, 10, 5 ) );
+        ctx.close();
+    }
+
+
+    public static void main( String[] args ) throws Exception
+    {
+        GracefulShutdown command = new GracefulShutdown();
+        command.execute();
+    }
+}

Propchange: directory/trunks/apacheds/tools/src/main/java/org/apache/ldap/server/dumptool/GracefulShutdown.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/server/dumptool/NotificationsExample.java
URL: http://svn.apache.org/viewcvs/directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/server/dumptool/NotificationsExample.java?rev=373434&view=auto
==============================================================================
--- directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/server/dumptool/NotificationsExample.java (added)
+++ directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/server/dumptool/NotificationsExample.java Sun Jan 29 20:49:12 2006
@@ -0,0 +1,110 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.dumptool;
+
+
+import java.util.Hashtable;
+
+import javax.naming.directory.SearchControls;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+import javax.naming.ldap.UnsolicitedNotification;
+import javax.naming.ldap.UnsolicitedNotificationListener;
+import javax.naming.ldap.UnsolicitedNotificationEvent;
+
+import org.apache.ldap.common.message.extended.GracefulDisconnect;
+import org.apache.ldap.common.message.extended.NoticeOfDisconnect;
+
+
+/**
+ * A simple program which demonstrates how to get unsolicited notifications
+ * especially GracefulDisconnect events.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class NotificationsExample implements UnsolicitedNotificationListener
+{
+    UnsolicitedNotification notification;
+
+    
+    public static void main( String[] args ) throws Exception
+    {
+        Hashtable env = new Hashtable();
+        env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+        env.put("java.naming.provider.url", "ldap://"+args[0]+":10389/ou=system" ); 
+        env.put("java.naming.security.principal", "uid=admin,ou=system" ); 
+        env.put("java.naming.security.credentials", "secret" );
+        env.put("java.naming.security.authentication", "simple");
+        
+        LdapContext ctx = new InitialLdapContext( env, null );
+        ctx = ctx.newInstance( null );
+        UnsolicitedNotificationListener listener = new NotificationsExample();
+        ( ( EventContext ) ctx ).addNamingListener( "", SearchControls.SUBTREE_SCOPE, listener );
+        
+        System.out.println( "Listening for notifications." );
+        System.out.println( "Press any key to terminate." );
+        System.in.read();
+        ctx.close();
+        System.out.println( "Process terminated!!!" );
+    }
+
+
+    public void notificationReceived( UnsolicitedNotificationEvent evt )
+    {
+        notification = evt.getNotification();
+        
+        if ( notification.getID().equals( NoticeOfDisconnect.OID ) )
+        {
+            System.out.println( "Recieved NoticeOfDisconnect: " + NoticeOfDisconnect.OID );
+            System.out.println( "Expect to loose this connection without further information." );
+        }
+        else if ( notification.getID().equals( GracefulDisconnect.OID ) )
+        {
+            System.out.println( "Recieved GracefulDisconnect: " + GracefulDisconnect.OID );
+            GracefulDisconnect gd = new GracefulDisconnect( notification.getEncodedValue() );
+            System.out.println( "LDAP server will shutdown in " + gd.getDelay() + " seconds." );
+            System.out.println( "LDAP server will be back online in " + gd.getTimeOffline() + " minutes." );
+            
+            if ( gd.getDelay() > 0 )
+            {
+                System.out.println( "Starting countdown until server shutdown:" );
+                System.out.print( "[" ); 
+                long delayMillis = gd.getDelay() * 1000;
+                long startTime = System.currentTimeMillis();
+                while ( System.currentTimeMillis() - startTime < delayMillis )
+                {
+                    try{ Thread.sleep( 990 ); }catch ( InterruptedException e ){}
+                    System.out.print( "." );
+                }
+                System.out.println( "]" );
+            }
+        }
+        else 
+        {
+            System.out.println( "Unknown event recieved with OID: " + evt.getNotification().getID() );
+        }
+    }
+
+
+    public void namingExceptionThrown( NamingExceptionEvent evt )
+    {
+        System.out.println( "Got an excption event: " + evt.getException().getMessage() );
+    }
+}

Propchange: directory/trunks/apacheds/tools/src/test/java/org/apache/ldap/server/dumptool/NotificationsExample.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/codec/TwixTransformer.java
URL: http://svn.apache.org/viewcvs/directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/codec/TwixTransformer.java?rev=373434&r1=373433&r2=373434&view=diff
==============================================================================
--- directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/codec/TwixTransformer.java (original)
+++ directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/codec/TwixTransformer.java Sun Jan 29 20:49:12 2006
@@ -104,6 +104,7 @@
 import org.apache.ldap.common.message.SearchResponseEntryImpl;
 import org.apache.ldap.common.message.SearchResponseReferenceImpl;
 import org.apache.ldap.common.message.UnbindRequestImpl;
+import org.apache.ldap.common.message.extended.GracefulShutdownRequest;
 import org.apache.ldap.common.message.spi.Provider;
 import org.apache.ldap.common.message.spi.TransformerSpi;
 import org.apache.ldap.common.name.LdapDN;
@@ -275,8 +276,17 @@
      */
     private Message transformExtendedRequest(LdapMessage twixMessage, int messageId)
     {
-    	ExtendedRequestImpl snickersMessage = new ExtendedRequestImpl( messageId );
-    	ExtendedRequest extendedRequest = twixMessage.getExtendedRequest();
+        ExtendedRequest extendedRequest = twixMessage.getExtendedRequest();
+    	ExtendedRequestImpl snickersMessage = null;
+        
+        if ( extendedRequest.getRequestName().equals( GracefulShutdownRequest.EXTENSION_OID ) )
+        {
+            snickersMessage = new GracefulShutdownRequest( messageId );
+        }
+        else
+        {
+            snickersMessage = new ExtendedRequestImpl( messageId );
+        }
 
     	// Twix : OID requestName -> Snickers : String oid
     	snickersMessage.setOid( extendedRequest.getRequestName() );

Modified: directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulDisconnect.java
URL: http://svn.apache.org/viewcvs/directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulDisconnect.java?rev=373434&r1=373433&r2=373434&view=diff
==============================================================================
--- directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulDisconnect.java (original)
+++ directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulDisconnect.java Sun Jan 29 20:49:12 2006
@@ -25,6 +25,7 @@
 import org.apache.asn1.codec.DecoderException;
 import org.apache.asn1.codec.EncoderException;
 import org.apache.ldap.common.codec.extended.operations.GracefulDisconnectContainer;
+import org.apache.ldap.common.codec.extended.operations.GracefulDisconnectDecoder;
 import org.apache.ldap.common.codec.util.LdapURL;
 import org.apache.ldap.common.codec.util.LdapURLEncodingException;
 import org.apache.ldap.common.message.ExtendedResponseImpl;
@@ -62,6 +63,14 @@
     private Referral replicatedContexts = new ReferralImpl();
 
 
+    public GracefulDisconnect( byte[] value )
+    {
+        super( 0 );
+        this.value = value;
+        decodeValue();
+    }
+    
+    
     public GracefulDisconnect( int timeOffline, int delay )
     {
         super( 0 );
@@ -77,6 +86,28 @@
         super.getLdapResult().setResultCode( ResultCodeEnum.UNAVAILABLE );
     }
     
+    
+    private void decodeValue()
+    {
+        GracefulDisconnectDecoder decoder = new GracefulDisconnectDecoder();
+        org.apache.ldap.common.codec.extended.operations.GracefulDisconnect codec = null; 
+        try
+        {
+            codec = ( org.apache.ldap.common.codec.extended.operations.GracefulDisconnect ) decoder.decode( value );
+            this.timeOffline = codec.getTimeOffline();
+            this.delay = codec.getDelay();
+            super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
+            List contexts = codec.getReplicatedContexts();
+            for ( int ii = 0; ii < contexts.size(); ii++ )
+            {
+                replicatedContexts.addLdapUrl( contexts.get( ii ).toString() );
+            }
+        }
+        catch ( DecoderException e )
+        {
+            log.error( "Failed to decode response value", e );
+        }
+    }
     
     private void encodeResponse()
     {

Modified: directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownRequest.java
URL: http://svn.apache.org/viewcvs/directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownRequest.java?rev=373434&r1=373433&r2=373434&view=diff
==============================================================================
--- directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownRequest.java (original)
+++ directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownRequest.java Sun Jan 29 20:49:12 2006
@@ -20,8 +20,10 @@
 import javax.naming.NamingException;
 import javax.naming.ldap.ExtendedResponse;
 
+import org.apache.asn1.codec.DecoderException;
 import org.apache.asn1.codec.EncoderException;
 import org.apache.ldap.common.codec.extended.operations.GracefulShutdown;
+import org.apache.ldap.common.codec.extended.operations.GracefulShutdownDecoder;
 import org.apache.ldap.common.message.ExtendedRequestImpl;
 import org.apache.ldap.common.message.ResultResponse;
 
@@ -71,8 +73,8 @@
         this.timeOffline = timeOffline;
         this.delay = delay;
     }
-    
-    
+
+
     private void encodePayload() throws EncoderException
     {
         GracefulShutdown gs = new GracefulShutdown();
@@ -81,7 +83,24 @@
         payload = gs.encode( null ).array();
     }
 
-
+    
+    public void setPayload( byte[] payload )
+    {
+        GracefulShutdownDecoder decoder = new GracefulShutdownDecoder();
+        try
+        {
+            GracefulShutdown gs = ( GracefulShutdown ) decoder.decode( payload );
+            this.payload = payload;
+            this.timeOffline = gs.getTimeOffline();
+            this.delay = gs.getDelay();
+        }
+        catch ( DecoderException e )
+        {
+            log.error( "failed to decode payload" );
+        }
+    }
+    
+    
     public ExtendedResponse createExtendedResponse(String id, byte[] berValue, int offset, int length)
         throws NamingException
     {
@@ -117,7 +136,8 @@
     {
         if ( response == null )
         {
-            response = new GracefulShutdownResponse( getMessageId() );
+            GracefulShutdownResponse gsr = new GracefulShutdownResponse( getMessageId() );
+            response = gsr;
         }
         
         return response;

Modified: directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownResponse.java
URL: http://svn.apache.org/viewcvs/directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownResponse.java?rev=373434&r1=373433&r2=373434&view=diff
==============================================================================
--- directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownResponse.java (original)
+++ directory/trunks/common/ldap/src/main/java/org/apache/ldap/common/message/extended/GracefulShutdownResponse.java Sun Jan 29 20:49:12 2006
@@ -90,7 +90,7 @@
      */
     public void setResponse( byte [] value )
     {
-        throw new UnsupportedOperationException( "the response is hardcoded as zero length array" );
+        // do nothing here instead
     }