You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
4.1 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. using Ionic.Zlib;
  2. using System;
  3. using System.IO;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace IPA.Logging.Printers
  7. {
  8. /// <summary>
  9. /// A <see cref="LogPrinter"/> abstract class that provides the utilities to write to a GZip file.
  10. /// </summary>
  11. public abstract class GZFilePrinter : LogPrinter, IDisposable
  12. {
  13. [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
  14. static extern bool CreateHardLink(
  15. string lpFileName,
  16. string lpExistingFileName,
  17. IntPtr lpSecurityAttributes
  18. );
  19. private FileInfo fileInfo;
  20. /// <summary>
  21. /// The <see cref="StreamWriter"/> that writes to the GZip file.
  22. /// </summary>
  23. protected StreamWriter FileWriter;
  24. private GZipStream zstream;
  25. private FileStream fstream;
  26. /// <summary>
  27. /// Gets the <see cref="FileInfo"/> for the file to write to without the .gz extension.
  28. /// </summary>
  29. /// <returns></returns>
  30. protected abstract FileInfo GetFileInfo();
  31. private void InitLog()
  32. {
  33. try
  34. {
  35. if (fileInfo == null)
  36. { // first init
  37. fileInfo = GetFileInfo();
  38. var ext = fileInfo.Extension;
  39. fileInfo = new FileInfo(fileInfo.FullName + ".gz");
  40. fileInfo.Create().Close();
  41. var symlink = new FileInfo(Path.Combine(fileInfo.DirectoryName ?? throw new InvalidOperationException(), $"latest{ext}.gz"));
  42. if (symlink.Exists) symlink.Delete();
  43. try
  44. {
  45. if (!CreateHardLink(symlink.FullName, fileInfo.FullName, IntPtr.Zero))
  46. {
  47. var error = Marshal.GetLastWin32Error();
  48. Logger.log.Error($"Hardlink creation failed ({error})");
  49. }
  50. }
  51. catch (Exception e)
  52. {
  53. Logger.log.Error("Error creating latest hardlink!");
  54. Logger.log.Error(e);
  55. }
  56. }
  57. }
  58. catch (Exception e)
  59. {
  60. Logger.log.Error("Error initializing log!");
  61. Logger.log.Error(e);
  62. }
  63. }
  64. /// <summary>
  65. /// Called at the start of any print session.
  66. /// </summary>
  67. public sealed override void StartPrint()
  68. {
  69. InitLog();
  70. fstream = fileInfo.Open(FileMode.Append, FileAccess.Write);
  71. zstream = new GZipStream(fstream, CompressionMode.Compress)
  72. {
  73. FlushMode = FlushType.Full
  74. };
  75. FileWriter = new StreamWriter(zstream, new UTF8Encoding(false));
  76. }
  77. /// <summary>
  78. /// Called at the end of any print session.
  79. /// </summary>
  80. public sealed override void EndPrint()
  81. {
  82. FileWriter.Flush();
  83. zstream.Flush();
  84. fstream.Flush();
  85. FileWriter.Close();
  86. zstream.Close();
  87. fstream.Close();
  88. FileWriter.Dispose();
  89. zstream.Dispose();
  90. fstream.Dispose();
  91. }
  92. /// <summary>
  93. /// Disposes the file printer.
  94. /// </summary>
  95. public void Dispose()
  96. {
  97. Dispose(true);
  98. GC.SuppressFinalize(this);
  99. }
  100. /// <summary>
  101. /// Disposes the file printer.
  102. /// </summary>
  103. /// <param name="disposing">does nothing</param>
  104. protected virtual void Dispose(bool disposing)
  105. {
  106. if (disposing)
  107. {
  108. FileWriter.Flush();
  109. zstream.Flush();
  110. fstream.Flush();
  111. FileWriter.Close();
  112. zstream.Close();
  113. fstream.Close();
  114. FileWriter.Dispose();
  115. zstream.Dispose();
  116. fstream.Dispose();
  117. }
  118. }
  119. }
  120. }