Ejemplo n.º 1
0
        public static SqlConnection Create(IPersistentStorageFaultInjector faultInjector, string databasePath)
        {
            faultInjector?.OnNewConnection();

            // Allocate dictionary before doing any sqlite work.  That way if it throws
            // we don't have to do any additional cleanup.
            var queryToStatement = new Dictionary <string, SqlStatement>();

            // Use SQLITE_OPEN_NOMUTEX to enable multi-thread mode, where multiple connections can be used provided each
            // one is only used from a single thread at a time.
            // see https://sqlite.org/threadsafe.html for more detail
            var flags  = OpenFlags.SQLITE_OPEN_CREATE | OpenFlags.SQLITE_OPEN_READWRITE | OpenFlags.SQLITE_OPEN_NOMUTEX;
            var handle = NativeMethods.sqlite3_open_v2(databasePath, (int)flags, vfs: null, out var result);

            if (result != Result.OK)
            {
                handle.Dispose();
                throw new SqlException(result, $"Could not open database file: {databasePath} ({result})");
            }

            try
            {
                NativeMethods.sqlite3_busy_timeout(handle, (int)TimeSpan.FromMinutes(1).TotalMilliseconds);
                return(new SqlConnection(handle, faultInjector, queryToStatement));
            }
            catch
            {
                // If we failed to create connection, ensure that we still release the sqlite
                // handle.
                handle.Dispose();
                throw;
            }
        }
Ejemplo n.º 2
0
        public static SqlConnection Create(IPersistentStorageFaultInjector faultInjector, string databasePath)
        {
            faultInjector?.OnNewConnection();

            // Allocate dictionary before doing any sqlite work.  That way if it throws
            // we don't have to do any additional cleanup.
            var queryToStatement = new Dictionary <string, SqlStatement>();

            // Use SQLITE_OPEN_NOMUTEX to enable multi-thread mode, where multiple connections can
            // be used provided each one is only used from a single thread at a time.
            //
            // Use SHAREDCACHE so that we can have an in-memory DB that we dump our writes into.  We
            // need SHAREDCACHE so that all connections see that same in-memory DB.  This also
            // requires OPEN_URI since we need a `file::memory:` uri for them all to refer to.
            //
            // see https://sqlite.org/threadsafe.html for more detail
            var flags = OpenFlags.SQLITE_OPEN_CREATE |
                        OpenFlags.SQLITE_OPEN_READWRITE |
                        OpenFlags.SQLITE_OPEN_NOMUTEX |
                        OpenFlags.SQLITE_OPEN_SHAREDCACHE |
                        OpenFlags.SQLITE_OPEN_URI;
            var result = (Result)raw.sqlite3_open_v2(databasePath, out var handle, (int)flags, vfs: null);

            if (result != Result.OK)
            {
                throw new SqlException(result, $"Could not open database file: {databasePath} ({result})");
            }

            Contract.ThrowIfNull(handle);

            try
            {
                raw.sqlite3_busy_timeout(handle, (int)TimeSpan.FromMinutes(1).TotalMilliseconds);
                var connection = new SqlConnection(handle, faultInjector, queryToStatement);

                // Attach (creating if necessary) a singleton in-memory write cache to this connection.
                //
                // From: https://www.sqlite.org/sharedcache.html Enabling shared-cache for an in-memory
                // database allows two or more database connections in the same process to have access
                // to the same in-memory database. An in-memory database in shared cache is
                // automatically deleted and memory is reclaimed when the last connection to that
                // database closes.
                //
                // Using `cache=shared as writecache` at the end ensures all connections see the same db
                // and the same data when reading and writing.  i.e. if one connection writes data to
                // this, another connection will see that data when reading.  Without this, each
                // connection would get their own private memory db independent of all other
                // connections.
                connection.ExecuteCommand($"attach database 'file::memory:?cache=shared' as {Database.WriteCache.GetName()};");

                return(connection);
            }
            catch
            {
                // If we failed to create connection, ensure that we still release the sqlite
                // handle.
                raw.sqlite3_close(handle);
                throw;
            }
        }
Ejemplo n.º 3
0
        public static SqlConnection Create(IPersistentStorageFaultInjector faultInjector, string databasePath)
        {
            faultInjector?.OnNewConnection();

            var flags  = OpenFlags.SQLITE_OPEN_CREATE | OpenFlags.SQLITE_OPEN_READWRITE;
            var result = (Result)raw.sqlite3_open_v2(databasePath, out var handle, (int)flags, vfs: null);

            if (result != Result.OK)
            {
                throw new SqlException(result, $"Could not open database file: {databasePath} ({result})");
            }

            Contract.ThrowIfNull(handle);

            raw.sqlite3_busy_timeout(handle, (int)TimeSpan.FromMinutes(1).TotalMilliseconds);

            return(new SqlConnection(faultInjector, handle));
        }
Ejemplo n.º 4
0
        public static SqlConnection Create(IPersistentStorageFaultInjector faultInjector, string databasePath)
        {
            faultInjector?.OnNewConnection();

            // 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_NOMUTEX | OpenFlags.SQLITE_OPEN_SHAREDCACHE;
            var result = (Result)raw.sqlite3_open_v2(databasePath, out var handle, (int)flags, vfs: null);

            if (result != Result.OK)
            {
                throw new SqlException(result, $"Could not open database file: {databasePath} ({result})");
            }

            Contract.ThrowIfNull(handle);

            raw.sqlite3_busy_timeout(handle, (int)TimeSpan.FromMinutes(1).TotalMilliseconds);

            return(new SqlConnection(faultInjector, handle));
        }
Ejemplo n.º 5
0
        public static SqlConnection Create(IPersistentStorageFaultInjector faultInjector, string databasePath)
        {
            faultInjector?.OnNewConnection();

            // Use SQLITE_OPEN_NOMUTEX to enable multi-thread mode, where multiple connections can be used provided each
            // one is only used from a single thread at a time.
            // see https://sqlite.org/threadsafe.html for more detail
            var flags  = OpenFlags.SQLITE_OPEN_CREATE | OpenFlags.SQLITE_OPEN_READWRITE | OpenFlags.SQLITE_OPEN_NOMUTEX;
            var result = (Result)raw.sqlite3_open_v2(databasePath, out var handle, (int)flags, vfs: null);

            if (result != Result.OK)
            {
                throw new SqlException(result, $"Could not open database file: {databasePath} ({result})");
            }

            Contract.ThrowIfNull(handle);

            raw.sqlite3_busy_timeout(handle, (int)TimeSpan.FromMinutes(1).TotalMilliseconds);

            return(new SqlConnection(faultInjector, handle));
        }