Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for issue 134 #135

Merged
merged 4 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ public void SubConfiguration_HappyPath()
[DataContract]
class ConfigurationWithField
{

// Suppress warnings about default values as that's what we're actually testing.
#pragma warning disable 0649
[DataMember]
[MFObjType(AllowEmpty = true)]
public MFIdentifier ObjectType;
Expand All @@ -224,6 +227,7 @@ class ConfigurationWithField
[DataMember]
public ConfigurationWithField SubConfiguration;

#pragma warning restore 0649
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ ClientOperations clientOps
var fileSizes = new List<string>();
long totalSize = 0;
long archiveSize = 0;
int inaccessibleFileCount = 0;
using (var memStream = new MemoryStream())
{
// Build the archive.
Expand All @@ -77,31 +78,49 @@ ClientOperations clientOps
// Add each log file to the archive.
foreach (string relPath in files)
{
// Sanity and safety check.
// All paths must be inside the log folder.
var fullPath = Path.GetFullPath(Path.Combine(rootPath, relPath));
if (!fullPath.StartsWith(rootPath) ||
Path.GetExtension(fullPath).ToLower() != ".log" ||
!File.Exists(fullPath))
throw new FileNotFoundException();

// Add the file to the archive.
// NOTE:
// We can't use archive.CreateEntryFromFile, because the log file may be
// open by the logger, and the method doesn't have options for how we open
// the file. To avoid issues, we must open the file with FileShare.ReadWrite.
var fileEntry = archive.CreateEntry(relPath, CompressionLevel.Optimal);
using (FileStream fileStream = File.Open(
fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (Stream entryStream = fileEntry.Open())
ZipArchiveEntry fileEntry = null;
string fullPath = null;
try
{
// Copy the file to the archive.
fileStream.CopyTo(entryStream);
// Sanity and safety check.
// All paths must be inside the log folder.
fullPath = Path.GetFullPath(Path.Combine(rootPath, relPath));
if (!fullPath.StartsWith(rootPath) ||
Path.GetExtension(fullPath).ToLower() != ".log" ||
!File.Exists(fullPath))
throw new FileNotFoundException();

// Bookkeeping.
var fileSize = fileStream.Length;
fileSizes.Add($"{relPath}: {fileSize} bytes");
totalSize += fileSize;
// Add the file to the archive.
// NOTE:
// We can't use archive.CreateEntryFromFile, because the log file may be
// open by the logger, and the method doesn't have options for how we open
// the file. To avoid issues, we must open the file with FileShare.ReadWrite.
using (FileStream fileStream = File.Open(
fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
fileEntry = archive.CreateEntry(relPath, CompressionLevel.Optimal);
using (Stream entryStream = fileEntry.Open())
{
// Copy the file to the archive.
fileStream.CopyTo(entryStream);

// Bookkeeping.
var fileSize = fileStream.Length;
fileSizes.Add($"{relPath}: {fileSize} bytes");
totalSize += fileSize;
}
}
}
catch (Exception e)
{
// The file was likely inaccessible. This can happen in some situations
// where the container is recycled and the file is locked.
inaccessibleFileCount++;

this.Logger?.Warn(e, $"Cannot add {relPath} to the log download.");

// Ensure we don't have a value in the zip for this file.
try { fileEntry?.Delete(); } catch { }
}
}
}
Expand All @@ -120,6 +139,16 @@ ClientOperations clientOps
String.Join( "\n - ", fileSizes ) );
*/

// If some files weren't accessible then inform the user.
if(inaccessibleFileCount > 0)
{
this.Logger?.Error($"There were {inaccessibleFileCount} files that could not be added to the log download.");
clientOps.ShowMessage
(
string.Format(Resources.Exceptions.Dashboard.LogFileDownloadIncomplete, inaccessibleFileCount)
);
}

// Prompt the user to download the archive.
clientOps.Directives.Add(new PromptDownloadFile
{
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions MFiles.VAF.Extensions/Resources/Exceptions/Dashboard.resx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="LogFileDownloadIncomplete" xml:space="preserve">
<value>{0} file(s) could not be added to the log download. This can happen when files are inaccessible due to container recycle or similar. The log data may be incomplete.</value>
<comment>{0} is replaced with the number of files affected.</comment>
</data>
<data name="XmlFragmentNull" xml:space="preserve">
<value>XML fragment for {0} was null so cannot be rendered.</value>
<comment>Thrown if a dashboard component returns a null XML (XHTML) fragment. {0} will be replaced with the name of the component.</comment>
Expand Down
Loading