LogRecordSequence Class

LogRecordSequence Class

 

Represents a record sequence stored in a LogStore.

Namespace:   System.IO.Log
Assembly:  System.IO.Log (in System.IO.Log.dll)

System.Object
  System.IO.Log.LogRecordSequence

public sealed class LogRecordSequence : IRecordSequence, IDisposable

NameDescription
System_CAPS_pubmethodLogRecordSequence(LogStore)

Initializes a new instance of the LogRecordSequence class with the specified log store.

System_CAPS_pubmethodLogRecordSequence(LogStore, Int32, Int32)

Initializes a new instance of the LogRecordSequence class with the specified log store, buffer size for each record, and buffer number.

System_CAPS_pubmethodLogRecordSequence(String, FileMode)

Initializes a new instance of the LogRecordSequence class with a specified path to the log store and the access mode.

System_CAPS_pubmethodLogRecordSequence(String, FileMode, FileAccess)

Initializes a new instance of the LogRecordSequence class with a specified path to the log store and the access and share modes.

System_CAPS_pubmethodLogRecordSequence(String, FileMode, FileAccess, FileShare)

Initializes a new instance of the LogRecordSequence class with a specified path to the log store and the access mode.

System_CAPS_pubmethodLogRecordSequence(String, FileMode, FileAccess, FileShare, Int32, Int32)

Initializes a new instance of the LogRecordSequence class with a specified path to the log store, file permission, access and share modes, and the buffer size and count for records.

System_CAPS_pubmethodLogRecordSequence(String, FileMode, FileAccess, FileShare, Int32, Int32, FileSecurity)

Initializes a new instance of the LogRecordSequence class.

NameDescription
System_CAPS_pubpropertyBaseSequenceNumber

Gets the sequence number of the first valid record in the current LogRecordSequence.

System_CAPS_pubpropertyLastSequenceNumber

Gets the sequence number which is greater than the last record appended

System_CAPS_pubpropertyLogStore

Gets the LogStore that contains the data for this record sequence. This method cannot be inherited.

System_CAPS_pubpropertyMaximumRecordLength

Gets the maximum size of a record that can be added to this record sequence.

System_CAPS_pubpropertyReservedBytes

Gets the total number of bytes that have been reserved.

System_CAPS_pubpropertyRestartSequenceNumber

Gets the sequence number of the restart area closest to the end of the log.

System_CAPS_pubpropertyRetryAppend

Gets or sets a value indicating whether or not appends are automatically retried if the log is full.

NameDescription
System_CAPS_pubmethodAdvanceBaseSequenceNumber(SequenceNumber)

Moves the base sequence number of the log forward. This method cannot be inherited.

System_CAPS_pubmethodAppend(ArraySegment<Byte>, SequenceNumber, SequenceNumber, RecordAppendOptions)

Writes a log record to the LogRecordSequence. This method cannot be inherited.

System_CAPS_pubmethodAppend(ArraySegment<Byte>, SequenceNumber, SequenceNumber, RecordAppendOptions, ReservationCollection)

Appends a log record to the IRecordSequence, using space previously reserved in the sequence. This method cannot be inherited.

System_CAPS_pubmethodAppend(IList<ArraySegment<Byte>>, SequenceNumber, SequenceNumber, RecordAppendOptions)

Appends a log record to the IRecordSequence. This method cannot be inherited.

System_CAPS_pubmethodAppend(IList<ArraySegment<Byte>>, SequenceNumber, SequenceNumber, RecordAppendOptions, ReservationCollection)

Appends a log record to the IRecordSequence, using space previously reserved in the sequence. This method cannot be inherited.

System_CAPS_pubmethodBeginAppend(ArraySegment<Byte>, SequenceNumber, SequenceNumber, RecordAppendOptions, AsyncCallback, Object)

Begins an asynchronous append operation. This method cannot be inherited.

System_CAPS_pubmethodBeginAppend(ArraySegment<Byte>, SequenceNumber, SequenceNumber, RecordAppendOptions, ReservationCollection, AsyncCallback, Object)

Begins an asynchronous append operation. This method cannot be inherited.

System_CAPS_pubmethodBeginAppend(IList<ArraySegment<Byte>>, SequenceNumber, SequenceNumber, RecordAppendOptions, AsyncCallback, Object)

Begins an asynchronous append operation. This method cannot be inherited.

System_CAPS_pubmethodBeginAppend(IList<ArraySegment<Byte>>, SequenceNumber, SequenceNumber, RecordAppendOptions, ReservationCollection, AsyncCallback, Object)

Begins an asynchronous append operation. This method cannot be inherited.

System_CAPS_pubmethodBeginFlush(SequenceNumber, AsyncCallback, Object)

Begins an asynchronous flush operation, using space previously reserved in the sequence. This method cannot be inherited.

System_CAPS_pubmethodBeginReserveAndAppend(ArraySegment<Byte>, SequenceNumber, SequenceNumber, RecordAppendOptions, ReservationCollection, Int64[], AsyncCallback, Object)

Begins an asynchronous reserve and append operation. This method cannot be inherited.

System_CAPS_pubmethodBeginReserveAndAppend(IList<ArraySegment<Byte>>, SequenceNumber, SequenceNumber, RecordAppendOptions, ReservationCollection, Int64[], AsyncCallback, Object)

Begins an asynchronous reserve and append operation. This method cannot be inherited.

System_CAPS_pubmethodBeginWriteRestartArea(ArraySegment<Byte>, SequenceNumber, ReservationCollection, AsyncCallback, Object)

Begins an asynchronous restart area write operation, using space previously reserved in the sequence. This method cannot be inherited.

System_CAPS_pubmethodBeginWriteRestartArea(IList<ArraySegment<Byte>>, SequenceNumber, ReservationCollection, AsyncCallback, Object)

Begins an asynchronous restart area write operation, using space previously reserved in the sequence. This method cannot be inherited.

System_CAPS_pubmethodCreateReservationCollection()

Creates a new ReservationCollection. This method cannot be inherited.

System_CAPS_pubmethodDispose()

Releases the resources used by the component.

System_CAPS_pubmethodEndAppend(IAsyncResult)

Ends an asynchronous append operation. This method cannot be inherited.

System_CAPS_pubmethodEndFlush(IAsyncResult)

Ends an asynchronous flush operation. This method cannot be inherited.

System_CAPS_pubmethodEndReserveAndAppend(IAsyncResult)

Ends an asynchronous reserve and append operation. This method cannot be inherited.

System_CAPS_pubmethodEndWriteRestartArea(IAsyncResult)

Ends an asynchronous restart area write operation. This method cannot be inherited.

System_CAPS_pubmethodEquals(Object)

Determines whether the specified object is equal to the current object.(Inherited from Object.)

System_CAPS_pubmethodFlush()

Ensures that all appended records have been written. This method cannot be inherited.

System_CAPS_pubmethodFlush(SequenceNumber)

Ensures that all appended records up to and including the record with the specified sequence number have been durably written. This method cannot be inherited.

System_CAPS_pubmethodGetHashCode()

Serves as the default hash function. (Inherited from Object.)

System_CAPS_pubmethodGetType()

Gets the Type of the current instance.(Inherited from Object.)

System_CAPS_pubmethodReadLogRecords(SequenceNumber, LogRecordEnumeratorType)

Returns an enumerable collection of records in the sequence. This method cannot be inherited.

System_CAPS_pubmethodReadRestartAreas()

Returns an enumerable collection of the restart areas in the sequence. This method cannot be inherited.

System_CAPS_pubmethodReserveAndAppend(ArraySegment<Byte>, SequenceNumber, SequenceNumber, RecordAppendOptions, ReservationCollection, Int64[])

Automatically makes a single reservation and appends a record to the sequence. This method cannot be inherited.

System_CAPS_pubmethodReserveAndAppend(IList<ArraySegment<Byte>>, SequenceNumber, SequenceNumber, RecordAppendOptions, ReservationCollection, Int64[])

Automatically makes a single reservation and appends a record to the sequence. This method cannot be inherited.

System_CAPS_pubmethodSetLastRecord(SequenceNumber)

Sets the last record in the LogRecordSequence.

System_CAPS_pubmethodToString()

Returns a string that represents the current object.(Inherited from Object.)

System_CAPS_pubmethodWriteRestartArea(ArraySegment<Byte>)

Writes a restart area to the LogRecordSequence. This method cannot be inherited.

System_CAPS_pubmethodWriteRestartArea(ArraySegment<Byte>, SequenceNumber)

Writes a restart area to the LogRecordSequence and updates the base sequence number. This method cannot be inherited.

System_CAPS_pubmethodWriteRestartArea(ArraySegment<Byte>, SequenceNumber, ReservationCollection)

