[Mono-devel-list] proposed patch for System.Configuration.ConfigurationSetting
eric lindvall
eric at 5stops.com
Wed Nov 19 12:35:37 EST 2003
sorry, forgot to cvs update first.
e.
On Wed, 19 Nov 2003, Gonzalo Paniagua Javier wrote:
> El mié, 19-11-2003 a las 07:07, eric lindvall escribió:
> > I noticed that with the last fixes for ConfigurationSetting (adding
> > caching) ends up not being very multi-threaded-friendly.
> >
> > This patch includes general cleanup with the biggest changes being
> > removing a lot of the redundant locks, making use of using() statements
> > (to make sure we don't leak any fd's), and generaly tried to clarify the
> > code.
>
> The patch does not apply cleanly to CVS. Could you send a patch that
> fixes this?
>
> -Gonzalo
>
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
-------------- next part --------------
Index: class/System/System.Configuration/ConfigurationSettings.cs
===================================================================
RCS file: /mono/mcs/class/System/System.Configuration/ConfigurationSettings.cs,v
retrieving revision 1.29
diff -u -p -u -r1.29 ConfigurationSettings.cs
--- class/System/System.Configuration/ConfigurationSettings.cs 17 Nov 2003 22:53:17 -0000 1.29
+++ class/System/System.Configuration/ConfigurationSettings.cs 19 Nov 2003 17:35:05 -0000
@@ -17,21 +17,19 @@ using System.IO;
using System.Runtime.CompilerServices;
using System.Xml;
using System.Xml.XPath;
+using System.Threading;
namespace System.Configuration
{
public sealed class ConfigurationSettings
{
- static IConfigurationSystem config;
-
private ConfigurationSettings ()
{
}
public static object GetConfig (string sectionName)
{
- if (config == null)
- config = DefaultConfig.GetInstance ();
+ IConfigurationSystem config = DefaultConfig.GetInstance ();
return config.GetConfig (sectionName);
}
@@ -39,14 +37,15 @@ namespace System.Configuration
public static NameValueCollection AppSettings
{
get {
- object appSettings = GetConfig ("appSettings");
+ NameValueCollection appSettings =
+ (NameValueCollection) GetConfig ("appSettings");
+
if (appSettings == null)
appSettings = new NameValueCollection ();
- return (NameValueCollection) appSettings;
+ return appSettings;
}
}
-
}
//
@@ -55,58 +54,55 @@ namespace System.Configuration
//
class DefaultConfig : IConfigurationSystem
{
- static object creatingInstance = new object ();
- static object buildingData = new object ();
- static DefaultConfig instance;
+ static object instance = null;
ConfigurationData config;
private DefaultConfig ()
{
+ this.Init();
}
public static DefaultConfig GetInstance ()
{
if (instance == null) {
- lock (creatingInstance) {
+ lock (typeof (DefaultConfig)) {
if (instance == null) {
- instance = new DefaultConfig ();
- instance.Init ();
+ Interlocked.Exchange (
+ ref instance, new DefaultConfig());
}
-
}
}
- return instance;
+ return ((DefaultConfig) instance);
}
public object GetConfig (string sectionName)
{
- if (config == null)
- return null;
+ if (config == null)
+ {
+ throw (new InvalidOperationException ("ConfigurationSettings not initialized."));
+ }
return config.GetConfig (sectionName);
}
public void Init ()
{
- if (config == null){
- lock (buildingData) {
- if (config != null)
- return;
-
- ConfigurationData data = new ConfigurationData ();
- if (data.Load (GetMachineConfigPath ())) {
- ConfigurationData appData = new ConfigurationData (data);
- appData.Load (GetAppConfigPath ());
- config = appData;
- } else {
- Console.WriteLine ("** Warning **: cannot find " + GetMachineConfigPath ());
- Console.WriteLine ("Trying to load app config file...");
- data.Load (GetAppConfigPath ());
- config = data;
- }
- }
- }
+ try
+ {
+ ConfigurationData data = new ConfigurationData (GetMachineConfigPath ());
+ ConfigurationData appData = new ConfigurationData (GetAppConfigPath (), data);
+ config = appData;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine ("** Warning **: cannot find " +
+ GetMachineConfigPath () + ": " + e.Message);
+ Console.WriteLine ("Trying to load app config file...");
+
+ ConfigurationData data = new ConfigurationData (GetAppConfigPath ());
+ config = data;
+ }
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -126,7 +122,6 @@ namespace System.Configuration
return null;
return configFile;
-
}
}
@@ -188,56 +183,31 @@ namespace System.Configuration
static object removedMark = new object ();
static object groupMark = new object ();
static object emptyMark = new object ();
- FileWatcherCache fileCache = null;
+ FileWatcherCache fileCache;
- private FileWatcherCache FileCache {
- get {
- if (fileCache == null) {
- if (fileName != null) {
- fileCache = new FileWatcherCache (fileName);
- } else {
- fileCache = parent.FileCache;
- }
- }
-
- return fileCache;
- }
- }
-
- public ConfigurationData () : this (null)
- {
- }
-
- public ConfigurationData (ConfigurationData parent)
+ public ConfigurationData (string fileName) : this (fileName, null)
{
- this.parent = (parent == this) ? null : parent;
- factories = new Hashtable ();
}
- public bool Load (string fileName)
+ public ConfigurationData (string fileName, ConfigurationData parent)
{
- if (fileName == null || !File.Exists (fileName))
- return false;
+ if (fileName == null)
+ {
+ throw (new ArgumentNullException ("fileName"));
+ }
this.fileName = fileName;
- XmlTextReader reader = null;
+ this.fileCache = new FileWatcherCache (fileName);
+ this.parent = (parent == this) ? null : parent;
+ factories = new Hashtable ();
- try {
- try {
- FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read);
- reader = new XmlTextReader (fs);
- } catch (Exception) {
- return false;
- }
+ using (FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read))
+ {
+ XmlTextReader reader = new XmlTextReader (fs);
InitRead (reader);
ReadConfigFile (reader);
- } finally {
- if (reader != null)
- reader.Close();
- }
-
- return true;
+ }
}
object GetHandler (string sectionName)
@@ -246,8 +216,8 @@ namespace System.Configuration
if (o == null || o == removedMark) {
if (parent != null)
return parent.GetHandler (sectionName);
-
- return null;
+ else
+ return null;
}
if (o is IConfigurationSectionHandler)
@@ -271,50 +241,44 @@ namespace System.Configuration
}
//TODO: Should use XPath when it works properly for this.
- XmlDocument GetDocumentForSection (string sectionName)
+ private XmlDocument GetDocumentForSection (string sectionName)
{
- if (fileName == null || !File.Exists (fileName))
- return null;
-
- XmlTextReader reader = null;
- try {
- FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read);
- reader = new XmlTextReader (fs);
- } catch {
- return null;
- }
-
- ConfigXmlDocument doc = new ConfigXmlDocument ();
- InitRead (reader);
- string [] sectionPath = sectionName.Split ('/');
- int i = 0;
- if (!reader.EOF) {
- if (reader.Name == "configSections")
- reader.Skip ();
-
- while (!reader.EOF) {
- if (reader.NodeType == XmlNodeType.Element &&
- reader.Name == sectionPath [i]) {
- if (++i == sectionPath.Length) {
- doc.LoadSingleElement (fileName, reader);
- break;
- }
- MoveToNextElement (reader);
- continue;
- }
- reader.Skip ();
- if (reader.NodeType != XmlNodeType.Element)
- MoveToNextElement (reader);
- }
- }
+ using (FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read))
+ {
+ XmlTextReader reader = new XmlTextReader (fs);
+
+ ConfigXmlDocument doc = new ConfigXmlDocument ();
+ InitRead (reader);
+ string [] sectionPath = sectionName.Split ('/');
+ int i = 0;
+ if (!reader.EOF) {
+ if (reader.Name == "configSections")
+ reader.Skip ();
+
+ while (!reader.EOF) {
+ if (reader.NodeType == XmlNodeType.Element &&
+ reader.Name == sectionPath [i]) {
+ if (++i == sectionPath.Length) {
+ doc.LoadSingleElement (fileName, reader);
+ break;
+ }
+ MoveToNextElement (reader);
+ continue;
+ }
+ reader.Skip ();
+ if (reader.NodeType != XmlNodeType.Element)
+ MoveToNextElement (reader);
+ }
+ }
- reader.Close ();
- return doc;
+ return doc;
+ }
}
- object GetConfigInternal (string sectionName)
+ private object GetConfigInternal (string sectionName)
{
object handler = GetHandler (sectionName);
+
if (handler == null)
return null;
@@ -322,6 +286,7 @@ namespace System.Configuration
return handler;
object parentConfig = null;
+
if (parent != null)
parentConfig = parent.GetConfig (sectionName);
@@ -329,8 +294,8 @@ namespace System.Configuration
if (doc == null || doc.DocumentElement == null) {
if (parentConfig == null)
return null;
-
- return parentConfig;
+ else
+ return parentConfig;
}
return ((IConfigurationSectionHandler) handler).Create (parentConfig, fileName, doc.DocumentElement);
@@ -338,17 +303,20 @@ namespace System.Configuration
public object GetConfig (string sectionName)
{
- object config = this.FileCache [sectionName];
+ lock (this)
+ {
+ object config = this.fileCache [sectionName];
- if (config == emptyMark)
- return null;
+ if (config == emptyMark)
+ return null;
- if (config != null)
- return config;
+ if (config != null)
+ return config;
- config = GetConfigInternal (sectionName);
- this.FileCache [sectionName] = (config == null) ? emptyMark : config;
- return config;
+ config = GetConfigInternal (sectionName);
+ this.fileCache [sectionName] = (config == null) ? emptyMark : config;
+ return config;
+ }
}
private object LookForFactory (string key)
More information about the Mono-devel-list
mailing list