internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation) { _conn = conn; _isolation = isolation; StringBuilder commandText = new StringBuilder("BEGIN; SET TRANSACTION ISOLATION LEVEL "); if (isolation == IsolationLevel.RepeatableRead) { commandText.Append("REPEATABLE READ"); } else if ((isolation == IsolationLevel.Serializable) || (isolation == IsolationLevel.Snapshot)) { commandText.Append("SERIALIZABLE"); } else { // Set isolation level default to read committed. _isolation = IsolationLevel.ReadCommitted; commandText.Append("READ COMMITTED"); } commandText.Append(";"); NpgsqlCommand command = new NpgsqlCommand(commandText.ToString(), conn.Connector); command.ExecuteBlind(); _conn.Connector.Transaction = this; }
private void _connection_Disposed(object sender, EventArgs e) { // TODO: what happens if this is called from another thread? // connections should not be shared across threads while in a transaction _connection.Disposed -= new EventHandler(_connection_Disposed); _connection = null; }
/* * Constructs the LargeObject API. * * <p><b>Important Notice</b> * <br>This method should only be called by org.postgresql.Connection * * <p>There should only be one LargeObjectManager per Connection. The * org.postgresql.Connection class keeps track of the various extension API's * and it's advised you use those to gain access, and not going direct. */ public LargeObjectManager(NpgsqlConnection conn) { // We need Fastpath to do anything // Now get the function oid's for the api // // This is an example of Fastpath.addFunctions(); // //String sql; StringBuilder sql = null; try { sql = new StringBuilder(); if (conn.PostgreSqlVersion > new Version(7, 3, 0)) { sql.Append("SELECT p.proname,p.oid "); sql.Append(" FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "); sql.Append(" WHERE p.pronamespace=n.oid AND n.nspname='pg_catalog' AND ("); } else { sql.Append("SELECT proname,oid FROM pg_proc WHERE "); } sql.Append(" proname = 'lo_open'"); sql.Append(" or proname = 'lo_close'"); sql.Append(" or proname = 'lo_creat'"); sql.Append(" or proname = 'lo_unlink'"); sql.Append(" or proname = 'lo_lseek'"); sql.Append(" or proname = 'lo_tell'"); sql.Append(" or proname = 'loread'"); sql.Append(" or proname = 'lowrite'"); if (conn.PostgreSqlVersion > new Version(7, 3, 0)) { sql.Append(")"); } using (IDbCommand cmd = new NpgsqlCommand(sql.ToString())) { cmd.Connection = conn; this.fp = new Fastpath(conn, conn.Connector.Stream); using (IDataReader res = cmd.ExecuteReader()) { if (res == null) { throw new NpgsqlException("postgresql.lo.init"); } fp.AddFunctions(res); } } } finally { sql = null; } }
public ConnectionInfo(string connectionString) { Contract.Requires(connectionString != null); this.ConnectionString = connectionString; this.Connection = new NpgsqlConnection(connectionString); LastCommandTimeout = Connection.CommandTimeout; }
private NpgsqlConnection GetConnection() { if (_connection == null || (_connection.FullState & ConnectionState.Open) != ConnectionState.Open) { _connection = new NpgsqlConnection(_connectionString); _connection.Open(); _closeConnectionRequired = true; return _connection; } else { return _connection; } }
/// <summary> /// Initializes a new instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> class with the text of the query, a <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>, and the <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see>. /// </summary> /// <param name="cmdText">The text of the query.</param> /// <param name="connection">A <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see> that represents the connection to a PostgreSQL server.</param> /// <param name="transaction">The <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see> in which the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> executes.</param> public NpgsqlCommand(String cmdText, NpgsqlConnection connection, NpgsqlTransaction transaction) { parameters = new NpgsqlParameterCollection(); planName = String.Empty; text = cmdText; this.connection = connection; if (this.connection != null) { this.m_Connector = connection.Connector; } type = CommandType.Text; this.Transaction = transaction; SetCommandTimeout(); }
/// <summary> /// Create a new connection based on this one. /// </summary> /// <returns>A new NpgsqlConnection object.</returns> public NpgsqlConnection Clone() { CheckNotDisposed(); NpgsqlConnection C = new NpgsqlConnection(settings); C.Notice += this.Notice; if (connector != null) { C.Open(); } return C; }
private void CleanUpConnectorMethod(NpgsqlConnection Connection, NpgsqlConnector Connector) { try { Connector.CurrentReader.Close(); Connector.CurrentReader = null; ReleaseConnector(Connection, Connector); } catch { } }
private void CleanUpConnector(NpgsqlConnection Connection, NpgsqlConnector Connector) { new CleanUpConnectorDel(CleanUpConnectorMethod).BeginInvoke(Connection, Connector, null, null); }
/* * Initialises the fastpath system * * @param conn BaseConnection to attach to * @param stream The network stream to the backend */ public Fastpath(NpgsqlConnection conn, Stream stream) { this.conn = conn; this.stream = stream; }
public void Release(NpgsqlConnection connection, bool valid) { switch (Mode) { case PoolMode.None: try { connection.Close(); } catch (Exception ex) { if (valid) TraceSource.TraceEvent(TraceEventType.Error, 5011, "{0}", ex); } break; default: if (valid && connection.State == ConnectionState.Open && Connections.Count < Size) { Connections.Add(connection); } else { try { connection.Close(); } catch (Exception ex) { if (valid) TraceSource.TraceEvent(TraceEventType.Error, 5012, "{0}", ex); } if (Connections.Count < Size) Connections.Add(Info.GetConnection()); } break; } }
/// <summary> /// Cancel the transaction without telling the backend about it. This is /// used to make the transaction go away when closing a connection. /// </summary> internal void Cancel() { CheckDisposed(); if (_conn != null) { _conn.Connector.Transaction = null; _conn = null; } }
/// <summary> /// Releases a connector, possibly back to the pool for future use. /// </summary> /// <remarks> /// Pooled connectors will be put back into the pool if there is room. /// Shared connectors should just have their use count decremented /// since they always stay in the shared pool. /// </remarks> /// <param name="Connector">The connector to release.</param> public void ReleaseConnector(NpgsqlConnection Connection, NpgsqlConnector Connector) { //We can only clean up a connector with a reader if the current thread hasn't been aborted //If it has then we need to just close it (ReleasePooledConnector will do this for an aborted thread) if (Connector.CurrentReader != null && (Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0) { CleanUpConnector(Connection, Connector); } else { ReleaseConnectorInternal(Connection, Connector); } }
/// <summary> /// Initializes a new instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> class with the text of the query and a <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>. /// </summary> /// <param name="cmdText">The text of the query.</param> /// <param name="connection">A <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see> that represents the connection to a PostgreSQL server.</param> public NpgsqlCommand(String cmdText, NpgsqlConnection connection) : this(cmdText, connection, null) { }
public NpgsqlPromotableSinglePhaseNotification(NpgsqlConnection connection) { _connection = connection; }
internal void ClearPool(NpgsqlConnection Connection) { // Prevent multithread access to connection pool count. lock (locker) { ConnectorQueue queue; // Try to find a queue. if (PooledConnectors.TryGetValue(Connection.ConnectionString, out queue)) { ClearQueue(queue); PooledConnectors.Remove(Connection.ConnectionString); } } }
/// <summary> /// Put a pooled connector into the pool queue. /// </summary> /// <param name="Connector">Connector to pool</param> private void UngetConnector(NpgsqlConnection Connection, NpgsqlConnector Connector) { ConnectorQueue queue; // Find the queue. // As we are handling all possible queues, we have to lock everything... lock (locker) { PooledConnectors.TryGetValue(Connection.ConnectionString, out queue); } if (queue == null) { Connector.Close(); // Release connection to postgres return; // Queue may be emptied by connection problems. See ClearPool below. } Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate; Connector.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate; Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate; Connector.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate; bool inQueue = false; lock (queue) { inQueue = queue.Busy.ContainsKey(Connector); queue.Busy.Remove(Connector); } if (!Connector.IsInitialized) { if (Connector.Transaction != null) { Connector.Transaction.Cancel(); } Connector.Close(); } else { if (Connector.Transaction != null) { try { Connector.Transaction.Rollback(); } catch { Connector.Close(); } } } if (Connector.State == ConnectionState.Open) { //If thread is good if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0) { // Release all resources associated with this connector. try { Connector.ReleaseResources(); } catch (Exception) { //If the connector fails to release its resources then it is probably broken, so make sure we don't add it to the queue. // Usually it already won't be in the queue as it would of broken earlier inQueue = false; } if (inQueue) lock (queue) { queue.Available.Enqueue(Connector); } else Connector.Close(); } else { //Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool Connector.Close(); } } }
/// <summary> /// This method is only called when NpgsqlConnection.Dispose(false) is called which means a /// finalization. This also means, an NpgsqlConnection was leak. We clear pool count so that /// client doesn't end running out of connections from pool. When the connection is finalized, its underlying /// socket is closed. /// </summary> public void FixPoolCountBecauseOfConnectionDisposeFalse(NpgsqlConnection Connection) { ConnectorQueue Queue; // Prevent multithread access to connection pool count. lock (locker) { // Try to find a queue. if (PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue) && Queue != null) { Queue.Busy.Remove(Connection.Connector); } } }
/// <summary> /// Find an available pooled connector in the non-shared pool, or create /// a new one if none found. /// </summary> private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection) { ConnectorQueue Queue; NpgsqlConnector Connector = null; // We only need to lock all pools when trying to get one pool or create one. lock (locker) { // Try to find a queue. if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue)) { Queue = new ConnectorQueue(); Queue.ConnectionLifeTime = Connection.ConnectionLifeTime; Queue.MinPoolSize = Connection.MinPoolSize; PooledConnectors[Connection.ConnectionString] = Queue; } } // Now we can simply lock on the pool itself. lock (Queue) { if (Queue.Available.Count > 0) { // Found a queue with connectors. Grab the top one. // Check if the connector is still valid. Connector = Queue.Available.Dequeue(); Queue.Busy.Add(Connector, null); } } if (Connector != null) { if (!Connector.IsValid()) { lock (Queue) { Queue.Busy.Remove(Connector); } Connector.Close(); return GetPooledConnector(Connection); //Try again } return Connector; } lock (Queue) { if (Queue.Available.Count + Queue.Busy.Count < Connection.MaxPoolSize) { Connector = new NpgsqlConnector(Connection); Queue.Busy.Add(Connector, null); } } if (Connector != null) { Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; Connector.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; Connector.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; Connector.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; try { Connector.Open(); } catch { lock (Queue) { Queue.Busy.Remove(Connector); } Connector.Close(); throw; } // Meet the MinPoolSize requirement if needed. if (Connection.MinPoolSize > 1) { lock (Queue) { while (Queue.Available.Count + Queue.Busy.Count < Connection.MinPoolSize) { NpgsqlConnector Spare = new NpgsqlConnector(Connection); Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; Spare.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; Spare.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; Spare.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; Spare.Open(); Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate; Spare.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate; Spare.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate; Spare.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate; Queue.Available.Enqueue(Spare); } } } } return Connector; }
/// <summary> /// Release a pooled connector. Handle shared/non-shared here. /// </summary> private void ReleaseConnectorInternal(NpgsqlConnection Connection, NpgsqlConnector Connector) { if (!Connector.Shared) { UngetConnector(Connection, Connector); } else { // Connection sharing? What's that? throw new NotImplementedException("Internal: Shared pooling not implemented"); } }
/// <summary> /// Rolls back a transaction from a pending state. /// </summary> public override void Rollback() { CheckDisposed(); if (_conn == null) { throw new InvalidOperationException(Exception_NoTransaction); } NpgsqlCommand command = new NpgsqlCommand("ROLLBACK", _conn.Connector); command.ExecuteBlind(); _conn.Connector.Transaction = null; _conn = null; }
private bool _disposeCopyStream; // user did not provide stream, so reset it after use /// <summary> /// Creates NpgsqlCommand to run given query upon Start(), after which CopyStream provides data from database as requested in the query. /// </summary> public NpgsqlCopyOut(string copyOutQuery, NpgsqlConnection conn) : this(new NpgsqlCommand(copyOutQuery, conn), conn) { }
internal NpgsqlTransaction(NpgsqlConnection conn) : this(conn, IsolationLevel.ReadCommitted) { }
/// <summary> /// Given command is run upon Start(), after which CopyStream provides data from database as requested in the query. /// </summary> public NpgsqlCopyOut(NpgsqlCommand cmd, NpgsqlConnection conn) : this(cmd, conn, null) { }
public NpgsqlConnector(NpgsqlConnection Connection) : this(Connection.ConnectionStringValues.Clone(), Connection.Pooling, false) { }
/// <summary> /// Given command is executed upon Start() and all requested copy data is written to toStream immediately. /// </summary> public NpgsqlCopyOut(NpgsqlCommand cmd, NpgsqlConnection conn, Stream toStream) { _context = conn.Connector; _cmd = cmd; _copyStream = toStream; }
/* * Initialises the fastpath system * * @param conn BaseConnection to attach to * @param stream The network stream to the backend */ public Fastpath(NpgsqlConnection conn) { this.conn = conn; // check if the connection is closed ? this.stream = conn.Connector.Stream; }
public NpgsqlTransactionCallbacks(NpgsqlConnection connection) { _connection = connection; _connectionString = _connection.ConnectionString; _connection.Disposed += new EventHandler(_connection_Disposed); }
/// <summary> /// Creates an NpgsqlSchema that can read schema information from the database. /// </summary> /// <param name="connection">An open database connection for reading metadata.</param> internal NpgsqlSchema(NpgsqlConnection connection) { _connection = connection; }
/// <summary> /// Find a pooled connector. Handle shared/non-shared here. /// </summary> private NpgsqlConnector RequestPooledConnectorInternal(NpgsqlConnection Connection) { NpgsqlConnector Connector = null; Boolean Shared = false; // If sharing were implemented, I suppose Shared would be set based // on some property on the Connection. if (Shared) { // Connection sharing? What's that? throw new NotImplementedException("Internal: Shared pooling not implemented"); } Connector = GetPooledConnector(Connection); return Connector; }