Changeset 16325


Ignore:
Timestamp:
11/23/18 15:37:24 (4 weeks ago)
Author:
pfleck
Message:

#2965

  • Added CancelationTokens for the Save and Serialize methods.
  • Fixed a potential temp-file-leak when replacing the old file with the new one after serialization.
Location:
branches/2965_CancelablePersistence
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/2965_CancelablePersistence/HeuristicLab.Common/3.3/Content/ContentManager.cs

    r15583 r16325  
    2121
    2222using System;
     23using System.Threading;
    2324
    2425namespace HeuristicLab.Common {
     
    4344      if (instance == null) throw new InvalidOperationException("ContentManager is not initialized.");
    4445      var func = new Func<string, IStorableContent>(instance.LoadContent);
    45       func.BeginInvoke(filename, delegate(IAsyncResult result) {
     46      func.BeginInvoke(filename, delegate (IAsyncResult result) {
    4647        Exception error = null;
    4748        IStorableContent content = null;
     
    4950          content = func.EndInvoke(result);
    5051          content.Filename = filename;
    51         }
    52         catch (Exception ex) {
     52        } catch (Exception ex) {
    5353          error = ex;
    5454        }
     
    5858    protected abstract IStorableContent LoadContent(string filename);
    5959
    60     public static void Save(IStorableContent content, string filename, bool compressed) {
     60    public static void Save(IStorableContent content, string filename, bool compressed, CancellationToken cancellationToken = default(CancellationToken)) {
    6161      if (instance == null) throw new InvalidOperationException("ContentManager is not initialized.");
    62       instance.SaveContent(content, filename, compressed);
     62      instance.SaveContent(content, filename, compressed, cancellationToken);
    6363      content.Filename = filename;
    6464    }
    65     public static void SaveAsync(IStorableContent content, string filename, bool compressed, Action<IStorableContent, Exception> savingCompletedCallback) {
     65    public static void SaveAsync(IStorableContent content, string filename, bool compressed, Action<IStorableContent, Exception> savingCompletedCallback, CancellationToken cancellationToken = default(CancellationToken)) {
    6666      if (instance == null) throw new InvalidOperationException("ContentManager is not initialized.");
    67       var action = new Action<IStorableContent, string, bool>(instance.SaveContent);
    68       action.BeginInvoke(content, filename, compressed, delegate(IAsyncResult result) {
     67      var action = new Action<IStorableContent, string, bool, CancellationToken>(instance.SaveContent);
     68      action.BeginInvoke(content, filename, compressed, cancellationToken, delegate (IAsyncResult result) {
    6969        Exception error = null;
    7070        try {
    7171          action.EndInvoke(result);
    7272          content.Filename = filename;
    73         }
    74         catch (Exception ex) {
     73        } catch (Exception ex) {
    7574          error = ex;
    7675        }
     
    7978
    8079    }
    81     protected abstract void SaveContent(IStorableContent content, string filename, bool compressed);
     80    protected abstract void SaveContent(IStorableContent content, string filename, bool compressed, CancellationToken cancellationToken);
    8281  }
    8382}
  • branches/2965_CancelablePersistence/HeuristicLab.Core/3.3/PersistenceContentManager.cs

    r15583 r16325  
    2121
    2222using System.IO.Compression;
     23using System.Threading;
    2324using HeuristicLab.Common;
    2425using HeuristicLab.Persistence.Default.Xml;
     
    3233    }
    3334
    34     protected override void SaveContent(IStorableContent content, string filename, bool compressed) {
    35       XmlGenerator.Serialize(content, filename, compressed ? CompressionLevel.Optimal : CompressionLevel.NoCompression);
     35    protected override void SaveContent(IStorableContent content, string filename, bool compressed, CancellationToken cancellationToken) {
     36      XmlGenerator.Serialize(content, filename, compressed ? CompressionLevel.Optimal : CompressionLevel.NoCompression, cancellationToken);
    3637    }
    3738  }
  • branches/2965_CancelablePersistence/HeuristicLab.Optimizer/3.3/FileManager.cs

    r15583 r16325  
    2323using System.Collections.Generic;
    2424using System.IO;
     25using System.Threading;
    2526using System.Windows.Forms;
    2627using HeuristicLab.Common;
     
    7879        if (view == null)
    7980          ErrorHandling.ShowErrorDialog("There is no view for the loaded item. It cannot be displayed.", new InvalidOperationException("No View Available"));
    80       }
    81       catch (Exception ex) {
     81      } catch (Exception ex) {
    8282        ErrorHandling.ShowErrorDialog((Control)MainFormManager.MainForm, "Cannot open file.", ex);
    83       }
    84       finally {
     83      } finally {
    8584        ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).ResetAppStartingCursor();
    8685      }
     
    10099        else {
    101100          MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().SetAppStartingCursor();
     101          var cancellationTokenSource = new CancellationTokenSource();
    102102          SetSaveOperationProgressInContentViews(content, true);
    103           ContentManager.SaveAsync(content, content.Filename, true, SavingCompleted);
     103          ContentManager.SaveAsync(content, content.Filename, true, SavingCompleted, cancellationTokenSource.Token);
    104104        }
    105105      }
     
    132132        if (saveFileDialog.ShowDialog() == DialogResult.OK) {
    133133          MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().SetAppStartingCursor();
    134           SetSaveOperationProgressInContentViews(content, true, saveFileDialog.FileName);
    135           if (saveFileDialog.FilterIndex == 1) {
    136             ContentManager.SaveAsync(content, saveFileDialog.FileName, false, SavingCompleted);
    137           } else {
    138             ContentManager.SaveAsync(content, saveFileDialog.FileName, true, SavingCompleted);
    139           }
     134          bool compressed = saveFileDialog.FilterIndex != 1;
     135          var cancellationTokenSource = new CancellationTokenSource();
     136          SetSaveOperationProgressInContentViews(content, compressed, saveFileDialog.FileName);
     137
     138          ContentManager.SaveAsync(content, saveFileDialog.FileName, compressed, SavingCompleted, cancellationTokenSource.Token);
    140139        }
    141140      }
     
    145144        if (error != null) throw error;
    146145        MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().UpdateTitle();
    147       }
    148       catch (Exception ex) {
     146      } catch (Exception ex) {
    149147        ErrorHandling.ShowErrorDialog((Control)MainFormManager.MainForm, "Cannot save file.", ex);
    150       }
    151       finally {
     148      } finally {
    152149        SetSaveOperationProgressInContentViews(content, false);
    153150        MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().ResetAppStartingCursor();
     
    167164      #endregion
    168165    }
     166
     167    /* For later merge with #2845
     168    private static void AddProgressInContentViews(IStorableContent content, CancellationTokenSource cancellationTokenSource, string fileName = null) {
     169      string message = string.Format("Saving to file \"{0}\"...", Path.GetFileName(fileName ?? content.Filename));
     170      Progress.Show(content, message, ProgressMode.Indeterminate, cancelRequestHandler: () => cancellationTokenSource.Cancel());
     171    }*/
    169172  }
    170173}
  • branches/2965_CancelablePersistence/HeuristicLab.Persistence/3.3/Default/Xml/XmlGenerator.cs

    r15583 r16325  
    2626using System.Linq;
    2727using System.Text;
     28using System.Threading;
    2829using HeuristicLab.Persistence.Core;
    2930using HeuristicLab.Persistence.Core.Tokens;
     
    6162    }
    6263
    63     protected enum NodeType { Start, End, Inline } ;
     64    protected enum NodeType { Start, End, Inline };
    6465
    6566    protected static void AddXmlTagContent(StringBuilder sb, string name, Dictionary<string, string> attributes) {
     
    256257          {"typeName", lastTypeToken.TypeName },
    257258          {"serializer", lastTypeToken.Serializer }});
    258       }
    259       finally {
     259      } finally {
    260260        lastTypeToken = null;
    261261      }
     
    284284    /// <param name="o">The object.</param>
    285285    /// <param name="filename">The filename.</param>
    286     public static void Serialize(object o, string filename) {
    287       Serialize(o, filename, ConfigurationService.Instance.GetConfiguration(new XmlFormat()), false, CompressionLevel.Optimal);
     286    public static void Serialize(object o, string filename, CancellationToken cancellationToken = default(CancellationToken)) {
     287      Serialize(o, filename, ConfigurationService.Instance.GetConfiguration(new XmlFormat()), false, CompressionLevel.Optimal, cancellationToken);
    288288    }
    289289
     
    296296    /// <param name="filename">The filename.</param>
    297297    /// <param name="compression">ZIP file compression level</param>
    298     public static void Serialize(object o, string filename, CompressionLevel compression) {
    299       Serialize(o, filename, ConfigurationService.Instance.GetConfiguration(new XmlFormat()), false, compression);
     298    public static void Serialize(object o, string filename, CompressionLevel compression, CancellationToken cancellationToken = default(CancellationToken)) {
     299      Serialize(o, filename, ConfigurationService.Instance.GetConfiguration(new XmlFormat()), false, compression, cancellationToken);
    300300    }
    301301
     
    307307    /// <param name="filename">The filename.</param>
    308308    /// <param name="config">The configuration.</param>
    309     public static void Serialize(object obj, string filename, Configuration config) {
    310       Serialize(obj, filename, config, false, CompressionLevel.Optimal);
    311     }
    312 
    313     private static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies
    314    , CompressionLevel compression) {
     309    public static void Serialize(object obj, string filename, Configuration config, CancellationToken cancellationToken = default(CancellationToken)) {
     310      Serialize(obj, filename, config, false, CompressionLevel.Optimal, cancellationToken);
     311    }
     312
     313    private static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies, CompressionLevel compression, CancellationToken cancellationToken = default(CancellationToken)) {
    315314      Serializer serializer = new Serializer(obj, config);
    316       Serialize(stream, includeAssemblies, compression, serializer);
    317     }
    318 
    319     private static void Serialize(Stream stream, bool includeAssemblies, CompressionLevel compression, Serializer serializer) {
     315      Serialize(stream, includeAssemblies, compression, serializer, cancellationToken);
     316    }
     317
     318    private static void Serialize(Stream stream, bool includeAssemblies, CompressionLevel compression, Serializer serializer, CancellationToken cancellationToken = default(CancellationToken)) {
    320319      try {
     320        cancellationToken.ThrowIfCancellationRequested();
    321321        DateTime start = DateTime.Now;
    322322        serializer.InterleaveTypeInformation = false;
     
    326326          using (StreamWriter writer = new StreamWriter(entry.Open())) {
    327327            foreach (ISerializationToken token in serializer) {
     328              cancellationToken.ThrowIfCancellationRequested();
    328329              string line = generator.Format(token);
    329330              writer.Write(line);
     
    338339          if (includeAssemblies) {
    339340            foreach (string name in serializer.RequiredFiles) {
     341              cancellationToken.ThrowIfCancellationRequested();
    340342              Uri uri = new Uri(name);
    341343              if (!uri.IsFile) {
     
    348350                  byte[] buffer = new byte[1024 * 1024];
    349351                  while (true) {
     352                    cancellationToken.ThrowIfCancellationRequested();
    350353                    int bytesRead = reader.Read(buffer, 0, 1024 * 1024);
    351354                    if (bytesRead == 0)
     
    360363        Logger.Info(String.Format("serialization took {0} seconds with compression level {1}",
    361364          (DateTime.Now - start).TotalSeconds, compression));
    362       }
    363       catch (Exception) {
     365      } catch (Exception) {
    364366        Logger.Warn("Exception caught, no data has been serialized.");
    365367        throw;
     
    375377    /// <param name="includeAssemblies">if set to <c>true</c> include needed assemblies.</param>
    376378    /// <param name="compression">The ZIP compression level.</param>
    377     public static void Serialize(object obj, string filename, Configuration config, bool includeAssemblies, CompressionLevel compression) {
     379    public static void Serialize(object obj, string filename, Configuration config, bool includeAssemblies, CompressionLevel compression, CancellationToken cancellationToken = default(CancellationToken)) {
     380      string tempfile = null;
    378381      try {
    379         string tempfile = Path.GetTempFileName();
     382        tempfile = Path.GetTempFileName();
    380383
    381384        using (FileStream stream = File.Create(tempfile)) {
    382           Serialize(obj, stream, config, includeAssemblies, compression);
    383         }
    384 
     385          Serialize(obj, stream, config, includeAssemblies, compression, cancellationToken);
     386        }
     387        // copy only if needed
    385388        File.Copy(tempfile, filename, true);
    386         File.Delete(tempfile);
    387       }
    388       catch (Exception) {
     389      } catch (Exception) {
    389390        Logger.Warn("Exception caught, no data has been written.");
    390391        throw;
     392      } finally {
     393        if (tempfile != null && File.Exists(tempfile))
     394          File.Delete(tempfile);
    391395      }
    392396    }
     
    399403    /// <param name="stream">The stream.</param>
    400404    /// <param name="compressionType">Type of compression, default is GZip.</param>
    401     public static void Serialize(object obj, Stream stream, CompressionType compressionType = CompressionType.GZip) {
    402       Serialize(obj, stream, ConfigurationService.Instance.GetConfiguration(new XmlFormat()), compressionType);
     405    public static void Serialize(object obj, Stream stream, CompressionType compressionType = CompressionType.GZip, CancellationToken cancellationToken = default(CancellationToken)) {
     406      Serialize(obj, stream, ConfigurationService.Instance.GetConfiguration(new XmlFormat()), compressionType, cancellationToken);
    403407    }
    404408
     
    411415    /// <param name="config">The configuration.</param>
    412416    /// <param name="compressionType">Type of compression, default is GZip.</param>
    413     public static void Serialize(object obj, Stream stream, Configuration config, CompressionType compressionType = CompressionType.GZip) {
    414       Serialize(obj, stream, config, false, compressionType);
     417    public static void Serialize(object obj, Stream stream, Configuration config, CompressionType compressionType = CompressionType.GZip, CancellationToken cancellationToken = default(CancellationToken)) {
     418      Serialize(obj, stream, config, false, compressionType, cancellationToken);
    415419    }
    416420
     
    423427    /// <param name="includeAssemblies">if set to <c>true</c> include need assemblies.</param>
    424428    /// <param name="compressionType">Type of compression, default is GZip.</param>
    425     public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies,
    426                                  CompressionType compressionType = CompressionType.GZip) {
     429    public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies, CompressionType compressionType = CompressionType.GZip, CancellationToken cancellationToken = default(CancellationToken)) {
    427430      try {
    428431        Serializer serializer = new Serializer(obj, config);
    429432        if (compressionType == CompressionType.Zip) {
    430           Serialize(obj, stream, config, includeAssemblies, CompressionLevel.Optimal);
     433          Serialize(obj, stream, config, includeAssemblies, CompressionLevel.Optimal, cancellationToken);
    431434        } else {
    432           Serialize(stream, serializer);
    433         }
    434       }
    435       catch (PersistenceException) {
     435          Serialize(stream, serializer, cancellationToken);
     436        }
     437      } catch (PersistenceException) {
    436438        throw;
    437       }
    438       catch (Exception e) {
     439      } catch (Exception e) {
    439440        throw new PersistenceException("Unexpected exception during Serialization.", e);
    440441      }
     
    451452    /// <param name="compressionType">Type of compression, default is GZip.</param>
    452453    public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies, out IEnumerable<Type> types,
    453                                  CompressionType compressionType = CompressionType.GZip) {
     454                                 CompressionType compressionType = CompressionType.GZip, CancellationToken cancellationToken = default(CancellationToken)) {
    454455      try {
    455456        Serializer serializer = new Serializer(obj, config);
    456457        if (compressionType == CompressionType.Zip) {
    457           Serialize(stream, includeAssemblies, CompressionLevel.Optimal, serializer);
     458          Serialize(stream, includeAssemblies, CompressionLevel.Optimal, serializer, cancellationToken);
    458459        } else {
    459           Serialize(stream, serializer);
     460          Serialize(stream, serializer, cancellationToken);
    460461        }
    461462        types = serializer.SerializedTypes;
    462       }
    463       catch (PersistenceException) {
     463      } catch (PersistenceException) {
    464464        throw;
    465       }
    466       catch (Exception e) {
     465      } catch (Exception e) {
    467466        throw new PersistenceException("Unexpected exception during Serialization.", e);
    468467      }
    469468    }
    470469
    471     private static void Serialize(Stream stream, Serializer serializer) {
     470    private static void Serialize(Stream stream, Serializer serializer, CancellationToken cancellationToken = default(CancellationToken)) {
     471      cancellationToken.ThrowIfCancellationRequested();
    472472      using (StreamWriter writer = new StreamWriter(new GZipStream(stream, CompressionMode.Compress))) {
    473473        serializer.InterleaveTypeInformation = true;
    474474        XmlGenerator generator = new XmlGenerator();
    475475        foreach (ISerializationToken token in serializer) {
     476          cancellationToken.ThrowIfCancellationRequested();
    476477          string line = generator.Format(token);
    477478          writer.Write(line);
Note: See TracChangeset for help on using the changeset viewer.