Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull reading of last storage subsystem out of lock (part2) #73295

Merged
merged 19 commits into from
May 2, 2024
Prev Previous commit
Next Next commit
Move off of map
  • Loading branch information
CyrusNajmabadi committed May 2, 2024
commit 9a717f57165a415b55c0c83b6c9c6cd30f7121ea
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal abstract partial class AbstractPersistentStorageService(IPersistentStor
protected readonly IPersistentStorageConfiguration Configuration = configuration;

private readonly SemaphoreSlim _lock = new(initialCount: 1);
private readonly ConcurrentDictionary<SolutionKey, IChecksummedPersistentStorage> _solutionKeyToStorage = new();
private IChecksummedPersistentStorage? _currentPersistentStorage;

protected abstract string GetDatabaseFilePath(string workingFolderPath);

Expand All @@ -49,23 +49,21 @@ public async ValueTask<IChecksummedPersistentStorage> GetStorageAsync(
return NoOpPersistentStorage.GetOrThrow(solutionKey, Configuration.ThrowOnFailure);

// Without taking the lock, see if we can lookup a storage for this key.
if (_solutionKeyToStorage.TryGetValue(solutionKey, out var storage))
return storage;
var existing = _currentPersistentStorage;
if (existing?.SolutionKey == solutionKey)
return existing;

var workingFolder = configuration.TryGetStorageLocation(solutionKey);
if (workingFolder == null)
return NoOpPersistentStorage.GetOrThrow(solutionKey, Configuration.ThrowOnFailure);

using (await _lock.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
// See if another thread set to the solution we care about while we were waiting on the lock.
if (!_solutionKeyToStorage.TryGetValue(solutionKey, out storage))
{
storage = await CreatePersistentStorageAsync(solutionKey, workingFolder, faultInjector, cancellationToken).ConfigureAwait(false);
_solutionKeyToStorage.Add(solutionKey, storage);
}
// Recheck if we have a storage for this key after taking the lock.
if (_currentPersistentStorage?.SolutionKey != solutionKey)
_currentPersistentStorage = await CreatePersistentStorageAsync(solutionKey, workingFolder, faultInjector, cancellationToken).ConfigureAwait(false);

return storage;
return _currentPersistentStorage;
}
}

Expand Down Expand Up @@ -129,10 +127,8 @@ internal readonly struct TestAccessor(AbstractPersistentStorageService service)
{
public void Shutdown()
{
foreach (var (_, storage) in service._solutionKeyToStorage)
(storage as SQLitePersistentStorage)?.DatabaseOwnership.Dispose();

service._solutionKeyToStorage.Clear();
(service._currentPersistentStorage as SQLitePersistentStorage)?.DatabaseOwnership.Dispose();
service._currentPersistentStorage = null;
}
}
}
Loading