LogManagementAsyncResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / Log / System / IO / Log / LogManagementAsyncResult.cs / 1 / 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 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 (DiagnosticUtility.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 (DiagnosticUtility.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.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK