Skip to content

Commit

Permalink
add ini parser, fixes, cleanup, etc...
Browse files Browse the repository at this point in the history
  • Loading branch information
CypherPotato committed Aug 8, 2024
1 parent 0f29e79 commit 5e269d3
Show file tree
Hide file tree
Showing 16 changed files with 180 additions and 76 deletions.
2 changes: 1 addition & 1 deletion src/Entity/MultipartObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ bool Equals(byte[] source, byte[] separator, int index)
}
}

if (fieldName == null)
if (fieldName is null)
{
throw new InvalidOperationException(string.Format(SR.MultipartObject_EmptyFieldName, i));
}
Expand Down
2 changes: 1 addition & 1 deletion src/Entity/StringValueCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal static StringValueCollection FromNameValueCollection(string paramName,
{
value = col[i];
if (value is null) continue;
vcol.items.Add(value, "");
vcol.items.Add(value, string.Empty);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/Http/Hosting/InitializationParameterCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public sealed class InitializationParameterCollection : IDictionary<string, stri
string? value = _decorator[property.Name];
Type propType = property.PropertyType;

if (value == null) continue;
if (value is null) continue;
if (propType.IsEnum)
{
mappingValue = Enum.Parse(propType, value, true);
Expand Down
2 changes: 1 addition & 1 deletion src/Http/HttpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public sealed partial class HttpServer : IDisposable
/// <summary>
/// Gets the X-Powered-By Sisk header value.
/// </summary>
public static string PoweredBy { get; private set; } = "";
public static string PoweredBy { get; private set; } = string.Empty;

/// <summary>
/// Gets the current Sisk version.
Expand Down
2 changes: 1 addition & 1 deletion src/Http/ListeningHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public override bool Equals(object? obj)
{
if (obj is ListeningHost other)
{
if (other == null) return false;
if (other is null) return false;
if (other._ports.Length != _ports.Length) return false;

for (int i = 0; i < _ports.Length; i++)
Expand Down
39 changes: 39 additions & 0 deletions src/Http/ListeningPort.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// File name: ListeningPort.cs
// Repository: https://github.com/sisk-http/core

using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Net.Sockets;

Expand Down Expand Up @@ -39,6 +40,9 @@ namespace Sisk.Core.Http
/// </code>
/// </example>
public readonly struct ListeningPort : IEquatable<ListeningPort>
#if NET7_0_OR_GREATER
, IParsable<ListeningPort>
#endif
{
/// <summary>
/// Gets or sets the DNS hostname pattern where this listening port will refer.
Expand Down Expand Up @@ -186,5 +190,40 @@ public override string ToString()
{
return $"{(Secure ? "https" : "http")}://{Hostname}:{Port}/";
}

/// <summary>
/// Parses a string into a <see cref="ListeningPort"/>.
/// </summary>
/// <param name="s">The string to parse.</param>
/// <param name="provider">An object that provides culture-specific formatting information about s.</param>
public static ListeningPort Parse(string s, IFormatProvider? provider)
{
return new ListeningPort(s);
}

/// <summary>
/// Tries to parse a string into a <see cref="ListeningPort"/>.
/// </summary>
/// <param name="s">The string to parse.</param>
/// <param name="provider">An object that provides culture-specific formatting information about s.</param>
/// <param name="result">When this method returns, contains the result of successfully parsing s or an undefined value on failure.</param>
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out ListeningPort result)
{
if (s is null)
{
result = default;
return false;
}
try
{
result = Parse(s, provider);
return true;
}
catch
{
result = default;
return false;
}
}
}
}
143 changes: 90 additions & 53 deletions src/Http/LogStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
// Repository: https://github.com/sisk-http/core

using Sisk.Core.Entity;
using System.Collections.Concurrent;
using System.Text;
using System.Threading.Channels;

namespace Sisk.Core.Http
{
Expand All @@ -18,19 +18,18 @@ namespace Sisk.Core.Http
/// </summary>
public class LogStream : IDisposable
{
readonly BlockingCollection<object?> logQueue = new BlockingCollection<object?>();
string? filePath;
private bool isDisposed;
Thread consumerThread;
AutoResetEvent logQueueEmptyEvent = new AutoResetEvent(true);
CircularBuffer<string>? _bufferingContent = null;

private readonly Channel<object?> channel = Channel.CreateUnbounded<object?>(new UnboundedChannelOptions() { SingleReader = true });
private readonly Thread consumerThread;
internal readonly ManualResetEvent writeEvent = new ManualResetEvent(false);
internal readonly ManualResetEvent rotatingPolicyLocker = new ManualResetEvent(true);
internal RotatingLogPolicy? rotatingLogPolicy = null;
internal ManualResetEvent rotatingPolicyLocker = new ManualResetEvent(true);
internal SemaphoreSlim sm = new SemaphoreSlim(1);

private string? filePath;
private bool isDisposed;
private CircularBuffer<string>? _bufferingContent = null;

/// <summary>
/// Represents a LogStream that writes its output to the <see cref="Console.Out"/> stream.
/// Represents a <see cref="LogStream"/> that writes its output to the <see cref="Console.Out"/> stream.
/// </summary>
public static readonly LogStream ConsoleOutput = new LogStream(Console.Out);

Expand All @@ -41,7 +40,7 @@ public RotatingLogPolicy RotatingPolicy
{
get
{
if (rotatingLogPolicy == null)
if (rotatingLogPolicy is null)
{
rotatingLogPolicy = new RotatingLogPolicy(this);
}
Expand All @@ -55,6 +54,18 @@ public RotatingLogPolicy RotatingPolicy
/// </summary>
public bool IsBuffering { get => _bufferingContent is not null; }


/// <summary>
/// Gets an boolean indicating if this <see cref="LogStream"/> was disposed.
/// </summary>
public bool Disposed { get => isDisposed; }

/// <summary>
/// Gets or sets a boolean that indicates that every input must be trimmed and normalized before
/// being written to some output stream.
/// </summary>
public bool NormalizeEntries { get; set; } = true;

/// <summary>
/// Gets or sets the absolute path to the file where the log is being written to.
/// </summary>
Expand Down Expand Up @@ -97,7 +108,6 @@ public string? FilePath
public LogStream()
{
consumerThread = new Thread(new ThreadStart(ProcessQueue));
consumerThread.IsBackground = true;
consumerThread.Start();
}

Expand Down Expand Up @@ -135,9 +145,7 @@ public LogStream(string? filename, TextWriter? tw) : this()
/// </summary>
public void Flush()
{
logQueueEmptyEvent.Reset();
logQueueEmptyEvent.WaitOne();
;
writeEvent.WaitOne();
}

/// <summary>
Expand All @@ -155,7 +163,7 @@ public string Peek()
lock (_bufferingContent)
{
string[] lines = _bufferingContent.ToArray();
return string.Join("", lines);
return string.Join(Environment.NewLine, lines);
}
}

Expand All @@ -177,39 +185,65 @@ public void StopBuffering()
_bufferingContent = null;
}

private void ProcessQueue()
private async void ProcessQueue()
{
while (!isDisposed)
var reader = channel.Reader;
while (!isDisposed && await reader.WaitToReadAsync())
{
if (!rotatingPolicyLocker.WaitOne(2500))
{
continue;
}
if (!logQueue.TryTake(out object? data, 2500))
{
continue;
}

string? dataStr = data?.ToString();
if (dataStr is null)
continue;
writeEvent.Reset();

if (TextWriter is not null)
{
TextWriter.WriteLine(dataStr);
TextWriter.Flush();
}
if (filePath is not null)
while (reader.TryRead(out var item))
{
File.AppendAllLines(filePath, contents: new string[] { dataStr });
rotatingPolicyLocker.WaitOne();

bool gotAnyError = false;
string? dataStr = item?.ToString();

if (dataStr is null)
continue;

try
{
TextWriter?.WriteLine(dataStr);
}
catch
{
if (!gotAnyError)
{
await channel.Writer.WriteAsync(item);
gotAnyError = true;
}
}

try
{
if (filePath is not null)
File.AppendAllText(filePath, dataStr + Environment.NewLine, Encoding);
}
catch
{
if (!gotAnyError)
{
await channel.Writer.WriteAsync(item);
gotAnyError = true;
}
}

try
{
_bufferingContent?.Add(dataStr);
}
catch
{
if (!gotAnyError)
{
await channel.Writer.WriteAsync(item);
gotAnyError = true;
}
}
}

_bufferingContent?.Add(dataStr);

if (logQueue.Count == 0)
{
logQueueEmptyEvent.Set();
}
writeEvent.Set();
}
}

Expand All @@ -234,7 +268,7 @@ public virtual void WriteException(Exception exp)
/// </summary>
public void WriteLine()
{
WriteLineInternal("");
WriteLineInternal(string.Empty);
}

/// <summary>
Expand All @@ -243,7 +277,7 @@ public void WriteLine()
/// <param name="message">The text that will be written in the output.</param>
public void WriteLine(object? message)
{
WriteLineInternal(message?.ToString() ?? "");
WriteLineInternal(message?.ToString() ?? string.Empty);
}

/// <summary>
Expand Down Expand Up @@ -271,7 +305,14 @@ public void WriteLine(string format, params object?[] args)
/// <param name="line">The line which will be written to the log stream.</param>
protected virtual void WriteLineInternal(string line)
{
EnqueueMessageLine(line.Normalize());
if (NormalizeEntries)
{
EnqueueMessageLine(line.Normalize().Trim().ReplaceLineEndings());
}
else
{
EnqueueMessageLine(line);
}
}

/// <summary>
Expand All @@ -293,10 +334,7 @@ public LogStream ConfigureRotatingPolicy(long maximumSize, TimeSpan dueTime)
void EnqueueMessageLine(string message)
{
ArgumentNullException.ThrowIfNull(message, nameof(message));
lock (logQueue)
{
logQueue.Add(message);
}
_ = channel.Writer.WriteAsync(message);
}

void WriteExceptionInternal(StringBuilder exceptionSbuilder, Exception exp, int currentDepth = 0)
Expand Down Expand Up @@ -328,9 +366,8 @@ protected virtual void Dispose(bool disposing)
if (disposing)
{
Flush();
channel.Writer.Complete();
TextWriter?.Dispose();
rotatingPolicyLocker?.Dispose();
logQueueEmptyEvent?.Dispose();
rotatingLogPolicy?.Dispose();
consumerThread.Join();
}
Expand Down
15 changes: 8 additions & 7 deletions src/Http/RotatingLogPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ namespace Sisk.Core.Http
public sealed class RotatingLogPolicy : IDisposable
{
private System.Timers.Timer? checkTimer = null;
private bool isTerminating = false;
internal LogStream? _logStream;
private bool disposedValue;

Expand Down Expand Up @@ -79,13 +78,13 @@ public void Configure(long maximumSize, TimeSpan due)

checkTimer.Interval = Due.TotalMilliseconds;
checkTimer.Elapsed += Check;
checkTimer?.Start();
checkTimer.Start();
}

private void Check(object? state, ElapsedEventArgs e)
{
if (isTerminating) return;
if (_logStream is null) return;
if (disposedValue) return;
if (_logStream is null || _logStream.Disposed) return;
if (checkTimer is null) return;

string file = _logStream.FilePath!;
Expand All @@ -104,14 +103,16 @@ private void Check(object? state, ElapsedEventArgs e)
try
{
_logStream.rotatingPolicyLocker.Reset();
_logStream.Flush();

using (FileStream logSs = fileInfo.Open(FileMode.OpenOrCreate))
using (FileStream gzFileSs = new FileInfo(gzippedFilename).Create())
using (GZipStream gzSs = new GZipStream(gzFileSs, CompressionMode.Compress))
{
logSs.CopyTo(gzSs);
logSs.SetLength(0);
if (logSs.CanRead)
logSs.CopyTo(gzSs);

if (logSs.CanWrite)
logSs.SetLength(0);
}
}
catch
Expand Down
Loading

0 comments on commit 5e269d3

Please sign in to comment.