Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / PeerResolvers / CustomPeerResolverService.cs / 1 / CustomPeerResolverService.cs
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.PeerResolvers
{
using System;
using System.ServiceModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.Net.Security;
using System.ServiceModel.Configuration;
using System.ServiceModel.Channels;
using System.Threading;
[ServiceBehavior(UseSynchronizationContext = false, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class CustomPeerResolverService : IPeerResolverContract
{
internal enum RegistrationState
{
OK, Deleted
}
internal class RegistrationEntry
{
Guid clientId;
Guid registrationId;
string meshId;
DateTime expires;
PeerNodeAddress address;
RegistrationState state;
public RegistrationEntry(Guid clientId, Guid registrationId, string meshId, DateTime expires, PeerNodeAddress address)
{
this.ClientId = clientId;
this.RegistrationId = registrationId;
this.MeshId = meshId;
this.Expires = expires;
this.Address = address;
this.State = RegistrationState.OK;
}
public Guid ClientId
{
get { return clientId; }
set { clientId = value; }
}
public Guid RegistrationId
{
get { return registrationId; }
set { registrationId = value; }
}
public string MeshId
{
get { return meshId; }
set { meshId = value; }
}
public DateTime Expires
{
get { return expires; }
set { expires = value; }
}
public PeerNodeAddress Address
{
get { return address; }
set { address = value; }
}
public RegistrationState State
{
get { return state; }
set { state = value; }
}
}
internal class LiteLock
{
bool forWrite;
bool upgraded;
ReaderWriterLock locker;
TimeSpan timeout = TimeSpan.FromMinutes(1);
LockCookie lc ;
LiteLock(ReaderWriterLock locker, bool forWrite)
{
this.locker = locker;
this.forWrite = forWrite;
}
public static void Acquire(out LiteLock liteLock, ReaderWriterLock locker)
{
Acquire(out liteLock, locker, false);
}
public static void Acquire(out LiteLock liteLock, ReaderWriterLock locker, bool forWrite)
{
LiteLock theLock = new LiteLock(locker, forWrite);
try { }
finally
{
if(forWrite)
{
locker.AcquireWriterLock(theLock.timeout);
}
else
{
locker.AcquireReaderLock(theLock.timeout);
}
liteLock = theLock;
}
}
public static void Release(LiteLock liteLock)
{
if (liteLock == null)
{
return;
}
if(liteLock.forWrite)
{
liteLock.locker.ReleaseWriterLock();
}
else
{
DiagnosticUtility.DebugAssert(!liteLock.upgraded, "Can't release while upgraded!");
liteLock.locker.ReleaseReaderLock();
}
}
public void UpgradeToWriterLock()
{
DiagnosticUtility.DebugAssert(!forWrite, "Invalid call to Upgrade!!");
DiagnosticUtility.DebugAssert(!upgraded, "Already upgraded!");
try { }
finally
{
lc = locker.UpgradeToWriterLock(timeout);
upgraded = true;
}
}
public void DowngradeFromWriterLock()
{
DiagnosticUtility.DebugAssert(!forWrite, "Invalid call to Downgrade!!");
if (upgraded)
{
locker.DowngradeFromWriterLock(ref lc);
upgraded = false;
}
}
}
internal class MeshEntry
{
Dictionary entryTable;
Dictionary service2EntryTable;
List entryList;
ReaderWriterLock gate;
internal MeshEntry()
{
EntryTable = new Dictionary();
Service2EntryTable = new Dictionary();
EntryList = new List();
Gate = new ReaderWriterLock();
}
public Dictionary EntryTable
{
get { return entryTable; }
set { entryTable = value; }
}
public Dictionary Service2EntryTable
{
get { return service2EntryTable; }
set { service2EntryTable = value; }
}
public List EntryList
{
get { return entryList; }
set { entryList = value; }
}
public ReaderWriterLock Gate
{
get { return gate; }
set { gate = value; }
}
}
Dictionary meshId2Entry = new Dictionary();
ReaderWriterLock gate;
TimeSpan timeout = TimeSpan.FromMinutes(1);
TimeSpan cleanupInterval = TimeSpan.FromMinutes(1);
TimeSpan refreshInterval = TimeSpan.FromMinutes(10);
bool controlShape;
bool isCleaning;
IOThreadTimer timer;
object thisLock = new object();
bool opened;
TimeSpan LockWait = TimeSpan.FromSeconds(5);
public CustomPeerResolverService()
{
isCleaning = false;
gate = new ReaderWriterLock();
}
public TimeSpan CleanupInterval
{
get
{
return cleanupInterval;
}
set
{
if (value < TimeSpan.Zero)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
SR.GetString(SR.SFxTimeoutOutOfRange0)));
}
if (TimeoutHelper.IsTooLarge(value))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
}
lock (ThisLock)
{
ThrowIfOpened("Set CleanupInterval");
this.cleanupInterval = value;
}
}
}
public TimeSpan RefreshInterval
{
get
{
return refreshInterval;
}
set
{
if (value < TimeSpan.Zero)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
SR.GetString(SR.SFxTimeoutOutOfRange0)));
}
if (TimeoutHelper.IsTooLarge(value))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
}
lock (ThisLock)
{
ThrowIfOpened("Set RefreshInterval");
this.refreshInterval = value;
}
}
}
public bool ControlShape
{
get
{
return this.controlShape;
}
set
{
lock (ThisLock)
{
ThrowIfOpened("Set ControlShape");
this.controlShape = value;
}
}
}
MeshEntry GetMeshEntry(string meshId){return GetMeshEntry(meshId,true);}
MeshEntry GetMeshEntry(string meshId, bool createIfNotExists)
{
MeshEntry meshEntry = null;
LiteLock ll = null;
try
{
LiteLock.Acquire(out ll, gate);
if(!this.meshId2Entry.TryGetValue(meshId, out meshEntry) && createIfNotExists)
{
meshEntry = new MeshEntry();
try
{
ll.UpgradeToWriterLock();
meshId2Entry.Add(meshId,meshEntry);
}
finally
{
ll.DowngradeFromWriterLock();
}
}
}
finally
{
LiteLock.Release(ll);
}
DiagnosticUtility.DebugAssert(meshEntry != null || !createIfNotExists, "GetMeshEntry failed to get an entry!");
return meshEntry;
}
public virtual RegisterResponseInfo Register(Guid clientId, string meshId, PeerNodeAddress address)
{
Guid registrationId = Guid.NewGuid();
DateTime expiry = DateTime.UtcNow + RefreshInterval;
RegistrationEntry entry = null;
MeshEntry meshEntry = null;
lock (ThisLock)
{
entry = new RegistrationEntry(clientId, registrationId, meshId, expiry, address);
meshEntry = GetMeshEntry(meshId);
if(meshEntry.Service2EntryTable.ContainsKey(address.ServicePath))
PeerExceptionHelper.ThrowInvalidOperation_DuplicatePeerRegistration(address.ServicePath);
LiteLock ll = null;
try
{
LiteLock.Acquire(out ll, meshEntry.Gate, true);
meshEntry.EntryTable.Add(registrationId,entry);
meshEntry.EntryList.Add(entry);
meshEntry.Service2EntryTable.Add(address.ServicePath, entry);
}
finally
{
LiteLock.Release(ll);
}
}
return new RegisterResponseInfo(registrationId, RefreshInterval);
}
public virtual RegisterResponseInfo Register(RegisterInfo registerInfo)
{
if (registerInfo == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("registerInfo", SR.GetString(SR.PeerNullRegistrationInfo));
}
ThrowIfClosed("Register");
if (!registerInfo.HasBody() || String.IsNullOrEmpty(registerInfo.MeshId))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("registerInfo", SR.GetString(SR.PeerInvalidMessageBody, registerInfo));
}
return Register(registerInfo.ClientId, registerInfo.MeshId, registerInfo.NodeAddress);
}
public virtual RegisterResponseInfo Update(UpdateInfo updateInfo)
{
if (updateInfo == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("updateInfo", SR.GetString(SR.PeerNullRegistrationInfo));
}
ThrowIfClosed("Update");
if(!updateInfo.HasBody() || String.IsNullOrEmpty(updateInfo.MeshId) || updateInfo.NodeAddress == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("updateInfo", SR.GetString(SR.PeerInvalidMessageBody, updateInfo));
}
Guid registrationId = updateInfo.RegistrationId;
RegistrationEntry entry;
MeshEntry meshEntry = GetMeshEntry(updateInfo.MeshId);
LiteLock ll = null;
//handle cases when Update races with Register.
if (updateInfo.RegistrationId == Guid.Empty || meshEntry == null)
return Register(updateInfo.ClientId, updateInfo.MeshId, updateInfo.NodeAddress);
try
{
LiteLock.Acquire(out ll, meshEntry.Gate);
if(!meshEntry.EntryTable.TryGetValue(updateInfo.RegistrationId, out entry))
return Register(updateInfo.ClientId, updateInfo.MeshId, updateInfo.NodeAddress);
lock(entry)
{
entry.Address = updateInfo.NodeAddress;
entry.Expires = DateTime.UtcNow + this.RefreshInterval;
}
}
finally
{
LiteLock.Release(ll);
}
return new RegisterResponseInfo(registrationId, RefreshInterval);
}
public virtual ResolveResponseInfo Resolve(ResolveInfo resolveInfo)
{
if (resolveInfo == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("resolveInfo", SR.GetString(SR.PeerNullResolveInfo));
}
ThrowIfClosed("Resolve");
if(!resolveInfo.HasBody())
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("resolveInfo", SR.GetString(SR.PeerInvalidMessageBody, resolveInfo));
}
int currentCount=0;
int index=0;
int maxEntries = resolveInfo.MaxAddresses;
ResolveResponseInfo response = new ResolveResponseInfo();
List results = new List();
List entries = null;
PeerNodeAddress address;
RegistrationEntry entry;
MeshEntry meshEntry = GetMeshEntry(resolveInfo.MeshId, false);
if(meshEntry != null)
{
LiteLock ll = null;
try
{
LiteLock.Acquire(out ll, meshEntry.Gate);
entries = meshEntry.EntryList;
if(entries.Count <= maxEntries)
{
foreach(RegistrationEntry e in entries)
{
results.Add(e.Address);
}
}
else
{
Random random = new Random();
while(currentCount keys = null;
LiteLock ll = null;
try
{
LiteLock.Acquire(out ll, gate);
keys = meshId2Entry.Keys;
}
finally
{
LiteLock.Release(ll);
}
foreach(string meshId in keys)
{
meshEntry = GetMeshEntry(meshId);
CleanupMeshEntry(meshEntry);
}
}
finally
{
isCleaning = false;
if(opened)
timer.Set(this.CleanupInterval);
}
}
}
}
}
//always call this from a readlock
void CleanupMeshEntry(MeshEntry meshEntry)
{
List remove = new List();
if(!opened)
return;
LiteLock ll = null;
try
{
LiteLock.Acquire(out ll, meshEntry.Gate, true);
foreach(KeyValuePair item in meshEntry.EntryTable)
{
if((item.Value.Expires <= DateTime.UtcNow)|| (item.Value.State == RegistrationState.Deleted))
{
remove.Add(item.Key);
meshEntry.EntryList.Remove(item.Value);
meshEntry.Service2EntryTable.Remove(item.Value.Address.ServicePath);
}
}
foreach(Guid id in remove)
{
meshEntry.EntryTable.Remove(id);
}
}
finally
{
LiteLock.Release(ll);
}
}
object ThisLock
{
get
{
return this.thisLock;
}
}
void ThrowIfOpened(string operation)
{
if (opened)
PeerExceptionHelper.ThrowInvalidOperation_NotValidWhenOpen(operation);
}
void ThrowIfClosed(string operation)
{
if (!opened)
PeerExceptionHelper.ThrowInvalidOperation_NotValidWhenClosed(operation);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PenThreadWorker.cs
- BindingExpression.cs
- TextElementCollectionHelper.cs
- FacetValues.cs
- SqlTriggerContext.cs
- EmbeddedMailObjectsCollection.cs
- Normalizer.cs
- QilGeneratorEnv.cs
- DrawingContext.cs
- WpfSharedBamlSchemaContext.cs
- SharedStatics.cs
- ModulesEntry.cs
- PenThread.cs
- ViewCellSlot.cs
- TableCell.cs
- SamlSecurityToken.cs
- PrtCap_Reader.cs
- OrderedDictionary.cs
- URLMembershipCondition.cs
- PriorityChain.cs
- RectangleHotSpot.cs
- _HTTPDateParse.cs
- InvalidOperationException.cs
- Substitution.cs
- PropertyChangeTracker.cs
- BrushMappingModeValidation.cs
- AppDomainProtocolHandler.cs
- SimpleParser.cs
- NetworkStream.cs
- CopyNamespacesAction.cs
- TransformValueSerializer.cs
- DataControlButton.cs
- ChtmlTextBoxAdapter.cs
- RoleServiceManager.cs
- RestHandler.cs
- TdsParserHelperClasses.cs
- DataServiceQueryException.cs
- processwaithandle.cs
- StringTraceRecord.cs
- InfoCardRSAPKCS1KeyExchangeDeformatter.cs
- InternalMappingException.cs
- CodeExporter.cs
- DoWhileDesigner.xaml.cs
- NameTable.cs
- SortedSet.cs
- ImageAutomationPeer.cs
- CompressEmulationStream.cs
- FormClosingEvent.cs
- Clock.cs
- MenuCommands.cs
- PersonalizationState.cs
- MenuDesigner.cs
- ComplusEndpointConfigContainer.cs
- ResizingMessageFilter.cs
- ExpressionWriter.cs
- AliasExpr.cs
- ControlType.cs
- DefaultTextStoreTextComposition.cs
- StrokeRenderer.cs
- FormViewUpdateEventArgs.cs
- Path.cs
- ModulesEntry.cs
- EffectiveValueEntry.cs
- CalendarDay.cs
- NumberFormatInfo.cs
- BindingValueChangedEventArgs.cs
- RelationshipDetailsCollection.cs
- RtType.cs
- WebEventTraceProvider.cs
- RoutedUICommand.cs
- ConfigXmlSignificantWhitespace.cs
- SqlConnectionString.cs
- SystemNetworkInterface.cs
- BoundsDrawingContextWalker.cs
- EntityConnectionStringBuilderItem.cs
- ItemChangedEventArgs.cs
- CounterSet.cs
- DataGridViewRowCancelEventArgs.cs
- WindowsButton.cs
- ArrangedElement.cs
- QueryResult.cs
- DynamicEntity.cs
- DiscardableAttribute.cs
- DataTemplate.cs
- Point3DCollection.cs
- EventLogPermissionAttribute.cs
- ContextMenu.cs
- TextElementEnumerator.cs
- SimpleFileLog.cs
- ProxyGenerationError.cs
- SqlReferenceCollection.cs
- AdRotatorDesigner.cs
- TemplateXamlTreeBuilder.cs
- IBuiltInEvidence.cs
- ProcessRequestArgs.cs
- SqlFormatter.cs
- TableDetailsCollection.cs
- DataGridViewCellCancelEventArgs.cs
- BufferedReadStream.cs
- TdsParameterSetter.cs