You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by to...@apache.org on 2007/05/19 19:40:33 UTC

svn commit: r539783 - in /incubator/qpid/branches/M2/dotnet: Qpid.Client.Tests/ Qpid.Client.Tests/Channel/ Qpid.Client.Tests/connection/ Qpid.Client/ Qpid.Client/Client/ Qpid.Client/Client/Handler/ Qpid.Client/Client/Message/ Qpid.Client/Client/Protoco...

Author: tomasr
Date: Sat May 19 10:40:32 2007
New Revision: 539783

URL: http://svn.apache.org/viewvc?view=rev&rev=539783
Log:
* QPID-495 (Contributed by Carlos Medina) Implement default timeouts for AttainState and SyncWrite
* Fix method signatures
* Remove SSL test with client-side certificates (requires extra setup)
* Add locks AMSQtateManager and AMQProtocolListener to prevent modification of listener collections while processing notifications
* Add library/runtime information to ConnectionStartMethodHandler
* Fix some compiler warnings
* Added XML documentation for some api interfaces

Added:
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs
Removed:
    incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/QpidTestCert.pfx
Modified:
    incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Channel/ChannelQueueTest.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj
    incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/ConnectionTest.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/SslConnectionTest.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/default.build
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/BasicMessageProducer.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/AMQStateManager.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/StateWaiter.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Client/Qpid.Client.csproj
    incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessageConsumer.cs
    incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessagePublisher.cs

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Channel/ChannelQueueTest.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Channel/ChannelQueueTest.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Channel/ChannelQueueTest.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Channel/ChannelQueueTest.cs Sat May 19 10:40:32 2007
@@ -93,20 +93,6 @@
         }
         
         [Test]
-        public void DeleteInExistentQueue()
-        {
-            try
-            {
-                _channel.DeleteQueue("Q1", false, false, true);
-                _logger.Info("queue deleted");
-            }
-            catch (AMQException e)
-            {
-                _logger.Info(e.ToString());
-            }
-        }
-
-        [Test]
         public void DeleteUsedQueue()
         {
             // Create the consumer
@@ -123,7 +109,7 @@
         }
 
         [Test]
