Skip to content

Commit 96e54b9

Browse files
committed
- Ensure all semaphore slim lock references are structured as :
Lock -> Try -> Finally(Unlock) To ensure no deadlock cases exist due to unexpected errors. - Batch cache updates to the end of the process for full-modlist enable/disable.
1 parent 1b38826 commit 96e54b9

File tree

3 files changed

+545
-496
lines changed

3 files changed

+545
-496
lines changed

xivModdingFramework/Mods/Modding.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using System.Linq;
2323
using System.Threading;
2424
using System.Threading.Tasks;
25+
using xivModdingFramework.Cache;
2526
using xivModdingFramework.General.Enums;
2627
using xivModdingFramework.Helpers;
2728
using xivModdingFramework.Mods.DataContainers;
@@ -387,6 +388,7 @@ public async Task ToggleAllMods(bool enable, IProgress<(int current, int total,
387388

388389
if (modList == null || modList.modCount == 0) return;
389390

391+
390392
var modNum = 0;
391393
foreach (var modEntry in modList.Mods)
392394
{
@@ -412,20 +414,27 @@ public async Task ToggleAllMods(bool enable, IProgress<(int current, int total,
412414
// Standard mod.
413415
if (enable && !modEntry.enabled)
414416
{
415-
await index.UpdateDataOffset(modEntry.data.modOffset, modEntry.fullPath);
417+
await index.UpdateDataOffset(modEntry.data.modOffset, modEntry.fullPath, false);
416418
modEntry.enabled = true;
417419
}
418420
else if (!enable && modEntry.enabled)
419421
{
420-
await index.UpdateDataOffset(modEntry.data.originalOffset, modEntry.fullPath);
422+
await index.UpdateDataOffset(modEntry.data.originalOffset, modEntry.fullPath, false);
421423
modEntry.enabled = false;
422424
}
423425
}
424426

425427
progress?.Report((++modNum, modList.Mods.Count, string.Empty));
426428
}
427429

430+
428431
SaveModList(modList);
432+
433+
434+
// Do these as a batch query at the end.
435+
progress?.Report((++modNum, modList.Mods.Count, "Adding modified files to Cache Queue..."));
436+
var allPaths = modList.Mods.Select(x => x.fullPath).Where(x => !String.IsNullOrEmpty(x)).ToList();
437+
await XivCache.QueueDependencyUpdate(allPaths);
429438
}
430439

431440
/// <summary>

xivModdingFramework/SqPack/FileTypes/Dat.cs

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,16 @@ public int CreateNewDat(XivDataFile dataFile)
9797
public int GetLargestDatNumber(XivDataFile dataFile)
9898
{
9999

100+
string[] allFiles = null;
100101
_lock.Wait();
101-
var allFiles = Directory.GetFiles(_gameDirectory.FullName);
102-
_lock.Release();
102+
try
103+
{
104+
allFiles = Directory.GetFiles(_gameDirectory.FullName);
105+
}
106+
finally
107+
{
108+
_lock.Release();
109+
}
103110

104111
var dataFiles = from file in allFiles where file.Contains(dataFile.GetDataFileName()) && file.Contains(".dat") select file;
105112

@@ -146,29 +153,35 @@ public async Task<List<string>> GetModdedDatList(XivDataFile dataFile)
146153
await Task.Run(async () =>
147154
{
148155
await _lock.WaitAsync();
149-
for (var i = 1; i < 20; i++)
156+
try
150157
{
151-
var datFilePath = $"{_gameDirectory}/{dataFile.GetDataFileName()}.win32.dat{i}";
152-
153-
if (File.Exists(datFilePath))
158+
for (var i = 1; i < 20; i++)
154159
{
155-
// Due to an issue where 060000 dat1 gets deleted, we are skipping it here
156-
if (datFilePath.Contains("060000.win32.dat1"))
157-
{
158-
continue;
159-
}
160-
using (var binaryReader = new BinaryReader(File.OpenRead(datFilePath)))
161-
{
162-
binaryReader.BaseStream.Seek(24, SeekOrigin.Begin);
160+
var datFilePath = $"{_gameDirectory}/{dataFile.GetDataFileName()}.win32.dat{i}";
163161

164-
if (binaryReader.ReadByte() == 0)
162+
if (File.Exists(datFilePath))
163+
{
164+
// Due to an issue where 060000 dat1 gets deleted, we are skipping it here
165+
if (datFilePath.Contains("060000.win32.dat1"))
165166
{
166-
datList.Add(datFilePath);
167+
continue;
168+
}
169+
using (var binaryReader = new BinaryReader(File.OpenRead(datFilePath)))
170+
{
171+
binaryReader.BaseStream.Seek(24, SeekOrigin.Begin);
172+
173+
if (binaryReader.ReadByte() == 0)
174+
{
175+
datList.Add(datFilePath);
176+
}
167177
}
168178
}
169179
}
170180
}
171-
_lock.Release();
181+
finally
182+
{
183+
_lock.Release();
184+
}
172185
});
173186
return datList;
174187
}
@@ -1317,22 +1330,27 @@ public async Task<int> WriteToDat(List<byte> importData, Mod modEntry, string in
13171330

13181331

13191332
await _lock.WaitAsync();
1320-
// If there is an existing modlist entry, use that data to get the modDatPath
1321-
if (modEntry != null)
1333+
try
13221334
{
1323-
datNum = ((modEntry.data.modOffset / 8) & 0x0F) / 2;
1324-
modDatPath = Path.Combine(_gameDirectory.FullName, $"{modEntry.datFile}{DatExtension}{datNum}");
1325-
1326-
if (!File.Exists(modDatPath))
1335+
// If there is an existing modlist entry, use that data to get the modDatPath
1336+
if (modEntry != null)
13271337
{
1328-
_lock.Release();
1329-
throw new Exception($"A mod entry is pointing to {Path.GetFileName(modDatPath)}, but the file does not exist.\n\n" +
1330-
$"It is recommended to do a Start Over.");
1338+
datNum = ((modEntry.data.modOffset / 8) & 0x0F) / 2;
1339+
modDatPath = Path.Combine(_gameDirectory.FullName, $"{modEntry.datFile}{DatExtension}{datNum}");
1340+
1341+
if (!File.Exists(modDatPath))
1342+
{
1343+
throw new Exception($"A mod entry is pointing to {Path.GetFileName(modDatPath)}, but the file does not exist.\n\n" +
1344+
$"It is recommended to do a Start Over.");
1345+
}
13311346
}
1332-
}
13331347

1334-
var fileLength = new FileInfo(modDatPath).Length;
1335-
_lock.Release();
1348+
var fileLength = new FileInfo(modDatPath).Length;
1349+
}
1350+
finally
1351+
{
1352+
_lock.Release();
1353+
}
13361354

13371355
// Checks to make sure the offsets in the mod list are not 0
13381356
// If they are 0, something went wrong in the import proccess (Technically shouldn't happen)
@@ -1606,7 +1624,7 @@ where entry.fullPath.Equals(modEntry.fullPath)
16061624
}
16071625

16081626
// Queue our dependency information updates.
1609-
XivCache.QueueDependencyUpdate(internalFilePath);
1627+
await XivCache.QueueDependencyUpdate(internalFilePath);
16101628

16111629
return offset;
16121630
}

0 commit comments

Comments
 (0)