Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Log / System / IO / Log / LogManagementAsyncResult.cs / 1305376 / LogManagementAsyncResult.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.IO.Log { using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Threading; using System.Runtime; using Microsoft.Win32.SafeHandles; delegate void HandleLogFullCallback(uint errorCode); sealed class LogManagementAsyncResult : OverlappedAsyncResult { LogStore logStore; CLFS_MGMT_NOTIFICATION notification; bool registered = false; bool active = false; // CLFS will hang if the user doesn't advance the base of the log or report failure to // to advance the base of the log in a tail pinned event. If user does any other append // in tail pinned event, the user will not be able to append subsequently. A conservative // timeout is used to break this hang in the event user ends up doing an append in tail pinned event. const int MaxLogFullNotificationTimeOut = 30000; // In milli seconds... arbitrary. ListhandleLogFullCallbackList; internal LogManagementAsyncResult(LogStore logStore) : base(null, null) { this.logStore = logStore; this.notification = new CLFS_MGMT_NOTIFICATION(); this.handleLogFullCallbackList = null; } object SyncRoot { get { return this.notification; } } event EventHandler InternalTailPinned; public event EventHandler TailPinned { add { EnsureStarted(); InternalTailPinned += value; } remove { InternalTailPinned -= value; } } public uint HandleLogFull(HandleLogFullCallback callback) { ManualResetEvent doneEvent = null; uint queuedErrorCode = Error.ERROR_SUCCESS; if (callback == null) { doneEvent = new ManualResetEvent(false); callback = delegate(uint code) { queuedErrorCode = code; doneEvent.Set(); }; } uint errorCode = Error.ERROR_IO_PENDING; lock(this.SyncRoot) { EnsureStarted(); if (this.handleLogFullCallbackList == null) { this.handleLogFullCallbackList = new List (); errorCode = UnsafeNativeMethods.HandleLogFull( this.logStore.Handle); if (errorCode != Error.ERROR_IO_PENDING) { return errorCode; } } this.handleLogFullCallbackList.Add(callback); } if (doneEvent != null) { if(doneEvent.WaitOne(MaxLogFullNotificationTimeOut, false)) { // Got ClfsMgmtLogFullHandlerNotification notification from CLFS errorCode = queuedErrorCode; } else { // Time out! We never got ClfsMgmtLogFullHandlerNotification notification from CLFS! // Remove the Callback from the Callback list. lock(this.SyncRoot) { this.handleLogFullCallbackList.Remove(callback); } errorCode = Error.ERROR_LOG_FULL; } doneEvent.Close(); } return errorCode; } internal override void IOCompleted(uint errorCode) { // We get ERROR_OPERATION_ABORTED here if the handle is // closed. // if (errorCode == Error.ERROR_OPERATION_ABORTED) return; try { HandleNotification(errorCode); lock(this.SyncRoot) { if (this.active) { // There is no synchronous return path for this call. // We don't need to call Free() in a finally block, // because any exception will failfast the process Pack(this.notification); unsafe { UnsafeNativeMethods.ReadLogNotification( this.logStore.Handle, this.notification, NativeOverlapped); } } } } #pragma warning suppress 56500 // We will be terminating the process with any exception in this call catch(Exception e) { // I don't know what to do with errors here... if I // can't re-issue a read, when will I get new // notifications? // // If ReadLogNotification fails, we cannot continue to process CLFS notifications. // There is really nothing we can do to continue executing correctly. DiagnosticUtility.InvokeFinalHandler(e); } } void EnsureStarted() { if (!this.registered) { UnsafeNativeMethods.RegisterManageableLogClient( this.logStore.Handle, IntPtr.Zero); this.registered = true; } if (!this.active) { bool throwing = true; try { Pack(this.notification); unsafe { UnsafeNativeMethods.ReadLogNotification( this.logStore.Handle, this.notification, NativeOverlapped); } throwing = false; } finally { if (throwing) { Free(); } } this.active = true; } } void HandleLogFullComplete(uint errorCode) { List callbacks; lock(this.SyncRoot) { callbacks = this.handleLogFullCallbackList; this.handleLogFullCallbackList = null; } try { foreach(HandleLogFullCallback callback in callbacks) { callback(errorCode); } } #pragma warning suppress 56500 // This is a callback exception catch(Exception e) { if (Fx.IsFatal(e)) throw; throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e); } } void HandleNotification(uint errorCode) { CLFS_MGMT_NOTIFICATION_TYPE nt; nt = (CLFS_MGMT_NOTIFICATION_TYPE)this.notification.Notification; switch(nt) { case CLFS_MGMT_NOTIFICATION_TYPE.ClfsMgmtAdvanceTailNotification: if (errorCode == Error.ERROR_SUCCESS) { HandleTailPinned(); } else { // Errr... what? } break; case CLFS_MGMT_NOTIFICATION_TYPE.ClfsMgmtLogFullHandlerNotification: HandleLogFullComplete(errorCode); break; case CLFS_MGMT_NOTIFICATION_TYPE.ClfsMgmtLogUnpinnedNotification: // Don't do anything right now. break; } } void HandleTailPinned() { TailPinnedEventArgs args; SequenceNumber targetLsn; targetLsn = new SequenceNumber(this.notification.Lsn); args = new TailPinnedEventArgs(targetLsn); EventHandler handler; handler = this.InternalTailPinned; if (handler != null) { try { handler(this, args); } #pragma warning suppress 56500 // This is a callback exception catch(Exception e) { try { int errorCode = Marshal.GetHRForException(e); UnsafeNativeMethods.LogTailAdvanceFailure(this.logStore.Handle, errorCode); } #pragma warning suppress 56500 // We will be terminating the process with any exception in this call catch(Exception exception) { // If LogTailAdvanceFailure fails, there's nothing we can do to recover. // If we keep executing, the log's tail will be pinned forever. // CLFS will never know that we have finished with its notification. DiagnosticUtility.InvokeFinalHandler(exception); } if (Fx.IsFatal(e)) throw; } } else { // User hasn't subscribed to TailPinnned. If RetryAppend is true, IO.Log will register for // notification and invoke CLFS policy to handle LogFull Condition. // IO.Log must report to CLFS that the log tail cannot be advanced. CLFS expects either // base to be advanced or report the failure else it will hang waiting for the outcome. // try { UnsafeNativeMethods.LogTailAdvanceFailure(this.logStore.Handle, 0); } #pragma warning suppress 56500 // We will be terminating the process with any exception in this call catch(Exception exception) { // If LogTailAdvanceFailure fails, there's nothing we can do to recover. // If we keep executing, the log's tail will be pinned forever. // CLFS will never know that we have finished with its notification. DiagnosticUtility.InvokeFinalHandler(exception); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.IO.Log { using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Threading; using System.Runtime; using Microsoft.Win32.SafeHandles; delegate void HandleLogFullCallback(uint errorCode); sealed class LogManagementAsyncResult : OverlappedAsyncResult { LogStore logStore; CLFS_MGMT_NOTIFICATION notification; bool registered = false; bool active = false; // CLFS will hang if the user doesn't advance the base of the log or report failure to // to advance the base of the log in a tail pinned event. If user does any other append // in tail pinned event, the user will not be able to append subsequently. A conservative // timeout is used to break this hang in the event user ends up doing an append in tail pinned event. const int MaxLogFullNotificationTimeOut = 30000; // In milli seconds... arbitrary. List handleLogFullCallbackList; internal LogManagementAsyncResult(LogStore logStore) : base(null, null) { this.logStore = logStore; this.notification = new CLFS_MGMT_NOTIFICATION(); this.handleLogFullCallbackList = null; } object SyncRoot { get { return this.notification; } } event EventHandler InternalTailPinned; public event EventHandler TailPinned { add { EnsureStarted(); InternalTailPinned += value; } remove { InternalTailPinned -= value; } } public uint HandleLogFull(HandleLogFullCallback callback) { ManualResetEvent doneEvent = null; uint queuedErrorCode = Error.ERROR_SUCCESS; if (callback == null) { doneEvent = new ManualResetEvent(false); callback = delegate(uint code) { queuedErrorCode = code; doneEvent.Set(); }; } uint errorCode = Error.ERROR_IO_PENDING; lock(this.SyncRoot) { EnsureStarted(); if (this.handleLogFullCallbackList == null) { this.handleLogFullCallbackList = new List (); errorCode = UnsafeNativeMethods.HandleLogFull( this.logStore.Handle); if (errorCode != Error.ERROR_IO_PENDING) { return errorCode; } } this.handleLogFullCallbackList.Add(callback); } if (doneEvent != null) { if(doneEvent.WaitOne(MaxLogFullNotificationTimeOut, false)) { // Got ClfsMgmtLogFullHandlerNotification notification from CLFS errorCode = queuedErrorCode; } else { // Time out! We never got ClfsMgmtLogFullHandlerNotification notification from CLFS! // Remove the Callback from the Callback list. lock(this.SyncRoot) { this.handleLogFullCallbackList.Remove(callback); } errorCode = Error.ERROR_LOG_FULL; } doneEvent.Close(); } return errorCode; } internal override void IOCompleted(uint errorCode) { // We get ERROR_OPERATION_ABORTED here if the handle is // closed. // if (errorCode == Error.ERROR_OPERATION_ABORTED) return; try { HandleNotification(errorCode); lock(this.SyncRoot) { if (this.active) { // There is no synchronous return path for this call. // We don't need to call Free() in a finally block, // because any exception will failfast the process Pack(this.notification); unsafe { UnsafeNativeMethods.ReadLogNotification( this.logStore.Handle, this.notification, NativeOverlapped); } } } } #pragma warning suppress 56500 // We will be terminating the process with any exception in this call catch(Exception e) { // I don't know what to do with errors here... if I // can't re-issue a read, when will I get new // notifications? // // If ReadLogNotification fails, we cannot continue to process CLFS notifications. // There is really nothing we can do to continue executing correctly. DiagnosticUtility.InvokeFinalHandler(e); } } void EnsureStarted() { if (!this.registered) { UnsafeNativeMethods.RegisterManageableLogClient( this.logStore.Handle, IntPtr.Zero); this.registered = true; } if (!this.active) { bool throwing = true; try { Pack(this.notification); unsafe { UnsafeNativeMethods.ReadLogNotification( this.logStore.Handle, this.notification, NativeOverlapped); } throwing = false; } finally { if (throwing) { Free(); } } this.active = true; } } void HandleLogFullComplete(uint errorCode) { List callbacks; lock(this.SyncRoot) { callbacks = this.handleLogFullCallbackList; this.handleLogFullCallbackList = null; } try { foreach(HandleLogFullCallback callback in callbacks) { callback(errorCode); } } #pragma warning suppress 56500 // This is a callback exception catch(Exception e) { if (Fx.IsFatal(e)) throw; throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e); } } void HandleNotification(uint errorCode) { CLFS_MGMT_NOTIFICATION_TYPE nt; nt = (CLFS_MGMT_NOTIFICATION_TYPE)this.notification.Notification; switch(nt) { case CLFS_MGMT_NOTIFICATION_TYPE.ClfsMgmtAdvanceTailNotification: if (errorCode == Error.ERROR_SUCCESS) { HandleTailPinned(); } else { // Errr... what? } break; case CLFS_MGMT_NOTIFICATION_TYPE.ClfsMgmtLogFullHandlerNotification: HandleLogFullComplete(errorCode); break; case CLFS_MGMT_NOTIFICATION_TYPE.ClfsMgmtLogUnpinnedNotification: // Don't do anything right now. break; } } void HandleTailPinned() { TailPinnedEventArgs args; SequenceNumber targetLsn; targetLsn = new SequenceNumber(this.notification.Lsn); args = new TailPinnedEventArgs(targetLsn); EventHandler handler; handler = this.InternalTailPinned; if (handler != null) { try { handler(this, args); } #pragma warning suppress 56500 // This is a callback exception catch(Exception e) { try { int errorCode = Marshal.GetHRForException(e); UnsafeNativeMethods.LogTailAdvanceFailure(this.logStore.Handle, errorCode); } #pragma warning suppress 56500 // We will be terminating the process with any exception in this call catch(Exception exception) { // If LogTailAdvanceFailure fails, there's nothing we can do to recover. // If we keep executing, the log's tail will be pinned forever. // CLFS will never know that we have finished with its notification. DiagnosticUtility.InvokeFinalHandler(exception); } if (Fx.IsFatal(e)) throw; } } else { // User hasn't subscribed to TailPinnned. If RetryAppend is true, IO.Log will register for // notification and invoke CLFS policy to handle LogFull Condition. // IO.Log must report to CLFS that the log tail cannot be advanced. CLFS expects either // base to be advanced or report the failure else it will hang waiting for the outcome. // try { UnsafeNativeMethods.LogTailAdvanceFailure(this.logStore.Handle, 0); } #pragma warning suppress 56500 // We will be terminating the process with any exception in this call catch(Exception exception) { // If LogTailAdvanceFailure fails, there's nothing we can do to recover. // If we keep executing, the log's tail will be pinned forever. // CLFS will never know that we have finished with its notification. DiagnosticUtility.InvokeFinalHandler(exception); } } } } } // 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
- HtmlForm.cs
- StringFunctions.cs
- DesignerActionVerbItem.cs
- IApplicationTrustManager.cs
- DataColumnPropertyDescriptor.cs
- ContactManager.cs
- WindowsRichEdit.cs
- PrinterResolution.cs
- OleDbRowUpdatedEvent.cs
- ItemsChangedEventArgs.cs
- _AuthenticationState.cs
- RoleServiceManager.cs
- ConvertTextFrag.cs
- TreeNode.cs
- XmlSchemaParticle.cs
- CacheRequest.cs
- WorkflowInvoker.cs
- ContractType.cs
- XsdDataContractImporter.cs
- OleDbStruct.cs
- ReverseQueryOperator.cs
- BuildManager.cs
- ScrollableControl.cs
- RefreshInfo.cs
- StateManagedCollection.cs
- AttachedPropertyBrowsableForTypeAttribute.cs
- StylusButtonCollection.cs
- TreeViewEvent.cs
- PerspectiveCamera.cs
- ControlBuilder.cs
- FactoryGenerator.cs
- TextTrailingCharacterEllipsis.cs
- DelegateSerializationHolder.cs
- HotSpot.cs
- TreeNodeSelectionProcessor.cs
- HMACSHA384.cs
- DataGridViewRowHeaderCell.cs
- baseaxisquery.cs
- IconHelper.cs
- GeneralTransform3D.cs
- ClientEventManager.cs
- OperationAbortedException.cs
- ToolStripDropDownClosingEventArgs.cs
- DataTableMappingCollection.cs
- SelectingProviderEventArgs.cs
- SqlDataSourceStatusEventArgs.cs
- HtmlTableCellCollection.cs
- CodeTypeDelegate.cs
- MarkupProperty.cs
- IconConverter.cs
- UnmanagedMarshal.cs
- RelatedCurrencyManager.cs
- columnmapfactory.cs
- CodeTypeDeclaration.cs
- Behavior.cs
- EntityWrapperFactory.cs
- ButtonChrome.cs
- SpeechSeg.cs
- StrongNamePublicKeyBlob.cs
- DesignBindingEditor.cs
- NamespaceCollection.cs
- DefaultBindingPropertyAttribute.cs
- EditModeSwitchButton.cs
- WebPartVerbsEventArgs.cs
- DataObjectPastingEventArgs.cs
- SerializationObjectManager.cs
- HMACSHA384.cs
- FileLoadException.cs
- CodeThrowExceptionStatement.cs
- OpCellTreeNode.cs
- LongValidator.cs
- CodeNamespace.cs
- DataGridViewTextBoxCell.cs
- UpdateCommand.cs
- SqlMethodAttribute.cs
- ImageSourceConverter.cs
- PeerEndPoint.cs
- WebCategoryAttribute.cs
- TypeHelpers.cs
- EventMappingSettingsCollection.cs
- IPipelineRuntime.cs
- DBCommand.cs
- DataGridViewAddColumnDialog.cs
- TitleStyle.cs
- TypeContext.cs
- XmlSchemaObject.cs
- SecurityContextKeyIdentifierClause.cs
- Literal.cs
- CheckBoxField.cs
- DataRowChangeEvent.cs
- AutomationAttributeInfo.cs
- DynamicResourceExtension.cs
- EventSinkHelperWriter.cs
- RSAPKCS1KeyExchangeFormatter.cs
- TextRangeSerialization.cs
- EmbeddedObject.cs
- DbResourceAllocator.cs
- ItemCollection.cs
- StringUtil.cs
- ArgumentNullException.cs