Commit fab48c2e authored by Antoni Zaprzała's avatar Antoni Zaprzała

update 2

parent 92edfcc2
......@@ -30,20 +30,21 @@ app.MapGet("/files", (LogFileBrowser browser) =>
// downloads to working directory a single log file by name
// example: curl -OJ http://127.0.0.1:8082/files/download/lcd-2026-07-01_09-18-33.log
app.MapGet("/files/download/{name}", async (string name, LogFileBrowser browser, CancellationToken ct) =>
app.MapGet("/files/download/{name}", (string name, LogFileBrowser browser) =>
{
var bytes = await browser.ReadSnapshotAsync(name, ct);
var bytes = browser.ReadSnapshot(name);
if (bytes is null) return Results.NotFound();
return Results.File(bytes, "application/octet-stream", fileDownloadName: name);
});
// example: curl -OJ http://127.0.0.1:8082/files/download-all
app.MapGet("/files/download-all", async (LogFileBrowser browser, CancellationToken ct) =>
app.MapGet("/files/download-all", (LogFileBrowser browser) =>
{
var zipBytes = await browser.BuildZipAsync(ct);
var zipName = $"lcd-logs-{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.zip";
var zipBytes = browser.BuildZip();
if (zipBytes is null) return Results.NotFound();
var zipName = $"lcd-logs-{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.zip";
return Results.File(zipBytes, "application/zip", fileDownloadName: zipName);
});
......
......@@ -44,7 +44,7 @@ namespace LcdLogger.Services
return File.Exists(fullPath) ? fullPath : null;
}
public async Task<byte[]?> ReadSnapshotAsync(string name, CancellationToken cancellationToken = default)
public byte[]? ReadSnapshot(string name)
{
var path = GetFilePath(name);
if (path is null) return null;
......@@ -55,26 +55,26 @@ namespace LcdLogger.Services
path,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite,
bufferSize: 4096,
useAsync: true);
FileShare.ReadWrite);
return await ReadExactSnapshotAsync(fileStream, name, fileStream.Length, cancellationToken);
var buffer = new byte[fileStream.Length];
fileStream.ReadExactly(buffer);
return buffer;
}
catch (IOException e)
catch (Exception e) when (e is IOException or EndOfStreamException)
{
_logger.LogError(e, "Failed to read snapshot of {FileName}", name);
return null;
}
}
public async Task<byte[]> BuildZipAsync(CancellationToken cancellationToken = default)
public byte[]? BuildZip()
{
var directoryInfo = new DirectoryInfo(_options.Directory);
if (!directoryInfo.Exists)
{
_logger.LogWarning("Directory {Directory} does not exist", _options.Directory);
return Array.Empty<byte>();
return null;
}
using var buffer = new MemoryStream();
......@@ -85,7 +85,6 @@ namespace LcdLogger.Services
{
try
{
var snapshotLength = file.Length;
var entry = zip.CreateEntry(file.Name, CompressionLevel.Fastest);
using (var entryStream = entry.Open())
......@@ -95,7 +94,9 @@ namespace LcdLogger.Services
FileAccess.Read,
FileShare.ReadWrite))
{
await CopyExactAsync(fileStream, entryStream, snapshotLength, cancellationToken);
var content = new byte[file.Length];
fileStream.ReadExactly(content);
entryStream.Write(content);
}
}
catch (Exception e)
......@@ -108,45 +109,5 @@ namespace LcdLogger.Services
return buffer.ToArray();
}
private async Task<byte[]> ReadExactSnapshotAsync(Stream source, string name, long length, CancellationToken cancellationToken)
{
var buffer = new byte[length];
var offset = 0;
while (offset < buffer.Length)
{
var read = await source.ReadAsync(buffer.AsMemory(offset), cancellationToken);
if (read == 0) break;
offset += read;
}
if (offset < buffer.Length)
{
_logger.LogWarning(
"Snapshot {FileName} truncated: expected {Expected} bytes, read {Actual}",
name, buffer.Length, offset);
return buffer[..offset];
}
return buffer;
}
private static async Task CopyExactAsync(Stream source, Stream destination, long count, CancellationToken cancellationToken)
{
var buffer = new byte[81920];
var remaining = count;
while (remaining > 0)
{
var toRead = (int)Math.Min(buffer.Length, remaining);
var read = await source.ReadAsync(buffer.AsMemory(0, toRead), cancellationToken);
if (read == 0) break;
await destination.WriteAsync(buffer.AsMemory(0, read), cancellationToken);
remaining -= read;
}
}
}
}
......@@ -106,45 +106,13 @@ namespace LcdLogger.Services
await _fileStream.FlushAsync(cancellationToken);
await _fileStream.DisposeAsync();
//var justClosedFile = _currentPath;
//_ = Task.Run(async () =>
//{
// await CompressAsync(justClosedFile);
//});
await PruneSurplusFilesAsync(cancellationToken);
await OpenNewAsync(cancellationToken);
}
//private async Task CompressAsync(string path)
//{
// try
// {
// var gzPath = path + ".gz";
// using (var source = File.OpenRead(path))
// using (var destination = File.Create(gzPath))
// using (var gzip = new GZipStream(destination, CompressionLevel.SmallestSize))
// {
// await source.CopyToAsync(gzip);
// }
// File.Delete(path);
// }
// catch (Exception e)
// {
// _logger.LogError(e.Message, "Compress failed");
// }
//}
private bool _disposed;
public async ValueTask DisposeAsync()
{
if (_disposed) return;
_disposed = true;
try
{
await _fileStream.FlushAsync();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment