internal void EndConversation(Guid conversationHandle, TimeSpan timeout)
        {
            ThrowIfDisposedOrNotOpen();
            TimeoutHelper helper = new TimeoutHelper(timeout);
            try
            {
                string SQL = "END CONVERSATION @ConversationHandle";

                using (SqlCommand cmd = new SqlCommand(SQL, con))
                {
                    cmd.CommandTimeout = helper.RemainingTimeInMillisecondsOrZero();
                    SqlParameter pConversation = cmd.Parameters.Add("@ConversationHandle", SqlDbType.UniqueIdentifier);
                    pConversation.Value = conversationHandle;
                    cmd.ExecuteNonQuery();
                }
            }
            catch (SqlException ex)
            {
                if (!helper.IsTimeRemaining)
                {
                    throw new TimeoutException(String.Format("Timed out while ending conversation {0}. Timeout value was {1} seconds", conversationHandle,timeout.TotalSeconds), ex);
                }
                else
                {
                    throw new CommunicationException(String.Format("An exception occurred while ending conversation {0}.", conversationHandle), ex);
                }
            }
        }
        public void EndConversation(TimeSpan timeout)
        {
            TimeoutHelper helper = new TimeoutHelper(timeout);

            try
            {
                string SQL = "END CONVERSATION @ConversationHandle";

                SqlCommand cmd = new SqlCommand(SQL, con);
                cmd.CommandTimeout = helper.RemainingTimeInMillisecondsOrZero();
                cmd.Parameters.Add("@ConversationHandle", SqlDbType.UniqueIdentifier).Value = conversation.ConversationHandle;

                cmd.ExecuteNonQuery();
                this.conversation = null;
            }
            catch (SqlException ex)
            {
                if (!helper.IsTimeRemaining)
                {
                    throw new TimeoutException(String.Format("Timed out while ending conversation {0}. Timeout value was {1} seconds", this.conversation.ConversationHandle, timeout.TotalSeconds), ex);
                }
                else
                {
                    throw new CommunicationException(String.Format("An exception occurred while ending conversation {0}.", this.conversation.ConversationHandle), ex);
                }
            }
        }
        internal void Send(byte[] buffer, TimeSpan timeout, string messageType)
        {
            ThrowIfDisposedOrNotOpen();
            TimeoutHelper helper = new TimeoutHelper(timeout);


            //if the client hasn't explicitly begun a conversation, start one here.
            // CONSIDER (dbrowne) automatically ending the conversation in this case.
            if (conversation == null)
            {
                BeginNewConversation();
                this.endConversationOnClose = true;
            }

            try
            {
                string     SQL = string.Format(@"SEND ON CONVERSATION @Conversation MESSAGE TYPE [{0}](@MessageBody)", SsbHelper.ValidateIdentifier(messageType));
                SqlCommand cmd = new SqlCommand(SQL, con);

                cmd.CommandTimeout = helper.RemainingTimeInMillisecondsOrZero();
                SqlParameter pConversation = cmd.Parameters.Add("@Conversation", SqlDbType.UniqueIdentifier);
                pConversation.Value = this.conversation.ConversationHandle;

                SqlParameter pMessageBody = cmd.Parameters.Add("@MessageBody", SqlDbType.VarBinary);
                pMessageBody.Value = buffer;

                try
                {
                    cmd.ExecuteNonQuery();
                }
                catch (SqlException ex)
                {
                    if (ex.Number == 8429)
                    {
                        string errorMessage = SsbHelper.CheckConversationForErrorMessage(con, this.conversation.ConversationHandle);
                        if (errorMessage != null)
                        {
                            throw new Exception(errorMessage);
                        }
                        throw;
                    }
                    throw;
                }
                SsbInstrumentation.MessageSent(buffer.Length);
            }
            catch (Exception e)
            {
                if (!helper.IsTimeRemaining)
                {
                    throw new TimeoutException("Timed out while sending a message. The timeout value passed in was " + timeout.TotalSeconds + " seconds");
                }
                else
                {
                    throw new CommunicationException(String.Format("An exception occurred while sending on conversation {0}.", this.conversation.ConversationHandle), e);
                }
            }
        }
