123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace VCommon.Logging
- {
- public class TextLogPool : IDisposable
- {
- private const int IntervalToCheckCloseInSec = 1;
- private bool _isDisposed;
- private readonly Dictionary<string, Entry> _dictionary = new Dictionary<string, Entry>();
- private class Entry
- {
- public FileStream FileStream { get; set; }
- public DateTime LastWriteTime { get; set; }
- }
- public TextLogPool(int idleToCloseInMin = 10)
- {
- Init(idleToCloseInMin);
- }
- public bool AppendText(string path, string content)
- {
- if (_isDisposed) throw new ObjectDisposedException("Cannot access a disposed object.");
- Entry inst = null;
- try
- {
- inst = GetInstance(path);
- if (inst == null) return false;
- lock (inst)
- {
- inst.LastWriteTime = DateTime.Now;
- var buf = Encoding.UTF8.GetBytes(content);
- inst.FileStream.Write(buf, 0, buf.Length);
- inst.FileStream.Flush();
- return true;
- }
- }
- catch (Exception exception)
- {
- Logger.Warn("TextLogPool write fail", new { path, FileStreamInstance = inst?.FileStream.GetHashCode().ToString("X4"), content, exception });
- return false;
- }
- }
- public void Dispose()
- {
- _isDisposed = true;
- foreach (var entry in _dictionary.Values) entry.FileStream.Dispose();
- _dictionary.Clear();
- }
- private void Init(int idleToCloseInMin)
- {
- Task.Factory.StartNew(() =>
- {
- while (false == _isDisposed)
- {
- lock (_dictionary)
- {
- var now = DateTime.Now;
- var toFree = _dictionary.Where(p => (now - p.Value.LastWriteTime).TotalMinutes > idleToCloseInMin)
- .ToArray();
- foreach (var pair in toFree) FreeInstance(pair.Key);
- }
- Thread.Sleep(1000 * IntervalToCheckCloseInSec);
- }
- });
- }
- private void FreeInstance(string path)
- {
- if (!_dictionary.TryGetValue(path, out var inst)) return;
- try
- {
- lock (inst) inst.FileStream.Dispose();
- _dictionary.Remove(path);
- Logger.Info("TextLogPool entry freed", new { path, FileStreamInstance = inst.FileStream.GetHashCode().ToString("X4") });
- }
- catch (Exception exception)
- {
- Logger.Warn($"TextLogPool on freeing entry", new { path, exception });
- }
- }
- private Entry GetInstance(string path)
- {
- lock (_dictionary)
- {
- if (_dictionary.TryGetValue(path, out var inst)) return inst;
- try
- {
- var fs = File.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read);
- var entry = new Entry { FileStream = fs, LastWriteTime = DateTime.Now };
- Logger.Info("TextLogPool entry created", new { path, FileStreamInstance = fs.GetHashCode().ToString("X4") });
- _dictionary[path] = entry;
- return entry;
- }
- catch (Exception exception)
- {
- Logger.Info("TextLogPool error on creating entry", new { path, exception });
- return null;
- }
- }
- }
- }
- }
|