From 3c98e1c1c9c8299bdd2af19f48f52074b29b281c Mon Sep 17 00:00:00 2001 From: "d.neuroth" Date: Thu, 14 Oct 2021 17:54:33 +0200 Subject: [PATCH] Implemented the DatFileDeletor as a post processing step --- Automation/ResultFiles/LoadTypeInformation.cs | 2 +- .../GeneralSteps/DatFileDeletor.cs | 45 ++++- CalculationController/Queue/DatFileDeletor.cs | 156 ------------------ .../InputLoggers/ResultFileEntryLogger.cs | 16 ++ .../SQLResultLoggingService.cs | 65 ++++++++ 5 files changed, 120 insertions(+), 164 deletions(-) delete mode 100644 CalculationController/Queue/DatFileDeletor.cs diff --git a/Automation/ResultFiles/LoadTypeInformation.cs b/Automation/ResultFiles/LoadTypeInformation.cs index 5a7a4fc2..564c732e 100644 --- a/Automation/ResultFiles/LoadTypeInformation.cs +++ b/Automation/ResultFiles/LoadTypeInformation.cs @@ -81,7 +81,7 @@ public LoadTypeInformation([JetBrains.Annotations.NotNull] string name, [JetBrai public string? FileName { get; set; } [JetBrains.Annotations.NotNull] - public StrGuid? Guid { get; } + public StrGuid? Guid { get; set; } // needed for xml deserialize [UsedImplicitly] diff --git a/CalcPostProcessor/GeneralSteps/DatFileDeletor.cs b/CalcPostProcessor/GeneralSteps/DatFileDeletor.cs index f862238c..029a918f 100644 --- a/CalcPostProcessor/GeneralSteps/DatFileDeletor.cs +++ b/CalcPostProcessor/GeneralSteps/DatFileDeletor.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Linq; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using Automation; @@ -6,28 +8,57 @@ using CalcPostProcessor.Steps; using Common; using Common.SQLResultLogging; +using Common.SQLResultLogging.InputLoggers; namespace CalcPostProcessor.GeneralSteps { + /// + /// A postprocessing step that deletes all .dat files created during the calculation + /// [SuppressMessage("ReSharper", "RedundantNameQualifier")] - public class DatFileDeletor: GeneralStepBase + public class DatFileDeletor : GeneralStepBase { [JetBrains.Annotations.NotNull] - private readonly IFileFactoryAndTracker _fft; + private readonly SqlResultLoggingService _srls; public DatFileDeletor([JetBrains.Annotations.NotNull] CalcDataRepository repository, [JetBrains.Annotations.NotNull] ICalculationProfiler calculationProfiler, - [JetBrains.Annotations.NotNull] IFileFactoryAndTracker fft) + [JetBrains.Annotations.NotNull] SqlResultLoggingService srls) : base(repository, AutomationUtili.GetOptionList(CalcOption.HouseholdContents), calculationProfiler, "Delete .dat files", 0) { - _fft = fft; + _srls = srls; } + /// + /// Performs the postprocessing step by calling the method to delete .dat files + /// + /// protected override void PerformActualStep(IStepParameters parameters) { - // insert deleting function here + DeleteDatFiles(); + } + + /// + /// Deletes all .dat files if the CalcOption DeleteDatFiles is set + /// + private void DeleteDatFiles() + { + if (Repository.CalcParameters.IsSet(CalcOption.DeleteDatFiles)) + { + // load a list of all created files from the database + ResultFileEntryLogger rfel = new ResultFileEntryLogger(_srls); + var resultFileEntries = rfel.Load(); + // filter all result files ending with .dat + var datFileEntries = resultFileEntries.Where(f => f.FileName.ToUpperInvariant().EndsWith(".DAT", StringComparison.Ordinal)); + foreach (var datFile in datFileEntries) + { + File.Delete(datFile.FullFileName); + // remove file entry from the result file list in the database + rfel.DeleteEntry(datFile); + } + } } [JetBrains.Annotations.NotNull] - public override List NeededOptions => new List() {CalcOption.DeleteDatFiles}; + public override List NeededOptions => new List() { CalcOption.DeleteDatFiles }; } } diff --git a/CalculationController/Queue/DatFileDeletor.cs b/CalculationController/Queue/DatFileDeletor.cs deleted file mode 100644 index 20ee726b..00000000 --- a/CalculationController/Queue/DatFileDeletor.cs +++ /dev/null @@ -1,156 +0,0 @@ -//----------------------------------------------------------------------- - -// -// -// Copyright (c) TU Chemnitz, Prof. Technische Thermodynamik -// Written by Noah Pflugradt. -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -// -// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the distribution. -// All advertising materials mentioning features or use of this software must display the following acknowledgement: -// “This product includes software developed by the TU Chemnitz, Prof. Technische Thermodynamik and its contributors.” -// Neither the name of the University nor the names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, S -// PECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; L -// OSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// - -//----------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.IO; -using Automation.ResultFiles; -using Common.SQLResultLogging; -using Common.SQLResultLogging.InputLoggers; -using JetBrains.Annotations; - -//using CalcController.CalcFactories; -//using Calculation.HouseholdElements; -//using Calculation.PostProcessing; -// ReSharper disable All - -//using JetBrains.Annotations; - -namespace CalculationController.Queue { - public class DatFileDeletor { - [JetBrains.Annotations.NotNull] - public string CalcObjectName { get; } - - [JetBrains.Annotations.NotNull] - //private readonly ObservableCollection _calculationEntries; - - private readonly string _resultPath; - private readonly bool _deleteDatFiles; - //[JetBrains.Annotations.NotNull] - //private readonly CalcStartParameterSet _csps; - //[JetBrains.Annotations.NotNull] - //private readonly CalculationResult _results; - - public DatFileDeletor(//[JetBrains.Annotations.NotNull] CalculationResult results, - bool deleteDatFiles, - //[JetBrains.Annotations.NotNull][ItemNotNull] ObservableCollection calculationEntries, - [JetBrains.Annotations.NotNull] string resultPath, [JetBrains.Annotations.NotNull] string calcObjectName) { - CalcObjectName = calcObjectName; - //_results = results; - //_calculationEntries = calculationEntries; - _resultPath = resultPath; - _deleteDatFiles = deleteDatFiles; - } - - private static void DeleteDatFiles([ItemNotNull] [JetBrains.Annotations.NotNull] List resultFiles) { - foreach (var rfe in resultFiles) { - if (rfe.FileName.ToUpperInvariant().EndsWith(".DAT", StringComparison.Ordinal)) { - File.Delete(rfe.FullFileName); - } - } - } -/* - private void ProcessResultfilesForSettlement(List results, string path,ObservableCollection settlementResults, [CanBeNull] Dispatcher dispatcher,Simulator sim) { - try { - { - //todo: change this to read the ltdict from the database - var ltdict = CalcLoadTypeFactory.MakeLoadTypes( - sim.LoadTypes.MyItems, _internalStepSize, LoadTypePriority.All); - //var calcLoadTypes = new List(ltdict.LtDict.Values); - throw new NotImplementedException("xxx"); - // var srfg = new SettlementResultFileGenerator(results,new FileFactoryAndTracker(path, "(none)"), settlementResults, calcLoadTypes.ToArray(),dispatcher); - // srfg.Run(); - } - } - catch (Exception e) { - MessageWindows.ShowDebugMessage(e); - Logger.Exception(e); - if (Config.IsInUnitTesting) { - throw; - } - } - } -*/ - public void ProcessResults() { - SqlResultLoggingService srls = new SqlResultLoggingService(_resultPath); - - // for a single household / house - //if (_calculationEntries.Count == 1) // && (_calculationEntries[0].CalcObject.GetType() == typeof (Household) - { - if (_deleteDatFiles) { - ResultFileEntryLogger rfel = new ResultFileEntryLogger(srls); - var resultFileEntries = rfel.Load(); - DeleteDatFiles(resultFileEntries); - } - // - return; - } - // for a settlement - //throw new LPGException("xxx - no settlement calculation anymore"); - //var results = new List(); - //foreach (var entry in _calculationEntries) { - //results.Add(entry.CalculationResult); - //} - - //var resultFileEntries = new ObservableCollection(); - //var everythingok = false; - /* if (results.Count > 0 && results[0] != null) { - everythingok = true; - throw new LPGException("xxx"); - //ProcessResultfilesForSettlement(results, _resultPath, resultFileEntries,_csps.Dispatcher, sim); - - }*/ - - /* - if (_deleteDatFiles) { - foreach (var entry in _calculationEntries) { - DeleteDatFiles(entry); - } - } - if (_calculationEntries.Count > 0) { - if (_csps.Dispatcher != null && Thread.CurrentThread != _csps.Dispatcher.Thread) { - _csps.Dispatcher.BeginInvoke(DispatcherPriority.Normal, _csps.ReportFinishFuncForHouseAndSettlement, - everythingok, _csps.CalcTarget.Name, resultFileEntries); - } - else { - _csps.ReportFinishFuncForHouseAndSettlement( everythingok, _csps.CalcTarget.Name, - resultFileEntries); - } - } - else { - if (_csps.Dispatcher != null) { - _csps.Dispatcher.BeginInvoke(DispatcherPriority.Normal, _csps.ReportFinishFuncForHouseAndSettlement, - null, false, string.Empty, resultFileEntries); - } - else { - _csps.ReportFinishFuncForHouseAndSettlement(null, false, string.Empty, resultFileEntries); - } - }*/ - } - } -} \ No newline at end of file diff --git a/Common/SQLResultLogging/InputLoggers/ResultFileEntryLogger.cs b/Common/SQLResultLogging/InputLoggers/ResultFileEntryLogger.cs index a0b74f62..c8ccf90a 100644 --- a/Common/SQLResultLogging/InputLoggers/ResultFileEntryLogger.cs +++ b/Common/SQLResultLogging/InputLoggers/ResultFileEntryLogger.cs @@ -42,6 +42,22 @@ public override void Run(HouseholdKey key, object o) } } + /// + /// Deletes an entry from the result file list in the database + /// + /// The entry to delete + public void DeleteEntry(ResultFileEntry rfe) + { + if (!_isTableCreated) + { + throw new LPGException("Tried to delete entries from a table that did not exist: " + TableName); + } + // create a row as the one already in the database that should be deleted + var row = RowBuilder.Start("Name", Constants.GeneralHouseholdKey) + .Add("Json", JsonConvert.SerializeObject(rfe, Formatting.Indented)).ToDictionary(); + Srls.DeleteEntry(row, TableName, Constants.GeneralHouseholdKey); + } + [ItemNotNull] [NotNull] public List Load() diff --git a/Common/SQLResultLogging/SQLResultLoggingService.cs b/Common/SQLResultLogging/SQLResultLoggingService.cs index 5f4d3e2a..727abfae 100644 --- a/Common/SQLResultLogging/SQLResultLoggingService.cs +++ b/Common/SQLResultLogging/SQLResultLoggingService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Data.SQLite; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -491,6 +492,11 @@ private bool IgnoreThisField([JetBrains.Annotations.NotNull] string fieldname) return false; }*/ + /// + /// Returns whether a matching table for the entry exists + /// + /// The entry for which the table is intended + /// True if a matching table exists, else false private bool IsTableCreated([JetBrains.Annotations.NotNull] SaveableEntry entry) { if (!_createdTablesPerHousehold.ContainsKey(entry.HouseholdKey)) { @@ -539,6 +545,65 @@ private void LoadFileNameDict() _isFileNameDictLoaded = true; } + /// + /// Deletes an entry from a database table + /// + /// A dictionary containing field values of the entry to delete. + /// The name of the table to delete from + /// The HouseholdKey matching the entry + public void DeleteEntry(Dictionary entry, [JetBrains.Annotations.NotNull] string tableName, HouseholdKey householdKey) + { + DeleteEntries(new List> { entry }, tableName, householdKey); + } + + /// + /// Deletes a list of entries from a database table + /// + /// A list of dictionaries, one for each entry to delete. Each dictionary contains field values of the entry to delete. + /// The name of the table to delete entries from + /// The HouseholdKey matching the entries + public void DeleteEntries([JetBrains.Annotations.NotNull][ItemNotNull] List> entries, + [JetBrains.Annotations.NotNull] string tableName, HouseholdKey householdKey) + { + if (entries.Count == 0) + { + // nothing to do + return; + } + + // open the SQLite database connection + string dstFileName = GetFilenameForHouseholdKey(householdKey); + using SQLiteConnection conn = new SQLiteConnection("Data Source=" + dstFileName + ";Version=3"); + conn.Open(); + + // prepare the sql command without the specific conditions + string sqlBase = "DELETE FROM " + tableName + " WHERE "; + using (var transaction = conn.BeginTransaction()) + { + using (var command = conn.CreateCommand()) + { + foreach (Dictionary row in entries) + { + // get an enumerable of "field=@field" strings and concatenate them with AND in between + var conditions = row.Select(pair => pair.Key + " = @" + pair.Key); + string conditionString = string.Join(" AND ", conditions); + // combine base and conditions to full command + command.CommandText = sqlBase + conditionString; + // add all parameter values + command.Parameters.Clear(); + foreach (KeyValuePair pair in row) + { + string parameter = "@" + pair.Key; + command.Parameters.AddWithValue(parameter, pair.Value); + } + command.ExecuteNonQuery(); + } + } + transaction.Commit(); + } + conn.Close(); + } + [JetBrains.Annotations.NotNull] private static string MakeconnectionString([JetBrains.Annotations.NotNull] string filename) => "Data Source=" + filename + ";Version=3;Synchronous=OFF;Journal Mode=WAL;";