Пример #1
0
        /// <summary>
        /// Registers the broadcast sender that sends a message to several receivers.
        /// Returns Guid (it's like URI for an MBR object) assigned for this sender that can be used
        /// to delete this broadcast sender later.
        /// </summary>
        /// <param name="generalBroadcastSender">The broadcast sender which sends a message via "true" multicast channel.</param>
        public string Add(GeneralBroadcastSender generalBroadcastSender)
        {
            // just add it as it would be the usual receiver
            ReceiverInfo receiverInfo = new ReceiverInfo();

            receiverInfo.GeneralBroadcastSender = generalBroadcastSender;
            receiverInfo.Local = false;

            string uri = Guid.NewGuid().ToString("N") + "/" + generalBroadcastSender.Court;

            receiverInfo.MbrUri = uri;

            // register it
            using (WriterAutoLocker writer = new WriterAutoLocker(this._readerWriterLock))
            {
                this._cachedReceiversInfoArray = null;
                this._receivers[uri]           = receiverInfo;
            }

            // LOG:
            BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;

            if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
            {
                binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.Add",
                                                          LogMessageType.BroadcastRecipientAdded, null, null, null, null,
                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                          null, null, false, this, null, true, receiverInfo,
                                                          generalBroadcastSender.Court, generalBroadcastSender.ITransportContext.HostIdentifier,
                                                          "The \"true\" multicast sender is added.");
            }

            return(uri);
        }
Пример #2
0
        /// <summary>
        /// Returns the filtered array of the ReceiverInfo instances.
        /// </summary>
        /// <param name="arrayOfReceiverInfo">The list of receivers being filtered out.</param>
        /// <param name="iMessage">The invocation.</param>
        /// <param name="resultCollector">The Result Collector obtaining the list of receivers. Is used for debugging purposes only.</param>
        public void GetListOfReceivers(out object[] arrayOfReceiverInfo, IMessage iMessage, ResultCollector resultCollector)
        {
            arrayOfReceiverInfo = null;

            try
            {
                using (ReaderAutoLocker reader = new ReaderAutoLocker(this._readerWriterLock))
                {
                    // check whether they were cached
                    if (this._cachedReceiversInfoArray == null)
                    {
                        this._cachedReceiversInfoArray = new object[this._receivers.Values.Count];
                        this._receivers.Values.CopyTo(this._cachedReceiversInfoArray, 0);
                    }

                    // get the cached array
                    arrayOfReceiverInfo = this._cachedReceiversInfoArray;

                    // and drive it thru the filter
                    IMulticastFilter iMulticastFilter = Dispatcher.GetCurrentFilter();
                    if (iMulticastFilter == null)
                    {
                        iMulticastFilter = this.IMulticastFilter;
                    }
                    if (iMulticastFilter != null)
                    {
                        // LOG:
                        BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
                        if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                        {
                            binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.GetListOfReceivers",
                                                                      LogMessageType.BroadcastFilterCalled, null, null, null, null,
                                                                      GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                      null, null, false, this, resultCollector, false, null,
                                                                      iMulticastFilter.GetType().ToString(), null,
                                                                      "The broadcast filter is called. The type of the filter: {0}.", iMulticastFilter.GetType().ToString());
                        }

                        arrayOfReceiverInfo = iMulticastFilter.GetReceivers(arrayOfReceiverInfo, iMessage);
                    }
                }
            }
            catch (Exception ex)
            {
                // LOG:
                BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                {
                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.GetListOfReceivers",
                                                              LogMessageType.BroadcastFilterCalled, ex, null, null, null,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                              null, null, false, this, resultCollector, false, null,
                                                              null, null,
                                                              "The exception occurred while calling the broadcast filter.");
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Removes the receiver or the broadcast sender associated with the specified uri.
        /// Returns false if there is no such receiver found in the list of receivers.
        /// </summary>
        /// <param name="uri">The uri of the receiver.</param>
        public bool Remove(string uri)
        {
            if (uri == null || uri.Length <= 0)
            {
                return(false);
            }

            using (WriterAutoLocker writer = new WriterAutoLocker(this._readerWriterLock))
            {
                // check if it is in the list
                if (!this._receivers.ContainsKey(uri))
                {
                    return(false);
                }

                this._cachedReceiversInfoArray = null;

                ReceiverInfo receiverInfo = (ReceiverInfo)this._receivers[uri];
                this._receivers.Remove(uri);

                // LOG:
                BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                {
                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.Remove",
                                                              LogMessageType.BroadcastRecipientRemoved, null, null, receiverInfo.DbgRemoteHost, null,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                              null, null, false, this, null, true, receiverInfo,
                                                              uri, null,
                                                              "The broadcast recipient or \"true\" broadcast sender is removed from the list of recipients.");
                }

                // Sponsor is being deleted in another thread; otherwise client disconnection
                // will cause dispatcher to be freezed for lengthy time out
                GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.DeleteSponsorFromTheObjectAndFireEvent), receiverInfo, false);
            }

            return(true);
        }
