//****************************************************************************************************** // NotifierBase.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 05/26/2007 - Pinal C. Patel // Generated original version of source code. // 04/21/2009 - Pinal C. Patel // Converted to C#. // 08/06/2009 - Pinal C. Patel // Made Initialize() virtual so inheriting classes can override the default behavior. // 09/15/2009 - Stephen C. Wills // Added new header and license agreement. // 11/05/2009 - Pinal C. Patel // Modified to abort notify operation during dispose. // 10/11/2010 - Mihir Brahmbhatt // Updated header and license agreement. // 12/14/2012 - Starlynn Danyelle Gilliam // Modifeid Header. // //****************************************************************************************************** using System; using System.Configuration; using System.Threading; using GSF.Adapters; using GSF.Configuration; namespace GSF.Historian.Notifiers { /// /// Base class for a notifier that can process notification messages. /// /// public abstract class NotifierBase : Adapter, INotifier { #region [ Members ] // Events /// /// Occurs when a notification is being sent. /// public event EventHandler NotificationSendStart; /// /// Occurs when a notification has been sent. /// public event EventHandler NotificationSendComplete; /// /// Occurs when a timeout is encountered while sending a notification. /// public event EventHandler NotificationSendTimeout; /// /// Occurs when an is encountered while sending a notification. /// /// /// is the exception encountered while sending a notification. /// public event EventHandler> NotificationSendException; // Fields private int m_notifyTimeout; private NotificationTypes m_notifyOptions; private Thread m_notifyThread; private bool m_disposed; #endregion #region [ Constructors ] /// /// Initializes a new instance of the notifier. /// /// that can be processed by the notifier. public NotifierBase(NotificationTypes notifyOptions) { m_notifyOptions = notifyOptions; m_notifyTimeout = 30; PersistSettings = true; } #endregion #region [ Properties ] /// /// Gets or sets the number of seconds to wait for to complete. /// /// /// Set to -1 to wait indefinitely on . /// public int NotifyTimeout { get { return m_notifyTimeout; } set { if (value < 1) m_notifyTimeout = -1; else m_notifyTimeout = value; } } /// /// Gets or set that can be processed by the notifier. /// public NotificationTypes NotifyOptions { get { return m_notifyOptions; } set { m_notifyOptions = value; } } #endregion #region [ Methods ] /// /// When overridden in a derived class, processes a notification. /// /// Subject matter for the notification. /// Brief message for the notification. /// Detailed message for the notification. protected abstract void NotifyAlarm(string subject, string message, string details); /// /// When overridden in a derived class, processes a notification. /// /// Subject matter for the notification. /// Brief message for the notification. /// Detailed message for the notification. protected abstract void NotifyWarning(string subject, string message, string details); /// /// When overridden in a derived class, processes a notification. /// /// Subject matter for the notification. /// Brief message for the notification. /// Detailed message for the notification. protected abstract void NotifyInformation(string subject, string message, string details); /// /// When overridden in a derived class, processes a notification. /// /// Subject matter for the notification. /// Brief message for the notification. /// Detailed message for the notification. protected abstract void NotifyHeartbeat(string subject, string message, string details); /// /// Saves notifier settings to the config file if the property is set to true. /// /// has a value of null or empty string. public override void SaveSettings() { base.SaveSettings(); if (PersistSettings) { // Save settings under the specified category. ConfigurationFile config = ConfigurationFile.Current; CategorizedSettingsElementCollection settings = config.Settings[SettingsCategory]; settings["Enabled", true].Update(Enabled); settings["NotifyTimeout", true].Update(m_notifyTimeout); settings["NotifyOptions", true].Update(m_notifyOptions); config.Save(); } } /// /// Loads saved notifier settings from the config file if the property is set to true. /// /// has a value of null or empty string. public override void LoadSettings() { base.LoadSettings(); if (PersistSettings) { // Load settings from the specified category. ConfigurationFile config = ConfigurationFile.Current; CategorizedSettingsElementCollection settings = config.Settings[SettingsCategory]; settings.Add("Enabled", Enabled, "True if this notifier is enabled; otherwise False."); settings.Add("NotifyTimeout", m_notifyTimeout, "Number of seconds to wait for notification processing to complete."); settings.Add("NotifyOptions", m_notifyOptions, "Types of notifications (Information; Warning; Alarm; Heartbeat) to be processed by this notifier."); Enabled = settings["Enabled"].ValueAs(Enabled); NotifyTimeout = settings["NotifyTimeout"].ValueAs(m_notifyTimeout); NotifyOptions = settings["NotifyOptions"].ValueAs(m_notifyOptions); } } /// /// Process a notification. /// /// Subject matter for the notification. /// Brief message for the notification. /// Detailed message for the notification. /// One of the values. /// true if notification is processed successfully; otherwise false. public bool Notify(string subject, string message, string details, NotificationTypes notificationType) { if (!Enabled || (m_notifyThread != null && m_notifyThread.IsAlive)) return false; // Start notification thread with appropriate parameters. m_notifyThread = new Thread(NotifyInternal); if ((notificationType & NotificationTypes.Alarm) == NotificationTypes.Alarm && (m_notifyOptions & NotificationTypes.Alarm) == NotificationTypes.Alarm) // Alarm notifications are supported. m_notifyThread.Start(new object[] { new Action(NotifyAlarm) , subject, message, details}); else if ((notificationType & NotificationTypes.Warning) == NotificationTypes.Warning && (m_notifyOptions & NotificationTypes.Warning) == NotificationTypes.Warning) // Warning notifications are supported. m_notifyThread.Start(new object[] { new Action(NotifyWarning), subject, message, details }); else if ((notificationType & NotificationTypes.Information) == NotificationTypes.Information && (m_notifyOptions & NotificationTypes.Information) == NotificationTypes.Information) // Information notifications are supported. m_notifyThread.Start(new object[] { new Action(NotifyInformation), subject, message, details }); else if ((notificationType & NotificationTypes.Heartbeat) == NotificationTypes.Heartbeat && (m_notifyOptions & NotificationTypes.Heartbeat) == NotificationTypes.Heartbeat) // Heartbeat notifications are supported. m_notifyThread.Start(new object[] { new Action(NotifyHeartbeat), subject, message, details }); else // Specified notification type is not supported. return false; if (m_notifyTimeout < 1) { // Wait indefinetely on the refresh. m_notifyThread.Join(Timeout.Infinite); } else { // Wait for the specified time on refresh. if (!m_notifyThread.Join(m_notifyTimeout * 1000)) { m_notifyThread.Abort(); return false; } } return true; } /// /// Releases the unmanaged resources used by the notifier and optionally releases the managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if (m_notifyThread != null) m_notifyThread.Abort(); } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); } } } /// /// Raises the event. /// protected virtual void OnNotificationSendStart() { if (NotificationSendStart != null) NotificationSendStart(this, EventArgs.Empty); } /// /// Raises the event. /// protected virtual void OnNotificationSendComplete() { if (NotificationSendComplete != null) NotificationSendComplete(this, EventArgs.Empty); } /// /// Raises the event. /// protected virtual void OnNotificationSendTimeout() { if (NotificationSendTimeout != null) NotificationSendTimeout(this, EventArgs.Empty); } /// /// Raises the event. /// /// to send to event. protected virtual void OnNotificationSendException(Exception exception) { if (NotificationSendException != null) NotificationSendException(this, new EventArgs(exception)); } private void NotifyInternal(object state) { try { // Unpackage the parameters. object[] args = (object[])state; string subject = args[1].ToString(); string message = args[2].ToString(); string details = args[3].ToString(); Action target = (Action)args[0]; OnNotificationSendStart(); target(subject, message, details); OnNotificationSendComplete(); } catch (ThreadAbortException) { OnNotificationSendTimeout(); } catch (Exception ex) { OnNotificationSendException(ex); } } #endregion } }