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.

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