Пример #4
0
        /// <summary>
        /// Initiate the receiving of responses.
        /// Returns true if the invocation has been completed synchronously.
        /// </summary>
        /// <returns>The true value if the invocation has been completed synchronously.</returns>
        public bool StartReceiving()
        {
            bool callIsAsync = false;

            lock (this._dispatcher)
            {
                callIsAsync = this._dispatcher.CallIsAsync;
                this._broadcastCallFinishedHandler = this._dispatcher.BroadcastCallFinishedHandler;
            }

            if (!callIsAsync || this._broadcastCallFinishedHandler == null)
            {
                this.AllMessagesReceived.WaitOne(this._dispatcher.ReceiveResultsTimeOut, false);

                // this call sends messages to failed receivers
                this.WaitUntilReceiversReplyOrTimeOut(null, false);

                // LOG:
                BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                {
                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.StartReceiving",
                                                              LogMessageType.BroadcastInvocationCompleted, null, null, null, null,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                              null, null, false, this._dispatcher, this, false, null,
                                                              null, null,
                                                              "The broadcast invocation is completed.");
                }

                this.AllMessagesReceived.Set();
                return(true);
            }

            ThreadPool.RegisterWaitForSingleObject(this.AllMessagesReceived, new WaitOrTimerCallback(this.WaitUntilReceiversReplyOrTimeOut), null, this._dispatcher.ReceiveResultsTimeOut, true);
            return(false);
        }