Writes a restart area to the LogRecordSequence using a reservation, and updates the base sequence number. This method cannot be inherited.

System_CAPS_pubmethodWriteRestartArea(IList<ArraySegment<Byte>>)

Writes a restart area to the LogRecordSequence. This method cannot be inherited.

System_CAPS_pubmethodWriteRestartArea(IList<ArraySegment<Byte>>, SequenceNumber)

Writes a restart area to the LogRecordSequence and updates the base sequence number. This method cannot be inherited.

System_CAPS_pubmethodWriteRestartArea(IList<ArraySegment<Byte>>, SequenceNumber, ReservationCollection)

Writes a restart area to the LogRecordSequence using a reservation, and updates the base sequence number. This method cannot be inherited.

NameDescription
System_CAPS_pubeventTailPinned

Signals the need to move the tail of the sequence.

The LogRecordSequence class provides an implementation of the record sequence interface on top of a Common Log File System (CLFS) log. In addition to the standard record-oriented features, it provides a policy model for avoiding log-full conditions, and multiplexing of clients on the same physical file. It works with the LogStore class, which provides an interface for directly manipulating and managing a CLFS log file. The relationship between the LogStore class and the LogRecordSequence class is similar to the relationship between a disk file and a FileStream object. The disk file provides the concrete storage, and has attributes such as length and last access time; while the FileStream object provides a view on the file that can be used to read from it and write to it. Similarly, the LogStore class has attributes like a policy and a collection of disk extents; and the LogRecordSequence class provides a record-oriented mechanism for reading and writing data.

This example shows how to use the LogRecordSequence class:

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.IO.Log;

namespace MyLogRecordSequence
{
    public class MyLog
    {
        string logName = "test.log";
        string logContainer = "MyExtent0";
        int containerSize = 32 * 1024;
        LogRecordSequence sequence = null;
        bool delete = true;

        // These are used in the TailPinned event handler.
        public static LogRecordSequence MySequence = null;
        public static bool AdvanceBase = true;

        public MyLog()
        {
            // Create a LogRecordSequence.
            sequence = new LogRecordSequence(this.logName,
                                              FileMode.CreateNew,
                                              FileAccess.ReadWrite,
                                              FileShare.None);

            // At least one container/extent must be added for Log Record Sequence.
            sequence.LogStore.Extents.Add(this.logContainer, this.containerSize);

            MySequence = sequence;

        }

        public void AddExtents()
        {
            // Add two additional extents. The extents are 
            // of the same size as the first extent.
            sequence.LogStore.Extents.Add("MyExtent1");
            sequence.LogStore.Extents.Add("MyExtent2");
        }

        public void EnumerateExtents()
        {
            LogStore store = sequence.LogStore;

            Console.WriteLine("Enumerating Log Extents...");
            Console.WriteLine("    Extent Count: {0} extents", store.Extents.Count);
            Console.WriteLine("    Extents Are...");
            foreach (LogExtent extent in store.Extents)
            {
                Console.WriteLine("      {0} ({1}, {2})",
                                  Path.GetFileName(extent.Path),
                                  extent.Size,
                                  extent.State);
            }
            Console.WriteLine("    Free Extents: {0} Free", store.Extents.FreeCount);   
        }

