Skip to content

Commit 88b9292

Browse files
committed
Mitigates false positives while handling the config cache.
1 parent 2bd18a2 commit 88b9292

File tree

1 file changed

+28
-16
lines changed

1 file changed

+28
-16
lines changed

Source/ModuleManager/MMPatchLoader.cs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ public class MMPatchLoader : LoadingSystem
3333
private static readonly KeyValueCache<string, Regex> regexCache = new KeyValueCache<string, Regex>();
3434

3535
private string configSha;
36-
private readonly Dictionary<string, string> filesSha = new Dictionary<string, string>();
36+
private int totalConfigFilesSize;
37+
private readonly Dictionary<string, string> filesShaMap = new Dictionary<string, string>();
38+
private readonly Dictionary<string, int> filesSizeMap = new Dictionary<string, int>();
3739

3840
private const int STATUS_UPDATE_INVERVAL_MS = 33;
3941

@@ -271,28 +273,32 @@ private bool IsCacheUpToDate()
271273
System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create();
272274
System.Security.Cryptography.SHA256 filesha = System.Security.Cryptography.SHA256.Create();
273275
UrlDir.UrlFile[] files = GameDatabase.Instance.root.AllConfigFiles.ToArray();
276+
this.totalConfigFilesSize = 0;
274277

275-
filesSha.Clear();
278+
this.filesShaMap.Clear();
279+
this.filesSizeMap.Clear();
276280

277281
for (int i = 0; i < files.Length; i++)
278282
{
279283
string url = files[i].GetUrlWithExtension();
280284
// Hash the file path so the checksum change if files are moved
281285
byte[] pathBytes = Encoding.UTF8.GetBytes(url);
282286
sha.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
287+
this.totalConfigFilesSize += pathBytes.Length;
283288

284289
// hash the file content
285290
byte[] contentBytes = File.ReadAllBytes(files[i].fullPath);
286291
sha.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0);
287292

288293
filesha.ComputeHash(contentBytes);
289-
if (!filesSha.ContainsKey(url))
294+
if (!(this.filesShaMap.ContainsKey(url) || this.filesSizeMap.ContainsKey(url)))
290295
{
291-
filesSha.Add(url, BitConverter.ToString(filesha.Hash));
296+
this.filesShaMap.Add(url, BitConverter.ToString(filesha.Hash));
297+
this.filesSizeMap.Add(url, contentBytes.Length);
292298
}
293299
else
294300
{
295-
logger.Warning("Duplicate fileSha key. This should not append. The key is " + url);
301+
logger.Warning("Duplicate filesShaMap/filesSizeMap key. This should not append. The key is {0}" + url);
296302
}
297303
}
298304

@@ -336,12 +342,15 @@ select s.modName
336342
logger.Info("ConfigSHA loaded");
337343
if (SHA_CONFIG.Node != null && SHA_CONFIG.Node.HasValue("SHA") && SHA_CONFIG.Node.HasValue("version") && SHA_CONFIG.Node.HasValue("KSPVersion"))
338344
{
339-
string storedSHA = SHA_CONFIG.Node.GetValue("SHA");
340-
string version = SHA_CONFIG.Node.GetValue("version");
341-
string kspVersion = SHA_CONFIG.Node.GetValue("KSPVersion");
342-
ConfigNode filesShaNode = SHA_CONFIG.Node.GetNode("FilesSHA");
345+
KSPe.ConfigNodeWithSteroids cs = KSPe.ConfigNodeWithSteroids.from(SHA_CONFIG.Node);
346+
string storedSHA = cs.GetValue("SHA","");
347+
int storedTotalSize = cs.GetValue<int>("SIZE", -1);
348+
string version = cs.GetValue("version","");
349+
string kspVersion = cs.GetValue("KSPVersion","");
350+
ConfigNode filesShaNode = cs.GetNode("FilesSHA");
343351
useCache = CheckFilesChange(files, filesShaNode);
344352
useCache = useCache && storedSHA.Equals(configSha);
353+
useCache = useCache && storedTotalSize == this.totalConfigFilesSize;
345354
useCache = useCache && version.Equals(Assembly.GetExecutingAssembly().GetName().Version.ToString());
346355
useCache = useCache && kspVersion.Equals(Versioning.version_major + "." + Versioning.version_minor + "." + Versioning.Revision + "." + Versioning.BuildID);
347356
useCache = useCache && CACHE_CONFIG.IsLoadable;
@@ -362,12 +371,13 @@ private bool CheckFilesChange(UrlDir.UrlFile[] files, ConfigNode shaConfigNode)
362371
{
363372
string url = files[i].GetUrlWithExtension();
364373
ConfigNode fileNode = GetFileNode(shaConfigNode, url);
365-
string fileSha = fileNode?.GetValue("SHA");
374+
if (fileNode == null) continue;
366375

367-
if (fileNode == null)
368-
continue;
376+
KSPe.ConfigNodeWithSteroids cs = KSPe.ConfigNodeWithSteroids.from(fileNode);
377+
string fileSha = cs.GetValue("SHA", "");
378+
int fileSize = cs.GetValue<int>("SIZE", -1);
369379

370-
if (fileSha == null || filesSha[url] != fileSha)
380+
if (-1 == fileSize || String.IsNullOrEmpty(fileSha) || filesShaMap[url] != fileSha)
371381
{
372382
logger.Info("Changed : " + fileNode.GetValue("filename") + ".cfg");
373383
noChange = false;
@@ -411,6 +421,7 @@ private void CreateCache(IEnumerable<IProtoUrlConfig> databaseConfigs, int patch
411421
{
412422
SHA_CONFIG.Clear();
413423
SHA_CONFIG.Node.AddValue("SHA", configSha);
424+
SHA_CONFIG.Node.AddValue("SIZE", this.totalConfigFilesSize);
414425
SHA_CONFIG.Node.AddValue("version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
415426
SHA_CONFIG.Node.AddValue("KSPVersion", Versioning.version_major + "." + Versioning.version_minor + "." + Versioning.Revision + "." + Versioning.BuildID);
416427
ConfigNode filesSHANode = SHA_CONFIG.Node.AddNode("FilesSHA");
@@ -433,12 +444,13 @@ private void CreateCache(IEnumerable<IProtoUrlConfig> databaseConfigs, int patch
433444
{
434445
string url = file.GetUrlWithExtension();
435446
// "/Physics" is the node we created manually to loads the PHYSIC config
436-
if (file.url != "/Physics" && filesSha.ContainsKey(url))
447+
if (file.url != "/Physics" && filesShaMap.ContainsKey(url))
437448
{
438449
ConfigNode shaNode = filesSHANode.AddNode("FILE");
439450
shaNode.AddValue("filename", url);
440-
shaNode.AddValue("SHA", filesSha[url]);
441-
filesSha.Remove(url);
451+
shaNode.AddValue("SHA", filesShaMap[url]);
452+
shaNode.AddValue("SIZE", this.filesSizeMap[url]);
453+
filesShaMap.Remove(url);
442454
}
443455
}
444456

0 commit comments

Comments
 (0)