Skip to content

Commit

Permalink
Make multiple attempts to remove the temporary melted save file if it…
Browse files Browse the repository at this point in the history
…'s used by another process (#2078) #patch

Sentry event ID: 24c5422a16cb4914ab7fa99143ff62c5
  • Loading branch information
IhateTrains authored Jul 15, 2024
1 parent 94397d4 commit 33db4fc
Show file tree
Hide file tree
Showing 18 changed files with 55 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using Exceptions;
using System.Text;

public static class FileOpeningHelper {
public static class FileHelper {
private const string CloseProgramsHint = "You should close all programs that may be using the file.";

private static bool IsFilesSharingViolation(Exception ex) {
Expand Down Expand Up @@ -45,4 +45,27 @@ public static StreamWriter OpenWriteWithRetries(string filePath, Encoding encodi

return writer;
}

public static void DeleteWithRetries(string filePath) {
const int maxAttempts = 10;

int currentAttempt = 0;

var policy = Policy
.Handle<IOException>(IsFilesSharingViolation)
.WaitAndRetry(maxAttempts,
sleepDurationProvider: _ => TimeSpan.FromSeconds(30),
onRetry: (_, _, _) => {
currentAttempt++;
Logger.Warn($"Attempt {currentAttempt} to delete \"{filePath}\" failed.");
Logger.Warn(CloseProgramsHint);
});

try {
policy.Execute(() => File.Delete(filePath));
} catch (IOException ex) when (IsFilesSharingViolation(ex)) {
Logger.Debug(ex.ToString());
throw new UserErrorException($"Failed to delete \"{filePath}\". {CloseProgramsHint}");
}
}
}
3 changes: 2 additions & 1 deletion ImperatorToCK3/Helpers/RakalyCaller.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using commonItems;
using ImperatorToCK3.CommonUtils;
using ImperatorToCK3.Exceptions;
using System;
using System.ComponentModel;
Expand Down Expand Up @@ -140,7 +141,7 @@ public static void MeltSave(string savePath) {
const string destFileName = "temp/melted_save.rome";
// first, delete target file if exists, as File.Move() does not support overwrite
if (File.Exists(destFileName)) {
File.Delete(destFileName);
FileHelper.DeleteWithRetries(destFileName);
}
File.Move(meltedSaveName, destFileName);
}
Expand Down
4 changes: 2 additions & 2 deletions ImperatorToCK3/Imperator/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private void LaunchImperatorToExportCountryFlags(Configuration config) {

string dataTypesLogPath = Path.Combine(config.ImperatorDocPath, "logs/data_types.log");
if (File.Exists(dataTypesLogPath)) {
File.Delete(dataTypesLogPath);
FileHelper.DeleteWithRetries(dataTypesLogPath);
}

Logger.Debug("Launching Imperator to extract coats of arms...");
Expand Down Expand Up @@ -218,7 +218,7 @@ private static EventHandler HandleImperatorProcessExit(Configuration config, Pro
return (_, _) => {
Logger.Debug($"Imperator process exited with code {imperatorProcess.ExitCode}. Removing temporary mod files...");
try {
File.Delete(Path.Combine(config.ImperatorDocPath, "mod/coa_export_mod.mod"));
FileHelper.DeleteWithRetries(Path.Combine(config.ImperatorDocPath, "mod/coa_export_mod.mod"));
Directory.Delete(Path.Combine(config.ImperatorDocPath, "mod/coa_export_mod"), recursive: true);
} catch (Exception e) {
Logger.Warn($"Failed to remove temporary mod files: {e.Message}");
Expand Down
6 changes: 3 additions & 3 deletions ImperatorToCK3/Outputter/BookmarkOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static async Task OutputBookmark(World world, Configuration config, CK3Lo
sb.AppendLine("}");

var path = Path.Combine("output", config.OutputModName, "common/bookmarks/bookmarks/00_bookmarks.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(path, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(path, Encoding.UTF8);
await output.WriteAsync(sb.ToString());

await DrawBookmarkMap(config, playerTitles, world);
Expand Down Expand Up @@ -141,7 +141,7 @@ Configuration config

private static async Task OutputBookmarkGroup(Configuration config) {
var path = Path.Combine("output", config.OutputModName, "common/bookmarks/groups/00_bookmark_groups.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(path, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(path, Encoding.UTF8);

await output.WriteLineAsync($"bm_converted = {{ default_start_date = {config.CK3BookmarkDate} }}");
}
Expand Down Expand Up @@ -317,6 +317,6 @@ private static async Task ResaveImageAsDDS(string imagePath) {
using (var magickImage = new MagickImage(imagePath)) {
await magickImage.WriteAsync(Path.ChangeExtension(imagePath, ".dds"));
}
File.Delete(imagePath);
FileHelper.DeleteWithRetries(imagePath);
}
}
10 changes: 5 additions & 5 deletions ImperatorToCK3/Outputter/CharactersOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ public static async Task OutputCharacters(string outputPath, CharacterCollection

var sb = new StringBuilder();
var pathForCharactersFromIR = $"{outputPath}/history/characters/IRToCK3_fromImperator.txt";
await using var charactersFromIROutput = FileOpeningHelper.OpenWriteWithRetries(pathForCharactersFromIR);
await using var charactersFromIROutput = FileHelper.OpenWriteWithRetries(pathForCharactersFromIR);
foreach (var character in charactersFromIR) {
CharacterOutputter.WriteCharacter(sb, character, conversionDate);
await charactersFromIROutput.WriteAsync(sb.ToString());
sb.Clear();
}

var pathForCharactersFromCK3 = $"{outputPath}/history/characters/IRToCK3_fromCK3.txt";
await using var charactersFromCK3Output = FileOpeningHelper.OpenWriteWithRetries(pathForCharactersFromCK3, Encoding.UTF8);
await using var charactersFromCK3Output = FileHelper.OpenWriteWithRetries(pathForCharactersFromCK3, Encoding.UTF8);
foreach (var character in charactersFromCK3) {
CharacterOutputter.WriteCharacter(sb, character, conversionDate);
await charactersFromCK3Output.WriteAsync(sb.ToString());
Expand All @@ -64,7 +64,7 @@ public static async Task BlankOutHistoricalPortraitModifiers(ModFilesystem ck3Mo

if (ck3ModFS.GetActualFileLocation(modifiersFilePath) is not null) {
string dummyPath = Path.Combine(outputPath, modifiersFilePath);
await using var output = FileOpeningHelper.OpenWriteWithRetries(dummyPath, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(dummyPath, Encoding.UTF8);
await output.WriteLineAsync("# Dummy file to blank out historical portrait modifiers from CK3.");
}
}
Expand All @@ -74,7 +74,7 @@ private static async Task OutputCharactersDNA(string outputPath, IEnumerable<Cha

// Dump all into one file.
var path = Path.Combine(outputPath, "common/dna_data/IRToCK3_dna_data.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(path, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(path, Encoding.UTF8);

var sb = new StringBuilder();
foreach (var character in charactersWithDNA) {
Expand Down Expand Up @@ -117,7 +117,7 @@ private static async Task OutputPortraitModifiers(string outputPath, IReadOnlyCo
var validAccessoryIDs = GetValidAccessoryIDs(ck3ModFS);

var portraitModifiersOutputPath = Path.Combine(outputPath, "gfx/portraits/portrait_modifiers/IRToCK3_portrait_modifiers.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(portraitModifiersOutputPath, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(portraitModifiersOutputPath, Encoding.UTF8);

await OutputPortraitModifiersForGene("hairstyles", validAccessoryIDs, charactersWithDNA, output, conversionDate);
var malesWithBeards = charactersWithDNA
Expand Down
2 changes: 1 addition & 1 deletion ImperatorToCK3/Outputter/CulturesOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static async Task OutputCultures(string outputModPath, CultureCollection
}

var outputPath = Path.Combine(outputModPath, "common/culture/cultures/IRtoCK3_all_cultures.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await output.WriteAsync(sb.ToString());

await OutputCultureHistory(outputModPath, cultures, date);
Expand Down
4 changes: 2 additions & 2 deletions ImperatorToCK3/Outputter/DynastiesOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static async Task OutputDynasties(string outputModPath, DynastyCollection
}

var outputPath = Path.Combine(outputModPath, "common/dynasties/irtock3_all_dynasties.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, encoding: Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputPath, encoding: Encoding.UTF8);
await output.WriteAsync(sb.ToString());
}

Expand All @@ -32,7 +32,7 @@ public static async Task OutputHouses(string outputModPath, HouseCollection hous
}

var outputPath = Path.Combine(outputModPath, "common/dynasty_houses/irtock3_all_houses.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, encoding: Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputPath, encoding: Encoding.UTF8);
await output.WriteAsync(sb.ToString());
}

Expand Down
4 changes: 2 additions & 2 deletions ImperatorToCK3/Outputter/LocalizationOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static void OutputLocalization(string outputModPath, World ck3World) {
}

var locFilePath = Path.Join(baseReplaceLocDir, language, $"converter_l_{language}.yml");
using var locWriter = FileOpeningHelper.OpenWriteWithRetries(locFilePath, encoding: Encoding.UTF8);
using var locWriter = FileHelper.OpenWriteWithRetries(locFilePath, encoding: Encoding.UTF8);
locWriter.WriteLine(sb.ToString());
sb.Clear();
}
Expand Down Expand Up @@ -76,7 +76,7 @@ private static void OutputFallbackLocForMissingSecondaryLanguageLoc(string baseL
}

var locFilePath = Path.Combine(baseLocDir, $"{language}/irtock3_fallback_loc_l_{language}.yml");
using var locWriter = FileOpeningHelper.OpenWriteWithRetries(locFilePath, Encoding.UTF8);
using var locWriter = FileHelper.OpenWriteWithRetries(locFilePath, Encoding.UTF8);
locWriter.Write(sb.ToString());
sb.Clear();
}
Expand Down
6 changes: 3 additions & 3 deletions ImperatorToCK3/Outputter/MenAtArmsOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ private static void OutputHiddenEvent(string outputModName, IEnumerable<Characte
sb.AppendLine("}");

var outputPath = Path.Combine("output", outputModName, "events", "irtock3_hidden_events.txt");
using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, System.Text.Encoding.UTF8);
using var output = FileHelper.OpenWriteWithRetries(outputPath, System.Text.Encoding.UTF8);
output.Write(sb.ToString());
}

Expand All @@ -49,7 +49,7 @@ private static void OutputMenAtArmsTypes(string outputModName, IdObjectCollectio
}

var outputPath = Path.Combine("output", outputModName, "common/men_at_arms_types/IRToCK3_generated_types.txt");
using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, System.Text.Encoding.UTF8);
using var output = FileHelper.OpenWriteWithRetries(outputPath, System.Text.Encoding.UTF8);
output.Write(sb.ToString());
}

Expand Down Expand Up @@ -105,7 +105,7 @@ private static void OutputGuiContainer(string outputModName, ModFilesystem modFS
sb.AppendLine("}");

var outputPath = Path.Combine("output", outputModName, relativeHudTopGuiPath);
using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, System.Text.Encoding.UTF8);
using var output = FileHelper.OpenWriteWithRetries(outputPath, System.Text.Encoding.UTF8);
output.Write(sb.ToString());
}

Expand Down
2 changes: 1 addition & 1 deletion ImperatorToCK3/Outputter/NamedColorsOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static async Task OutputNamedColors(string outputModPath, NamedColorColle
sb.AppendLine("}");

var outputPath = Path.Combine(outputModPath, "common", "named_colors", "IRtoCK3_colors_from_Imperator.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await output.WriteAsync(sb.ToString());

Logger.IncrementProgress();
Expand Down
2 changes: 1 addition & 1 deletion ImperatorToCK3/Outputter/OnActionOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private static async Task RemoveStruggleStartFromFallenEagleOnActions(ModFilesys
}

var outputPath = $"{outputModPath}/common/on_action/TFE_game_start.txt";
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath);
await using var output = FileHelper.OpenWriteWithRetries(outputPath);
await output.WriteAsync(fileContent);
}
}
2 changes: 1 addition & 1 deletion ImperatorToCK3/Outputter/PillarOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static async Task OutputPillars(string outputPath, PillarCollection pilla
}

var outputFilePath = Path.Combine(outputPath, "common/culture/pillars/IRtoCK3_all_pillars.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputFilePath, System.Text.Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputFilePath, System.Text.Encoding.UTF8);
await output.WriteAsync(sb.ToString());
}
}
2 changes: 1 addition & 1 deletion ImperatorToCK3/Outputter/ProvincesOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Title.LandedTitles titles
// Create province mapping file.
if (alreadyOutputtedProvinces.Count != provinces.Count) {
var mappingsPath = $"{outputModPath}/history/province_mapping/province_mapping.txt";
await using var mappingsWriter = FileOpeningHelper.OpenWriteWithRetries(mappingsPath, System.Text.Encoding.UTF8);
await using var mappingsWriter = FileHelper.OpenWriteWithRetries(mappingsPath, System.Text.Encoding.UTF8);
await using var threadSafeWriter = TextWriter.Synchronized(mappingsWriter);

foreach (var province in provinces) {
Expand Down
4 changes: 2 additions & 2 deletions ImperatorToCK3/Outputter/ReligionsOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private static async Task OutputHolySites(string outputModPath, ReligionCollecti
}

var outputPath = Path.Combine(outputModPath, "common/religion/holy_sites/IRtoCK3_sites.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await output.WriteAsync(sb.ToString());
sb.Clear();

Expand Down Expand Up @@ -64,7 +64,7 @@ private static async Task OutputReligions(string outputModPath, ReligionCollecti
}

var outputPath = Path.Combine(outputModPath, "common/religion/religions/IRtoCK3_all_religions.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await output.WriteAsync(sb.ToString());
}
}
2 changes: 1 addition & 1 deletion ImperatorToCK3/Outputter/SuccessionTriggersOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static async Task OutputSuccessionTriggers(string outputModPath, Title.La
sb.AppendLine("}");

var outputPath = Path.Combine(outputModPath, "common/scripted_triggers/IRToCK3_succession_triggers.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputPath, Encoding.UTF8);
await output.WriteAsync(sb.ToString());

Logger.IncrementProgress();
Expand Down
2 changes: 1 addition & 1 deletion ImperatorToCK3/Outputter/TitlesOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static async Task OutputTitles(string outputModPath, Title.LandedTitles t
sb.Append(PDXSerializer.Serialize(topDeJureTitles, string.Empty, withBraces: false));

var outputPath = Path.Combine(outputModPath, "common/landed_titles/00_landed_titles.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(outputPath, System.Text.Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(outputPath, System.Text.Encoding.UTF8);
await output.WriteAsync(sb.ToString());

await OutputTitlesHistory(outputModPath, titles);
Expand Down
2 changes: 1 addition & 1 deletion ImperatorToCK3/Outputter/WarsOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static async Task OutputWars(string outputModPath, IEnumerable<War> wars)
}

var path = Path.Combine(outputModPath, "history/wars/00_wars.txt");
await using var output = FileOpeningHelper.OpenWriteWithRetries(path, Encoding.UTF8);
await using var output = FileHelper.OpenWriteWithRetries(path, Encoding.UTF8);
await output.WriteAsync(sb.ToString());

Logger.IncrementProgress();
Expand Down
4 changes: 2 additions & 2 deletions ImperatorToCK3/Outputter/WorldOutputter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ private static void OutputPlaysetInfo(World ck3World, string outputModName) {

const string outFilePath = "playset_info.txt";
if (File.Exists(outFilePath)) {
File.Delete(outFilePath);
FileHelper.DeleteWithRetries(outFilePath);
}
using var output = FileOpeningHelper.OpenWriteWithRetries(outFilePath, Encoding.UTF8);
using var output = FileHelper.OpenWriteWithRetries(outFilePath, Encoding.UTF8);

foreach (var mod in modsForPlayset) {
output.WriteLine($"{mod.Name.AddQuotes()}={mod.Path.AddQuotes()}");
Expand Down

0 comments on commit 33db4fc

Please sign in to comment.