Пример #5
0
        /// <summary>
        /// Unregisters the sponsor.
        /// </summary>
        /// <param name="receiverInfoItemsAsObject">Array of receivers.</param>
        private void UnregisterSponsor(object receiverInfoItemsAsObject)
        {
            object[] receiverInfoItems = (object[])receiverInfoItemsAsObject;

            // go though the list of receivers to remove sponsors from all MBR objects
            foreach (ReceiverInfo receiverInfo in receiverInfoItems)
            {
                try
                {
                    // remove the sponsor
                    if (receiverInfo.MbrObject != null)
                    {
                        // LOG:
                        BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
                        if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                        {
                            binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.UnregisterSponsor",
                                                                      LogMessageType.BroadcastRecipientRemoved, null, null, receiverInfo.DbgRemoteHost, null,
                                                                      GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                      null, null, false, this, null, true, receiverInfo,
                                                                      null, null,
                                                                      "The broadcast recipient is removed after Dispatcher.Clear call.");
                        }

                        ILease lease = (ILease)RemotingServices.GetLifetimeService(receiverInfo.MbrObject);
                        if (lease != null)
                        {
                            lease.Unregister(this.GlobalSponsor);
                        }
                    }
                }
                catch
                {
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Looks for a failed broadcast receivers and invoke them again.
        /// </summary>
        public void SendMessageToFailedReceiversDirectly()
        {
            if (this._secondStagePerformed)
            {
                return;
            }

            this._secondStagePerformed = true;
            BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;

            // the second stage of the broadcasting
            using (ReaderAutoLocker reader = new ReaderAutoLocker(this._dispatcher._readerWriterLock))
            {
                // to prevent firing resultCollector.AllMessagesReceived event
                this.UnrepliedReceivers[_uniqueReceiverName] = null;

                lock (this)
                {
                    foreach (DictionaryEntry entry in this.Failed)
                    {
                        OperationException operationException = entry.Value as OperationException;
                        if (operationException != null && operationException.OperationErrorMessage != null &&
                            operationException.OperationErrorMessage.ErrorIdentifier == "GenuineChannels.Exception.Broadcast.RemoteEndPointDidNotReplyForTimeOut")
                        {
                            string       uri          = (string)entry.Key;
                            ReceiverInfo receiverInfo = this._dispatcher.GetReceiverInfo(uri);

                            // whether this receiver is expected to receive message via broadcast channel
                            if (receiverInfo == null || receiverInfo.NeedsBroadcastSimulation)
                            {
                                continue;
                            }

                            // switch it back to simulation mode if the limit is exceeded
                            lock (receiverInfo)
                            {
                                receiverInfo.NumberOfMulticastFails++;
                                if (this._dispatcher.MaximumNumberOfConsecutiveFailsToEnableSimulationMode != 0 &&
                                    receiverInfo.NumberOfMulticastFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToEnableSimulationMode)
                                {
                                    // force simulation
                                    receiverInfo.NeedsBroadcastSimulation = true;
                                    receiverInfo.NumberOfMulticastFails   = 0;
                                }
                            }

                            // each time a new stream is created because sinks change stream position concurrently
                            Stream           messageToBeSent  = (Stream)this._messageStream.Clone();
                            TransportHeaders transportHeaders = new TransportHeaders();

                            // LOG:
                            if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                            {
                                string methodName       = BinaryLogWriter.ParseInvocationMethod(this._iMessage.Properties["__MethodName"] as string, this._iMessage.Properties["__TypeName"] as string);
                                string invocationTarget = receiverInfo.MbrUri;

                                binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.SendMessageToFailedReceiversDirectly",
                                                                          LogMessageType.BroadcastRecipientInvokedAfterTimeout, null, null, receiverInfo.DbgRemoteHost, null,
                                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                          null, null, false, this._dispatcher, this, false, receiverInfo,
                                                                          invocationTarget, methodName,
                                                                          "The broadcast invocation is being directed to the recipient, which did not respond during the first stage.");
                            }

                            // set destination MBR
                            this._iMessage.Properties["__Uri"] = receiverInfo.MbrUri;
                            transportHeaders[Message.TransportHeadersBroadcastObjRefOrCourt] = receiverInfo.SerializedObjRef;
                            ClientChannelSinkStack clientChannelSinkStack = new ClientChannelSinkStack(this);
                            clientChannelSinkStack.Push(this, null);
                            receiverInfo.IClientChannelSink.AsyncProcessRequest(clientChannelSinkStack, this._iMessage, transportHeaders, messageToBeSent);
                        }
                    }
                }

                this.UnrepliedReceivers.Remove(_uniqueReceiverName);
                if (this.UnrepliedReceivers.Count <= 0)
                {
                    this.AllMessagesReceived.Set();
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Sends the invocation to all registered receivers.
        /// </summary>
        /// <param name="msg">The message to be sent.</param>
        public void PerformBroadcasting(IMessage msg)
        {
            BinaryLogWriter binaryLogWriter  = GenuineLoggingServices.BinaryLogWriter;
            string          methodName       = null;
            string          invocationTarget = null;

            // the first stage of the broadcasting
            try
            {
                ArrayList listOfExcludedReceivers = new ArrayList();
                this._iMessage = msg;
                methodName     = BinaryLogWriter.ParseInvocationMethod(msg.Properties["__MethodName"] as string, msg.Properties["__TypeName"] as string);

                BinaryFormatter formatterForLocalRecipients = null;

                // serialize the message
                BinaryFormatter binaryFormatter = new BinaryFormatter(new RemotingSurrogateSelector(), new StreamingContext(StreamingContextStates.Other));
                this._messageStream = new GenuineChunkedStream(false);
                binaryFormatter.Serialize(this._messageStream, msg);

                // to trace the message if it could reach the server via several channels
                string callGuidSubstring = null;
                if (this._dispatcher.IgnoreRecurrentCalls)
                {
                    callGuidSubstring = Guid.NewGuid().ToString("N");
                }

                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                {
                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                              LogMessageType.BroadcastInvocationInitiated, null, null, null,
                                                              binaryLogWriter[LogCategory.BroadcastEngine] > 1 ? (Stream)this._messageStream.Clone() : null,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                              null, null, true, this._dispatcher, this, false, null,
                                                              methodName, null,
                                                              "The broadcast invocation is initiated.");
                }

                // to prevent firing resultCollector.AllMessagesReceived event
                this.UnrepliedReceivers[_uniqueReceiverName] = null;

                object[] listOfReceiverInfo;
                this._dispatcher.GetListOfReceivers(out listOfReceiverInfo, msg, this);

                // through all recipients
                for (int i = 0; i < listOfReceiverInfo.Length; i++)
                {
                    ReceiverInfo receiverInfo = listOfReceiverInfo[i] as ReceiverInfo;
                    if (receiverInfo == null)
                    {
                        continue;
                    }

                    string mbrUri = (string)receiverInfo.MbrUri;
                    invocationTarget = mbrUri;

                    try
                    {
                        lock (receiverInfo)
                        {
                            if (this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically != 0 &&
                                receiverInfo.NumberOfFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically)
                            {
                                // put it to the list containing receivers being excluded
                                listOfExcludedReceivers.Add(mbrUri);
                                continue;
                            }
                        }

                        // think that it'll fail
                        if (!receiverInfo.Local && receiverInfo.GeneralBroadcastSender == null)
                        {
                            lock (this)
                            {
                                this.Failed[mbrUri] = GenuineExceptions.Get_Broadcast_RemoteEndPointDidNotReplyForTimeOut();
                            }
                        }

                        if (receiverInfo.Local)
                        {
                            // call to local appdomain
                            // ignore recurrent calls
                            if (this._dispatcher.IgnoreRecurrentCalls && UniqueCallTracer.Instance.WasGuidRegistered(mbrUri + callGuidSubstring))
                            {
                                continue;
                            }

                            // we'll wait for the answer from this receiver
                            this.UnrepliedReceivers[mbrUri] = null;

                            // LOG:
                            if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                            {
                                binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                                          LogMessageType.BroadcastRecipientInvoked, null, null, null, null,
                                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                          null, null, false, this._dispatcher, this, false, receiverInfo,
                                                                          null, null,
                                                                          "The local receiver is invoked via LocalPerformer.");
                            }

                            if (formatterForLocalRecipients == null)
                            {
                                formatterForLocalRecipients = new BinaryFormatter();
                            }

                            // fixed in 2.5.9.6
                            IMessage iLocalMessage = (IMessage)formatterForLocalRecipients.Deserialize((Stream)this._messageStream.Clone());

                            // queue task to run the call locally
                            //IMessage iLocalMessage = (IMessage) binaryFormatter.Deserialize( (Stream) this._messageStream.Clone() );
                            LocalPerformer localPerformer = new LocalPerformer(iLocalMessage, this, receiverInfo.MbrObject);
                            GenuineThreadPool.QueueUserWorkItem(new WaitCallback(localPerformer.Call), null, false);
                        }
                        else if (receiverInfo.GeneralBroadcastSender != null)
                        {
                            // call via true multicast channel
                            Stream messageToBeSent = (Stream)this._messageStream.Clone();

                            // send via real broadcast sender to the specific court
                            msg.Properties["__Uri"] = string.Empty;
                            Message message = Message.CreateOutcomingMessage(receiverInfo.GeneralBroadcastSender.ITransportContext, msg, new TransportHeaders(), messageToBeSent, false);
                            message.DestinationMarshalByRef = receiverInfo.SerializedObjRef;
                            message.GenuineMessageType      = GenuineMessageType.TrueBroadcast;

                            // to ignore recurrent calls on the remote side
                            if (this._dispatcher.IgnoreRecurrentCalls)
                            {
                                message.ITransportHeaders[Message.TransportHeadersBroadcastSendGuid] = callGuidSubstring;
                            }

                            // LOG:
                            if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                            {
                                message.ITransportHeaders[Message.TransportHeadersInvocationTarget] = invocationTarget;
                                message.ITransportHeaders[Message.TransportHeadersMethodName]       = methodName;

                                binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                                          LogMessageType.BroadcastRecipientInvoked, null, null, null, null,
                                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                          null, null, false, this._dispatcher, this, false, receiverInfo,
                                                                          null, null,
                                                                          "Mulsticast sender is being invoked.");
                            }

                            // register to catch all the answers
                            receiverInfo.GeneralBroadcastSender.ITransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, this);
                            // and send it
                            receiverInfo.GeneralBroadcastSender.SendMessage(message, this);
                        }
                        else
                        {
                            // send the invocation through the usual channel
                            // we'll wait for the reply
                            this.UnrepliedReceivers[mbrUri] = null;

                            // send only if this receiver is not expected to receive message via broadcast channel
                            if (receiverInfo.NeedsBroadcastSimulation)
                            {
                                // each time a new stream is created because sinks change stream position concurrently
                                Stream           messageToBeSent  = (Stream)this._messageStream.Clone();
                                TransportHeaders transportHeaders = new TransportHeaders();

                                // to ignore recurrent calls on the remote side
                                if (this._dispatcher.IgnoreRecurrentCalls)
                                {
                                    transportHeaders[Message.TransportHeadersBroadcastSendGuid] = callGuidSubstring;
                                }

                                // LOG:
                                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                                {
                                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                                              LogMessageType.BroadcastRecipientInvoked, null, null, receiverInfo.DbgRemoteHost, null,
                                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                              null, null, false, this._dispatcher, this, false, receiverInfo,
                                                                              null, null,
                                                                              "The broadcast recipient is being invoked directly.");
                                }

                                // invoke the destination MBR
                                msg.Properties["__Uri"] = receiverInfo.MbrUri;
                                transportHeaders[Message.TransportHeadersBroadcastObjRefOrCourt] = receiverInfo.SerializedObjRef;
                                transportHeaders[Message.TransportHeadersMbrUriName]             = receiverInfo.MbrUri;
                                transportHeaders[Message.TransportHeadersGenuineMessageType]     = GenuineMessageType.BroadcastEngine;
                                transportHeaders[Message.TransportHeadersInvocationTarget]       = invocationTarget;
                                transportHeaders[Message.TransportHeadersMethodName]             = methodName;
                                ClientChannelSinkStack clientChannelSinkStack = new ClientChannelSinkStack(this);
                                clientChannelSinkStack.Push(this, null);
                                receiverInfo.IClientChannelSink.AsyncProcessRequest(clientChannelSinkStack, this._iMessage, transportHeaders, messageToBeSent);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.ParseResult(mbrUri, null, ex);
                    }
                }

                // remove set uri from the hash to check wither the invocation finished
                this.UnrepliedReceivers.Remove(_uniqueReceiverName);
                if (this.UnrepliedReceivers.Count <= 0)
                {
                    this.AllMessagesReceived.Set();
                }

                this.StartReceiving();

                if (listOfExcludedReceivers.Count > 0)
                {
                    foreach (string uri in listOfExcludedReceivers)
                    {
                        this._dispatcher.Remove(uri);
                    }
                }
            }
            catch (Exception ex)
            {
                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                {
                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                              LogMessageType.BroadcastInvocationInitiated, ex, null, null, null,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                              null, null, false, this._dispatcher, this, false, null,
                                                              invocationTarget, methodName,
                                                              "A critical failure occurred during broadcast.");
                }

                throw;
            }
        }
