diff --git a/src/Workspaces/Core/Desktop/Workspace/SQLite/Interop/OpenFlags.cs b/src/Workspaces/Core/Desktop/Workspace/SQLite/Interop/OpenFlags.cs index 436c5a884e03531accad02ec8504a56f864892a0..4504758846d432525486049b6793eb7e943aee87 100644 --- a/src/Workspaces/Core/Desktop/Workspace/SQLite/Interop/OpenFlags.cs +++ b/src/Workspaces/Core/Desktop/Workspace/SQLite/Interop/OpenFlags.cs @@ -23,7 +23,7 @@ internal enum OpenFlags // SQLITE_OPEN_SUBJOURNAL = 0x00002000, /* VFS only */ // SQLITE_OPEN_MASTER_JOURNAL = 0x00004000, /* VFS only */ // SQLITE_OPEN_NOMUTEX = 0x00008000, /* Ok for sqlite3_open_v2() */ - SQLITE_OPEN_FULLMUTEX = 0x00010000, /* Ok for sqlite3_open_v2() */ + // SQLITE_OPEN_FULLMUTEX = 0x00010000, /* Ok for sqlite3_open_v2() */ SQLITE_OPEN_SHAREDCACHE = 0x00020000, /* Ok for sqlite3_open_v2() */ // SQLITE_OPEN_PRIVATECACHE = 0x00040000, /* Ok for sqlite3_open_v2() */ // SQLITE_OPEN_WAL = 0x00080000, /* VFS only */ diff --git a/src/Workspaces/Core/Desktop/Workspace/SQLite/Interop/SqlConnection.cs b/src/Workspaces/Core/Desktop/Workspace/SQLite/Interop/SqlConnection.cs index 78112e6192bfae5cb2bf6521998835f1a917f698..3dd5f22710bb0d6732922ffa365c2055988052cc 100644 --- a/src/Workspaces/Core/Desktop/Workspace/SQLite/Interop/SqlConnection.cs +++ b/src/Workspaces/Core/Desktop/Workspace/SQLite/Interop/SqlConnection.cs @@ -51,10 +51,9 @@ public static SqlConnection Create(IPersistentStorageFaultInjector faultInjector { faultInjector?.OnNewConnection(); - // Explicitly set for Serialized mode to be safe. - // Also, enable shared cache so that multiple connections inside of same process share cache + // Enable shared cache so that multiple connections inside of same process share cache // see https://sqlite.org/threadsafe.html for more detail - var flags = OpenFlags.SQLITE_OPEN_CREATE | OpenFlags.SQLITE_OPEN_READWRITE | OpenFlags.SQLITE_OPEN_FULLMUTEX | OpenFlags.SQLITE_OPEN_SHAREDCACHE; + var flags = OpenFlags.SQLITE_OPEN_CREATE | OpenFlags.SQLITE_OPEN_READWRITE | OpenFlags.SQLITE_OPEN_SHAREDCACHE; var result = (Result)raw.sqlite3_open_v2(databasePath, out var handle, (int)flags, vfs: null); if (result != Result.OK) diff --git a/src/Workspaces/Core/Desktop/Workspace/SQLite/SQLitePersistentStorageService.cs b/src/Workspaces/Core/Desktop/Workspace/SQLite/SQLitePersistentStorageService.cs index 11603d817125f59b9a71985938f6e552f90b106d..99639bbadafe4639cef25488f98b5504822a545d 100644 --- a/src/Workspaces/Core/Desktop/Workspace/SQLite/SQLitePersistentStorageService.cs +++ b/src/Workspaces/Core/Desktop/Workspace/SQLite/SQLitePersistentStorageService.cs @@ -37,13 +37,22 @@ protected override string GetDatabaseFilePath(string workingFolderPath) return Path.Combine(workingFolderPath, StorageExtension, PersistentStorageFileName); } - protected override AbstractPersistentStorage OpenDatabase(Solution solution, string workingFolderPath, string databaseFilePath) + protected override bool TryOpenDatabase( + Solution solution, string workingFolderPath, string databaseFilePath, out AbstractPersistentStorage storage) { + storage = null; + // try to get db ownership lock. if someone else already has the lock. it will throw var dbOwnershipLock = TryGetDatabaseOwnership(databaseFilePath); + if (dbOwnershipLock == null) + { + return false; + } - return new SQLitePersistentStorage( + storage = new SQLitePersistentStorage( OptionService, workingFolderPath, solution.FilePath, databaseFilePath, this.Release, dbOwnershipLock, _faultInjectorOpt); + + return true; } private static IDisposable TryGetDatabaseOwnership(string databaseFilePath) @@ -57,9 +66,9 @@ private static IDisposable TryGetDatabaseOwnership(string databaseFilePath) Path.Combine(Path.GetDirectoryName(databaseFilePath), LockFile), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); } - catch (Exception ex) + catch (Exception) { - throw new InvalidOperationException("can't get the ownership", ex); + return null; } } @@ -76,12 +85,6 @@ private static void EnsureDirectory(string databaseFilePath) protected override bool ShouldDeleteDatabase(Exception exception) { - if (exception is InvalidOperationException) - { - // db is owned by another process - return false; - } - // Error occurred when trying to open this DB. Try to remove it so we can create a good dB. return true; } diff --git a/src/Workspaces/Core/Desktop/Workspace/Storage/PersistentStorageService.cs b/src/Workspaces/Core/Desktop/Workspace/Storage/PersistentStorageService.cs index 6ed03e29f7c0bcab9161de3d128249ece89c7d79..2a9a9d5f98a5fe858ff64fa8ac6d0e99417660f5 100644 --- a/src/Workspaces/Core/Desktop/Workspace/Storage/PersistentStorageService.cs +++ b/src/Workspaces/Core/Desktop/Workspace/Storage/PersistentStorageService.cs @@ -54,7 +54,7 @@ protected AbstractPersistentStorageService(IOptionService optionService, bool te } protected abstract string GetDatabaseFilePath(string workingFolderPath); - protected abstract AbstractPersistentStorage OpenDatabase(Solution solution, string workingFolderPath, string databaseFilePath); + protected abstract bool TryOpenDatabase(Solution solution, string workingFolderPath, string databaseFilePath, out AbstractPersistentStorage storage); protected abstract bool ShouldDeleteDatabase(Exception exception); public IPersistentStorage GetStorage(Solution solution) @@ -235,7 +235,11 @@ private AbstractPersistentStorage TryCreatePersistentStorage(Solution solution, var databaseFilePath = GetDatabaseFilePath(workingFolderPath); try { - database = OpenDatabase(solution, workingFolderPath, databaseFilePath); + if (!TryOpenDatabase(solution, workingFolderPath, databaseFilePath, out database)) + { + return false; + } + database.Initialize(solution); persistentStorage = database;