        public void SetLogPolicy()
        {
            Console.WriteLine();
            Console.WriteLine("Setting current log policy...");

            // SET LOG POLICY

            LogPolicy policy = sequence.LogStore.Policy;

            // Set AutoGrow policy. This enables the log to automatically grow
            // when the existing extents are full. New extents are added until
            // we reach the MaximumExtentCount extents.
            // AutoGrow policy is supported only in Windows Vista and not available in R2.

            //policy.AutoGrow = true;

            // Set the Growth Rate in terms of extents. This policy specifies
            // "how much" the log should grow. 
            policy.GrowthRate = new PolicyUnit(2, PolicyUnitType.Extents);

            // Set the AutoShrink policy. This enables the log to automatically
            // shrink if the available free space exceeds the shrink percentage. 
            // AutoGrow/shrink policy is supported only in Windows Vista and not available in R2.

            //policy.AutoShrinkPercentage = new PolicyUnit(30, PolicyUnitType.Percentage);

            // Set the PinnedTailThreshold policy.
            // A tail pinned event is triggered when there is no
            // log space available and log space may be freed by advancing the base.
            // The user must handle the tail pinned event by advancing the base of the log. 
            // If the user is not able to move the base of the log, the user should report with exception in
            // the tail pinned handler.
            // PinnedTailThreashold policy dictates the amount of space that the TailPinned event requests 
            // for advancing the base of the log. The amount of space can be in percentage or in terms of bytes 
            // which is rounded off to the nearest containers in CLFS. The default is 35 percent.


            policy.PinnedTailThreshold = new PolicyUnit(10, PolicyUnitType.Percentage);

            // Set the maximum extents the log can have.
            policy.MaximumExtentCount = 6;

            // Set the minimum extents the log can have.
            policy.MinimumExtentCount = 2;

            // Set the prefix for new containers that are added. 
            // when AutoGrow is enabled.
            //policy.NewExtentPrefix = "MyLogPrefix";

            // Set the suffix number for new containers that are added.
            // when AutoGrow is enabled. 
            policy.NextExtentSuffix = 3;

            // Commit the log policy.
            policy.Commit();

            // Refresh updates the IO.Log policy properties with current log policy 
            // set in the log. 
            policy.Refresh();

            // LOG POLICY END
            // 

            //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Setting up IO.Log provided capabilities...
            // 

            // SET RETRY APPEND

            // IO.Log provides a mechanism similar to AutoGrow.
            // If the existing log is full and an append fails, setting RetryAppend
            // invokes the CLFS policy engine to add new extents and re-tries
            // record appends. If MaximumExtent count has been reached, 
            // a SequenceFullException is thrown. 
            // 

            sequence.RetryAppend = true;

            // RETRY APPEND END

            // REGISTER FOR TAILPINNED EVENT NOTIFICATIONS

            // Register for TailPinned Event by passing in an event handler.
            // An event is raised when the log full condition is reached.
            // The user should either advance the base sequence number to the 
            // nearest valid sequence number recommended in the tail pinned event or
            // report a failure that it is not able to advance the base sequence 
            // number. 
            //

            sequence.TailPinned += new EventHandler<TailPinnedEventArgs>(HandleTailPinned);  

            Console.WriteLine("Done...");
        }

        public void ShowLogPolicy()
        {
            Console.WriteLine();
            Console.WriteLine("Showing current log policy...");

            LogPolicy policy = sequence.LogStore.Policy;

            Console.WriteLine("    Minimum extent count:  {0}", policy.MinimumExtentCount);
            Console.WriteLine("    Maximum extent count:  {0}", policy.MaximumExtentCount);
            Console.WriteLine("    Growth rate:           {0}", policy.GrowthRate);
            Console.WriteLine("    Pinned tail threshold: {0}", policy.PinnedTailThreshold);
            Console.WriteLine("    Auto shrink percent:   {0}", policy.AutoShrinkPercentage);
            Console.WriteLine("    Auto grow enabled:     {0}", policy.AutoGrow);
            Console.WriteLine("    New extent prefix:     {0}", policy.NewExtentPrefix);
            Console.WriteLine("    Next extent suffix:    {0}", policy.NextExtentSuffix);

	}

        // Append records. Appending three records.  
        public void AppendRecords()
        {
            Console.WriteLine("Appending Log Records...");
            SequenceNumber previous = SequenceNumber.Invalid;

            previous = sequence.Append(CreateData("Hello World!"), SequenceNumber.Invalid, SequenceNumber.Invalid, RecordAppendOptions.ForceFlush);
            previous = sequence.Append(CreateData("This is my first Logging App"), SequenceNumber.Invalid, SequenceNumber.Invalid, RecordAppendOptions.ForceFlush);
            previous = sequence.Append(CreateData("Using LogRecordSequence..."), SequenceNumber.Invalid, SequenceNumber.Invalid, RecordAppendOptions.ForceFlush);

            Console.WriteLine("Done...");
        }


