Skip to content

Commit

Permalink
SKA-224: Delete temporarily extracted FMUs
Browse files Browse the repository at this point in the history
* If there is a folder with the extracted FMU in the same directory as the FMU, this extracted content will be used and remains there after the FMU Importer stops.
* Otherwise, the FMU is now extracted to a temporary directory. This directory and its contents are deleted after the simulation run.
  • Loading branch information
DominikHerr committed Jun 18, 2024
1 parent a34f730 commit a90958a
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 31 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ The format is based on `Keep a Changelog (http://keepachangelog.com/en/1.0.0/) <
### Changed

* If the value of an enumeration-typed variable is set, strings are now considered referring to an enumerator's name, whereas integers refer to an enumerators' value.
* Temporarily extracted FMUs are now deleted by default
* If there is a folder with the extracted FMU in the same directory as the FMU, this extracted content will be used and remains there after the FMU Importer stops.
* Otherwise, the FMU is now extracted to a temporary directory. This directory and its contents are deleted after the simulation run.

## [1.2.0] - 2024-03-28

Expand Down
7 changes: 4 additions & 3 deletions FmuImporter/FmiBridge/Binding/BindingFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ namespace Fmi.Binding;

public static class BindingFactory
{
public static IFmiBindingCommon CreateBinding(FmiVersions fmiVersion, string fmuPath)
public static IFmiBindingCommon CreateBinding(
FmiVersions fmiVersion, string fmuPath, Action<LogSeverity, string> logCallback)
{
switch (fmiVersion)
{
case FmiVersions.Fmi2:
return new Fmi2Binding(fmuPath);
return new Fmi2Binding(fmuPath, logCallback);
case FmiVersions.Fmi3:
return new Fmi3Binding(fmuPath);
return new Fmi3Binding(fmuPath, logCallback);
default:
throw new ArgumentOutOfRangeException(nameof(fmiVersion), fmiVersion, null);
}
Expand Down
2 changes: 1 addition & 1 deletion FmuImporter/FmiBridge/Binding/Fmi2Binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private static string OsPath

private static readonly AutoResetEvent WaitForDoStepEvent = new AutoResetEvent(false);

public Fmi2Binding(string fmuPath) : base(fmuPath, OsPath)
public Fmi2Binding(string fmuPath, Action<LogSeverity, string> logCallback) : base(fmuPath, OsPath, logCallback)
{
// Common Functions
SetDelegate(out _fmi2SetDebugLogging);
Expand Down
2 changes: 1 addition & 1 deletion FmuImporter/FmiBridge/Binding/Fmi3Binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private static string OsPath
}
}

public Fmi3Binding(string fmuPath) : base(fmuPath, OsPath)
public Fmi3Binding(string fmuPath, Action<LogSeverity, string> logCallback) : base(fmuPath, OsPath, logCallback)
{
// Common functions
SetDelegate(out _fmi3InstantiateCoSimulation);
Expand Down
67 changes: 58 additions & 9 deletions FmuImporter/FmiBridge/Binding/FmiBindingBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,43 @@ internal abstract class FmiBindingBase : IDisposable, IFmiBindingCommon

public ModelDescription ModelDescription { get; }

public string ExtractedFolderPath { get; }
private readonly string _extractedFolderPath;

public string ExtractedFolderPath
{
get
{
return _extractedFolderPath;
}
}

public string FullFmuLibPath { get; }

private IntPtr DllPtr { set; get; }

private bool _isTemporary;

internal bool IsTemporary
{
get
{
return _isTemporary;
}
set
{
_isTemporary = value;
}
}

// ctor
protected FmiBindingBase(string fmuPath, string osDependentPath)
protected FmiBindingBase(string fmuPath, string osDependentPath, Action<LogSeverity, string> logCallback)
{
ExtractedFolderPath = ModelLoader.ExtractFmu(fmuPath);
_loggerAction = logCallback;
ModelLoader.ExtractFmu(fmuPath, out _extractedFolderPath, out _isTemporary);
if (IsTemporary)
{
Log(LogSeverity.Debug, $"Temporarily extracted the FMU to '{_extractedFolderPath}'.");
}

ModelDescription = InitializeModelDescription(ExtractedFolderPath);

Expand All @@ -49,6 +77,32 @@ protected FmiBindingBase(string fmuPath, string osDependentPath)

private void ReleaseUnmanagedResources()
{
var failCounter = 10;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
while (NativeMethods.FreeLibrary(DllPtr) && failCounter > 0)
{
--failCounter;
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
while (NativeMethods.dlclose(DllPtr) != 0 && failCounter > 0)
{
--failCounter;
}
}
else
{
throw new NotSupportedException();
}

// if DLL was freed successfully and FMU was extracted to temporary folder, delete that folder and its content
if (failCounter > 0 && IsTemporary)
{
var dir = Directory.GetParent(ExtractedFolderPath) ?? new DirectoryInfo(ExtractedFolderPath);
dir.Delete(true);
}
}

private bool _disposedValue;
Expand Down Expand Up @@ -235,10 +289,5 @@ protected void Log(LogSeverity severity, string message)
_loggerAction?.Invoke(severity, message);
}

private Action<LogSeverity, string>? _loggerAction;

public void SetLoggerCallback(Action<LogSeverity, string> callback)
{
_loggerAction = callback;
}
private readonly Action<LogSeverity, string>? _loggerAction;
}
2 changes: 0 additions & 2 deletions FmuImporter/FmiBridge/Binding/IFmiBindingCommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,4 @@ public void DoStep(
public void FreeInstance();

public FmiVersions GetFmiVersion();

public void SetLoggerCallback(Action<LogSeverity, string> callback);
}
27 changes: 19 additions & 8 deletions FmuImporter/FmiBridge/FmiModel/ModelLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Fmi.FmiModel;

public class ModelLoader
{
internal static string ExtractFmu(string fmuPath)
internal static void ExtractFmu(string fmuPath, out string extractedPath, out bool isTemporary)
{
// check if the directory exists
var targetFolderPath =
Expand All @@ -21,23 +21,34 @@ internal static string ExtractFmu(string fmuPath)
// $"SilKitImporter_{Path.GetFileNameWithoutExtension(fmuPath)}");
if (Directory.Exists(targetFolderPath) && Directory.EnumerateFileSystemEntries(targetFolderPath).Any())
{
isTemporary = false;
extractedPath = targetFolderPath;
// directory exists and has entries -> skip extraction
return targetFolderPath;
return;
}

var tempDirectory = CreateTempDirectory();

var dir = Directory.CreateDirectory(
$"{Path.GetDirectoryName(fmuPath)}/{Path.GetFileNameWithoutExtension(fmuPath)}");
$"{tempDirectory}/{Path.GetFileNameWithoutExtension(fmuPath)}");

ZipFile.ExtractToDirectory(fmuPath, dir.FullName);
return dir.FullName;
isTemporary = true;
extractedPath = dir.FullName;
}

internal static void RemoveExtractedFmu(string fmuPath)
private static string CreateTempDirectory()
{
var dir = $"{Path.GetDirectoryName(fmuPath)}/{Path.GetFileNameWithoutExtension(fmuPath)}";
if (Directory.Exists(dir))
var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
if (File.Exists(tempDirectory))
{
// try again
return CreateTempDirectory();
}
else
{
Directory.Delete(dir, true);
Directory.CreateDirectory(tempDirectory);
return tempDirectory;
}
}

Expand Down
6 changes: 3 additions & 3 deletions FmuImporter/FmuImporter/Fmu/FmuEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ public enum FmuSuperStates

public event FmiLog? OnFmuLog;

public FmuEntity(string fmuPath)
public FmuEntity(string fmuPath, FmiLog fmiLogCallback)
{
FmiVersion = ModelLoader.FindFmiVersion(fmuPath);
OnFmuLog = fmiLogCallback;

Binding = BindingFactory.CreateBinding(FmiVersion, fmuPath);
Binding.SetLoggerCallback(RaiseOnFmuLogEvent);
Binding = BindingFactory.CreateBinding(FmiVersion, fmuPath, RaiseOnFmuLogEvent);
ModelDescription = Binding.ModelDescription;
}

Expand Down
5 changes: 1 addition & 4 deletions FmuImporter/FmuImporter/FmuImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public FmuImporter(
throw;
}

FmuEntity = new FmuEntity(fmuPath);
FmuEntity = new FmuEntity(fmuPath, FmuEntity_OnFmuLog);

try
{
Expand All @@ -119,9 +119,6 @@ public FmuImporter(
_configuredStructuralParameters.Add(myStructParam, param!);
}

// Register logger callback
FmuEntity.OnFmuLog += FmuEntity_OnFmuLog;

// Initialize FMU
FmuEntity.PrepareFmu(ApplyParameterConfiguration, ApplyParameterConfiguration);

Expand Down

0 comments on commit a90958a

Please sign in to comment.