View Javadoc

1   /**
2    * This file is part of GoldenGate Project (named also GoldenGate or GG).
3    * 
4    * Copyright 2009, Frederic Bregier, and individual contributors by the @author
5    * tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    * 
8    * All GoldenGate Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   * 
13   * GoldenGate is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Public License along with
18   * GoldenGate . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package goldengate.common.database.model;
21  
22  import java.sql.Connection;
23  import java.sql.DriverManager;
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.sql.Statement;
27  
28  import goldengate.common.database.DbAdmin;
29  import goldengate.common.database.DbConstant;
30  import goldengate.common.database.DbSession;
31  import goldengate.common.database.exception.GoldenGateDatabaseNoConnectionException;
32  import goldengate.common.database.exception.GoldenGateDatabaseSqlException;
33  import goldengate.common.logging.GgInternalLogger;
34  import goldengate.common.logging.GgInternalLoggerFactory;
35  
36  /**
37   * This Abstract class regroups common methods for all implementation classes.
38   * 
39   * @author Frederic Bregier
40   * 
41   */
42  public abstract class DbModelAbstract implements DbModel {
43      /**
44       * Internal Logger
45       */
46      private static final GgInternalLogger logger = GgInternalLoggerFactory
47              .getLogger(DbModelAbstract.class);
48  
49      /**
50       * Recreate the disconnected session
51       * 
52       * @param dbSession
53       * @throws GoldenGateDatabaseNoConnectionException
54       */
55      private void recreateSession(DbSession dbSession)
56              throws GoldenGateDatabaseNoConnectionException {
57          DbAdmin admin = dbSession.getAdmin();
58          if (admin == null) {
59              if (dbSession.autoCommit) {
60                  admin = DbConstant.admin;
61              } else {
62                  admin = DbConstant.noCommitAdmin;
63              }
64          }
65          DbSession newdbSession = new DbSession(admin, dbSession.isReadOnly);
66          try {
67              if (dbSession.conn != null) {
68                  dbSession.conn.close();
69              }
70          } catch (SQLException e1) {
71          }
72          dbSession.conn = newdbSession.conn;
73          DbAdmin.addConnection(dbSession.internalId, dbSession);
74          DbAdmin.removeConnection(newdbSession.internalId);
75          logger.warn("Database Connection lost: database connection reopened");
76      }
77  
78      /**
79       * Internal use for closing connection while validating it
80       * 
81       * @param dbSession
82       */
83      protected void closeInternalConnection(DbSession dbSession) {
84          try {
85              if (dbSession.conn != null) {
86                  dbSession.conn.close();
87              }
88          } catch (SQLException e1) {
89          }
90          dbSession.isDisconnected = true;
91          if (dbSession.admin != null) dbSession.admin.isConnected = false;
92          DbAdmin.removeConnection(dbSession.internalId);
93      }
94  
95      @Override
96      public void validConnection(DbSession dbSession)
97              throws GoldenGateDatabaseNoConnectionException {
98          // try to limit the number of check!
99          synchronized (dbSession) {
100             try {
101                 if (!dbSession.conn.isClosed()) {
102                     if (!dbSession.conn.isValid(DbConstant.VALIDTESTDURATION)) {
103                         // Give a try by closing the current connection
104                         throw new SQLException("Cannot connect to database");
105                     }
106                 }
107                 dbSession.isDisconnected = false;
108                 if (dbSession.admin != null)
109                     dbSession.admin.isConnected = true;
110             } catch (SQLException e2) {
111                 dbSession.isDisconnected = true;
112                 if (dbSession.admin != null)
113                     dbSession.admin.isConnected = false;
114                 // Might be unsupported so switch to SELECT 1 way
115                 if (e2 instanceof org.postgresql.util.PSQLException) {
116                     validConnectionSelect(dbSession);
117                     return;
118                 }
119                 try {
120                     try {
121                         recreateSession(dbSession);
122                     } catch (GoldenGateDatabaseNoConnectionException e) {
123                         closeInternalConnection(dbSession);
124                         throw e;
125                     }
126                     try {
127                         if (!dbSession.conn.isValid(DbConstant.VALIDTESTDURATION)) {
128                             // Not ignored
129                             closeInternalConnection(dbSession);
130                             throw new GoldenGateDatabaseNoConnectionException(
131                                     "Cannot connect to database", e2);
132                         }
133                     } catch (SQLException e) {
134                         closeInternalConnection(dbSession);
135                         throw new GoldenGateDatabaseNoConnectionException(
136                                 "Cannot connect to database", e);
137                     }
138                     dbSession.isDisconnected = false;
139                     if (dbSession.admin != null)
140                         dbSession.admin.isConnected = true;
141                     dbSession.recreateLongTermPreparedStatements();
142                     return;
143                 } catch (GoldenGateDatabaseSqlException e1) {
144                     // ignore and will send a No Connection error
145                 }
146                 closeInternalConnection(dbSession);
147                 throw new GoldenGateDatabaseNoConnectionException(
148                         "Cannot connect to database", e2);
149             }
150         }
151     }
152 
153     public void validConnectionSelect(DbSession dbSession)
154             throws GoldenGateDatabaseNoConnectionException {
155         // try to limit the number of check!
156         synchronized (dbSession) {
157             Statement stmt = null;
158             try {
159                 stmt = dbSession.conn.createStatement();
160                 if (stmt.execute(validConnectionString())) {
161                     ResultSet set = stmt.getResultSet();
162                     if (!set.next()) {
163                         stmt.close();
164                         stmt = null;
165                         // Give a try by closing the current connection
166                         throw new SQLException("Cannot connect to database");
167                     }
168                 }
169                 dbSession.isDisconnected = false;
170                 if (dbSession.admin != null)
171                     dbSession.admin.isConnected = true;
172             } catch (SQLException e2) {
173                 dbSession.isDisconnected = true;
174                 if (dbSession.admin != null)
175                     dbSession.admin.isConnected = false;
176                 try {
177                     try {
178                         recreateSession(dbSession);
179                     } catch (GoldenGateDatabaseNoConnectionException e) {
180                         closeInternalConnection(dbSession);
181                         throw e;
182                     }
183                     try {
184                         if (stmt != null) {
185                             stmt.close();
186                             stmt = null;
187                         }
188                     } catch (SQLException e) {
189                         // ignore
190                     }
191                     try {
192                         stmt = dbSession.conn.createStatement();
193                     } catch (SQLException e) {
194                         // Not ignored
195                         closeInternalConnection(dbSession);
196                         throw new GoldenGateDatabaseNoConnectionException(
197                                 "Cannot connect to database", e);
198                     }
199                     try {
200                         if (stmt.execute(validConnectionString())) {
201                             ResultSet set = stmt.getResultSet();
202                             if (!set.next()) {
203                                 if (stmt != null) {
204                                     stmt.close();
205                                     stmt = null;
206                                 }
207                                 closeInternalConnection(dbSession);
208                                 throw new GoldenGateDatabaseNoConnectionException(
209                                         "Cannot connect to database");
210                             }
211                         }
212                     } catch (SQLException e) {
213                         // not ignored
214                         try {
215                             if (stmt != null) {
216                                 stmt.close();
217                                 stmt = null;
218                             }
219                         } catch (SQLException e1) {
220                         }
221                         closeInternalConnection(dbSession);
222                         throw new GoldenGateDatabaseNoConnectionException(
223                                 "Cannot connect to database", e);
224                     }
225                     dbSession.isDisconnected = false;
226                     if (dbSession.admin != null)
227                         dbSession.admin.isConnected = true;
228                     dbSession.recreateLongTermPreparedStatements();
229                     return;
230                 } catch (GoldenGateDatabaseSqlException e1) {
231                     // ignore and will send a No Connection error
232                 }
233                 closeInternalConnection(dbSession);
234                 throw new GoldenGateDatabaseNoConnectionException(
235                         "Cannot connect to database", e2);
236             } finally {
237                 if (stmt != null) {
238                     try {
239                         stmt.close();
240                     } catch (SQLException e) {
241                     }
242                 }
243             }
244         }
245     }
246 
247     /**
248      * 
249      * @return the associated String to validate the connection (as
250      *         "select 1 frm dual")
251      */
252     protected abstract String validConnectionString();
253 
254     @Override
255     public Connection getDbConnection(String server, String user, String passwd)
256             throws SQLException {
257         // Default implementation
258         return DriverManager.getConnection(server, user, passwd);
259     }
260 
261     @Override
262     public void releaseResources() {
263     }
264 
265     @Override
266     public int currentNumberOfPooledConnections() {
267         return DbAdmin.getNbConnection();
268     }
269 
270 }