        // Read the records added to the log. 
        public void ReadRecords()
        {
            Encoding enc = Encoding.Unicode;

            Console.WriteLine();

            Console.WriteLine("Reading Log Records...");
            try
            {
                foreach (LogRecord record in this.sequence.ReadLogRecords(this.sequence.BaseSequenceNumber, LogRecordEnumeratorType.Next))
                {
                    byte[] data = new byte[record.Data.Length];
                    record.Data.Read(data, 0, (int)record.Data.Length);
                    string mystr = enc.GetString(data);
                    Console.WriteLine("    {0}", mystr);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception {0} {1}", e.GetType(), e.Message);
            }

            Console.WriteLine();
        }

        public void FillLog()
        {
            bool append = true;

            while (append)
            {
                try
                {
                    sequence.Append(CreateData(16 * 1024), SequenceNumber.Invalid, SequenceNumber.Invalid, RecordAppendOptions.ForceFlush);
                }

                catch (SequenceFullException)
                {
                    Console.WriteLine("Log is Full...");
                    append = false;
                }
            }
        }

        // Dispose the record sequence and delete the log file. 
        public void Cleanup()
        {
            // Dispose the sequence
            sequence.Dispose();

            // Delete the log file.
            if (delete)
            {
                try
                {
                    // This deletes the base log file and all the extents associated with the log.
                    LogStore.Delete(this.logName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception {0} {1}", e.GetType(), e.Message);
                }
            }
        }

        // Converts the given data to an Array of ArraySegment<byte> 
        public static IList<ArraySegment<byte>> CreateData(string str)
        {
            Encoding enc = Encoding.Unicode;

            byte[] array = enc.GetBytes(str);

            ArraySegment<byte>[] segments = new ArraySegment<byte>[1];
            segments[0] = new ArraySegment<byte>(array);

            return Array.AsReadOnly<ArraySegment<byte>>(segments);
        }

        public static IList<ArraySegment<byte>> CreateData(int size)
        {
            byte[] array = new byte[size];

            Random rnd = new Random();
            rnd.NextBytes(array);

            ArraySegment<byte>[] segments = new ArraySegment<byte>[1];
            segments[0] = new ArraySegment<byte>(array);

            return Array.AsReadOnly<ArraySegment<byte>>(segments);
        }

        public static SequenceNumber GetAdvanceBaseSeqNumber(SequenceNumber recTargetSeqNum)
        {
            SequenceNumber targetSequenceNumber = SequenceNumber.Invalid;

            Console.WriteLine("Getting actual target sequence number...");

            // 
            // Implement the logic for returning a valid sequence number closer to
            // recommended target sequence number. 
            //

            return targetSequenceNumber;
        }

        public static void HandleTailPinned(object arg, TailPinnedEventArgs tailPinnedEventArgs)
        {
            Console.WriteLine("TailPinned has fired");

            // Based on the implementation of a logging application, the log base can be moved
            // to free up more log space and if it is not possible to move the 
            // base, the application should report by throwing an exception.

            if(MyLog.AdvanceBase)
            {
                try
                {
                    // TailPnnedEventArgs has the recommended sequence number and its generated 
                    // based on PinnedTailThreshold policy. 
                    // This does not map to an actual sequence number in the record sequence
                    // but an approximation and potentially frees up the threshold % log space
                    // when the log base is advanced to a valid sequence number closer to the 
                    // recommended sequence number. 
                    // The user should use this sequence number to locate a closest valid sequence
                    // number to advance the base of the log.

                    SequenceNumber recommendedTargetSeqNum = tailPinnedEventArgs.TargetSequenceNumber; 

                    // Get the actual Target sequence number.
                    SequenceNumber actualTargetSeqNum = MyLog.GetAdvanceBaseSeqNumber(recommendedTargetSeqNum);

                    MySequence.AdvanceBaseSequenceNumber(actualTargetSeqNum);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception thrown {0} {1}", e.GetType(), e.Message);
                }
            }
            else
            {
                // Report back Error if under some conditions the log cannot
                // advance the base sequence number.

                Console.WriteLine("Reporting Error! Unable to move the base sequence number!");
                throw new IOException();
            }
        }
    }

    class LogSample
    {
        static void Main(string[] args)
        {
            // Create log record sequence.
            MyLog log = new MyLog();

            // Add additional extents.
            log.AddExtents();

            // Enumerate the current log extents.
            log.EnumerateExtents();

            // Set log policies and register for TailPinned event notifications. 
            log.SetLogPolicy();

            log.ShowLogPolicy();

            // Append a few records and read the appended records. 
            log.AppendRecords();
            log.ReadRecords();

            // Fill the Log to trigger log growth...and subsequent TailPinned notifications.
            log.FillLog();

            log.EnumerateExtents();

            log.Cleanup();
        }
    }
}

.NET Framework
Available since 3.0

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Return to top
Show:
© 2016 Microsoft