-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathWrappedConnection.java
135 lines (117 loc) · 5.39 KB
/
WrappedConnection.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - [email protected]
*/
package sirius.db.jdbc;
import sirius.db.DB;
import sirius.kernel.async.ExecutionPoint;
import sirius.kernel.async.Operation;
import sirius.kernel.commons.Watch;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Duration;
/**
* Used to make connection pooling more robust. (Doesn't call close() twice,
* etc.).
*/
class WrappedConnection extends DelegatingConnection<Connection> {
protected final Database database;
private final Watch watch = Watch.start();
private final ExecutionPoint connected = ExecutionPoint.fastSnapshot();
private boolean longRunning;
WrappedConnection(Connection c, Database database) {
super(c);
this.database = database;
Databases.numUses.inc();
}
@Override
public String toString() {
return "WrappedConnection [" + database.getUrl() + "] (" + delegate.toString() + ")";
}
/**
* Marks this connection as potentially long running.
* <p>
* This suppresses the "long running connection" warning emitted by {@link #close()}.
*
* @return the connection itself for fluent method calls
*/
public WrappedConnection markAsLongRunning() {
this.longRunning = true;
return this;
}
@Override
public void close() throws SQLException {
try (Operation op = new Operation(() -> database.name + ".close()", Duration.ofSeconds(5))) {
delegate.close();
} catch (SQLException e) {
// Most likely this exception will be a false alert because DBCP 1.2.2 cannot deal with connections which
// are closed by their driver (due to network issues).
// The next release of DBCP will fix this problem. The exception is logged at INFO level in case a "real"
// problem occurred. If we wouldn't call delegate.close, the connection would remain active and might block
// the pool.
Databases.LOG.INFO("Error closing connection");
Databases.LOG.INFO(e);
} finally {
watch.submitMicroTiming("SQL", "Connection Duration: " + database.name);
if (!longRunning && watch.elapsedMillis() > Databases.getLogConnectionThresholdMillis()) {
DB.SLOW_DB_LOG.INFO("A long running connection was detected (%s): Opened:\n%s\n\nClosed:\n%s",
watch.duration(),
connected.toString(),
ExecutionPoint.snapshot().toString());
}
}
}
@Override
public Statement createStatement() throws SQLException {
return new WrappedStatement(delegate.createStatement());
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return new WrappedStatement(delegate.createStatement(resultSetType,
resultSetConcurrency,
resultSetHoldability));
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return new WrappedStatement(delegate.createStatement(resultSetType, resultSetConcurrency));
}
@Override
public PreparedStatement prepareStatement(String sql,
int resultSetType,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return new WrappedPreparedStatement(delegate.prepareStatement(sql,
resultSetType,
resultSetConcurrency,
resultSetHoldability), longRunning, sql);
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
return new WrappedPreparedStatement(delegate.prepareStatement(sql, resultSetType, resultSetConcurrency),
longRunning,
sql);
}
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return new WrappedPreparedStatement(delegate.prepareStatement(sql, autoGeneratedKeys), longRunning, sql);
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return new WrappedPreparedStatement(delegate.prepareStatement(sql, columnIndexes), longRunning, sql);
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return new WrappedPreparedStatement(delegate.prepareStatement(sql, columnNames), longRunning, sql);
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return new WrappedPreparedStatement(delegate.prepareStatement(sql), longRunning, sql);
}
}