System.IO.Log中的日志记录支持

System.IO.Log命名空间定义用于登录到面向记录的顺序I/O系统的接口.
可以实现自己的诊断日志记录系统或事务处理系统,以便实现事务持久性.

system.io.log.dll 的默认位置为 %programfiles%\Reference Assemblies\Microsoft\Framework\v3.0\
简单文件日志系统
描述FileRecordSequence类型,该类型是基于文件系统中的单一日志文件的记录序列.它是在IRecordSequence接口在基于简单文件的日志上简单实现.
public sealed class FileRecordSequence : IRecordSequence,IDisposable
例子:

代码
public   class  MyLog
{
      
string  logName  =   " test.log " ;
      FileRecordSequence sequence 
=   null ;
      
bool  delete  =   true ;
      
public  MyLog()
      {
                sequence 
=  New FileRecordSequence(logName);
       }
      
      
public   void  AppendRecords()
      {
             SequenceNumber previous 
=  SequenceNumber.Invalid;
             previous 
=  sequence.Append(CreateData( " Hello Wordl! " ), SequenceNumber.Invalid,SequenceNumber.Invalid,RecordAppendOption.ForceFlush);
      }

    
public   void  ReadRecords()
    {
             Encoding enc 
=  Encoding.Unicode;
             
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);
             }
     }
     
public   void  Cleanup()
     {
            sequence.Dispose();
            
if (delete)
            {
             
try {  File.Delete( this .logName); }
             
catch (Exception e) {}
            }
     }
      
// 把str转成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);
      }
}

LogRecordSequence 类提供记录序列接口在公用日志文件系统 (CLFS) 日志之上的实现。除了标准的面向记录的功能,此类还提供一个策略模型,用于避免出现日志满的状况并允许多个客户端复用同一个物理文件。它与 LogStore 类一起使用,该类提供了直接操作和管理 CLFS 日志文件的接口。LogStore 类和 LogRecordSequence 类之间的关系类似于磁盘文件和 FileStream 对象之间的关系。磁盘文件提供实际存储区,并具有长度和上次访问时间等属性,而 FileStream 对象提供文件的视图,可用来在实际存储区中读取和写入数据。与之类似,LogStore 类具有策略和磁盘范围集合等属性;而 LogRecordSequence 类提供面向记录的数据读取和写入机制。

 

代码
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 rand 
=   new  Random();
            rand.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();
        }
    }
}

 

 

你可能感兴趣的:(System)