Example #4
0
        internal static ServiceInfo GetServiceInfo(string serviceName, TimeSpan timeout, SqlConnection con)
        {
            TimeoutHelper helper = new TimeoutHelper(timeout);
            ServiceInfo   info   = null;
            string        SQL    = @"
                select 
                  s.name As ServiceName
                , s.service_id As ServiceId
                , q.name As QueueName
                , q.object_id As QueueId 
                from sys.services s
                inner join sys.service_queues q
                  on s.service_queue_id=q.object_id 
                where s.name=@ServiceName";

            SqlCommand cmd = new SqlCommand(SQL, con);

            cmd.Parameters.Add("@ServiceName", SqlDbType.VarChar).Value = serviceName;
            cmd.CommandTimeout = helper.RemainingTimeInMillisecondsOrZero();

            try
            {
                using (SqlDataReader rdr = cmd.ExecuteReader())
                {
                    if (!rdr.Read())
                    {
                        throw new CommunicationException(string.Format("Service {0} not found", serviceName));
                    }

                    info             = new ServiceInfo();
                    info.ServiceName = rdr.GetString(0);
                    info.ServiceId   = rdr.GetInt32(1);
                    info.QueueName   = rdr.GetString(2);
                    info.QueueId     = rdr.GetInt32(3);

                    rdr.Close();
                }
            }
            catch (SqlException ex)
            {
                if (!helper.IsTimeRemaining)
                {
                    throw new TimeoutException(String.Format("Timed out while getting service information. Timeout value was {0} seconds", timeout.TotalSeconds), ex);
                }
                else
                {
                    throw new CommunicationException("An exception occurred while getting service information", ex);
                }
            }

            return(info);
        }
        public Guid BeginNewConversation(Guid conversationGroupId, TimeSpan timeout)
        {
            ThrowIfDisposedOrNotOpen();
            endConversationOnClose = false; //if a conversation is explicitly started, don't automatically close it.
            TimeoutHelper helper = new TimeoutHelper(timeout);

            try
            {
                string SQL = string.Format(
                    @"BEGIN DIALOG CONVERSATION @ConversationHandle 
                               FROM SERVICE @Source TO SERVICE @Target 
                               ON CONTRACT [{0}] WITH ENCRYPTION = {1}", contract, useEncryption?"ON":"OFF");
                if (conversationGroupId != Guid.Empty)
                {
                    SQL += String.Format(", RELATED_CONVERSATION_GROUP = '{0}'", conversationGroupId);
                }
                SqlCommand cmd = new SqlCommand(SQL, con);
                cmd.CommandTimeout = helper.RemainingTimeInMillisecondsOrZero();
                SqlParameter pconversationHandle = cmd.Parameters.Add("@ConversationHandle", SqlDbType.UniqueIdentifier);
                pconversationHandle.Direction = ParameterDirection.Output;

                SqlParameter pTarget = cmd.Parameters.Add("@Target", SqlDbType.VarChar);
                pTarget.Value = this.target;
                SqlParameter pSource = cmd.Parameters.Add("@Source", SqlDbType.VarChar);
                pSource.Value = this.source;

                cmd.ExecuteNonQuery();

                this.conversation = SsbHelper.GetConversationInfo((Guid)pconversationHandle.Value, con);
                return(this.conversation.ConversationHandle);
            }
            catch (SqlException ex)
            {
                if (!helper.IsTimeRemaining)
                {
                    throw new TimeoutException(String.Format("Timed out while beginning new conversation to service {0}. Timeout value was {1} seconds", this.target, timeout.TotalSeconds), ex);
                }
                else
                {
                    throw new CommunicationException(String.Format("An exception occurred while beginning new conversation to service {0}", this.target), ex);
                }
            }
            finally
            {
            }
        }
        internal SsbConversationGroupReceiver AcceptConversationGroup(Guid conversationGroupId, TimeSpan timeout)
        {
            TimeoutHelper helper = new TimeoutHelper(timeout);

            TransactionOptions to = new TransactionOptions();

            to.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
            to.Timeout        = TimeSpan.MaxValue;


            CommittableTransaction tx           = new CommittableTransaction(to);
            Transaction            currentTrans = Transaction.Current;

            Transaction.Current = tx;
            SqlConnection cn = SsbHelper.GetConnection(this.connstring);

            cn.Open();
            Transaction.Current = currentTrans;

            //first lock the the Conversation Group.  This will prevent other SsbConversationGroupReceivers
            //from poaching the messages.

            string sql = @"
                    declare @cg uniqueidentifier
                    declare @rc int
                    set @cg = @conversation_group_id

                    exec @rc = sp_getapplock @Resource=@cg, @LockMode='Exclusive'
                    if @rc not in (0,1)
                    begin
                     raiserror('Failed to lock conversation group. sp_getapplock failure code %d.',16,1,@rc);
                    end
                    ";

            SqlCommand   cmd = new SqlCommand(sql, cn);
            SqlParameter pConversationGroupId = cmd.Parameters.Add("@conversation_group_id", SqlDbType.UniqueIdentifier);

            pConversationGroupId.Value = conversationGroupId;

            cmd.CommandTimeout = helper.RemainingTimeInMillisecondsOrZero();

            //Run the command, but abort if the another thread runs Close or Abort
            IAsyncResult result = cmd.BeginExecuteNonQuery();
            int          rc     = WaitHandle.WaitAny(new WaitHandle[] { result.AsyncWaitHandle, cancelEvent });

            if (rc == 1) //cancel event
            {
                cmd.Cancel();
                TraceHelper.TraceEvent(System.Diagnostics.TraceEventType.Verbose, "Canceling Service Broker wait on SsbChannelListener shutdown", "AcceptConversationGroup");
                cn.Close();
                return(null);
            }
            if (rc != 0)
            {
                throw new InvalidOperationException("Unexpected state");
            }
            cmd.EndExecuteNonQuery(result);

            SsbConversationGroupReceiver cg = new SsbConversationGroupReceiver(cn, tx, conversationGroupId, this.serviceInfo, this);

            cg.Open();
            //now wait for a message on the conversation.  Do it here because WCF expects the wait to be here instead of in a subsequent receive.
            //And also there is a different timeout to accepting a channel and waiting for additional messages.
            //But we need to pass in the cancelEvent to abort the listen, if this ChannelListener is closed or aborted
            if (!cg.WaitForFirstMessage(helper.RemainingTime(), cancelEvent))
            {
                if (this.State != CommunicationState.Opened)//this ChannelListener was closed or aborted, so this is expected.
                {
                    //for some reason the transaction tx is in an uncommitable state here. Not sure why.
                    //however no other work has occured on this connection, so we can just shut it down.
                    cn.Close();
                    return(null);
                }
                throw new TimeoutException(String.Format("Timed out while waiting for Conversation Group"));
            }

            return(cg);
        }
Example #7
0
        internal static ServiceInfo GetServiceInfo(string serviceName, TimeSpan timeout, SqlConnection con)
        {
            TimeoutHelper helper=new TimeoutHelper(timeout);
            ServiceInfo info = null;
            string SQL = @"
                select
                  s.name As ServiceName
                , s.service_id As ServiceId
                , q.name As QueueName
                , q.object_id As QueueId
                from sys.services s
                inner join sys.service_queues q
                  on s.service_queue_id=q.object_id
                where s.name=@ServiceName";

            SqlCommand cmd = new SqlCommand(SQL, con);
            cmd.Parameters.Add("@ServiceName", SqlDbType.VarChar).Value = serviceName;
            cmd.CommandTimeout = helper.RemainingTimeInMillisecondsOrZero();

            try
            {
                using (SqlDataReader rdr = cmd.ExecuteReader())
                {
                    if (!rdr.Read())
                    {
                        throw new CommunicationException(string.Format("Service {0} not found", serviceName));
                    }

                    info = new ServiceInfo();
                    info.ServiceName = rdr.GetString(0);
                    info.ServiceId = rdr.GetInt32(1);
                    info.QueueName = rdr.GetString(2);
                    info.QueueId = rdr.GetInt32(3);

                    rdr.Close();
                }
            }
            catch (SqlException ex)
            {
                if (!helper.IsTimeRemaining)
                {
                    throw new TimeoutException(String.Format("Timed out while getting service information. Timeout value was {0} seconds",timeout.TotalSeconds),ex);

                }
                else
                {
                    throw new CommunicationException("An exception occurred while getting service information", ex);
                }
            }

            return info;
        }