-        public void DeleteUnUsedQueue()
+        public void DeleteUnusedQueue()
         {
             // delete the queue
             _channel.DeleteQueue(_queueName, true, true, true);

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj Sat May 19 10:40:32 2007
@@ -90,7 +90,6 @@
   </ItemGroup>
   <ItemGroup>
     <None Include="App.config" />
-    <EmbeddedResource Include="connection\QpidTestCert.pfx" />
     <None Include="Qpid.Common.DLL.config">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/ConnectionTest.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/ConnectionTest.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/ConnectionTest.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/ConnectionTest.cs Sat May 19 10:40:32 2007
@@ -62,7 +62,7 @@
 
         [Test]
         [ExpectedException(typeof(AMQConnectionException))]
-        public void connectionFailure()
+        public void ConnectionFailure()
         {
             string url = "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5673?retries='0''";
             new AMQConnection(QpidConnectionInfo.FromUrl(url));

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/SslConnectionTest.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/SslConnectionTest.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/SslConnectionTest.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/connection/SslConnectionTest.cs Sat May 19 10:40:32 2007
@@ -48,20 +48,6 @@
          MakeBrokerConnection(sslConfig);
       }
 
-      /// <summary>
-      /// Make a TLS connection to the broker with a 
-      /// client-side certificate
-      /// </summary>
-      [Test]
-      public void DoSslConnectionWithClientCert()
-      {
-         // because for tests we don't usually trust the server certificate
-         // we need here to tell the client to ignore certificate validation errors
-         SslOptions sslConfig = new SslOptions(LoadClientCert(), true);
-
-         MakeBrokerConnection(sslConfig);
-      }
-
       private static void MakeBrokerConnection(SslOptions options)
       {
          IConnectionInfo connectionInfo = new QpidConnectionInfo();
@@ -72,20 +58,6 @@
          {
             Console.WriteLine("connection = " + connection);
          }
-      }
-
-      private static X509Certificate LoadClientCert()
-      {
-         // load a self-issued certificate from an embedded
-         // resource
-         const string name = "Qpid.Client.Tests.connection.QpidTestCert.pfx";
-         Assembly assembly = typeof(SslConnectionTest).Assembly;
-         
-         Stream res = assembly.GetManifestResourceStream(name);
-         byte[] buffer = new byte[res.Length];
-         res.Read(buffer, 0, buffer.Length);
-         
-         return new X509Certificate(buffer);
       }
    }
 }

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/default.build
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/default.build?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/default.build (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/default.build Sat May 19 10:40:32 2007
@@ -18,9 +18,6 @@
                <include name="${build.dir}/Qpid.Messaging.dll" />
                <include name="${build.dir}/Qpid.Sasl.dll" />
             </references>
-            <resources dynamicprefix="true" prefix="${project::get-name()}.Tests">
-               <include name="connection/QpidTestCert.pfx"/>
-            </resources>
         </csc>
          <copy 
             tofile="${build.dir}/${project::get-name()}.Tests.dll.config" 

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/BasicMessageProducer.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/BasicMessageProducer.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/BasicMessageProducer.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/BasicMessageProducer.cs Sat May 19 10:40:32 2007
@@ -44,7 +44,7 @@
 
       /// <summary>
       /// Time to live of messages. Specified in milliseconds but AMQ has 1 second resolution.
-      ///
+      /// </summary>
       private long _timeToLive;
 
       /// <summary>
@@ -88,17 +88,6 @@
       /// </summary>
       private AmqChannel _channel;
 
-      /// <summary>
-      /// Default value for immediate flag is false, i.e. a consumer does not need to be attached to a queue
-      /// </summary>
-      protected const bool DEFAULT_IMMEDIATE = false;
-
-      /// <summary>
-      /// Default value for mandatory flag is true, i.e. server will not silently drop messages where no queue is
-      /// connected to the exchange for the message
-      /// </summary>
-      protected const bool DEFAULT_MANDATORY = true;
-
       public BasicMessageProducer(string exchangeName, string routingKey,
           bool transacted,
           ushort channelId,
@@ -206,15 +195,31 @@
       public void Send(IMessage msg, DeliveryMode deliveryMode, int priority, long timeToLive)
       {
          CheckNotClosed();
-         SendImpl(_exchangeName, _routingKey, (AbstractQmsMessage)msg, deliveryMode, priority, (uint)timeToLive, DEFAULT_MANDATORY,
-                  DEFAULT_IMMEDIATE);
+         SendImpl(
+            _exchangeName, 
+            _routingKey, 
+            (AbstractQmsMessage)msg, 
+            deliveryMode, 
+            priority, 
+            (uint)timeToLive, 
+            _mandatory,
+            _immediate
+            );
       }
 
       public void Send(IMessage msg)
       {
          CheckNotClosed();
-         SendImpl(_exchangeName, _routingKey, (AbstractQmsMessage)msg, _deliveryMode, _messagePriority, (uint)_timeToLive,
-                  DEFAULT_MANDATORY, DEFAULT_IMMEDIATE);
+         SendImpl(
+            _exchangeName, 
+            _routingKey, 
+            (AbstractQmsMessage)msg, 
+            _deliveryMode, 
+            _messagePriority, 
+            (uint)_timeToLive,
+            _mandatory, 
+            _immediate
+            );
       }
 
       // This is a short-term hack (knowing that this code will be re-vamped sometime soon)
@@ -222,8 +227,16 @@
       public void Send(IMessage msg, bool mandatory)
       {
          CheckNotClosed();
-         SendImpl(_exchangeName, _routingKey, (AbstractQmsMessage)msg, _deliveryMode, _messagePriority, (uint)_timeToLive,
-                  mandatory, DEFAULT_IMMEDIATE);
+         SendImpl(
+            _exchangeName, 
+            _routingKey, 
+            (AbstractQmsMessage)msg, 
+            _deliveryMode, 
+            _messagePriority, 
+            (uint)_timeToLive,
+            mandatory, 
+            _immediate
+            );
       }
 
       public long TimeToLive
@@ -248,6 +261,11 @@
 
       public string MimeType
       {
+         get
+         {
+            CheckNotClosed();
+            return _mimeType;
+         }
          set
          {
             CheckNotClosed();
@@ -257,6 +275,11 @@
 
       public string Encoding
       {
+         get
+         {
+            CheckNotClosed();
+            return _encoding;
+         }
          set
          {
             CheckNotClosed();

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs Sat May 19 10:40:32 2007
@@ -89,16 +89,16 @@
 
         private string GetFullSystemInfo()
         {
-            /*StringBuffer fullSystemInfo = new StringBuffer();
-            fullSystemInfo.append(System.getProperty("java.runtime.name"));
-            fullSystemInfo.append(", " + System.getProperty("java.runtime.version"));
-            fullSystemInfo.append(", " + System.getProperty("java.vendor"));
-            fullSystemInfo.append(", " + System.getProperty("os.arch"));
-            fullSystemInfo.append(", " + System.getProperty("os.name"));
-            fullSystemInfo.append(", " + System.getProperty("os.version"));
-            fullSystemInfo.append(", " + System.getProperty("sun.os.patch.level"));*/
-            // TODO: add in details here
-            return ".NET 1.1 Client";
+            StringBuilder sysInfo = new StringBuilder();
+            // check if we're running on mono or .net
+            Type monoRuntime = Type.GetType("Mono.Runtime");
+            if ( monoRuntime != null )
+               sysInfo.Append("Mono");
+            else
+               sysInfo.Append(".NET");
+            sysInfo.Append(" ").Append(Environment.Version);
+            sysInfo.Append(", ").Append(Environment.OSVersion);
+            return sysInfo.ToString();
         }
 
        private string ChooseMechanism(string mechanisms)

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs Sat May 19 10:40:32 2007
@@ -30,8 +30,6 @@
 {
     public abstract class AbstractQmsMessage : AMQMessage, IMessage
     {
-        private static readonly ILog _log = LogManager.GetLogger(typeof(AbstractQmsMessage));
-
         protected bool _redelivered;
 
         protected ByteBuffer _data;

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs Sat May 19 10:40:32 2007
@@ -234,16 +234,21 @@
         {
             // FIXME: not sure if required as StateManager is in _frameListeners. Probably something to do with fail-over.
             _stateManager.Error(e);
-
-            foreach (IAMQMethodListener listener in _frameListeners)
+            lock ( _lock )
             {
-                listener.Error(e);
+               foreach ( IAMQMethodListener listener in _frameListeners )
+               {
+                  listener.Error(e);
+               }
             }
         }
 
         public void AddFrameListener(IAMQMethodListener listener)
         {
-            _frameListeners.Add(listener);
+           lock ( _lock )
+           {
+              _frameListeners.Add(listener);
+           }
         }
 
         public void RemoveFrameListener(IAMQMethodListener listener)
@@ -252,7 +257,10 @@
             {
                 _log.Debug("Removing frame listener: " + listener.ToString());
             }
-            _frameListeners.Remove(listener);
+            lock ( _lock )
+            {
+               _frameListeners.Remove(listener);
+            }
         }
 
         public void BlockUntilNotFailingOver()

Added: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs?view=auto&rev=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs (added)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs Sat May 19 10:40:32 2007
@@ -0,0 +1,47 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ *
+ */
+
+using System;
+using System.Text;
+
+namespace Qpid.Client.Protocol
+{
+   /// <summary>
+   /// Default timeout values for the protocol
+   /// </summary>
+   sealed class DefaultTimeouts
+   {
+      /// <summary>
+      /// Maximum number of milliseconds to wait for a state change
+      /// in the protocol's state machine
+      /// </summary>
+      public const int MaxWaitForState = 30* 1000;
+      /// <summary>
+      /// Maximum number of milliseconds to wait for a reply
+      /// frame when doing synchronous writer to the broker
+      /// </summary>
+      public const int MaxWaitForSyncWriter = 30 * 1000;
+
+      private DefaultTimeouts()
+      {
+      }
+   }
+}

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs Sat May 19 10:40:32 2007
@@ -80,9 +80,10 @@
         /// <summary>
         /// This method is called by the thread that wants to wait for a frame.
         /// </summary>
-        public AMQMethodEvent BlockForFrame()
+        /// <param name="timeout">Set the number of milliseconds to wait</param>
+        public AMQMethodEvent BlockForFrame(int timeout)
         {
-            _resetEvent.WaitOne();
+            _resetEvent.WaitOne(timeout, true);
             //at this point the event will have been signalled. The error field might or might not be set
             // depending on whether an error occurred
             if (_error != null)

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs Sat May 19 10:40:32 2007
@@ -23,6 +23,8 @@
 using Qpid.Client.Transport;
 using Qpid.Framing;
 
+using log4net;
+
 namespace Qpid.Client.Protocol
 {
     /// <summary>
@@ -30,6 +32,9 @@
     /// </summary>
     public class ProtocolWriter
     {
+
+        private ILog _logger = LogManager.GetLogger(typeof(ProtocolWriter));
+
         IProtocolWriter _protocolWriter;
         IProtocolListener _protocolListener;
         
@@ -51,13 +56,15 @@
         /// </summary>
         /// <param name="frame">the frame</param>
         /// <param name="listener">the blocking listener. Note the calling thread will block.</param>         
-        private AMQMethodEvent SyncWrite(AMQFrame frame, BlockingMethodFrameListener listener)            
+        /// <param name="timeout">set the number of milliseconds to wait</param>
+        private AMQMethodEvent SyncWrite(AMQFrame frame, BlockingMethodFrameListener listener, int timeout)
         {
             try
             {
                 _protocolListener.AddFrameListener(listener);
                 _protocolWriter.Write(frame);
-                return listener.BlockForFrame();                
+                
+                return listener.BlockForFrame(timeout);
             }
             finally
             {
@@ -67,11 +74,32 @@
             // that matches the criteria defined in the blocking listener
         }
 
+        /// <summary>
+        /// Convenience method that writes a frame to the protocol session and waits for
+        /// a particular response. Equivalent to calling getProtocolSession().write() then
+        /// waiting for the response.
+        /// </summary>
+        /// <param name="frame">the frame</param>
+        /// <param name="responseType">the type of method response</param>
         public AMQMethodEvent SyncWrite(AMQFrame frame, Type responseType)
         {
             // TODO: If each frame knew it's response type, then the responseType argument would
             // TODO: not be neccesary.
-            return SyncWrite(frame, new SpecificMethodFrameListener(frame.Channel, responseType));
+            return SyncWrite(frame, responseType, DefaultTimeouts.MaxWaitForSyncWriter);
+        }
+
+        /// <summary>
+        /// Convenience method that writes a frame to the protocol session and waits for
+        /// a particular response. Equivalent to calling getProtocolSession().write() then
+        /// waiting for the response.
+        /// </summary>
+        /// <param name="frame">the frame</param>
+        /// <param name="responseType">the type of method response</param>
+        /// <param name="timeout">set the number of milliseconds to wait</param>
+        /// <returns>set the number of milliseconds to wait</returns>
+        public AMQMethodEvent SyncWrite(AMQFrame frame, Type responseType, int timeout)
+        {
+            return SyncWrite(frame, new SpecificMethodFrameListener(frame.Channel, responseType), timeout);
         }
     }
 }

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/AMQStateManager.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/AMQStateManager.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/AMQStateManager.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/AMQStateManager.cs Sat May 19 10:40:32 2007
@@ -43,13 +43,15 @@
         /// Maps from an AMQState instance to a Map from Class to StateTransitionHandler.
         /// The class must be a subclass of AMQFrame.
         /// </summary>
-        private readonly IDictionary _state2HandlersMap = new Hashtable();
-
-        //private CopyOnWriteArraySet _stateListeners = new CopyOnWriteArraySet();
-        private ArrayList _stateListeners = ArrayList.Synchronized(new ArrayList(5));
+        private readonly IDictionary _state2HandlersMap;
+        private ArrayList _stateListeners;
+        private object _syncLock;
         
         public AMQStateManager()
         {
+            _syncLock = new object();
+            _state2HandlersMap = new Hashtable();
+            _stateListeners = ArrayList.Synchronized(new ArrayList(5));
             _currentState = AMQState.CONNECTION_NOT_STARTED;
             RegisterListeners();
         }
@@ -132,18 +134,24 @@
             AMQState oldState = _currentState;
             _currentState = newState;
 
-            foreach (IStateListener l in _stateListeners)
+            lock ( _syncLock )
             {
-                l.StateChanged(oldState, newState);
+               foreach ( IStateListener l in _stateListeners )
+               {
+                  l.StateChanged(oldState, newState);
+               }
             }
         }
 
         public void Error(Exception e)
         {
             _logger.Debug("State manager receive error notification: " + e);
-            foreach (IStateListener l in _stateListeners)
+            lock ( _syncLock )
             {
-                l.Error(e);
+               foreach ( IStateListener l in _stateListeners )
+               {
+                  l.Error(e);
+               }
             }
         }
 
@@ -206,23 +214,37 @@
         public void AddStateListener(IStateListener listener)
         {
             _logger.Debug("Adding state listener");
-            _stateListeners.Add(listener);
+            lock ( _syncLock )
+            {
+               _stateListeners.Add(listener);
+            }
         }
 
         public void RemoveStateListener(IStateListener listener)
         {
-            _stateListeners.Remove(listener);
+           lock ( _syncLock )
+           {
+              _stateListeners.Remove(listener);
+           }
         }
 
         public void AttainState(AMQState s)
         {
             if (_currentState != s)
             {
-                _logger.Debug("Adding state wait to reach state " + s);
-                StateWaiter sw = new StateWaiter(s);
-                AddStateListener(sw);
-                sw.WaituntilStateHasChanged();
-                // at this point the state will have changed.
+                StateWaiter sw = null;
+                try
+                {
+                    _logger.Debug("Adding state wait to reach state " + s);
+                    sw = new StateWaiter(s);
+                    AddStateListener(sw);
+                    sw.WaituntilStateHasChanged();
+                    // at this point the state will have changed.
+                }
+                finally
+                { 
+                    RemoveStateListener(sw);
+                }
             }
         }        
     }

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/StateWaiter.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/StateWaiter.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/StateWaiter.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/State/StateWaiter.cs Sat May 19 10:40:32 2007
@@ -20,6 +20,7 @@
  */
 using System;
 using System.Threading;
+using Qpid.Client.Protocol;
 using log4net;
 
 namespace Qpid.Client.State
@@ -29,6 +30,7 @@
         private static readonly ILog _logger = LogManager.GetLogger(typeof(StateWaiter));
 
         private readonly AMQState _state;
+        private AMQState _newState;
 
         private volatile bool _newStateAchieved;
 
@@ -42,7 +44,8 @@
         }
 
         public void StateChanged(AMQState oldState, AMQState newState)
-        {            
+        {
+            _newState = newState;
             if (_logger.IsDebugEnabled)
             {
                 _logger.Debug("stateChanged called");
@@ -76,23 +79,42 @@
             // The guard is required in case we are woken up by a spurious
             // notify().
             //
-            while (!_newStateAchieved && _exception == null)
-            {                    
+
+            TimeSpan waitTime = TimeSpan.FromMilliseconds(DefaultTimeouts.MaxWaitForState);
+            DateTime waitUntilTime = DateTime.Now + waitTime;
+
+            while ( !_newStateAchieved 
+               && _exception == null 
+               && waitTime.TotalMilliseconds > 0 )
+            {
                 _logger.Debug("State not achieved so waiting...");
-                _resetEvent.WaitOne();                    
+                try
+                {
+                    _resetEvent.WaitOne(waitTime, true);
+                }
+                finally
+                {
+                    if (!_newStateAchieved)
+                    {
+                        waitTime = waitUntilTime - DateTime.Now;
+                    }
+                }
             }
 
             if (_exception != null)
             {
                 _logger.Debug("Throwable reached state waiter: " + _exception);
                 if (_exception is AMQException)
-                {
                     throw _exception;
-                }
                 else
-                {
                     throw new AMQException("Error: "  + _exception, _exception);
-                }
+            }
+
+            if (!_newStateAchieved)
+            {
+                string error = string.Format("State not achieved within permitted time. Current state: {0}, desired state: {1}", _state, _newState);
+                _logger.Warn(error);
+                throw new AMQException(error);
             }
         }
     }

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs Sat May 19 10:40:32 2007
@@ -82,10 +82,11 @@
             _byteChannel.Write(Encode(o));
         }
 
-        private void OnAsyncWriteDone(IAsyncResult result)
-        {
-           _byteChannel.EndWrite(result);
-        }
+        // not used for now
+        //private void OnAsyncWriteDone(IAsyncResult result)
+        //{
+        //   _byteChannel.EndWrite(result);
+        //}
 
         private void Decode(ByteBuffer buffer)
         {

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Client/Qpid.Client.csproj
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client/Qpid.Client.csproj?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client/Qpid.Client.csproj (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client/Qpid.Client.csproj Sat May 19 10:40:32 2007
@@ -52,6 +52,7 @@
     <Compile Include="Client\Configuration\AuthenticationConfigurationSectionHandler.cs" />
     <Compile Include="Client\Handler\QueueDeleteOkMethodHandler.cs" />
     <Compile Include="Client\Handler\QueuePurgeOkMethodHandler.cs" />
+    <Compile Include="Client\Protocol\DefaultTimeouts.cs" />
     <Compile Include="Client\SslOptions.cs" />
     <Compile Include="Client\Message\QpidHeaders.cs" />
     <Compile Include="Client\QpidConnectionInfo.cs" />

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessageConsumer.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessageConsumer.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessageConsumer.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessageConsumer.cs Sat May 19 10:40:32 2007
@@ -22,12 +22,55 @@
 
 namespace Qpid.Messaging
 {
-    public interface IMessageConsumer : IDisposable
-    {
-        MessageReceivedDelegate OnMessage { get; set; }
+   /// <summary>
+   /// Describes an object that can be used to receive (consume)
+   /// messages from an AMQP queue.
+   /// </summary>
+   /// <remarks>
+   /// Consumers are created using either 
+   /// <see cref="IChannel.CreateConsumer"/> or using 
+   /// the builder pattern (preferred) with 
+   /// <see cref="IChannel.CreateConsumerBuilder"/>.
+   /// 
+   /// <para>
+   /// Consumers offer two different ways of receiving messages:
+   /// You can attach a delegate to the <see cref="OnMessage"/>
+   /// event and be notified when a message arrives, or you can
+   /// use the <see cref="Receive"/> and <see cref="ReceiveNoWait"/>
+   /// methods to control when you receive messages.
+   /// </para>
+   /// <para>
+   /// Regardless of which method you choose, the prefetch settings
+   /// specified when creating the channel will still control when messages
+   /// are actually received from the AMQP broker. Any messages that arrive
+   /// between the prefetch window will be queued by the channel
+   /// until they can be delivered to the consumer (either though the event
+   /// or until the consumer actively calls <see cref="Receive"/>).
+   /// </para>
+   /// </remarks>
+   public interface IMessageConsumer : IDisposable
+   {
+      /// <summary>
+      /// Fired when a message is received from the broker by the consumer
+      /// </summary>
+      MessageReceivedDelegate OnMessage { get; set; }
 
-        IMessage Receive();
-        IMessage Receive(long delay);
-        IMessage ReceiveNoWait();
-    }
+      /// <summary>
+      /// Wait infinitely for a message to be received from the broker
+      /// </summary>
+      /// <returns>The message received</returns>
+      IMessage Receive();
+      /// <summary>
+      /// Wait the specified time until a message is receive from the broker
+      /// </summary>
+      /// <param name="delay">Maximum number of milliseconds to wait for a message</param>
+      /// <returns>The message received, or null if the timeout expires</returns>
+      IMessage Receive(long delay);
+      /// <summary>
+      /// Return a message if one is already available in the channel. 
+      /// Does not wait for one to be received from the broker.
+      /// </summary>
+      /// <returns>The message, if it was available, otherwise null</returns>
+      IMessage ReceiveNoWait();
+   }
 }

Modified: incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessagePublisher.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessagePublisher.cs?view=diff&rev=539783&r1=539782&r2=539783
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessagePublisher.cs (original)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Messaging/IMessagePublisher.cs Sat May 19 10:40:32 2007
@@ -22,34 +22,71 @@
 
 namespace Qpid.Messaging
 {
-    public interface IMessagePublisher : IDisposable
-    {
-        DeliveryMode DeliveryMode { get; set; }
-        string ExchangeName { get; }
-        string RoutingKey { get; }
-        bool DisableMessageID { get; set; }
-        bool DisableMessageTimestamp { get; set; }
-        int Priority { get; set; }
-        long TimeToLive { get; set; }
+   /// <summary>
+   /// Defines an object capable of publishing messages
+   /// to an AMQP broker. 
+   /// </summary>
+   /// <remarks>
+   /// A publisher can be created using either 
+   /// <see cref="IChannel.CreatePublisher"/> or 
+   /// using the builder pattern (preferred) with 
+   /// <see cref="IChannel.CreatePublisherBuilder"/>
+   /// </remarks>
+   public interface IMessagePublisher : IDisposable
+   {
+      /// <summary>
+      /// Default delivery mode to use with this publisher
+      /// </summary>
+      DeliveryMode DeliveryMode { get; set; }
+      /// <summary>
+      /// Name of exchange messages are published to
+      /// </summary>
+      string ExchangeName { get; }
+      /// <summary>
+      /// Routing key used when publishing messages
+      /// </summary>
+      string RoutingKey { get; }
+      /// <summary>
+      /// If true, a message ID will not be generated by the publisher
+      /// when sending the message
+      /// </summary>
+      bool DisableMessageID { get; set; }
+      /// <summary>
+      /// If true, no timestamp will be added to the message
+      /// when publishing it
+      /// </summary>
+      bool DisableMessageTimestamp { get; set; }
+      /// <summary>
+      /// Default priority used when publishing messages
+      /// </summary>
+      int Priority { get; set; }
+      /// <summary>
+      /// Default time to live used when publishing messages
+      /// </summary>
+      long TimeToLive { get; set; }
+      /// <summary>
+      /// Set the default MIME type for messages produced by this producer. 
+      /// This reduces the overhead of each message.
+      /// </summary>
+      string MimeType { get; set; }
+      /// <summary>
+      /// Set the default encoding for messages produced by this producer. 
+      /// This reduces the overhead of each message.
+      /// </summary>        
+      string Encoding { get; set; }
 
-        /// <summary>
-        /// Set the default MIME type for messages produced by this producer. This reduces the overhead of each message.
-        /// </summary>
-        /// <param>mimeType</param>         
-        string MimeType
-        {
-            set;
-        }
-
-        /// <summary>
-        /// Set the default encoding for messages produced by this producer. This reduces the overhead of each message.
-        /// </summary>        
-        string Encoding
-        {
-            set;
-        }
-
-        void Send(IMessage msg);
-        void Send(IMessage msg, DeliveryMode deliveryMode, int priority, long timeToLive);
-    }
+      /// <summary>
+      /// Publish a message, using any default values configured
+      /// </summary>
+      /// <param name="msg">Message to publish</param>
+      void Send(IMessage msg);
+      /// <summary>
+      /// Publish a message with the specified options
+      /// </summary>
+      /// <param name="msg">Message to publish</param>
+      /// <param name="deliveryMode">Delivery mode to use</param>
+      /// <param name="priority">Priority of the message</param>
+      /// <param name="timeToLive">Time to live of the message</param>
+      void Send(IMessage msg, DeliveryMode deliveryMode, int priority, long timeToLive);
+   }
 }