示例#1
0
 void InvalidateMarshalContext()
 {
     lock (this.store.SyncRoot)
     {
         if (this.marshalContext != null)
         {
             this.marshalContext.Close();
             this.marshalContext = null;
         }
     }
 }
示例#2
0
        void EnsureMarshalContext()
        {
            // NOTE: Simple synchronization here may cause problems. I
            //       am counting on the unfairness of the lock object to
            //       make this fast enough.
            //
            lock (this.store.SyncRoot)
            {
                if ((this.marshalContext != null) &&
                    (!this.marshalContext.IsInvalid))
                {
                    return;
                }

                try
                {
                    this.marshalContext =
                        UnsafeNativeMethods.CreateLogMarshallingArea(
                            this.store.Handle,
                            IntPtr.Zero,
                            IntPtr.Zero,
                            IntPtr.Zero,
                            this.bufferSize,
                            this.writeBufferCount,
                            DefaultReadBufferCount);
                }
                catch (InvalidOperationException)
                {
                    if (this.store.Extents.Count == 0)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                  Error.InvalidOperation(SR.InvalidOperation_MustHaveExtents));
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
        protected override void FreeReservation(long size)
        {
            if (size < 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentOutOfRange("size"));
            }

            lock (this.recordSequence.LogStore.SyncRoot)
            {
                SafeMarshalContext context = this.recordSequence.InternalMarshalContext;

                if (context == null || context.IsInvalid)
                {
                    return;
                }

                // Reservation coming from collection, add record header
                // size.
                //
                size += LogLogRecordHeader.Size;

                long aligned;
                UnsafeNativeMethods.AlignReservedLogSingle(
                    context,
                    size,
                    out aligned);

                // Adjustment must be negative, otherwise it's considered
                // a "set".  (Yuck.)
                //
                aligned = -aligned;
                UnsafeNativeMethods.FreeReservedLog(
                    context,
                    1,
                    ref aligned);
            }
        }
        public static void AlignReservedLogSingle(SafeMarshalContext pvMarshal,
                                                  long reservation,
                                                  out long pcbAlignReservation)
        {
            if (!_AlignReservedLogSingle(pvMarshal,
                                         1,
                                         ref reservation,
                                         out pcbAlignReservation))
            {
                uint errorCode = (uint)Marshal.GetLastWin32Error();
                switch (errorCode)
                {
                    case Error.ERROR_INVALID_HANDLE:
                    case Error.ERROR_INVALID_PARAMETER:
                    case Error.ERROR_IO_DEVICE:
                    case Error.ERROR_LOG_RESERVATION_INVALID:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForKnownCode(errorCode));

                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForUnknownCode(errorCode));
                }
            }
        }
        public static void FreeReservedLog(SafeMarshalContext pvMarshal,
                                           uint cReservedRecords,
                                           ref long pcbAdjustment)
        {
            if (!_FreeReservedLog(pvMarshal,
                                  cReservedRecords,
                                  ref pcbAdjustment))
            {
                uint errorCode = (uint)Marshal.GetLastWin32Error();
                switch (errorCode)
                {
                    case Error.ERROR_NO_SYSTEM_RESOURCES:
                    case Error.ERROR_LOG_FULL:
                    case Error.ERROR_INVALID_HANDLE:
                    case Error.ERROR_ACCESS_DENIED:
                    case Error.ERROR_INVALID_PARAMETER:
                    case Error.ERROR_IO_DEVICE:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForKnownCode(errorCode));

                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForUnknownCode(errorCode));
                }
            }
        }
        public static void FlushLogToLsnSync(
            SafeMarshalContext pvMarshalContext,
            ref ulong plsnFlush,
            out ulong plsnLastFlushed)
        {
            if (!_FlushLogToLsnSync(pvMarshalContext,
                                    ref plsnFlush,
                                    out plsnLastFlushed,
                                    null))
            {
                uint errorCode = (uint)Marshal.GetLastWin32Error();
                if (errorCode == Error.ERROR_IO_PENDING)
                {
                    // The CLFS API was called with a NULL overlapped, so the operation should not be asynchronous.
                    // This means that CLFS has a bug, so it is not safe to continue processing.
                    DiagnosticUtility.FailFast("Unexpected IO in progress (FlushToLsnSync)");
                }
                switch (errorCode)
                {
                    case Error.ERROR_INVALID_HANDLE:
                    case Error.ERROR_ACCESS_DENIED:
                    case Error.ERROR_INVALID_PARAMETER:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForKnownCode(errorCode));

                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForUnknownCode(errorCode));
                }
            }
        }
        public static uint FlushLogToLsnAsync(
            SafeMarshalContext pvMarshalContext,
            ref ulong plsnFlush,
            IntPtr plsnLastFlushed,
            NativeOverlapped* overlapped)
        {
            uint errorCode = Error.ERROR_SUCCESS;
            if (!_FlushLogToLsnAsync(pvMarshalContext,
                                     ref plsnFlush,
                                     plsnLastFlushed,
                                     overlapped))
            {
                errorCode = (uint)Marshal.GetLastWin32Error();
            }

            return errorCode;
        }
        public static void AdvanceLogBaseSync(
            SafeMarshalContext pvMarshal,
            [In] ref ulong plsnBase,
            int fFlags)
        {
            if (!_AdvanceLogBase(pvMarshal, ref plsnBase, fFlags, null))
            {
                uint errorCode = (uint)Marshal.GetLastWin32Error();
                switch (errorCode)
                {
                    case Error.ERROR_NO_SYSTEM_RESOURCES:
                    case Error.ERROR_LOG_FULL:
                    case Error.ERROR_INVALID_HANDLE:
                    case Error.ERROR_ACCESS_DENIED:
                    case Error.ERROR_IO_DEVICE:
                    case Error.ERROR_INVALID_PARAMETER:
                    case Error.ERROR_LOG_TAIL_INVALID:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForKnownCode(errorCode));

                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForUnknownCode(errorCode));
                }
            }
        }
 extern static bool _CreateLogMarshallingArea(
     SafeFileHandle hLog,
     IntPtr pfnAllocBuffer,
     IntPtr pfnFreeBuffer,
     IntPtr pvBlockAllocContext,
     int cbMarshallingBlock,
     int cMaxWriteBlocks,
     int cMaxReadBlocks,
     out SafeMarshalContext ppvMarshal);
 extern static bool _WriteLogRestartArea(
     SafeMarshalContext pvMarshal,
     byte* pvRestartBuffer,
     int cbRestartBuffer,
     [In] ref ulong plsnBase,
     int fFlags,
     IntPtr pcbWritten, // int*
     IntPtr plsnRestart, // ulong*
     NativeOverlapped* pOverlapped);
        public static uint ReserveAndAppendLog(
            SafeMarshalContext pvMarshal,
            CLFS_WRITE_ENTRY[] rgWriteEntries,
            int cWriteEntries,
            [In] ref ulong plsnUndoNext,
            [In] ref ulong plsnPrevious,
            int cReserveRecords,
            long[] rgcbReservation,
            int fFlags,
            IntPtr plsn,
            NativeOverlapped* pOverlapped)
        {
            uint errorCode = Error.ERROR_SUCCESS;
            if (!_ReserveAndAppendLog(pvMarshal,
                                      rgWriteEntries,
                                      cWriteEntries,
                                      ref plsnUndoNext,
                                      ref plsnPrevious,
                                      cReserveRecords,
                                      rgcbReservation,
                                      fFlags,
                                      plsn,
                                      pOverlapped))
            {
                errorCode = (uint)Marshal.GetLastWin32Error();
            }

            return errorCode;
        }
 extern static bool _ReadLogRecord(
     SafeMarshalContext pvMarshal,
     [In] ref ulong plsnFirst,
     CLFS_CONTEXT_MODE ecxMode,
     out byte* ppvReadBuffer,
     out int pcbReadBuffer,
     out byte peRecordType,
     out ulong plsnUndoNext,
     out ulong plsnPrevious,
     out SafeReadContext ppvReadContext,
     NativeOverlapped* pOverlapped);
 extern static bool _ReserveAndAppendLog(
     SafeMarshalContext pvMarshal,
     CLFS_WRITE_ENTRY[] rgWriteEntries,
     int cWriteEntries,
     [In] ref ulong plsnUndoNext,
     [In] ref ulong plsnPrevious,
     int cReserveRecords,
     long[] rgcbReservation,
     int fFlags,
     IntPtr plsn,
     NativeOverlapped* pOverlapped);
 extern static bool _ReadLogRestartArea(
     SafeMarshalContext pvMarshal,
     out byte* ppvRestartBuffer,
     out int pcbRestartBuffer,
     out ulong plsn,
     out SafeReadContext ppvContext,
     NativeOverlapped* overlapped);
 extern static bool _FreeReservedLog(
     SafeMarshalContext pvMarshal,
     uint cReservedRecords,
     [In] ref long pcbAdjustment);
 extern static bool _AlignReservedLogSingle(
     SafeMarshalContext pvMarshal,
     int cReservedRecords,
     ref long rgcbReservation,
     out long pcbAlignReservation);
        public static bool ReadLogRestartAreaSync(
            SafeMarshalContext pvMarshal,
            out byte* ppvRestartBuffer,
            out int pcbRestartBuffer,
            out ulong plsn,
            out SafeReadContext ppvContext)
        {
            if (!_ReadLogRestartArea(pvMarshal,
                                     out ppvRestartBuffer,
                                     out pcbRestartBuffer,
                                     out plsn,
                                     out ppvContext,
                                     null))
            {
                uint errorCode = (uint)Marshal.GetLastWin32Error();
                Utility.CloseInvalidOutSafeHandle(ppvContext);
                ppvContext = null;
                if (errorCode == Error.ERROR_IO_PENDING)
                {
                    // The CLFS API was called with a NULL overlapped, so the operation should not be asynchronous.
                    // This means that CLFS has a bug, so it is not safe to continue processing.
                    DiagnosticUtility.FailFast("Unexpected IO in progress (ReadLogRA)");
                }
                switch (errorCode)
                {
                    case Error.ERROR_LOG_NO_RESTART:
                        return false;

                    case Error.ERROR_LOG_BLOCK_INCOMPLETE:
                    case Error.ERROR_INVALID_HANDLE:
                    case Error.ERROR_ACCESS_DENIED:
                    case Error.ERROR_INVALID_PARAMETER:
                    case Error.ERROR_IO_DEVICE:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForKnownCode(errorCode));

                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForUnknownCode(errorCode));
                }
            }

            return true;
        }
 extern static bool _WriteLogRestartAreaNoBase(
     SafeMarshalContext pvMarshal,
     byte* pvRestartBuffer,
     int cbRestartBuffer,
     IntPtr mustBeZero,
     int fFlags,
     IntPtr pcbWritten, // int*
     IntPtr plsnRestart, // ulong*
     NativeOverlapped* pOverlapped);
        public static bool ReadLogRecordSync(SafeMarshalContext pvMarshal,
                                             [In] ref ulong plsnFirst,
                                             CLFS_CONTEXT_MODE ecxMode,
                                             out byte* ppvReadBuffer,
                                             out int pcbReadBuffer,
                                             out byte peRecordType,
                                             out ulong plsnUndoNext,
                                             out ulong plsnPrevious,
                                             out SafeReadContext ppvReadContext)
        {
            if (!_ReadLogRecord(pvMarshal,
                                ref plsnFirst,
                                ecxMode,
                                out ppvReadBuffer,
                                out pcbReadBuffer,
                                out peRecordType,
                                out plsnUndoNext,
                                out plsnPrevious,
                                out ppvReadContext,
                                null))
            {
                uint errorCode = (uint)Marshal.GetLastWin32Error();
                Utility.CloseInvalidOutSafeHandle(ppvReadContext);
                ppvReadContext = null;
                if (errorCode == Error.ERROR_IO_PENDING)
                {
                    // The CLFS API was called with a NULL overlapped, so the operation should not be asynchronous.
                    // This means that CLFS has a bug, so it is not safe to continue processing.
                    DiagnosticUtility.FailFast("No async in ReadLogRecordSync");
                }
                switch (errorCode)
                {
                    case Error.ERROR_HANDLE_EOF:
                        return false;

                    case Error.ERROR_NOT_FOUND:
                    case Error.ERROR_LOG_START_OF_LOG:
                    case Error.ERROR_LOG_BLOCK_INVALID:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.Argument_InvalidStartSequenceNumber));

                    case Error.ERROR_LOG_BLOCK_INCOMPLETE:
                    case Error.ERROR_INVALID_HANDLE:
                    case Error.ERROR_ACCESS_DENIED:
                    case Error.ERROR_INVALID_PARAMETER:
                    case Error.ERROR_IO_DEVICE:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForKnownCode(errorCode));

                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForUnknownCode(errorCode));
                }
            }

            return true;
        }
        public static void TruncateLogSync(SafeMarshalContext pvMarshal,
                                           ref ulong plsnEnd)
        {
            if (!_TruncateLog(pvMarshal, ref plsnEnd, null))
            {
                uint errorCode = (uint)Marshal.GetLastWin32Error();
                if (errorCode == Error.ERROR_IO_PENDING)
                {
                    // The CLFS API was called with a NULL overlapped, so the operation should not be asynchronous.
                    // This means that CLFS has a bug, so it is not safe to continue processing.
                    DiagnosticUtility.FailFast("No async in TruncateLogSync");
                }
                switch (errorCode)
                {
                    case Error.ERROR_LOG_START_OF_LOG:
                    case Error.ERROR_LOG_BLOCK_INVALID:
                    case Error.ERROR_LOG_SECTOR_PARITY_INVALID:
                    case Error.ERROR_HANDLE_EOF:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.Argument_InvalidSequenceNumber));

                    case Error.ERROR_LOG_METADATA_CORRUPT:
                    case Error.ERROR_INVALID_HANDLE:
                    case Error.ERROR_ACCESS_DENIED:
                    case Error.ERROR_INVALID_PARAMETER:
                    case Error.ERROR_LOG_INVALID_RANGE:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForKnownCode(errorCode));

                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ExceptionForUnknownCode(errorCode));
                }
            }
        }
        public static uint WriteLogRestartArea(SafeMarshalContext pvMarshal,
                                               byte* pvRestartBuffer,
                                               int cbRestartBuffer,
                                               [In] ref ulong plsnBase,
                                               int fFlags,
                                               IntPtr pcbWritten, // int*
                                               IntPtr plsnRestart, // ulong*
                                               NativeOverlapped* pOverlapped)
        {
            uint errorCode = Error.ERROR_SUCCESS;
            if (!_WriteLogRestartArea(pvMarshal,
                                      pvRestartBuffer,
                                      cbRestartBuffer,
                                      ref plsnBase,
                                      fFlags,
                                      pcbWritten,
                                      plsnRestart,
                                      pOverlapped))
            {
                errorCode = (uint)Marshal.GetLastWin32Error();
            }

            return errorCode;
        }
 extern static bool _AdvanceLogBase(
     SafeMarshalContext pvMarshal,
     [In] ref ulong plsnBase,
     int fFlags,
     NativeOverlapped* pOverlapped);
 extern static bool _TruncateLog(SafeMarshalContext pvMarshal,
                                 [In] ref ulong plsnEnd,
                                 NativeOverlapped* lpOverlapped);
 extern static bool _FlushLogToLsnAsync(
     SafeMarshalContext pvMarshalContext,
     [In] ref ulong plsnFlush,
     IntPtr plsnLastFlushed,
     NativeOverlapped* overlapped);