2
Copyright (C) 2004 MySQL AB
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of version 2 of the GNU General Public License as
6
published by the Free Software Foundation.
8
There are special exceptions to the terms and conditions of the GPL
9
as it is applied to this software. View the full text of the
10
exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
11
software distribution.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
package com.mysql.jdbc;
24
import java.sql.CallableStatement;
25
import java.sql.DatabaseMetaData;
26
import java.sql.PreparedStatement;
27
import java.sql.SQLException;
28
import java.sql.SQLWarning;
29
import java.sql.Savepoint;
30
import java.sql.Statement;
32
import java.util.Properties;
35
* Connection that opens two connections, one two a replication master, and
36
* another to one or more slaves, and decides to use master when the connection
37
* is not read-only, and use slave(s) when the connection is read-only.
39
* @version $Id: ReplicationConnection.java,v 1.1.2.1 2005/05/13 18:58:38
42
public class ReplicationConnection implements java.sql.Connection {
43
private Connection currentConnection;
45
private Connection masterConnection;
47
private Connection slavesConnection;
49
public ReplicationConnection(Properties masterProperties,
50
Properties slaveProperties) throws SQLException {
51
Driver driver = new Driver();
53
StringBuffer masterUrl = new StringBuffer("jdbc:mysql://");
54
StringBuffer slaveUrl = new StringBuffer("jdbc:mysql://");
56
String masterHost = masterProperties
57
.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY);
59
if (masterHost != null) {
60
masterUrl.append(masterHost);
63
String slaveHost = slaveProperties
64
.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY);
66
if (slaveHost != null) {
67
slaveUrl.append(slaveHost);
70
String masterDb = masterProperties
71
.getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY);
73
masterUrl.append("/");
75
if (masterDb != null) {
76
masterUrl.append(masterDb);
79
String slaveDb = slaveProperties
80
.getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY);
84
if (slaveDb != null) {
85
slaveUrl.append(slaveDb);
88
this.masterConnection = (com.mysql.jdbc.Connection) driver.connect(
89
masterUrl.toString(), masterProperties);
90
this.slavesConnection = (com.mysql.jdbc.Connection) driver.connect(
91
slaveUrl.toString(), slaveProperties);
93
this.currentConnection = this.masterConnection;
99
* @see java.sql.Connection#clearWarnings()
101
public synchronized void clearWarnings() throws SQLException {
102
this.currentConnection.clearWarnings();
108
* @see java.sql.Connection#close()
110
public synchronized void close() throws SQLException {
111
this.masterConnection.close();
112
this.slavesConnection.close();
118
* @see java.sql.Connection#commit()
120
public synchronized void commit() throws SQLException {
121
this.currentConnection.commit();
127
* @see java.sql.Connection#createStatement()
129
public Statement createStatement() throws SQLException {
130
return this.currentConnection.createStatement();
136
* @see java.sql.Connection#createStatement(int, int)
138
public synchronized Statement createStatement(int resultSetType,
139
int resultSetConcurrency) throws SQLException {
140
return this.currentConnection.createStatement(resultSetType,
141
resultSetConcurrency);
147
* @see java.sql.Connection#createStatement(int, int, int)
149
public synchronized Statement createStatement(int resultSetType,
150
int resultSetConcurrency, int resultSetHoldability)
151
throws SQLException {
152
return this.currentConnection.createStatement(resultSetType,
153
resultSetConcurrency, resultSetHoldability);
159
* @see java.sql.Connection#getAutoCommit()
161
public synchronized boolean getAutoCommit() throws SQLException {
162
return this.currentConnection.getAutoCommit();
168
* @see java.sql.Connection#getCatalog()
170
public synchronized String getCatalog() throws SQLException {
171
return this.currentConnection.getCatalog();
174
public synchronized Connection getCurrentConnection() {
175
return this.currentConnection;
181
* @see java.sql.Connection#getHoldability()
183
public synchronized int getHoldability() throws SQLException {
184
return this.currentConnection.getHoldability();
187
public synchronized Connection getMasterConnection() {
188
return this.masterConnection;
194
* @see java.sql.Connection#getMetaData()
196
public synchronized DatabaseMetaData getMetaData() throws SQLException {
197
return this.currentConnection.getMetaData();
200
public synchronized Connection getSlavesConnection() {
201
return this.slavesConnection;
207
* @see java.sql.Connection#getTransactionIsolation()
209
public synchronized int getTransactionIsolation() throws SQLException {
210
return this.currentConnection.getTransactionIsolation();
216
* @see java.sql.Connection#getTypeMap()
218
public synchronized Map getTypeMap() throws SQLException {
219
return this.currentConnection.getTypeMap();
225
* @see java.sql.Connection#getWarnings()
227
public synchronized SQLWarning getWarnings() throws SQLException {
228
return this.currentConnection.getWarnings();
234
* @see java.sql.Connection#isClosed()
236
public synchronized boolean isClosed() throws SQLException {
237
return this.currentConnection.isClosed();
243
* @see java.sql.Connection#isReadOnly()
245
public synchronized boolean isReadOnly() throws SQLException {
246
return this.currentConnection == this.slavesConnection;
252
* @see java.sql.Connection#nativeSQL(java.lang.String)
254
public synchronized String nativeSQL(String sql) throws SQLException {
255
return this.currentConnection.nativeSQL(sql);
261
* @see java.sql.Connection#prepareCall(java.lang.String)
263
public CallableStatement prepareCall(String sql) throws SQLException {
264
return this.currentConnection.prepareCall(sql);
270
* @see java.sql.Connection#prepareCall(java.lang.String, int, int)
272
public synchronized CallableStatement prepareCall(String sql,
273
int resultSetType, int resultSetConcurrency) throws SQLException {
274
return this.currentConnection.prepareCall(sql, resultSetType,
275
resultSetConcurrency);
281
* @see java.sql.Connection#prepareCall(java.lang.String, int, int, int)
283
public synchronized CallableStatement prepareCall(String sql,
284
int resultSetType, int resultSetConcurrency,
285
int resultSetHoldability) throws SQLException {
286
return this.currentConnection.prepareCall(sql, resultSetType,
287
resultSetConcurrency, resultSetHoldability);
293
* @see java.sql.Connection#prepareStatement(java.lang.String)
295
public PreparedStatement prepareStatement(String sql) throws SQLException {
296
return this.currentConnection.prepareStatement(sql);
302
* @see java.sql.Connection#prepareStatement(java.lang.String, int)
304
public synchronized PreparedStatement prepareStatement(String sql,
305
int autoGeneratedKeys) throws SQLException {
306
return this.currentConnection.prepareStatement(sql, autoGeneratedKeys);
312
* @see java.sql.Connection#prepareStatement(java.lang.String, int, int)
314
public synchronized PreparedStatement prepareStatement(String sql,
315
int resultSetType, int resultSetConcurrency) throws SQLException {
316
return this.currentConnection.prepareStatement(sql, resultSetType,
317
resultSetConcurrency);
323
* @see java.sql.Connection#prepareStatement(java.lang.String, int, int,
326
public synchronized PreparedStatement prepareStatement(String sql,
327
int resultSetType, int resultSetConcurrency,
328
int resultSetHoldability) throws SQLException {
329
return this.currentConnection.prepareStatement(sql, resultSetType,
330
resultSetConcurrency, resultSetHoldability);
336
* @see java.sql.Connection#prepareStatement(java.lang.String, int[])
338
public synchronized PreparedStatement prepareStatement(String sql,
339
int[] columnIndexes) throws SQLException {
340
return this.currentConnection.prepareStatement(sql, columnIndexes);
346
* @see java.sql.Connection#prepareStatement(java.lang.String,
347
* java.lang.String[])
349
public synchronized PreparedStatement prepareStatement(String sql,
350
String[] columnNames) throws SQLException {
351
return this.currentConnection.prepareStatement(sql, columnNames);
357
* @see java.sql.Connection#releaseSavepoint(java.sql.Savepoint)
359
public synchronized void releaseSavepoint(Savepoint savepoint)
360
throws SQLException {
361
this.currentConnection.releaseSavepoint(savepoint);
367
* @see java.sql.Connection#rollback()
369
public synchronized void rollback() throws SQLException {
370
this.currentConnection.rollback();
376
* @see java.sql.Connection#rollback(java.sql.Savepoint)
378
public synchronized void rollback(Savepoint savepoint) throws SQLException {
379
this.currentConnection.rollback(savepoint);
385
* @see java.sql.Connection#setAutoCommit(boolean)
387
public synchronized void setAutoCommit(boolean autoCommit)
388
throws SQLException {
389
this.currentConnection.setAutoCommit(autoCommit);
395
* @see java.sql.Connection#setCatalog(java.lang.String)
397
public synchronized void setCatalog(String catalog) throws SQLException {
398
this.currentConnection.setCatalog(catalog);
404
* @see java.sql.Connection#setHoldability(int)
406
public synchronized void setHoldability(int holdability)
407
throws SQLException {
408
this.currentConnection.setHoldability(holdability);
414
* @see java.sql.Connection#setReadOnly(boolean)
416
public synchronized void setReadOnly(boolean readOnly) throws SQLException {
418
if (currentConnection != slavesConnection) {
419
switchToSlavesConnection();
422
if (currentConnection != masterConnection) {
423
switchToMasterConnection();
431
* @see java.sql.Connection#setSavepoint()
433
public synchronized Savepoint setSavepoint() throws SQLException {
434
return this.currentConnection.setSavepoint();
440
* @see java.sql.Connection#setSavepoint(java.lang.String)
442
public synchronized Savepoint setSavepoint(String name) throws SQLException {
443
return this.currentConnection.setSavepoint(name);
449
* @see java.sql.Connection#setTransactionIsolation(int)
451
public synchronized void setTransactionIsolation(int level)
452
throws SQLException {
453
this.currentConnection.setTransactionIsolation(level);
461
* @see java.sql.Connection#setTypeMap(java.util.Map)
463
public synchronized void setTypeMap(Map arg0) throws SQLException {
464
this.currentConnection.setTypeMap(arg0);
467
private synchronized void switchToMasterConnection() throws SQLException {
468
swapConnections(this.masterConnection, this.slavesConnection);
471
private synchronized void switchToSlavesConnection() throws SQLException {
472
swapConnections(this.slavesConnection, this.masterConnection);
476
* Swaps current context (catalog, autocommit and txn_isolation) from
477
* sourceConnection to targetConnection, and makes targetConnection
478
* the "current" connection that will be used for queries.
480
* @param switchToConnection the connection to swap from
481
* @param switchFromConnection the connection to swap to
483
* @throws SQLException if an error occurs
485
private synchronized void swapConnections(Connection switchToConnection,
486
Connection switchFromConnection) throws SQLException {
487
String switchFromCatalog = switchFromConnection.getCatalog();
488
String switchToCatalog = switchToConnection.getCatalog();
490
if (switchToCatalog != null && !switchToCatalog.equals(switchFromCatalog)) {
491
switchToConnection.setCatalog(switchFromCatalog);
492
} else if (switchFromCatalog != null) {
493
switchToConnection.setCatalog(switchFromCatalog);
496
boolean switchToAutoCommit = switchToConnection.getAutoCommit();
497
boolean switchFromConnectionAutoCommit = switchFromConnection.getAutoCommit();
499
if (switchFromConnectionAutoCommit != switchToAutoCommit) {
500
switchToConnection.setAutoCommit(switchFromConnectionAutoCommit);
503
int switchToIsolation = switchToConnection
504
.getTransactionIsolation();
506
int switchFromIsolation = switchFromConnection.getTransactionIsolation();
508
if (switchFromIsolation != switchToIsolation) {
510
.setTransactionIsolation(switchFromIsolation);
513
this.currentConnection = switchToConnection;