public SQLiteDataReaderED(DbCommand cmd, CommandBehavior behaviour, SQLiteTransactionED <TConn> txn = null, SQLiteTxnLockED <TConn> txnlock = null) { this._command = cmd; this.InnerReader = cmd.ExecuteReader(behaviour); this._transaction = txn; this._txnlock = txnlock; }
public void OpenReader() { if (_owningThread != Thread.CurrentThread) { throw new InvalidOperationException("Transaction lock passed between threads"); } if (!_lock.IsWriteLockHeld) { if (!_isReader) { try { Interlocked.Increment(ref _readsWaiting); while (!_lock.TryEnterReadLock(1000)) { SQLiteTxnLockED <TConn> lockowner = _writeLockOwner; if (lockowner != null) { Trace.WriteLine($"Thread {Thread.CurrentThread.Name} waiting for thread {lockowner._owningThread.Name} to finish writer"); DebugLongRunningOperation(lockowner); } } _isReader = true; } finally { Interlocked.Decrement(ref _readsWaiting); } } } }
private static void DebugLongRunningOperation(SQLiteTxnLockED <TConn> txnlock) { if (txnlock != null) { txnlock._isLongRunning = true; if (txnlock._commandExecuting) { if (txnlock._isLongRunning) { Trace.WriteLine($"The following command is taking a long time to execute:\n{txnlock._commandText}"); } if (txnlock._owningThread == Thread.CurrentThread) { StackTrace trace = new StackTrace(1, true); Trace.WriteLine(trace.ToString()); } } else { Trace.WriteLine($"The transaction lock has been held for a long time."); if (txnlock._commandText != null) { Trace.WriteLine($"Last command to execute:\n{txnlock._commandText}"); } } } }
// disposing: true if Dispose() was called, false // if being finalized by the garbage collector protected override void Dispose(bool disposing) { if (disposing) { if (_cn != null) { _cn.Close(); _cn.Dispose(); _cn = null; } if (_schemaLock.IsReadLockHeld) { _schemaLock.ExitReadLock(); } if (_transactionLock != null) { _transactionLock.Dispose(); _transactionLock = null; } } base.Dispose(disposing); }
public SQLiteCommandED(DbCommand cmd, SQLiteConnectionED conn, SQLiteTxnLockED <TConn> txnlock, DbTransaction txn = null) { _connection = conn; _txnlock = txnlock; InnerCommand = cmd; if (txn != null) { SetTransaction(txn); } }
public override void Close() { InnerReader.Close(); if (_txnlock != null) { _txnlock.CloseReader(); _txnlock = null; } }
public SQLiteConnectionED(EDDSqlDbSelection?maindb = null, bool utctimeindicator = false, bool initializing = false, bool shortlived = true) : base(initializing) { bool locktaken = false; try { if (!initializing && !_initialized) { System.Diagnostics.Trace.WriteLine($"Database {typeof(TConn).Name} initialized before Initialize()"); System.Diagnostics.Trace.WriteLine(new System.Diagnostics.StackTrace(2, true).ToString()); if (typeof(TConn) == typeof(SQLiteConnectionUser)) { SQLiteConnectionUser.Initialize(); } else if (typeof(TConn) == typeof(SQLiteConnectionSystem)) { SQLiteConnectionSystem.Initialize(); } } _schemaLock.EnterReadLock(); locktaken = true; // System.Threading.Monitor.Enter(monitor); //Console.WriteLine("Connection open " + System.Threading.Thread.CurrentThread.Name); DBFile = GetSQLiteDBFile(maindb ?? EDDSqlDbSelection.EDDUser); _cn = DbFactory.CreateConnection(); // Use the database selected by maindb as the 'main' database _cn.ConnectionString = "Data Source=" + DBFile + ";Pooling=true;"; if (utctimeindicator) // indicate treat dates as UTC. { _cn.ConnectionString += "DateTimeKind=Utc;"; } _transactionLock = new SQLiteTxnLockED <TConn>(); _cn.Open(); } catch { if (_transactionLock != null) { _transactionLock.Dispose(); } if (locktaken) { _schemaLock.ExitReadLock(); } throw; } }
public void OpenWriter() { if (_owningThread != Thread.CurrentThread) { throw new InvalidOperationException("Transaction lock passed between threads"); } if (_lock.IsReadLockHeld) { throw new InvalidOperationException("Write attempted in read-only connection"); } if (!_isWriter) { try { if (!_lock.IsUpgradeableReadLockHeld) { while (!_lock.TryEnterUpgradeableReadLock(1000)) { SQLiteTxnLockED <TConn> lockowner = _writeLockOwner; if (lockowner != null) { Trace.WriteLine($"Thread {Thread.CurrentThread.Name} waiting for thread {lockowner._owningThread.Name} to finish writer"); DebugLongRunningOperation(lockowner); } } _isWriter = true; _writeLockOwner = this; } while (!_lock.TryEnterWriteLock(1000)) { Trace.WriteLine($"Thread {Thread.CurrentThread.Name} waiting for readers to finish"); } } catch { if (_isWriter) { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } if (_lock.IsUpgradeableReadLockHeld) { _lock.ExitUpgradeableReadLock(); } } } } }
private static void DebugLongRunningOperation(object state) { WeakReference weakref = state as WeakReference; if (weakref != null) { SQLiteTxnLockED <TConn> txnlock = weakref.Target as SQLiteTxnLockED <TConn>; DebugLongRunningOperation(txnlock); } }
public SQLiteConnectionED(EDDSqlDbSelection?maindb = null, bool utctimeindicator = false, bool initializing = false, bool shortlived = true) : base(initializing) { bool locktaken = false; try { _schemaLock.EnterReadLock(); locktaken = true; // System.Threading.Monitor.Enter(monitor); //Console.WriteLine("Connection open " + System.Threading.Thread.CurrentThread.Name); DBFile = GetSQLiteDBFile(maindb ?? SQLiteDBClass.DefaultMainDatabase); _cn = SQLiteDBClass.CreateCN(); // Use the database selected by maindb as the 'main' database _cn.ConnectionString = "Data Source=" + DBFile + ";Pooling=true;"; if (utctimeindicator) // indicate treat dates as UTC. { _cn.ConnectionString += "DateTimeKind=Utc;"; } _transactionLock = new SQLiteTxnLockED <TConn>(); _cn.Open(); } catch { if (_transactionLock != null) { _transactionLock.Dispose(); } if (locktaken) { _schemaLock.ExitReadLock(); } throw; } }
public DbTransaction BeginTransaction() { // Take the transaction lock before beginning the // transaction to avoid a deadlock var txnlock = new SQLiteTxnLockED(); txnlock.Open(); return new SQLiteTransactionED(_cn.BeginTransaction(), txnlock); }
public SQLiteTransactionED(DbTransaction txn, SQLiteTxnLockED <TConn> txnlock) { _transactionLock = txnlock; InnerTransaction = txn; }
public SQLiteDataReaderED(DbCommand cmd, CommandBehavior behaviour, SQLiteTransactionED txn = null, SQLiteTxnLockED txnlock = null) { this._command = cmd; this.InnerReader = cmd.ExecuteReader(behaviour); this._transaction = txn; this._txnlock = txnlock; }
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { if (this._transaction != null) { // The transaction should already have the transaction lock return new SQLiteDataReaderED(this.InnerCommand, behavior, txn: this._transaction); } else { // Take the transaction lock for the duration of this command using (var txnlock = new SQLiteTxnLockED()) { txnlock.Open(); return new SQLiteDataReaderED(this.InnerCommand, behavior, txnlock: txnlock); } } }
// disposing: true if Dispose() was called, false // if being finalized by the garbage collector protected override void Dispose(bool disposing) { if (disposing) { // Close the transaction before closing the lock if (InnerTransaction != null) { InnerTransaction.Dispose(); InnerTransaction = null; } if (_transactionLock != null) { _transactionLock.Dispose(); _transactionLock = null; } } base.Dispose(disposing); }
public SQLiteTransactionED(DbTransaction txn, SQLiteTxnLockED txnlock) { _transactionLock = txnlock; InnerTransaction = txn; }
public override object ExecuteScalar() { if (this._transaction != null) { this._transaction.BeginCommand(this); // The transaction should already have the transaction lock object result = InnerCommand.ExecuteScalar(); this._transaction.EndCommand(); return result; } else { // Take the transaction lock for the duration of this command using (var txnlock = new SQLiteTxnLockED()) { txnlock.Open(); txnlock.BeginCommand(this); object result = InnerCommand.ExecuteScalar(); txnlock.EndCommand(); return result; } } }