Пример #1
0
        /// <summary>
        /// Register subscriber using a string token, which is usually defined as a constant.
        /// Subscriber performs internal notifications.
        /// </summary>
        /// <param name="token">String identifying a message token</param>
        /// <param name="subscriber">Subscriber requesting notifications</param>
        public void Register(string token, INotifyable subscriber)
        {
            lock (_sharedLock)
            {
                // Add token if not present
                if (!_subscriptions.ContainsKey(token))
                {
                    _subscriptions.Add(token, new List <WeakReference> {
                        new WeakReference(subscriber)
                    });
                    return;
                }

                // Get subscribers for this token
                List <WeakReference> weakSubscribers;
                if (_subscriptions.TryGetValue(token, out weakSubscribers))
                {
                    // See if subcriber is already present
                    var existing = (from w in weakSubscribers
                                    where w != null && w.IsAlive &&
                                    ReferenceEquals(w.Target, subscriber)
                                    select w).SingleOrDefault();

                    // Add if subcriber is already present
                    if (existing == null)
                    {
                        _subscriptions[token].Add(new WeakReference(subscriber));
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Remove subscriber from the invocation list
        /// </summary>
        /// <param name="token">String identifying a message token</param>
        /// <param name="subscriber">Subscriber to remove from notifications</param>
        public void Unregister(string token, INotifyable subscriber)
        {
            lock (_sharedLock)
            {
                List <WeakReference> weakSubscribers;
                if (_subscriptions.TryGetValue(token, out weakSubscribers))
                {
                    // Find subscriber
                    WeakReference weakSubscriber = weakSubscribers
                                                   .SingleOrDefault(w => w.IsAlive && ReferenceEquals
                                                                        (w.Target, subscriber));

                    // Remove subscriber
                    if (weakSubscriber != null)
                    {
                        weakSubscribers.Remove(weakSubscriber);
                    }

                    // Remove dictionary entry if no subscibers left
                    if (_subscriptions[token].Count == 0)
                    {
                        _subscriptions.Remove(token);
                    }
                }
            }
        }
Пример #3
0
        public Buffer SetState(QpcTimeStamp qpcTimeStamp, BufferState state, string reason)
        {
            BufferState entryState = State;

            State     = state;
            TimeStamp = qpcTimeStamp;

            switch (state)
            {
            case BufferState.SendPosted: CopyHeaderToByteArray(); SendPostedTimeStamp = qpcTimeStamp; break;

            case BufferState.Received: UpdateHeaderFromByteArray(); break;

            default: break;
            }

            if (StateEmitter.IsEnabled)
            {
                StateEmitter.Emit("{0} State changed to {1} [from: {2}, reason: {3}]", BufferName, state, entryState, reason ?? "NoReasonGiven");
            }

            INotifyable notifyOnStateChange = NotifyOnSetState;

            if (notifyOnStateChange != null)
            {
                notifyOnStateChange.Notify();
            }

            return(this);
        }
Пример #4
0
            public SerialEchoTracker(string portPartID, string portTargetSpec, double[] binBoundariesArray, SerialEchoPerformancePartConfig config, INotifyable notifyOnDone, Logging.IBasicLogger logger)
            {
                PortTargetSpec = portTargetSpec;
                Config         = config;
                NotifyOnDone   = notifyOnDone;
                Logger         = logger;

                h = new Histogram(binBoundariesArray);

                timeoutCountGPI = new MDRF.Writer.GroupPointInfo()
                {
                    Name = "timeoutCount", ValueCST = ContainerStorageType.UInt64, VC = new ValueContainer(0L)
                };
                failureCountGPI = new MDRF.Writer.GroupPointInfo()
                {
                    Name = "failureCount", ValueCST = ContainerStorageType.UInt64, VC = new ValueContainer(0L)
                };

                hGrp = new MDRFHistogramGroupSource("{0}".CheckedFormat(portPartID),
                                                    h,
                                                    (ulong)config.AggregateGroupsFileIndexUserRowFlagBits,
                                                    extraClientNVS: new NamedValueSet()
                {
                    { "SerialEcho" }, { "PortTargetSpec", PortTargetSpec }
                },
                                                    extraGPISet: new[] { timeoutCountGPI, failureCountGPI });

                try
                {
                    portConfig = new PortConfig(portPartID, portTargetSpec)
                    {
                        TxLineTerm          = LineTerm.None,
                        RxLineTerm          = LineTerm.CR,
                        ConnectTimeout      = (2.0).FromSeconds(),
                        WriteTimeout        = (1.0).FromSeconds(),
                        ReadTimeout         = (1.0).FromSeconds(),
                        IdleTime            = (1.0).FromSeconds(),
                        EnableAutoReconnect = true,
                    };

                    port = MosaicLib.SerialIO.Factory.CreatePort(portConfig);

                    portGetNextPacketAction = port.CreateGetNextPacketAction();
                    portFlushAction         = port.CreateFlushAction();
                    portWriteAction         = port.CreateWriteAction(portWriteActionParam = new WriteActionParam());
                }
                catch (System.Exception ex)
                {
                    Logger.Error.Emit("Port setup for '{0}' failed: {1}", portTargetSpec, ex.ToString(ExceptionFormat.TypeAndMessage));
                }
            }
Пример #5
0
        private void InternalNotify(string token, object sender,
                                    NotificationEventArgs e, bool post)
        {
            // Get weak subscribers
            List <WeakReference> weakSubscribers;

            lock (_sharedLock)
            {
                if (!_subscriptions.TryGetValue(token, out weakSubscribers))
                {
                    return;
                }

                // Make a copy while locked
                weakSubscribers = weakSubscribers.ToList();
            }

            // Get compatible living subscribers
            var subscribers = from w in weakSubscribers
                              let s = w.Target as INotifyable
                                      where w != null && w.IsAlive && s != null
                                      select s;

            // Invoke each callback associated with token
            foreach (var subscriber in subscribers)
            {
                INotifyable subscriber1 = subscriber;
                SafeNotify(() => subscriber1.Notify(token, sender, e));
            }

            lock (_sharedLock)
            {
                if (_subscriptions.ContainsKey(token))
                {
                    // Remove subscribers who are no longer alive
                    var deadSubscribers = weakSubscribers
                                          .Where(w => w == null || !w.IsAlive);
                    foreach (var s in deadSubscribers)
                    {
                        _subscriptions[token].Remove(s);
                    }

                    // Remove dictionary entry if no subscibers left
                    if (_subscriptions[token].Count == 0)
                    {
                        _subscriptions.Remove(token);
                    }
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Sets the byteCount to the headerSize and sets the header's BufferSeqNum to zero.
        /// </summary>
        public void Clear(QpcTimeStamp qpcTimeStamp, bool clearByteArrayContents = false, string reason = null)
        {
            header           = BufferHeaderV1.Empty;
            byteCount        = header.Length;
            Message          = null;
            NotifyOnSetState = null;

            if (clearByteArrayContents)
            {
                System.Array.Clear(byteArray, 0, byteArraySize);
            }

            SetState(qpcTimeStamp, Buffers.BufferState.Clear, reason);
        }
Пример #7
0
        public Buffer Update(PurposeCode?purposeCode = null, BufferHeaderFlags?orInFlags = null, ulong?seqNum = null, int?byteCount = null, ulong?ackSeqNum = null, INamedValueSet buildPayloadDataFromE005NVS = null, bool throwOnException = false, byte[] copyPayloadDataFromByteArray = null, INotifyable notifyOnSetState = null)
        {
            if (purposeCode != null)
            {
                header.PurposeCode = purposeCode ?? PurposeCode.None;
            }

            if (orInFlags != null)
            {
                header.Flags |= orInFlags ?? BufferHeaderFlags.None;
            }

            if (seqNum != null)
            {
                SeqNum = seqNum ?? 0;
            }

            if (byteCount != null)
            {
                this.byteCount = byteCount ?? 0;
            }

            if (ackSeqNum != null)
            {
                header.AckSeqNum = ackSeqNum ?? 0;
            }

            if (buildPayloadDataFromE005NVS != null)
            {
                header.Flags |= BufferHeaderFlags.BufferContainsE005NVS;
                copyPayloadDataFromByteArray = buildPayloadDataFromE005NVS.ConvertToE005Data(throwOnException: throwOnException);
            }

            if (copyPayloadDataFromByteArray != null)
            {
                byteArray.SafeCopyFrom(header.Length, copyPayloadDataFromByteArray);
                this.byteCount = Math.Min(header.Length + copyPayloadDataFromByteArray.Length, byteArraySize);
            }

            if (notifyOnSetState != null)
            {
                NotifyOnSetState = notifyOnSetState;
            }

            return(this);
        }
Пример #8
0
        /// <summary>Adds/Replaces the indicated socket, settings and notification target to the monitor list and starts the background service thread if it is not already running.</summary>
        public void AddSocketToList(Socket s, bool read, bool write, bool error, INotifyable notifyTarget)
        {
            TableItem tableItem = new TableItem()
            {
                Socket       = s,
                read         = read,
                write        = write,
                error        = error,
                notifyTarget = notifyTarget,
            };

            string notUsableReason = tableItem.NotUsableReason;

            if (!notUsableReason.IsNullOrEmpty())
            {
                tableItem.LastLoggedNotUsableReason = notUsableReason;

                Logger.Debug.Emit("{0} given unusable socket {1} : {2} [Adding inactive]", Fcns.CurrentMethodName, tableItem.shAsInt64, notUsableReason);
            }

            lock (userTableMutex)
            {
                // the following passes ownership of the tableItem to this object's service thread.
                userTableDictionary[s] = tableItem;

                notifyOnNextTableRebuildTableItemList.Add(tableItem);

                rebuildTablesFromUserTable = true;

                NumActiveSockets += 1;
            }

            StartBackgroundThreadIfNeeded();

            threadWaitEventNotifier.Notify();
        }
Пример #9
0
            public PingTracker(string hostNameOrAddress, double[] binBoundariesArray, PingPerformancePartConfig config, INotifyable notifyOnDone)
            {
                HostNameOrAddress = hostNameOrAddress;
                NotifyOnDone      = notifyOnDone;

                // calling GetHostAddresses can throw for many reasons (invalid app.config for example...)
                Func <System.Net.IPAddress []> getHostAddressesDelegate = () => System.Net.Dns.GetHostAddresses(hostNameOrAddress);

                IPAddressArray = getHostAddressesDelegate.TryGet();

                IPAddress = IPAddressArray.SafeAccess(0, System.Net.IPAddress.None);
                h         = new Histogram(binBoundariesArray);

                timeoutCountGPI = new MDRF.Writer.GroupPointInfo()
                {
                    Name = "timeoutCount", ValueCST = ContainerStorageType.UInt64, VC = new ValueContainer(0L)
                };
                failureCountGPI = new MDRF.Writer.GroupPointInfo()
                {
                    Name = "failureCount", ValueCST = ContainerStorageType.UInt64, VC = new ValueContainer(0L)
                };

                hGrp = new MDRFHistogramGroupSource("hPing_{0}".CheckedFormat(HostNameOrAddress),
                                                    h,
                                                    (ulong)config.AggregateGroupsFileIndexUserRowFlagBits,
                                                    extraClientNVS: new NamedValueSet()
                {
                    { "Ping" }, { "Host", HostNameOrAddress }, { "IPAddress", IPAddress.ToString() }
                },
                                                    extraGPISet: new[] { timeoutCountGPI, failureCountGPI });

                extraData = new byte[config.ExtraLength];

                responseTimeLimitInMSec = unchecked ((int)config.ResponseTimeLimit.TotalMilliseconds);
                responseWaitTimeLimit   = (config.ResponseTimeLimit.TotalSeconds + 0.25).FromSeconds();
            }
Пример #10
0
        /// <summary>Adds/Replaces the indicated socket, settings and notification target to the monitor list and starts the background service thread if it is not already running.</summary>
        public void AddSocketToList(Socket s, bool read, bool write, bool error, INotifyable notifyTarget)
        {
            TableItem tableItem = new TableItem() { s = s, read = read, write = write, error = error, notifyTarget = notifyTarget };

            lock (userTableMutex)
            {
                userTableDictionary[s] = tableItem;
                rebuildTablesFromUserTable = true;
            }

            StartBackgroundThreadIfNeeded();
        }
Пример #11
0
        /// <summary>
        /// Obtains the ISharedDispatcherTimer instance from the dictionary (createing one if needed),
        /// Adds any of the optional Tick event handler signatures (as supported by the ISharedDispatchTimer's TickNotificationList)
        /// and returns an IDisposable token that will release use of the timer and will remove any given Tick event handler signatures from the underlying TickNotificationList when the token is dipsosed.
        /// </summary>
        public static IDisposable GetAndStartSharedTimer(double rate, string clientName, BasicNotificationDelegate onTickNotifyDelegate = null, INotifyable notifyableTarget = null, System.Threading.EventWaitHandle eventWaitHandle = null)
        {
            ISharedDispatcherTimer sharedDispatcherTimer = GetSharedTimer(rate);

            if (onTickNotifyDelegate != null)
            {
                sharedDispatcherTimer.TickNotificationList.OnNotify += onTickNotifyDelegate;
            }

            if (notifyableTarget != null)
            {
                sharedDispatcherTimer.TickNotificationList.AddItem(notifyableTarget);
            }

            if (eventWaitHandle != null)
            {
                sharedDispatcherTimer.TickNotificationList.AddItem(eventWaitHandle);
            }

            IDisposable token = sharedDispatcherTimer.GetRunTimerToken(clientName);

            return(new ExplicitDisposeActionList()
                   .AddItems(() => Fcns.DisposeOfGivenObject(token),
                             () =>
            {
                if (onTickNotifyDelegate != null)
                {
                    sharedDispatcherTimer.TickNotificationList.OnNotify -= onTickNotifyDelegate;
                }

                if (notifyableTarget != null)
                {
                    sharedDispatcherTimer.TickNotificationList.RemoveItem(notifyableTarget);
                }

                if (eventWaitHandle != null)
                {
                    sharedDispatcherTimer.TickNotificationList.RemoveItem(eventWaitHandle);
                }
            }));
        }