未验证 提交 1e8302c5 编写于 作者: M msftbot[bot] 提交者: GitHub

Merge pull request #43980 from CyrusNajmabadi/dirInfo

Don't cache FileInfo instances.
...@@ -90,7 +90,6 @@ private class Updater ...@@ -90,7 +90,6 @@ private class Updater
private readonly SymbolSearchUpdateEngine _service; private readonly SymbolSearchUpdateEngine _service;
private readonly string _source; private readonly string _source;
private readonly DirectoryInfo _cacheDirectoryInfo; private readonly DirectoryInfo _cacheDirectoryInfo;
private readonly FileInfo _databaseFileInfo;
public Updater(SymbolSearchUpdateEngine service, string source, string localSettingsDirectory) public Updater(SymbolSearchUpdateEngine service, string source, string localSettingsDirectory)
{ {
...@@ -99,9 +98,6 @@ public Updater(SymbolSearchUpdateEngine service, string source, string localSett ...@@ -99,9 +98,6 @@ public Updater(SymbolSearchUpdateEngine service, string source, string localSett
_cacheDirectoryInfo = new DirectoryInfo(Path.Combine( _cacheDirectoryInfo = new DirectoryInfo(Path.Combine(
localSettingsDirectory, "PackageCache", string.Format(Invariant($"Format{AddReferenceDatabase.TextFileFormatVersion}")))); localSettingsDirectory, "PackageCache", string.Format(Invariant($"Format{AddReferenceDatabase.TextFileFormatVersion}"))));
_databaseFileInfo = new FileInfo(
Path.Combine(_cacheDirectoryInfo.FullName, ConvertToFileName(source) + ".txt"));
} }
/// <summary> /// <summary>
...@@ -175,19 +171,25 @@ private async Task<TimeSpan> UpdateDatabaseInBackgroundWorkerAsync(CancellationT ...@@ -175,19 +171,25 @@ private async Task<TimeSpan> UpdateDatabaseInBackgroundWorkerAsync(CancellationT
{ {
await CleanCacheDirectoryAsync(cancellationToken).ConfigureAwait(false); await CleanCacheDirectoryAsync(cancellationToken).ConfigureAwait(false);
// If we have a local database, then see if it needs to be patched. // If we have a local database, then see if it needs to be patched. Otherwise download the full
// Otherwise download the full database. // database.
// //
// (intentionally not wrapped in IOUtilities. If this throws we want to restart). // (intentionally not wrapped in IOUtilities. If this throws we want to restart).
if (_service._ioService.Exists(_databaseFileInfo)) //
// Ensure we get a fresh FileInfo for the db. We need to make sure that the data we're querying
// (like .Exists) is up to date and isn't the a cached value from a prior run.
var databaseFileInfo = new FileInfo(
Path.Combine(_cacheDirectoryInfo.FullName, ConvertToFileName(_source) + ".txt"));
if (_service._ioService.Exists(databaseFileInfo))
{ {
await _service.LogInfoAsync("Local database file exists. Patching local database").ConfigureAwait(false); await _service.LogInfoAsync("Local database file exists. Patching local database").ConfigureAwait(false);
return await PatchLocalDatabaseAsync(cancellationToken).ConfigureAwait(false); return await PatchLocalDatabaseAsync(databaseFileInfo, cancellationToken).ConfigureAwait(false);
} }
else else
{ {
await _service.LogInfoAsync("Local database file does not exist. Downloading full database").ConfigureAwait(false); await _service.LogInfoAsync("Local database file does not exist. Downloading full database").ConfigureAwait(false);
return await DownloadFullDatabaseAsync(cancellationToken).ConfigureAwait(false); return await DownloadFullDatabaseAsync(databaseFileInfo, cancellationToken).ConfigureAwait(false);
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)
...@@ -226,14 +228,14 @@ private async Task CleanCacheDirectoryAsync(CancellationToken cancellationToken) ...@@ -226,14 +228,14 @@ private async Task CleanCacheDirectoryAsync(CancellationToken cancellationToken)
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
} }
private async Task<TimeSpan> DownloadFullDatabaseAsync(CancellationToken cancellationToken) private async Task<TimeSpan> DownloadFullDatabaseAsync(FileInfo databaseFileInfo, CancellationToken cancellationToken)
{ {
try try
{ {
var title = string.Format(EditorFeaturesWpfResources.Downloading_IntelliSense_index_for_0, _source); var title = string.Format(EditorFeaturesWpfResources.Downloading_IntelliSense_index_for_0, _source);
await _service._progressService.OnDownloadFullDatabaseStartedAsync(title).ConfigureAwait(false); await _service._progressService.OnDownloadFullDatabaseStartedAsync(title).ConfigureAwait(false);
var (succeeded, delay) = await DownloadFullDatabaseWorkerAsync(cancellationToken).ConfigureAwait(false); var (succeeded, delay) = await DownloadFullDatabaseWorkerAsync(databaseFileInfo, cancellationToken).ConfigureAwait(false);
if (succeeded) if (succeeded)
{ {
await _service._progressService.OnDownloadFullDatabaseSucceededAsync().ConfigureAwait(false); await _service._progressService.OnDownloadFullDatabaseSucceededAsync().ConfigureAwait(false);
...@@ -261,20 +263,21 @@ private async Task<TimeSpan> DownloadFullDatabaseAsync(CancellationToken cancell ...@@ -261,20 +263,21 @@ private async Task<TimeSpan> DownloadFullDatabaseAsync(CancellationToken cancell
} }
} }
private async Task<(bool succeeded, TimeSpan delay)> DownloadFullDatabaseWorkerAsync(CancellationToken cancellationToken) private async Task<(bool succeeded, TimeSpan delay)> DownloadFullDatabaseWorkerAsync(FileInfo databaseFileInfo, CancellationToken cancellationToken)
{ {
var serverPath = Invariant($"Elfie_V{AddReferenceDatabase.TextFileFormatVersion}/Latest.xml"); var serverPath = Invariant($"Elfie_V{AddReferenceDatabase.TextFileFormatVersion}/Latest.xml");
await _service.LogInfoAsync($"Downloading and processing full database: {serverPath}").ConfigureAwait(false); await _service.LogInfoAsync($"Downloading and processing full database: {serverPath}").ConfigureAwait(false);
var element = await DownloadFileAsync(serverPath, cancellationToken).ConfigureAwait(false); var element = await DownloadFileAsync(serverPath, cancellationToken).ConfigureAwait(false);
var result = await ProcessFullDatabaseXElementAsync(element, cancellationToken).ConfigureAwait(false); var result = await ProcessFullDatabaseXElementAsync(databaseFileInfo, element, cancellationToken).ConfigureAwait(false);
await _service.LogInfoAsync("Downloading and processing full database completed").ConfigureAwait(false); await _service.LogInfoAsync("Downloading and processing full database completed").ConfigureAwait(false);
return result; return result;
} }
private async Task<(bool succeeded, TimeSpan delay)> ProcessFullDatabaseXElementAsync(XElement element, CancellationToken cancellationToken) private async Task<(bool succeeded, TimeSpan delay)> ProcessFullDatabaseXElementAsync(
FileInfo databaseFileInfo, XElement element, CancellationToken cancellationToken)
{ {
await _service.LogInfoAsync("Processing full database element").ConfigureAwait(false); await _service.LogInfoAsync("Processing full database element").ConfigureAwait(false);
...@@ -315,14 +318,14 @@ private async Task<(bool succeeded, TimeSpan delay)> ProcessFullDatabaseXElement ...@@ -315,14 +318,14 @@ private async Task<(bool succeeded, TimeSpan delay)> ProcessFullDatabaseXElement
// Write the file out to disk so we'll have it the next time we launch VS. Do this // Write the file out to disk so we'll have it the next time we launch VS. Do this
// after we set the in-memory instance so we at least have something to search while // after we set the in-memory instance so we at least have something to search while
// we're waiting to write. // we're waiting to write.
await WriteDatabaseFileAsync(bytes, cancellationToken).ConfigureAwait(false); await WriteDatabaseFileAsync(databaseFileInfo, bytes, cancellationToken).ConfigureAwait(false);
var delay = _service._delayService.UpdateSucceededDelay; var delay = _service._delayService.UpdateSucceededDelay;
await _service.LogInfoAsync($"Processing full database element completed. Update again in {delay}").ConfigureAwait(false); await _service.LogInfoAsync($"Processing full database element completed. Update again in {delay}").ConfigureAwait(false);
return (succeeded: true, delay); return (succeeded: true, delay);
} }
private async Task WriteDatabaseFileAsync(byte[] bytes, CancellationToken cancellationToken) private async Task WriteDatabaseFileAsync(FileInfo databaseFileInfo, byte[] bytes, CancellationToken cancellationToken)
{ {
await _service.LogInfoAsync("Writing database file").ConfigureAwait(false); await _service.LogInfoAsync("Writing database file").ConfigureAwait(false);
...@@ -349,16 +352,16 @@ private async Task WriteDatabaseFileAsync(byte[] bytes, CancellationToken cancel ...@@ -349,16 +352,16 @@ private async Task WriteDatabaseFileAsync(byte[] bytes, CancellationToken cancel
// If we have an existing db file, try to replace it file with the temp file. // If we have an existing db file, try to replace it file with the temp file.
// Otherwise, just move the temp file into place. // Otherwise, just move the temp file into place.
if (_service._ioService.Exists(_databaseFileInfo)) if (_service._ioService.Exists(databaseFileInfo))
{ {
await _service.LogInfoAsync("Replacing database file").ConfigureAwait(false); await _service.LogInfoAsync("Replacing database file").ConfigureAwait(false);
_service._ioService.Replace(tempFilePath, _databaseFileInfo.FullName, destinationBackupFileName: null, ignoreMetadataErrors: true); _service._ioService.Replace(tempFilePath, databaseFileInfo.FullName, destinationBackupFileName: null, ignoreMetadataErrors: true);
await _service.LogInfoAsync("Replace database file completed").ConfigureAwait(false); await _service.LogInfoAsync("Replace database file completed").ConfigureAwait(false);
} }
else else
{ {
await _service.LogInfoAsync("Moving database file").ConfigureAwait(false); await _service.LogInfoAsync("Moving database file").ConfigureAwait(false);
_service._ioService.Move(tempFilePath, _databaseFileInfo.FullName); _service._ioService.Move(tempFilePath, databaseFileInfo.FullName);
await _service.LogInfoAsync("Moving database file completed").ConfigureAwait(false); await _service.LogInfoAsync("Moving database file completed").ConfigureAwait(false);
} }
} }
...@@ -373,13 +376,13 @@ private async Task WriteDatabaseFileAsync(byte[] bytes, CancellationToken cancel ...@@ -373,13 +376,13 @@ private async Task WriteDatabaseFileAsync(byte[] bytes, CancellationToken cancel
await _service.LogInfoAsync("Writing database file completed").ConfigureAwait(false); await _service.LogInfoAsync("Writing database file completed").ConfigureAwait(false);
} }
private async Task<TimeSpan> PatchLocalDatabaseAsync(CancellationToken cancellationToken) private async Task<TimeSpan> PatchLocalDatabaseAsync(FileInfo databaseFileInfo, CancellationToken cancellationToken)
{ {
await _service.LogInfoAsync("Patching local database").ConfigureAwait(false); await _service.LogInfoAsync("Patching local database").ConfigureAwait(false);
await _service.LogInfoAsync("Reading in local database").ConfigureAwait(false); await _service.LogInfoAsync("Reading in local database").ConfigureAwait(false);
// (intentionally not wrapped in IOUtilities. If this throws we want to restart). // (intentionally not wrapped in IOUtilities. If this throws we want to restart).
var databaseBytes = _service._ioService.ReadAllBytes(_databaseFileInfo.FullName); var databaseBytes = _service._ioService.ReadAllBytes(databaseFileInfo.FullName);
await _service.LogInfoAsync($"Reading in local database completed. databaseBytes.Length={databaseBytes.Length}").ConfigureAwait(false); await _service.LogInfoAsync($"Reading in local database completed. databaseBytes.Length={databaseBytes.Length}").ConfigureAwait(false);
// Make a database instance out of those bytes and set is as the current in memory database // Make a database instance out of those bytes and set is as the current in memory database
...@@ -394,7 +397,7 @@ private async Task<TimeSpan> PatchLocalDatabaseAsync(CancellationToken cancellat ...@@ -394,7 +397,7 @@ private async Task<TimeSpan> PatchLocalDatabaseAsync(CancellationToken cancellat
catch (Exception e) when (_service._reportAndSwallowException(e)) catch (Exception e) when (_service._reportAndSwallowException(e))
{ {
await _service.LogExceptionAsync(e, "Error creating database from local copy. Downloading full database").ConfigureAwait(false); await _service.LogExceptionAsync(e, "Error creating database from local copy. Downloading full database").ConfigureAwait(false);
return await DownloadFullDatabaseAsync(cancellationToken).ConfigureAwait(false); return await DownloadFullDatabaseAsync(databaseFileInfo, cancellationToken).ConfigureAwait(false);
} }
var databaseVersion = database.DatabaseVersion; var databaseVersion = database.DatabaseVersion;
...@@ -405,7 +408,7 @@ private async Task<TimeSpan> PatchLocalDatabaseAsync(CancellationToken cancellat ...@@ -405,7 +408,7 @@ private async Task<TimeSpan> PatchLocalDatabaseAsync(CancellationToken cancellat
await _service.LogInfoAsync("Downloading and processing patch file: " + serverPath).ConfigureAwait(false); await _service.LogInfoAsync("Downloading and processing patch file: " + serverPath).ConfigureAwait(false);
var element = await DownloadFileAsync(serverPath, cancellationToken).ConfigureAwait(false); var element = await DownloadFileAsync(serverPath, cancellationToken).ConfigureAwait(false);
var delayUntilUpdate = await ProcessPatchXElementAsync(element, databaseBytes, cancellationToken).ConfigureAwait(false); var delayUntilUpdate = await ProcessPatchXElementAsync(databaseFileInfo, element, databaseBytes, cancellationToken).ConfigureAwait(false);
await _service.LogInfoAsync("Downloading and processing patch file completed").ConfigureAwait(false); await _service.LogInfoAsync("Downloading and processing patch file completed").ConfigureAwait(false);
await _service.LogInfoAsync("Patching local database completed").ConfigureAwait(false); await _service.LogInfoAsync("Patching local database completed").ConfigureAwait(false);
...@@ -427,12 +430,12 @@ private async Task<AddReferenceDatabase> CreateAndSetInMemoryDatabaseAsync(byte[ ...@@ -427,12 +430,12 @@ private async Task<AddReferenceDatabase> CreateAndSetInMemoryDatabaseAsync(byte[
} }
private async Task<TimeSpan> ProcessPatchXElementAsync( private async Task<TimeSpan> ProcessPatchXElementAsync(
XElement patchElement, byte[] databaseBytes, CancellationToken cancellationToken) FileInfo databaseFileInfo, XElement patchElement, byte[] databaseBytes, CancellationToken cancellationToken)
{ {
try try
{ {
await _service.LogInfoAsync("Processing patch element").ConfigureAwait(false); await _service.LogInfoAsync("Processing patch element").ConfigureAwait(false);
var delayUntilUpdate = await TryProcessPatchXElementAsync(patchElement, databaseBytes, cancellationToken).ConfigureAwait(false); var delayUntilUpdate = await TryProcessPatchXElementAsync(databaseFileInfo, patchElement, databaseBytes, cancellationToken).ConfigureAwait(false);
if (delayUntilUpdate != null) if (delayUntilUpdate != null)
{ {
await _service.LogInfoAsync($"Processing patch element completed. Update again in {delayUntilUpdate.Value}").ConfigureAwait(false); await _service.LogInfoAsync($"Processing patch element completed. Update again in {delayUntilUpdate.Value}").ConfigureAwait(false);
...@@ -447,11 +450,11 @@ private async Task<AddReferenceDatabase> CreateAndSetInMemoryDatabaseAsync(byte[ ...@@ -447,11 +450,11 @@ private async Task<AddReferenceDatabase> CreateAndSetInMemoryDatabaseAsync(byte[
// Fall through and download full database. // Fall through and download full database.
} }
return await DownloadFullDatabaseAsync(cancellationToken).ConfigureAwait(false); return await DownloadFullDatabaseAsync(databaseFileInfo, cancellationToken).ConfigureAwait(false);
} }
private async Task<TimeSpan?> TryProcessPatchXElementAsync( private async Task<TimeSpan?> TryProcessPatchXElementAsync(
XElement patchElement, byte[] databaseBytes, CancellationToken cancellationToken) FileInfo databaseFileInfo, XElement patchElement, byte[] databaseBytes, CancellationToken cancellationToken)
{ {
ParsePatchElement(patchElement, out var upToDate, out var tooOld, out var patchBytes); ParsePatchElement(patchElement, out var upToDate, out var tooOld, out var patchBytes);
...@@ -477,7 +480,7 @@ private async Task<AddReferenceDatabase> CreateAndSetInMemoryDatabaseAsync(byte[ ...@@ -477,7 +480,7 @@ private async Task<AddReferenceDatabase> CreateAndSetInMemoryDatabaseAsync(byte[
await CreateAndSetInMemoryDatabaseAsync(finalBytes).ConfigureAwait(false); await CreateAndSetInMemoryDatabaseAsync(finalBytes).ConfigureAwait(false);
await WriteDatabaseFileAsync(finalBytes, cancellationToken).ConfigureAwait(false); await WriteDatabaseFileAsync(databaseFileInfo, finalBytes, cancellationToken).ConfigureAwait(false);
return _service._delayService.UpdateSucceededDelay; return _service._delayService.UpdateSucceededDelay;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册