Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Configuration / System / Configuration / Internal / InternalConfigRoot.cs / 1305376 / InternalConfigRoot.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Configuration.Internal {
using System.Configuration.Internal;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security;
using System.Text;
using System.Xml;
using System.Threading;
//
// InternalConfigRoot holds the root of a configuration hierarchy.
// It managed creation, removal, and the search for BaseConfigurationRecord's.
// in a thread-safe manner.
//
// The BaseConfigurationRecord hierarchy is protected with the
// _hierarchyLock. Functions that assume that the lock as been
// taken begin with the prefix "hl", for example, "hlFindConfigRecord".
//
internal sealed class InternalConfigRoot : IInternalConfigRoot {
IInternalConfigHost _host; // host, need to create records
ReaderWriterLock _hierarchyLock; // lock to protect hierarchy
BaseConfigurationRecord _rootConfigRecord; // root config record, one level above machine.config.
bool _isDesignTime; // Is the hierarchy for runtime or designtime?
private Configuration _CurrentConfiguration = null;
public event InternalConfigEventHandler ConfigChanged;
public event InternalConfigEventHandler ConfigRemoved;
internal InternalConfigRoot() { }
internal InternalConfigRoot(Configuration currentConfiguration) {
_CurrentConfiguration = currentConfiguration;
}
void IInternalConfigRoot.Init(IInternalConfigHost host, bool isDesignTime) {
_host = host;
_isDesignTime = isDesignTime;
_hierarchyLock = new ReaderWriterLock();
// Dummy record to hold _children for root
if (_isDesignTime) {
_rootConfigRecord = MgmtConfigurationRecord.Create(this, null, string.Empty, null);
}
else {
_rootConfigRecord = (BaseConfigurationRecord) RuntimeConfigurationRecord.Create(this, null, string.Empty);
}
}
internal IInternalConfigHost Host {
get {return _host;}
}
internal BaseConfigurationRecord RootConfigRecord {
get {return _rootConfigRecord;}
}
bool IInternalConfigRoot.IsDesignTime {
get {return _isDesignTime;}
}
private void AcquireHierarchyLockForRead() {
// Protect against unexpected recursive entry on this thread.
// We do this in retail, too, because the results would be very bad if this were to fail,
// and the testing for this is not easy for all scenarios.
Debug.Assert(!_hierarchyLock.IsReaderLockHeld, "!_hierarchyLock.IsReaderLockHeld");
if (_hierarchyLock.IsReaderLockHeld) {
throw ExceptionUtil.UnexpectedError("System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForRead - reader lock already held by this thread");
}
Debug.Assert(!_hierarchyLock.IsWriterLockHeld, "!_hierarchyLock.IsWriterLockHeld");
if (_hierarchyLock.IsWriterLockHeld) {
throw ExceptionUtil.UnexpectedError("System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForRead - writer lock already held by this thread");
}
_hierarchyLock.AcquireReaderLock(-1);
}
private void ReleaseHierarchyLockForRead() {
Debug.Assert(!_hierarchyLock.IsWriterLockHeld, "!_hierarchyLock.IsWriterLockHeld");
if (_hierarchyLock.IsReaderLockHeld) {
_hierarchyLock.ReleaseReaderLock();
}
}
private void AcquireHierarchyLockForWrite() {
// Protect against unexpected recursive entry on this thread.
// We do this in retail, too, because the results would be very bad if this were to fail,
// and the testing for this is not easy for all scenarios.
if (_hierarchyLock.IsReaderLockHeld) {
throw ExceptionUtil.UnexpectedError("System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForWrite - reader lock already held by this thread");
}
if (_hierarchyLock.IsWriterLockHeld) {
throw ExceptionUtil.UnexpectedError("System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForWrite - writer lock already held by this thread");
}
_hierarchyLock.AcquireWriterLock(-1);
}
private void ReleaseHierarchyLockForWrite() {
Debug.Assert(!_hierarchyLock.IsReaderLockHeld, "!_hierarchyLock.IsReaderLockHeld");
if (_hierarchyLock.IsWriterLockHeld) {
_hierarchyLock.ReleaseWriterLock();
}
}
//
// Find a config record.
// If found, nextIndex == parts.Length and the resulting record is in currentRecord.
// If not found, nextIndex is the index of the part of the path not found, and currentRecord
// is the record that has been found so far (nexIndex - 1).
//
private void hlFindConfigRecord(string[] parts, out int nextIndex, out BaseConfigurationRecord currentRecord) {
currentRecord = _rootConfigRecord;
nextIndex = 0;
for (; nextIndex < parts.Length; nextIndex++) {
BaseConfigurationRecord childRecord = currentRecord.hlGetChild(parts[nextIndex]);
if (childRecord == null)
break;
currentRecord = childRecord;
}
}
//
// Get a config section.
//
public object GetSection(string section, string configPath) {
BaseConfigurationRecord configRecord = (BaseConfigurationRecord) GetUniqueConfigRecord(configPath);
object result = configRecord.GetSection(section);
return result;
}
//
// Get the nearest ancestor path (including self) which contains unique configuration information.
//
public string GetUniqueConfigPath(string configPath) {
IInternalConfigRecord configRecord = GetUniqueConfigRecord(configPath);
if (configRecord == null) {
return null;
}
return configRecord.ConfigPath;
}
//
// Get the nearest ancestor record (including self) which contains unique configuration information.
//
public IInternalConfigRecord GetUniqueConfigRecord(string configPath) {
BaseConfigurationRecord configRecord = (BaseConfigurationRecord) GetConfigRecord(configPath);
while (configRecord.IsEmpty) {
BaseConfigurationRecord parentConfigRecord = configRecord.Parent;
// If all config records are empty, return the immediate child of the
// root placeholder (e.g. machine.config)
if (parentConfigRecord.IsRootConfig) {
break;
}
configRecord = parentConfigRecord;
}
return configRecord;
}
//
// Get the config record for a path.
// If the record does not exist, create it if it is needed.
//
public IInternalConfigRecord GetConfigRecord(string configPath) {
if (!ConfigPathUtility.IsValid(configPath)) {
throw ExceptionUtil.ParameterInvalid("configPath");
}
string[] parts = ConfigPathUtility.GetParts(configPath);
//
// First search under the reader lock, so that multiple searches
// can proceed in parallel.
//
try {
int index;
BaseConfigurationRecord currentRecord;
AcquireHierarchyLockForRead();
hlFindConfigRecord(parts, out index, out currentRecord);
// check if found
if (index == parts.Length || !currentRecord.hlNeedsChildFor(parts[index])) {
return currentRecord;
}
}
finally {
ReleaseHierarchyLockForRead();
}
//
// Not found, so search again under exclusive writer lock so that
// we can create the record.
//
try {
int index;
BaseConfigurationRecord currentRecord;
AcquireHierarchyLockForWrite();
hlFindConfigRecord(parts, out index, out currentRecord);
if (index == parts.Length) {
return currentRecord;
}
string currentConfigPath = String.Join(BaseConfigurationRecord.ConfigPathSeparatorString, parts, 0, index);
//
// create new records
//
while (index < parts.Length && currentRecord.hlNeedsChildFor(parts[index])) {
string configName = parts[index];
currentConfigPath = ConfigPathUtility.Combine(currentConfigPath, configName);
BaseConfigurationRecord childRecord;
Debug.Trace("ConfigurationCreate", "Creating config record for " + currentConfigPath);
if (_isDesignTime) {
childRecord = MgmtConfigurationRecord.Create(this, currentRecord, currentConfigPath, null);
}
else {
childRecord = (BaseConfigurationRecord) RuntimeConfigurationRecord.Create(this, currentRecord, currentConfigPath);
}
currentRecord.hlAddChild(configName, childRecord);
index++;
currentRecord = childRecord;
}
return currentRecord;
}
finally {
ReleaseHierarchyLockForWrite();
}
}
//
// Find and remove the config record and all its children for the config path.
// Optionally ensure the config record matches a desired config record.
//
void RemoveConfigImpl(string configPath, BaseConfigurationRecord configRecord) {
if (!ConfigPathUtility.IsValid(configPath)) {
throw ExceptionUtil.ParameterInvalid("configPath");
}
string[] parts = ConfigPathUtility.GetParts(configPath);
BaseConfigurationRecord currentRecord;
// search under exclusive writer lock
try {
int index;
AcquireHierarchyLockForWrite();
hlFindConfigRecord(parts, out index, out currentRecord);
// Return if not found, or does not match the one we are trying to remove.
if (index != parts.Length || (configRecord != null && !Object.ReferenceEquals(configRecord, currentRecord)))
return;
// Remove it from the hierarchy.
currentRecord.Parent.hlRemoveChild(parts[parts.Length - 1]);
}
finally {
ReleaseHierarchyLockForWrite();
}
OnConfigRemoved(new InternalConfigEventArgs(configPath));
// Close the record. This is safe to do outside the lock.
currentRecord.CloseRecursive();
}
//
// Find and remove the config record and all its children for the config path.
//
public void RemoveConfig(string configPath) {
RemoveConfigImpl(configPath, null);
}
//
// Remove the config record and all its children for the config path.
//
public void RemoveConfigRecord(BaseConfigurationRecord configRecord) {
RemoveConfigImpl(configRecord.ConfigPath, configRecord);
}
//
// Clear the result of a configSection evaluation at a particular point
// in the hierarchy.
//
public void ClearResult(BaseConfigurationRecord configRecord, string configKey, bool forceEvaluation) {
string[] parts = ConfigPathUtility.GetParts(configRecord.ConfigPath);
try {
int index;
BaseConfigurationRecord currentRecord;
AcquireHierarchyLockForRead();
hlFindConfigRecord(parts, out index, out currentRecord);
// clear result only if configRecord it is still in the hierarchy
if (index == parts.Length && Object.ReferenceEquals(configRecord, currentRecord)) {
currentRecord.hlClearResultRecursive(configKey, forceEvaluation);
}
}
finally {
ReleaseHierarchyLockForRead();
}
}
// Fire the ConfigRemoved event.
private void OnConfigRemoved(InternalConfigEventArgs e) {
InternalConfigEventHandler handler = ConfigRemoved;
if (handler != null) {
handler(this, e);
}
}
// Fire the ConfigChanged event for a configPath.
internal void FireConfigChanged(string configPath) {
OnConfigChanged(new InternalConfigEventArgs(configPath));
}
// Fire the ConfigChanged event.
private void OnConfigChanged(InternalConfigEventArgs e) {
InternalConfigEventHandler handler = ConfigChanged;
if (handler != null) {
handler(this, e);
}
}
internal Configuration CurrentConfiguration {
get {
return _CurrentConfiguration;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XmlSortKey.cs
- TypeContext.cs
- ServiceElementCollection.cs
- RequestUriProcessor.cs
- Math.cs
- QueryCreatedEventArgs.cs
- ClientSponsor.cs
- SerializationAttributes.cs
- DataGridPageChangedEventArgs.cs
- XmlElement.cs
- SafeNativeMethodsCLR.cs
- XmlLoader.cs
- NaturalLanguageHyphenator.cs
- WindowsListViewGroupSubsetLink.cs
- CodeDefaultValueExpression.cs
- ControlEvent.cs
- TemplateNodeContextMenu.cs
- TransactionManagerProxy.cs
- LinearGradientBrush.cs
- ColorPalette.cs
- EntityContainerAssociationSet.cs
- GenericIdentity.cs
- SqlTriggerAttribute.cs
- GroupBoxRenderer.cs
- PolyLineSegment.cs
- Panel.cs
- Operand.cs
- Int32KeyFrameCollection.cs
- SessionPageStatePersister.cs
- SqlTransaction.cs
- TdsParserSafeHandles.cs
- EventHandlerService.cs
- Int32AnimationBase.cs
- LinqDataSourceContextEventArgs.cs
- OracleRowUpdatingEventArgs.cs
- DefaultSerializationProviderAttribute.cs
- DropShadowEffect.cs
- DesignerRegion.cs
- HttpServerChannel.cs
- DesignerEditorPartChrome.cs
- PartitionedStreamMerger.cs
- AudioBase.cs
- StringResourceManager.cs
- TreeViewBindingsEditor.cs
- NeutralResourcesLanguageAttribute.cs
- DataViewSettingCollection.cs
- QilLiteral.cs
- MsmqInputSessionChannelListener.cs
- HtmlHead.cs
- TdsParameterSetter.cs
- ThicknessKeyFrameCollection.cs
- ContainerUIElement3D.cs
- RadioButton.cs
- EmptyStringExpandableObjectConverter.cs
- TargetParameterCountException.cs
- AuthenticationSection.cs
- ThemeDictionaryExtension.cs
- CompiledRegexRunnerFactory.cs
- DoubleLink.cs
- CodeNamespace.cs
- _ScatterGatherBuffers.cs
- InstanceOwnerException.cs
- AppSettingsExpressionBuilder.cs
- WorkflowInspectionServices.cs
- SingleAnimationUsingKeyFrames.cs
- AuthenticationModuleElement.cs
- SqlDataReader.cs
- Vector.cs
- SocketElement.cs
- WebPartEditorOkVerb.cs
- DefaultEventAttribute.cs
- QueryStoreStatusRequest.cs
- TreeViewImageGenerator.cs
- _LocalDataStore.cs
- WindowsTreeView.cs
- ManagementDateTime.cs
- FastEncoderWindow.cs
- ParagraphResult.cs
- BreakRecordTable.cs
- AttachedPropertyBrowsableAttribute.cs
- DropDownButton.cs
- ConfigXmlDocument.cs
- QueryOperationResponseOfT.cs
- UrlAuthorizationModule.cs
- Utilities.cs
- CompensateDesigner.cs
- CommonRemoteMemoryBlock.cs
- ExtenderControl.cs
- HttpConfigurationContext.cs
- InfoCardRSAPKCS1SignatureDeformatter.cs
- WsdlExporter.cs
- FileInfo.cs
- TabControlDesigner.cs
- WebServiceHandlerFactory.cs
- XamlRtfConverter.cs
- ProfileSection.cs
- ClientProxyGenerator.cs
- Number.cs
- FileDialog.cs
- ObjectViewListener.cs