Пример #8
0
        /// <summary>
        /// Calls the callback when either all receivers reply or wait time elapses.
        /// </summary>
        /// <param name="state">Ignored.</param>
        /// <param name="timeOut">Ignored.</param>
        private void WaitUntilReceiversReplyOrTimeOut(object state, bool timeOut)
        {
            // check whether we have any unreplied true multicast-enabled receivers
            bool unrepliedReceivers = false;

            lock (this)
            {
                if (this.Failed.Count > 0 && !this._secondStagePerformed)
                {
                    foreach (DictionaryEntry entry in this.Failed)
                    {
                        // fixed in 2.2 version
                        string       uri           = (string)entry.Key;
                        ReceiverInfo receiverInfo  = this._dispatcher.GetReceiverInfo(uri);
                        int          numberOfFails = 0;
                        if (receiverInfo != null)
                        {
                            lock (receiverInfo)
                            {
                                numberOfFails = ++receiverInfo.NumberOfFails;
                            }
                        }

                        if (this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically != 0 &&
                            numberOfFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically)
                        {
                            this._dispatcher.Remove(uri);
                        }

                        // set time-out exception
                        OperationException operationException = entry.Value as OperationException;
                        if (operationException != null && operationException.OperationErrorMessage != null &&
                            operationException.OperationErrorMessage.ErrorIdentifier == "GenuineChannels.Exception.Broadcast.RemoteEndPointDidNotReplyForTimeOut")
                        {
                            unrepliedReceivers = true;
                            break;
                        }
                    }
                }
            }

            if (unrepliedReceivers)
            {
                this.SendMessageToFailedReceiversDirectly();
                this.StartReceiving();
                return;
            }

            // LOG:
            BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;

            if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
            {
                binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.WaitUntilReceiversReplyOrTimeOut",
                                                          LogMessageType.BroadcastInvocationCompleted, null, null, null, null,
                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                          null, null, false, this._dispatcher, this, false, null,
                                                          null, null,
                                                          "The broadcast invocation is completed.");
            }

            // to stop receiving info
            this.AllMessagesReceived.Set();
            if (this._broadcastCallFinishedHandler != null)
            {
                this._broadcastCallFinishedHandler(this._dispatcher, this._iMessage, this);
            }
        }
