?? fileappender.cs
字號:
#region Copyright & License
//
// Copyright 2001-2006 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.IO;
using System.Text;
using log4net.Util;
using log4net.Layout;
using log4net.Core;
namespace log4net.Appender
{
/// <summary>
/// Appends logging events to a file.
/// </summary>
/// <remarks>
/// <para>
/// Logging events are sent to the file specified by
/// the <see cref="File"/> property.
/// </para>
/// <para>
/// The file can be opened in either append or overwrite mode
/// by specifying the <see cref="AppendToFile"/> property.
/// If the file path is relative it is taken as relative from
/// the application base directory. The file encoding can be
/// specified by setting the <see cref="Encoding"/> property.
/// </para>
/// <para>
/// The layout's <see cref="ILayout.Header"/> and <see cref="ILayout.Footer"/>
/// values will be written each time the file is opened and closed
/// respectively. If the <see cref="AppendToFile"/> property is <see langword="true"/>
/// then the file may contain multiple copies of the header and footer.
/// </para>
/// <para>
/// This appender will first try to open the file for writing when <see cref="ActivateOptions"/>
/// is called. This will typically be during configuration.
/// If the file cannot be opened for writing the appender will attempt
/// to open the file again each time a message is logged to the appender.
/// If the file cannot be opened for writing when a message is logged then
/// the message will be discarded by this appender.
/// </para>
/// <para>
/// The <see cref="FileAppender"/> supports pluggable file locking models via
/// the <see cref="LockingModel"/> property.
/// The default behavior, implemented by <see cref="FileAppender.ExclusiveLock"/>
/// is to obtain an exclusive write lock on the file until this appender is closed.
/// The alternative model, <see cref="FileAppender.MinimalLock"/>, only holds a
/// write lock while the appender is writing a logging event.
/// </para>
/// </remarks>
/// <author>Nicko Cadell</author>
/// <author>Gert Driesen</author>
/// <author>Rodrigo B. de Oliveira</author>
/// <author>Douglas de la Torre</author>
/// <author>Niall Daley</author>
public class FileAppender : TextWriterAppender
{
#region LockingStream Inner Class
/// <summary>
/// Write only <see cref="Stream"/> that uses the <see cref="LockingModelBase"/>
/// to manage access to an underlying resource.
/// </summary>
private sealed class LockingStream : Stream, IDisposable
{
public sealed class LockStateException : LogException
{
public LockStateException(string message): base(message)
{
}
}
private Stream m_realStream=null;
private LockingModelBase m_lockingModel=null;
private int m_readTotal=-1;
private int m_lockLevel=0;
public LockingStream(LockingModelBase locking) : base()
{
if (locking==null)
{
throw new ArgumentException("Locking model may not be null","locking");
}
m_lockingModel=locking;
}
#region Override Implementation of Stream
// Methods
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
AssertLocked();
IAsyncResult ret=m_realStream.BeginRead(buffer,offset,count,callback,state);
m_readTotal=EndRead(ret);
return ret;
}
/// <summary>
/// True asynchronous writes are not supported, the implementation forces a synchronous write.
/// </summary>
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
AssertLocked();
IAsyncResult ret=m_realStream.BeginWrite(buffer,offset,count,callback,state);
EndWrite(ret);
return ret;
}
public override void Close()
{
m_lockingModel.CloseFile();
}
public override int EndRead(IAsyncResult asyncResult)
{
AssertLocked();
return m_readTotal;
}
public override void EndWrite(IAsyncResult asyncResult)
{
//No-op, it has already been handled
}
public override void Flush()
{
AssertLocked();
m_realStream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return m_realStream.Read(buffer,offset,count);
}
public override int ReadByte()
{
return m_realStream.ReadByte();
}
public override long Seek(long offset, SeekOrigin origin)
{
AssertLocked();
return m_realStream.Seek(offset,origin);
}
public override void SetLength(long value)
{
AssertLocked();
m_realStream.SetLength(value);
}
void IDisposable.Dispose()
{
this.Close();
}
public override void Write(byte[] buffer, int offset, int count)
{
AssertLocked();
m_realStream.Write(buffer,offset,count);
}
public override void WriteByte(byte value)
{
AssertLocked();
m_realStream.WriteByte(value);
}
// Properties
public override bool CanRead
{
get { return false; }
}
public override bool CanSeek
{
get
{
AssertLocked();
return m_realStream.CanSeek;
}
}
public override bool CanWrite
{
get
{
AssertLocked();
return m_realStream.CanWrite;
}
}
public override long Length
{
get
{
AssertLocked();
return m_realStream.Length;
}
}
public override long Position
{
get
{
AssertLocked();
return m_realStream.Position;
}
set
{
AssertLocked();
m_realStream.Position=value;
}
}
#endregion Override Implementation of Stream
#region Locking Methods
private void AssertLocked()
{
if (m_realStream == null)
{
throw new LockStateException("The file is not currently locked");
}
}
public bool AcquireLock()
{
bool ret=false;
lock(this)
{
if (m_lockLevel==0)
{
// If lock is already acquired, nop
m_realStream=m_lockingModel.AcquireLock();
}
if (m_realStream!=null)
{
m_lockLevel++;
ret=true;
}
}
return ret;
}
public void ReleaseLock()
{
lock(this)
{
m_lockLevel--;
if (m_lockLevel==0)
{
// If already unlocked, nop
m_lockingModel.ReleaseLock();
m_realStream=null;
}
}
}
#endregion Locking Methods
}
#endregion LockingStream Inner Class
#region Locking Models
/// <summary>
/// Locking model base class
/// </summary>
/// <remarks>
/// <para>
/// Base class for the locking models available to the <see cref="FileAppender"/> derived loggers.
/// </para>
/// </remarks>
public abstract class LockingModelBase
{
private FileAppender m_appender=null;
/// <summary>
/// Open the output file
/// </summary>
/// <param name="filename">The filename to use</param>
/// <param name="append">Whether to append to the file, or overwrite</param>
/// <param name="encoding">The encoding to use</param>
/// <remarks>
/// <para>
/// Open the file specified and prepare for logging.
/// No writes will be made until <see cref="AcquireLock"/> is called.
/// Must be called before any calls to <see cref="AcquireLock"/>,
/// <see cref="ReleaseLock"/> and <see cref="CloseFile"/>.
/// </para>
/// </remarks>
public abstract void OpenFile(string filename, bool append,Encoding encoding);
/// <summary>
/// Close the file
/// </summary>
/// <remarks>
/// <para>
/// Close the file. No further writes will be made.
/// </para>
/// </remarks>
public abstract void CloseFile();
/// <summary>
/// Acquire the lock on the file
/// </summary>
/// <returns>A stream that is ready to be written to.</returns>
/// <remarks>
/// <para>
/// Acquire the lock on the file in preparation for writing to it.
/// Return a stream pointing to the file. <see cref="ReleaseLock"/>
/// must be called to release the lock on the output file.
/// </para>
/// </remarks>
public abstract Stream AcquireLock();
/// <summary>
/// Release the lock on the file
/// </summary>
/// <remarks>
/// <para>
/// Release the lock on the file. No further writes will be made to the
/// stream until <see cref="AcquireLock"/> is called again.
/// </para>
/// </remarks>
public abstract void ReleaseLock();
/// <summary>
/// Gets or sets the <see cref="FileAppender"/> for this LockingModel
/// </summary>
/// <value>
/// The <see cref="FileAppender"/> for this LockingModel
/// </value>
/// <remarks>
/// <para>
/// The file appender this locking model is attached to and working on
/// behalf of.
/// </para>
/// <para>
/// The file appender is used to locate the security context and the error handler to use.
/// </para>
/// <para>
/// The value of this property will be set before <see cref="OpenFile"/> is
/// called.
/// </para>
/// </remarks>
public FileAppender CurrentAppender
{
get { return m_appender; }
set { m_appender = value; }
}
}
/// <summary>
/// Hold an exclusive lock on the output file
/// </summary>
/// <remarks>
/// <para>
/// Open the file once for writing and hold it open until <see cref="CloseFile"/> is called.
/// Maintains an exclusive lock on the file during this time.
/// </para>
/// </remarks>
public class ExclusiveLock : LockingModelBase
{
private Stream m_stream = null;
/// <summary>
/// Open the file specified and prepare for logging.
/// </summary>
/// <param name="filename">The filename to use</param>
/// <param name="append">Whether to append to the file, or overwrite</param>
/// <param name="encoding">The encoding to use</param>
/// <remarks>
/// <para>
/// Open the file specified and prepare for logging.
/// No writes will be made until <see cref="AcquireLock"/> is called.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -