//******************************************************************************************************
// 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
}
}