Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / peernodestatemanager.cs / 1 / peernodestatemanager.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Collections.Generic; using System.Diagnostics; using System.ServiceModel.Diagnostics; using System.Threading; partial class PeerNodeImplementation { // A simple state manager for the PeerNode. Unlike the state managers used for channels and other // classes, a PeerNode's Open/Close is counted, a PeerNode is re-openable, and Abort only // takes effect if the outstanding number of Opens is 1. // The PeerNode defers to this object for all state related operations. // // Whenever a call is made that may change the state of the object (openCount transitions between 0 and 1), // an operation is queued. When an operation is removed from the queue, if the target state is still the // same as the operation (e.g. openCount > 0 and operation == Open) and the object is not already in that // state, the operation is performed by calling back into the PeerNode // // Because each operation is pulled form the queue one at a time, the open and close of the // PeerNode is serialized class SimpleStateManager { internal enum State { NotOpened, Opening, Opened, Closing }; State currentState = State.NotOpened; object thisLock = new object(); Queuequeue = new Queue (); bool queueRunning; int openCount; PeerNodeImplementation peerNode; public SimpleStateManager(PeerNodeImplementation peerNode) { this.peerNode = peerNode; } object ThisLock { get { return thisLock; } } public void Abort() { lock (ThisLock) { bool runAbort = false; if (openCount <= 1 && currentState != State.NotOpened) { runAbort = true; } if (openCount > 0) { --openCount; } if(runAbort) { try { peerNode.OnAbort(); } finally { currentState = State.NotOpened; } } } } public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state) { CloseOperation op = null; lock (ThisLock) { if (openCount > 0) { --openCount; } if (openCount > 0) { return new CompletedAsyncResult(callback, state); } else { op = new CloseOperation(this, peerNode, timeout, callback, state); queue.Enqueue(op); RunQueue(); } } return op; } public IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state, bool waitForOnline) { bool completedSynchronously = false; OpenOperation op = null; lock (ThisLock) { openCount++; if (openCount > 1 && currentState == State.Opened) { completedSynchronously = true; } else { op = new OpenOperation(this, peerNode, timeout, callback, state, waitForOnline); queue.Enqueue(op); RunQueue(); } } if(completedSynchronously) { return new CompletedAsyncResult(callback, state); } return op; } public void Close(TimeSpan timeout) { EndClose(BeginClose(timeout, null, null)); } public static void EndOpen(IAsyncResult result) { // result can be either an OpenOperation or a CompletedAsyncResult if (result is CompletedAsyncResult) CompletedAsyncResult.End(result); else OpenOperation.End(result); } public static void EndClose(IAsyncResult result) { // result can be either an CloseOperation or a CompletedAsyncResult if (result is CompletedAsyncResult) CompletedAsyncResult.End(result); else CloseOperation.End(result); } // Process IP Address change event from IP helper public void OnIPAddressesChanged(object sender, EventArgs e) { IPAddressChangeOperation op = null; lock (ThisLock) { op = new IPAddressChangeOperation(peerNode); queue.Enqueue(op); RunQueue(); } } public void Open(TimeSpan timeout, bool waitForOnline) { EndOpen(BeginOpen(timeout, null, null, waitForOnline)); } // Start running operations from the queue (must be called within lock) void RunQueue() { if (queueRunning) return; queueRunning = true; IOThreadScheduler.ScheduleCallback(new WaitCallback(RunQueueCallback), null); } void RunQueueCallback(object state) { IOperation op; // remove an operation from the queue lock (ThisLock) { DiagnosticUtility.DebugAssert(queue.Count > 0, "queue should not be empty"); op = queue.Dequeue(); } try { // execute the operation op.Run(); } finally { lock (ThisLock) { // if there are still pending operations, schedule another thread if (queue.Count > 0) { try { IOThreadScheduler.ScheduleCallback(new WaitCallback(RunQueueCallback), null); } catch(Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } } else { queueRunning = false; } } } } interface IOperation { void Run(); } class CloseOperation : OperationBase { PeerNodeImplementation peerNode; public CloseOperation(SimpleStateManager stateManager, PeerNodeImplementation peerNode, TimeSpan timeout, AsyncCallback callback, object state) : base(stateManager, timeout, callback, state) { this.peerNode = peerNode; } protected override void Run() { Exception lclException = null; try { lock (ThisLock) { if (stateManager.openCount > 0) { // the current target state is no longer Closed invokeOperation = false; } else if (stateManager.currentState == State.NotOpened) { // the state is already Closed invokeOperation = false; } else if(timeoutHelper.RemainingTime() <= TimeSpan.Zero) { // Time out has already happened complete will be taken care of in the // OperationBase class invokeOperation = false; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException()); } else { // the PeerNode needs to be closed if (!(stateManager.currentState != State.Opening && stateManager.currentState != State.Closing)) { DiagnosticUtility.DebugAssert("Open and close are serialized by queue We should not be either in Closing or Opening state at this point"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } if(stateManager.currentState != State.NotOpened) { stateManager.currentState = State.Closing; invokeOperation = true; } } } } catch(Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); lclException = e; } if (invokeOperation) { try { peerNode.OnClose(timeoutHelper.RemainingTime()); } catch (Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); lclException = e; } lock (ThisLock) { stateManager.currentState = State.NotOpened; } } Complete(lclException); } } class OpenOperation : OperationBase { PeerNodeImplementation peerNode; bool waitForOnline; public OpenOperation(SimpleStateManager stateManager, PeerNodeImplementation peerNode, TimeSpan timeout, AsyncCallback callback, object state, bool waitForOnline) : base(stateManager, timeout, callback, state) { this.peerNode = peerNode; this.waitForOnline = waitForOnline; } protected override void Run() { Exception lclException = null; try { lock (ThisLock) { if (stateManager.openCount < 1) { // the current target state is no longer Opened invokeOperation = false; } else if (stateManager.currentState == State.Opened) { // the state is already Opened invokeOperation = false; } else if(timeoutHelper.RemainingTime() <= TimeSpan.Zero) { // Time out has already happened complete will be taken care of in the // OperationBase class invokeOperation = false; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException()); } else { // the PeerNode needs to be opened if (!(stateManager.currentState != State.Opening && stateManager.currentState != State.Closing)) { DiagnosticUtility.DebugAssert("Open and close are serialized by queue We should not be either in Closing or Opening state at this point"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } if(stateManager.currentState != State.Opened) { stateManager.currentState = State.Opening; invokeOperation = true; } } } } catch(Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); lclException = e; } if (invokeOperation) { try { peerNode.OnOpen(timeoutHelper.RemainingTime(), waitForOnline); lock (ThisLock) { stateManager.currentState = State.Opened; } } catch(Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; lock (ThisLock) { stateManager.currentState = State.NotOpened; // since Open is throwing, we roll back the openCount because a matching Close is not // expected stateManager.openCount--; } lclException = e; DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } } Complete(lclException); } } // Base class for Open and Cose abstract class OperationBase : AsyncResult, IOperation { protected SimpleStateManager stateManager; protected TimeoutHelper timeoutHelper; AsyncCallback callback; protected bool invokeOperation; bool completed; public OperationBase(SimpleStateManager stateManager, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.stateManager = stateManager; timeoutHelper = new TimeoutHelper(timeout); this.callback = callback; invokeOperation = false; completed = false; } void AsyncComplete(object o) { try { base.Complete(false, (Exception)o); } catch(Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(SR.GetString(SR.AsyncCallbackException), e); } } protected abstract void Run(); void IOperation.Run() { Run(); } protected void Complete(Exception exception) { if(completed) { return; } lock(ThisLock) { if(completed) { return; } completed = true; } try { if (callback != null) { // complete the AsyncResult on a separate thread so that the queue can progress. // this prevents a deadlock when the callback attempts to call Close. // this may cause the callbacks to be called in a differnet order in which they completed, but that // is ok because each callback is associated with a different object (channel or listener factory) IOThreadScheduler.ScheduleCallback(new WaitCallback(AsyncComplete), exception); } else { AsyncComplete(exception); } } catch(Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(SR.GetString(SR.MessagePropagationException), e); } } protected object ThisLock { get { return stateManager.thisLock; } } static public void End(IAsyncResult result) { AsyncResult.End (result); } } // To serialize IP address change processing class IPAddressChangeOperation : IOperation { PeerNodeImplementation peerNode; public IPAddressChangeOperation(PeerNodeImplementation peerNode) { this.peerNode = peerNode; } void IOperation.Run() { peerNode.OnIPAddressChange(); } } } } } // 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
- HttpResponseBase.cs
- ExceptionUtil.cs
- XamlWrapperReaders.cs
- VariantWrapper.cs
- MultiPageTextView.cs
- DatatypeImplementation.cs
- RawKeyboardInputReport.cs
- PointHitTestResult.cs
- RegexMatchCollection.cs
- ExpandCollapseProviderWrapper.cs
- EncodingDataItem.cs
- documentsequencetextcontainer.cs
- ResourceDictionaryCollection.cs
- OleDbFactory.cs
- MouseBinding.cs
- HttpRawResponse.cs
- DependencyPropertyAttribute.cs
- URLMembershipCondition.cs
- SSmlParser.cs
- AutomationPropertyInfo.cs
- SymLanguageVendor.cs
- ComplexLine.cs
- ClonableStack.cs
- ProfileModule.cs
- webproxy.cs
- Brush.cs
- TypedTableBaseExtensions.cs
- DockPatternIdentifiers.cs
- KeyInterop.cs
- UnmanagedMarshal.cs
- MergeFailedEvent.cs
- ContentIterators.cs
- ClientTargetSection.cs
- TriState.cs
- DataViewListener.cs
- ColumnMap.cs
- FamilyTypeface.cs
- SqlGatherConsumedAliases.cs
- Translator.cs
- Behavior.cs
- PointLight.cs
- FixedSOMTableRow.cs
- Span.cs
- ReferenceAssemblyAttribute.cs
- StringAnimationBase.cs
- ImmComposition.cs
- ControlBuilderAttribute.cs
- RadialGradientBrush.cs
- ComAdminInterfaces.cs
- DataGridViewSortCompareEventArgs.cs
- CapabilitiesSection.cs
- WebConfigurationManager.cs
- RotateTransform3D.cs
- DurableTimerExtension.cs
- SafeNativeMethods.cs
- PropertyValueChangedEvent.cs
- NodeLabelEditEvent.cs
- XmlWrappingReader.cs
- BinaryCommonClasses.cs
- Label.cs
- ModelFunctionTypeElement.cs
- MaskPropertyEditor.cs
- TypeGeneratedEventArgs.cs
- Stack.cs
- HttpPostProtocolImporter.cs
- DefaultShape.cs
- __TransparentProxy.cs
- StateMachineWorkflowDesigner.cs
- CqlQuery.cs
- AutoResizedEvent.cs
- CharKeyFrameCollection.cs
- IConvertible.cs
- SchemaMapping.cs
- TimerExtension.cs
- cookieexception.cs
- TypeNameConverter.cs
- AssemblyUtil.cs
- WpfPayload.cs
- SymLanguageType.cs
- HostedTransportConfigurationManager.cs
- TheQuery.cs
- VerificationException.cs
- HttpProcessUtility.cs
- ImmutableAssemblyCacheEntry.cs
- CustomErrorCollection.cs
- CollectionViewProxy.cs
- OdbcTransaction.cs
- GuidConverter.cs
- IntSecurity.cs
- ObjectListItem.cs
- RenderContext.cs
- Baml6Assembly.cs
- TraceInternal.cs
- XmlMapping.cs
- CapabilitiesRule.cs
- ConcurrentBag.cs
- RemotingSurrogateSelector.cs
- DefaultTraceListener.cs
- DataGridViewCellCollection.cs
- Compiler.cs