Beispiel #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);
        }
Beispiel #2
0
        /// <summary>
        /// Fires the BroadcastReceiverHasBeenExcluded event and detach the sponsor from the specified receiver.
        /// </summary>
        /// <param name="state">The receiver being excluded.</param>
        public void DeleteSponsorFromTheObjectAndFireEvent(object state)
        {
            ReceiverInfo       receiverInfo       = (ReceiverInfo)state;
            MarshalByRefObject marshalByRefObject = (MarshalByRefObject)receiverInfo.MbrObject;

            // fire the event
            try
            {
                if (this.BroadcastReceiverHasBeenExcluded != null)
                {
                    this.BroadcastReceiverHasBeenExcluded(marshalByRefObject, receiverInfo);
                }
            }
            catch
            {
                // ignore all exceptions
            }

            // detach sponsor
            try
            {
                ILease lease = (ILease)RemotingServices.GetLifetimeService(marshalByRefObject);
                if (lease != null)
                {
                    lease.Unregister(this.GlobalSponsor);
                }
            }
            catch
            {
                // ignore all exceptions
            }
        }
Beispiel #3
0
        /// <summary>
        /// Returns the receiver associated with the specified uri.
        /// </summary>
        /// <param name="uri">The uri associated with the receiver.</param>
        /// <returns>The receiver associated with the specified uri.</returns>
        public MarshalByRefObject FindObjectByUri(string uri)
        {
            using (ReaderAutoLocker reader = new ReaderAutoLocker(this._readerWriterLock))
            {
                ReceiverInfo receiverInfo = this._receivers[uri] as ReceiverInfo;
                if (receiverInfo == null)
                {
                    return(null);
                }

                return(receiverInfo.MbrObject);
            }
        }
        /// <summary>
        /// Processes the received response.
        /// </summary>
        /// <param name="message">The response.</param>
        public void ProcessRespose(Message message)
        {
            // it's a response via the usual channel that the remote host successfully received a message via broadcast channel
            // message.Sender - remote MBR uri
            string objectUri = message.DestinationMarshalByRef as string;

            if (objectUri == null)
            {
                return;
            }

            lock (this._dispatcher)
            {
                ReceiverInfo receiverInfo = this._dispatcher.GetReceiverInfo(objectUri);
                if (receiverInfo == null)
                {
                    return;
                }

                receiverInfo.NeedsBroadcastSimulation = false;
                receiverInfo.NumberOfMulticastFails   = 0;
            }

            // if time-out has expired
            if (this.AllMessagesReceived.WaitOne(0, false))
            {
                return;
            }

            try
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                object          reply           = binaryFormatter.Deserialize(message.Stream);
                this.ParseResult(objectUri, reply as IMethodReturnMessage, reply as Exception);
            }
            catch (Exception ex)
            {
                this.ParseResult(objectUri, null, ex);
            }
        }
Beispiel #5
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);
        }
        /// <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();
                }
            }
        }
        /// <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;
            }
        }
        /// <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);
            }
        }
        /// <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();
                }
            }
        }