Пример #9
0
        /// <summary>
        /// Writes down response came from the remote host.
        /// </summary>
        /// <param name="mbrUri">The uri of the remote MBR.</param>
        /// <param name="returnMessage">The received message or a null reference.</param>
        /// <param name="ex">The exception occurred during sending or receiving.</param>
        public void ParseResult(string mbrUri, IMethodReturnMessage returnMessage, Exception ex)
        {
            // if time-out has expired
            if (this.AllMessagesReceived.WaitOne(0, false))
            {
                return;
            }

            // to increase or zero the number of consecutive fails
            ReceiverInfo    receiverInfo    = this._dispatcher.GetReceiverInfo(mbrUri);
            BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;

            // if an exception is received
            Exception exception = null;

            if (ex != null || (returnMessage != null && returnMessage.Exception != null))
            {
                exception = ex != null ? ex : returnMessage.Exception;

                HostInformation dbgRemoteHost = (receiverInfo == null ? null : receiverInfo.DbgRemoteHost);
                string          numberOfFails = (receiverInfo == null ? string.Empty : receiverInfo.NumberOfFails.ToString());

                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                {
                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.ParseResult",
                                                              LogMessageType.BroadcastResponseParsed, exception, null, dbgRemoteHost, null,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                              null, null, false, this._dispatcher, this, false, receiverInfo,
                                                              numberOfFails, "false",
                                                              "The exception is received in response to the broadcast. NumberOfFails: {0}.", numberOfFails);
                }
            }

            // if it's a message that the invocation was repeated, ignore it
            if (exception is OperationException)
            {
                OperationException operationException = (OperationException)exception;
                if (operationException.OperationErrorMessage.ErrorIdentifier == "GenuineChannels.Exception.Broadcast.CallHasAlreadyBeenMade")
                {
                    return;
                }
            }

            lock (this)
            {
                // if successful response from this object has already been received
                this.UnrepliedReceivers.Remove(mbrUri);

                if (this.Successful.ContainsKey(mbrUri))
                {
                    return;
                }
            }

            lock (this)
            {
                // if an exception is received
                if (exception != null)
                {
                    this.Failed[mbrUri] = exception;

                    if (receiverInfo != null)
                    {
                        lock (receiverInfo)
                        {
                            if (receiverInfo.GeneralBroadcastSender == null && this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically != 0 &&
                                receiverInfo.NumberOfFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically)
                            {
                                // exclude it
                                this._dispatcher.Remove(receiverInfo.MbrObject);
                            }
                        }
                    }
                }
                else
                {
                    // successful response
                    this.Successful[mbrUri] = returnMessage;
                    this.Failed.Remove(mbrUri);

                    // LOG:
                    if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                    {
                        HostInformation dbgRemoteHost = (receiverInfo == null ? null : receiverInfo.DbgRemoteHost);

                        binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.ParseResult",
                                                                  LogMessageType.BroadcastResponseParsed, null, null, dbgRemoteHost, null,
                                                                  GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                  null, null, false, this._dispatcher, this, false, receiverInfo,
                                                                  null, "true",
                                                                  "The successful response is received.");
                    }

                    if (receiverInfo != null)
                    {
                        lock (receiverInfo)
                        {
                            receiverInfo.NumberOfFails = 0;
                        }
                    }
                }

                if (this.UnrepliedReceivers.Count == 0)
                {
                    this.AllMessagesReceived.Set();
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Registers the receiver and associate the provided object with it.
        /// Returns false if the receiver has already been registered.
        /// WARNING: does not check whether the receiver supports the required interface (via Reflection)
        /// because this check requires client's dll.
        /// </summary>
        /// <param name="obj">The receiver being registered.</param>
        /// <param name="tag">The object associated with the receiver. This object is accessible when receiver is being unregistered or during filtering.</param>
        /// <param name="remoteGenuineUri">The uri of the remote host provided by any of Genuine Channels.</param>
        /// <param name="transportContext">The transport context of the remote host.</param>
        /// <returns>False if the receiver has been already registered.</returns>
        public bool Add(MarshalByRefObject obj, object tag, string remoteGenuineUri, ITransportContext transportContext)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }

            BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;

            // check if it is in the list
            string uri = RemotingServices.GetObjectUri(obj);

            if (uri == null && !RemotingServices.IsObjectOutOfAppDomain(obj))
            {
                // it was not marshalled
                RemotingServices.Marshal(obj);
                uri = RemotingServices.GetObjectUri(obj);
            }

            using (ReaderAutoLocker reader = new ReaderAutoLocker(this._readerWriterLock))
            {
                if (this._receivers.ContainsKey(uri))
                {
                    return(false);
                }
            }

            // this check can not be performed because client's dll is required
