//****************************************************************************************************** // MetadataProviderBase.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: // ---------------------------------------------------------------------------------------------------- // 07/07/2009 - Pinal C. Patel // Generated original version of source code. // 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. // 09/15/2009 - Pinal C. Patel // Throwing ArgumentNullException exception in Refresh() if Metadata is null. // 11/05/2009 - Pinal C. Patel // Modified to abort refresh operation during dispose. // 03/30/2010 - Pinal C. Patel // Corrected the usage of Enabled in Refresh(). // 10/11/2010 - Mihir Brahmbhatt // Updated header and license agreement. // 12/14/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** using System; using System.Configuration; using System.Threading; using System.Timers; using GSF.Adapters; using GSF.Configuration; using GSF.Historian.Files; using Timer = System.Timers.Timer; namespace GSF.Historian.MetadataProviders { /// /// Base class for a provider of updates to the data in a . /// public abstract class MetadataProviderBase : Adapter, IMetadataProvider { #region [ Members ] // Events /// /// Occurs when of is started. /// public event EventHandler MetadataRefreshStart; /// /// Occurs when of is completed. /// public event EventHandler MetadataRefreshComplete; /// /// Occurs when of times out. /// public event EventHandler MetadataRefreshTimeout; /// /// Occurs when an is encountered during of . /// /// /// is the encountered during . /// public event EventHandler> MetadataRefreshException; // Fields private int m_refreshInterval; private int m_refreshTimeout; private MetadataFile m_metadata; private Thread m_refreshThread; private Timer m_refreshTimer; private bool m_disposed; private bool m_initialized; #endregion #region [ Constructors ] /// /// Initializes a new instance of the metadata provider. /// protected MetadataProviderBase() { m_refreshInterval = -1; m_refreshTimeout = 60; PersistSettings = true; } #endregion #region [ Properties ] /// /// Gets or sets the number of seconds to wait for the to complete. /// /// /// Set to -1 to wait indefinitely on . /// public int RefreshTimeout { get { return m_refreshTimeout; } set { if (value < 1) m_refreshTimeout = -1; else m_refreshTimeout = value; } } /// /// Gets or sets the interval in minutes at which the if to be refreshed automatically. /// /// /// Set to -1 to disable auto . /// public int RefreshInterval { get { return m_refreshInterval; } set { if (value < 1) m_refreshInterval = -1; else m_refreshInterval = value; } } /// /// Gets or sets the to be refreshed by the metadata provider. /// public MetadataFile Metadata { get { return m_metadata; } set { m_metadata = value; } } #endregion #region [ Methods ] /// /// When overridden in a derived class, refreshes the from an external source. /// protected abstract void RefreshMetadata(); /// /// Initializes the metadata provider. /// public override void Initialize() { base.Initialize(); if (!m_initialized) { // Start refresh timer for auto-refresh. if (Enabled && m_refreshInterval > 0) { m_refreshTimer = new Timer(m_refreshInterval * 60000); m_refreshTimer.Elapsed += RefreshTimer_Elapsed; m_refreshTimer.Start(); } // Initialize only once. m_initialized = true; } } /// /// Saves metadata provider 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["RefreshTimeout", true].Update(m_refreshTimeout); settings["RefreshInterval", true].Update(m_refreshInterval); config.Save(); } } /// /// Loads saved metadata provider 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 metadata provider is enabled; otherwise False."); settings.Add("RefreshTimeout", m_refreshTimeout, "Number of seconds to wait for metadata refresh to complete."); settings.Add("RefreshInterval", m_refreshInterval, "Interval in minutes at which the metadata is to be refreshed."); Enabled = settings["Enabled"].ValueAs(Enabled); RefreshTimeout = settings["RefreshTimeout"].ValueAs(m_refreshTimeout); RefreshInterval = settings["RefreshInterval"].ValueAs(m_refreshInterval); } } /// /// Refreshes the from an external source. /// /// true if the is refreshed; otherwise false. /// is null. public bool Refresh() { if (!Enabled || (m_refreshThread != null && m_refreshThread.IsAlive)) return false; if (m_metadata == null) throw new ArgumentNullException("Metadata"); m_refreshThread = new Thread(RefreshInternal); m_refreshThread.Start(); if (m_refreshTimeout < 1) { // Wait indefinetely on the refresh. m_refreshThread.Join(Timeout.Infinite); } else { // Wait for the specified time on refresh. if (!m_refreshThread.Join(m_refreshTimeout * 1000)) { m_refreshThread.Abort(); return false; } } return true; } /// /// Releases the unmanaged resources used by the metadata provider 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_refreshThread != null) m_refreshThread.Abort(); if (m_refreshTimer != null) { m_refreshTimer.Elapsed -= RefreshTimer_Elapsed; m_refreshTimer.Dispose(); } } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); } } } /// /// Raises the event. /// protected virtual void OnMetadataRefreshStart() { if (MetadataRefreshStart != null) MetadataRefreshStart(this, EventArgs.Empty); } /// /// Raises the event. /// protected virtual void OnMetadataRefreshComplete() { if (MetadataRefreshComplete != null) MetadataRefreshComplete(this, EventArgs.Empty); } /// /// Raises the event. /// protected virtual void OnMetadataRefreshTimeout() { if (MetadataRefreshTimeout != null) MetadataRefreshTimeout(this, EventArgs.Empty); } /// /// Raises the event. /// /// to send to event. protected virtual void OnMetadataRefreshException(Exception ex) { if (MetadataRefreshException != null) MetadataRefreshException(this, new EventArgs(ex)); } private void RefreshInternal() { try { OnMetadataRefreshStart(); RefreshMetadata(); OnMetadataRefreshComplete(); } catch (ThreadAbortException) { OnMetadataRefreshTimeout(); } catch (Exception ex) { OnMetadataRefreshException(ex); } } private void RefreshTimer_Elapsed(object sender, ElapsedEventArgs e) { Refresh(); } #endregion } }