Beispiel #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);
        }
        /// <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;
        }
        /// <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;
        }
        /// <summary>
        /// Puts down a record containing information about the specified broadcast recipient.
        /// </summary>
        /// <param name="writeFullInformation">True if it is necessary to write all settings of the ReceiverInfo.</param>
        /// <param name="receiverInfo">The ReceiverInfo.</param>
        public void WriteReceiverInfo(bool writeFullInformation, ReceiverInfo receiverInfo)
        {
            this.BinaryWriter.Write( receiverInfo != null );
            if (receiverInfo == null)
                return ;

            this.BinaryWriter.Write( (int) receiverInfo.DbgRecipientId );
            this.BinaryWriter.Write( (bool) writeFullInformation );

            if (! writeFullInformation)
                return ;

            this.WriteString( receiverInfo.MbrUri);
            this.BinaryWriter.Write((bool) receiverInfo.Local);

            if (receiverInfo.GeneralBroadcastSender != null)
                this.WriteString( receiverInfo.GeneralBroadcastSender.Court);
            else
                this.BinaryWriter.Write(string.Empty);
        }
        /// <summary>
        /// Puts down a record describing a general Genuine Channels event.
        /// </summary>
        /// <param name="logCategory">The category of the event.</param>
        /// <param name="author">The author.</param>
        /// <param name="type">The type of the event(Subcategory).</param>
        /// <param name="exception">The exception associated with the event.</param>
        /// <param name="message">The message associated with the event.</param>
        /// <param name="remote">The remote host participating in the event.</param>
        /// <param name="content">The content associated with the record.</param>
        /// <param name="sourceThreadId">The id of the thread where the invocation was made.</param>
        /// <param name="sourceThreadName">The name of the thread.</param>
        /// <param name="securitySession">The Security Session.</param>
        /// <param name="securitySessionName">The name of the Security Session</param>
        /// <param name="writeDispatcherSettings">A value indicating whether it is necessary to put down broadcast dispatcher's settings.</param>
        /// <param name="dispatcher">The broadcast dispatcher.</param>
        /// <param name="resultCollector">The broadcast result collector.</param>
        /// <param name="writeReceiverInfoSettings">A value indicating whether it is necessary to put down information about the specified broadcast recipient.</param>
        /// <param name="receiverInfo">The broadcast recipient.</param>
        /// <param name="string1">The first string that elaborates the current event.</param>
        /// <param name="string2">The second string that elaborates the current event.</param>
        /// <param name="description">The description of the event.</param>
        /// <param name="parameters">Parameters to the description.</param>
        public void WriteBroadcastEngineEvent(LogCategory logCategory, string author, LogMessageType type, Exception exception, 
            Message message, HostInformation remote, Stream content, int sourceThreadId, string sourceThreadName,
            SecuritySession securitySession, string securitySessionName,
            bool writeDispatcherSettings, Dispatcher dispatcher, ResultCollector resultCollector, bool writeReceiverInfoSettings,
            ReceiverInfo receiverInfo, string string1, string string2, string description, params object[] parameters)
        {
            if (dispatcher == null)
            {
                this.WriteImplementationWarningEvent("BinaryLogWriter.WriteBroadcastEngineEvent", LogMessageType.Error, null,
                    sourceThreadId, sourceThreadName, "The reference is null. Stack trace: " + Environment.StackTrace);
                return ;
            }

            lock (this._streamLock)
            {
                this.WriteRecordHeader(BinaryRecordVersion.TransportBroadcastEngineRecord, logCategory, type, author);
                this.WriteException( exception );

                this.WriteMessageSeqNo( message );
                this.WriteHostInformationId( remote );
                this.WriteBinaryContent( content );

                this.BinaryWriter.Write( (int) sourceThreadId);
                this.WriteString( sourceThreadName );

                this.WriteSecuritySessionId( securitySession );
                this.WriteString( securitySessionName );

                this.WriteResultCollectorId(resultCollector);
                this.WriteDispatcherSettings(writeDispatcherSettings, dispatcher);
                this.WriteReceiverInfo(writeReceiverInfoSettings, receiverInfo);

                this.WriteString( string1 );
                this.WriteString( string2 );
                this.WriteStringWithParameters( description, parameters);

                this.BinaryWriter.Flush();
            }
        }
Beispiel #15
0
 private void _dispatcher_BroadcastReceiverHasBeenExcluded(MarshalByRefObject marshalByRefObject, ReceiverInfo receiverInfo)
 {
     if(receiverInfo!=null)
     {
         lock(FailedReciverURIList)
         {
             FailedReciverURIList.Add(receiverInfo.MbrUri+"  receiver fails "+receiverInfo.NumberOfFails.ToString());
         }
         showFailReciverList("private void _dispatcher_BroadcastReceiverHasBeenExcluded(MarshalByRefObject marshalByRefObject, ReceiverInfo receiverInfo)");
     }
 }