//			// check on the interface
//			bool supportInterface = false;
//			foreach(Type interfaceType in obj.GetType().GetInterfaces())
//				if (interfaceType == this._interfaceToSupport)
//				{
//					supportInterface = true;
//					break;
//				}
//			if (! supportInterface)
//				throw GenuineExceptions.Get_Broadcast_ObjectDoesNotSupportDestinationInterface();

            // adds the object to the receiver list
            ReceiverInfo receiverInfo = new ReceiverInfo();

            receiverInfo.MbrObject = obj;
            receiverInfo.MbrUri    = uri;
            receiverInfo.Tag       = tag;

            if (binaryLogWriter != null)
            {
                try
                {
                    if (receiverInfo.MbrObject != null)
                    {
                        receiverInfo.DbgRemoteHost = GenuineUtility.FetchHostInformationFromMbr(receiverInfo.MbrObject);
                    }
                }
                catch (Exception ex)
                {
                    binaryLogWriter.WriteImplementationWarningEvent("Dispatcher.Add",
                                                                    LogMessageType.Error, ex, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                    "Can't get HostInformation from MbrObject.");
                }
            }

            ObjRef objRef = receiverInfo.MbrObject.CreateObjRef(typeof(MarshalByRefObject));

            receiverInfo.Local = objRef.IsFromThisAppDomain();

            // cache object's info to speed up sending thru Genuine Channels
            if (!receiverInfo.Local)
            {
                if (remoteGenuineUri != null)
                {
                    receiverInfo.IClientChannelSink = new GenuineTcpClientTransportSink(remoteGenuineUri, transportContext);
                }
                else
                {
                    // check whether the client sink has registered itself on this MBR
                    receiverInfo.IClientChannelSink = ChannelServices.GetChannelSinkProperties(obj)["GC_TS"] as IClientChannelSink;
                    if (receiverInfo.IClientChannelSink == null)
                    {
                        throw GenuineExceptions.Get_Broadcast_ClientSinkIsUnknown();
                    }
                }

                // object uri
                receiverInfo.SerializedObjRef = objRef;

//				// and shell's uri
//				string shellUri;
//				ITransportContext iTransportContext;
//				GenuineUtility.FetchChannelUriFromMbr(obj, out shellUri, out iTransportContext);
//				if (shellUri == null)
//					throw GenuineExceptions.Get_Send_NoSender(objRef.URI);
//
//				receiverInfo.ReceiverUri = shellUri;
            }

            // LOG:
            if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
            {
                binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "Dispatcher.Add",
                                                          LogMessageType.BroadcastRecipientAdded, null, null, receiverInfo.DbgRemoteHost, null,
                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                          null, null, false, this, null, true, receiverInfo,
                                                          null, null,
                                                          "The broadcast recipient is added.");
            }

            // register the sponsor to prevent unexpected reclaiming
            ILease lease = (ILease)RemotingServices.GetLifetimeService(obj);

            if (lease != null)
            {
                lease.Register(this.GlobalSponsor);
            }

            // and register it
            using (WriterAutoLocker writer = new WriterAutoLocker(this._readerWriterLock))
            {
                this._cachedReceiversInfoArray = null;
                this._receivers[uri]           = receiverInfo;
            }
            return(true);
        }