/// <summary> /// Un-register a readonly connection /// </summary> internal void RegisterReadonlyConnection(ReadonlySQLiteConnection conn) { List <LockableSQLiteConnection> connections = this.GetOrRegisterConnections(conn.DatabasePath); // Are there other connections that this thread owns? bool skipTrafficStop = false; WriteableSQLiteConnection writerConnection = null; lock (s_lockObject) skipTrafficStop = this.m_writeConnections.TryGetValue(conn.DatabasePath, out writerConnection) && Monitor.IsEntered(writerConnection) || connections.Any(o => Monitor.IsEntered(o)); if (!skipTrafficStop) // then we must adhere to traffic jams { var mre = this.GetOrRegisterResetEvent(conn.DatabasePath); mre.WaitOne(); this.RegisterConnection(conn); } }
/// <summary> /// Wrapper with lock /// </summary> public SQLiteConnectionWrapperLock(ReadonlySQLiteConnection wrappedConnection) { this.m_connection = wrappedConnection; Object lockObject = null; if (!m_lockBox.TryGetValue(wrappedConnection.DatabasePath, out lockObject)) { lockObject = new object(); lock (m_lockBox) if (!m_lockBox.ContainsKey(wrappedConnection.DatabasePath)) { m_lockBox.Add(wrappedConnection.DatabasePath, lockObject); } else { lockObject = m_lockBox[wrappedConnection.DatabasePath]; } } Monitor.Enter(lockObject); SQLiteConnectionManager.Current.RegisterReadonlyConnection(this.m_connection); this.m_connection.m_lockCount++; }
/// <summary> /// Un-register a readonly connection /// </summary> internal void UnregisterReadonlyConnection(ReadonlySQLiteConnection conn) { this.UnregisterConnection(conn); }
/// <summary> /// Get or create a pooled connection /// </summary> private LockableSQLiteConnection GetOrCreatePooledConnection(string dataSource, bool isReadonly) { // First is there a connection already? var connections = this.GetOrRegisterConnections(dataSource); WriteableSQLiteConnection writeConnection = null; lock (s_lockObject) { if (this.m_writeConnections.TryGetValue(dataSource, out writeConnection)) { if (Monitor.IsEntered(writeConnection)) { return(writeConnection); } } var conn = connections.FirstOrDefault(o => Monitor.IsEntered(o)); if (conn != null) { return(conn); } } ISQLitePlatform platform = ApplicationContext.Current.GetService <ISQLitePlatform>(); lock (s_lockObject) { LockableSQLiteConnection retVal = null; if (isReadonly) { retVal = this.m_connectionPool.OfType <ReadonlySQLiteConnection>().FirstOrDefault(o => o.DatabasePath == dataSource); } else { if (!this.m_writeConnections.TryGetValue(dataSource, out writeConnection)) // Writeable connection can only have one in the pool so if it isn't there make sure it isn't in the current { writeConnection = new WriteableSQLiteConnection(platform, dataSource, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.FullMutex | SQLiteOpenFlags.Create) { Persistent = true }; writeConnection.Execute("PRAGMA synchronous = 1"); //writeConnection.Execute("PRAGMA automatic_index = true"); //writeConnection.Execute("PRAGMA journal_mode = WAL"); this.m_writeConnections.Add(dataSource, writeConnection); } retVal = writeConnection; } // Remove return value if (retVal != null) { this.m_connectionPool.Remove(retVal); } else if (isReadonly) { retVal = new ReadonlySQLiteConnection(platform, dataSource, SQLiteOpenFlags.ReadOnly | SQLiteOpenFlags.FullMutex) { Persistent = true }; //retVal.Execute("PRAGMA threads = 2"); } else { throw new InvalidOperationException("Should not be here"); } return(retVal); } }