LogManagementAsyncResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / 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.

        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

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