001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2002-2004 French National Institute For Research In Computer
004: * Science And Control (INRIA).
005: * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
006: * Contact: sequoia@continuent.org
007: *
008: * Licensed under the Apache License, Version 2.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: * Initial developer(s): Emmanuel Cecchet.
021: * Contributor(s): ______________________.
022: */package org.continuent.sequoia.controller.connection;
023:
024: import java.sql.Connection;
025: import java.util.NoSuchElementException;
026:
027: import org.continuent.sequoia.common.exceptions.UnreachableBackendException;
028: import org.continuent.sequoia.common.i18n.Translate;
029: import org.continuent.sequoia.common.xml.DatabasesXmlTags;
030:
031: /**
032: * This connection manager returns <code>null</code> when the pool is empty.
033: * Therefore all requests fail fast until connections are freed.
034: *
035: * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
036: * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
037: * @version 1.0
038: */
039: public class FailFastPoolConnectionManager extends
040: AbstractPoolConnectionManager {
041:
042: /**
043: * Creates a new <code>FailFastPoolConnectionManager</code> instance.
044: *
045: * @param backendUrl URL of the <code>DatabaseBackend</code> owning this
046: * connection manager
047: * @param backendName name of the <code>DatabaseBackend</code> owning this
048: * connection manager
049: * @param login backend connection login to be used by this connection manager
050: * @param password backend connection password to be used by this connection
051: * manager
052: * @param driverPath path for driver
053: * @param driverClassName class name for driver
054: * @param poolSize size of the connection pool
055: */
056: public FailFastPoolConnectionManager(String backendUrl,
057: String backendName, String login, String password,
058: String driverPath, String driverClassName, int poolSize) {
059: super (backendUrl, backendName, login, password, driverPath,
060: driverClassName, poolSize);
061: }
062:
063: /**
064: * Gets a connection from the pool. Returns <code>null</code> if the pool is
065: * empty.
066: *
067: * @return a connection from the pool or <code>null</code> if the pool is
068: * exhausted
069: * @throws UnreachableBackendException if the backend must be disabled
070: * @see org.continuent.sequoia.controller.connection.AbstractConnectionManager#getConnection()
071: */
072: public synchronized PooledConnection getConnection()
073: throws UnreachableBackendException {
074: if (!initialized) {
075: logger.error(Translate
076: .get("connection.request.not.initialized"));
077: return null;
078: }
079: if (isShutdown) {
080: return null;
081: }
082: try { // Both freeConnections and activeConnections are synchronized
083: PooledConnection c = (PooledConnection) freeConnections
084: .removeLast();
085: activeConnections.add(c);
086: return c;
087: } catch (NoSuchElementException e) { // No free connection
088: int missing = poolSize
089: - (activeConnections.size() + freeConnections
090: .size());
091: if (missing > 0) { // Re-allocate missing connections
092: logger.info(Translate.get(
093: "connection.reallocate.missing", missing));
094: PooledConnection connectionToBeReturned = null;
095: while (missing > 0) {
096: Connection c = getConnectionFromDriver();
097: if (c == null) {
098: if (missing == poolSize) {
099: logger.error(Translate.get(
100: "connection.backend.unreachable",
101: backendName));
102: throw new UnreachableBackendException();
103: }
104: logger.warn(Translate
105: .get("connection.reallocate.failed",
106: missing));
107: break;
108: } else {
109: if (connectionToBeReturned == null)
110: connectionToBeReturned = new PooledConnection(
111: c);
112: else
113: freeConnections
114: .addLast(new PooledConnection(c));
115: }
116: missing--;
117: }
118: return connectionToBeReturned;
119: }
120: if (logger.isWarnEnabled())
121: logger.warn(Translate.get(
122: "connection.backend.out.of.connections",
123: new String[] { backendName,
124: String.valueOf(poolSize) }));
125: return null;
126: }
127: }
128:
129: /**
130: * @see org.continuent.sequoia.controller.connection.AbstractConnectionManager#releaseConnection(org.continuent.sequoia.controller.connection.PooledConnection)
131: */
132: public synchronized void releaseConnection(PooledConnection c) {
133: if (!initialized) {
134: closeConnection(c);
135: return; // We probably have been disabled
136: }
137:
138: if (activeConnections.remove(c)) {
139: c.removeAllTemporaryTables();
140: freeConnections.addLast(c);
141: } else
142: logger.error(Translate.get("connection.release.failed", c
143: .toString()));
144: }
145:
146: /**
147: * @see org.continuent.sequoia.controller.connection.AbstractConnectionManager#deleteConnection(org.continuent.sequoia.controller.connection.PooledConnection)
148: */
149: public synchronized void deleteConnection(PooledConnection c) {
150: closeConnection(c);
151: if (!initialized)
152: return; // We probably have been disabled
153:
154: if (activeConnections.remove(c)) {
155: Connection newConnection = getConnectionFromDriver();
156: if (newConnection == null) {
157: if (logger.isDebugEnabled())
158: logger
159: .error(Translate.get(
160: "connection.replaced.failed", c
161: .toString()));
162: } else {
163: freeConnections.addLast(newConnection);
164: if (logger.isDebugEnabled())
165: logger.debug(Translate
166: .get("connection.replaced.success", c
167: .toString()));
168: }
169: } else
170: logger.error(Translate.get(
171: "connection.replaced.failed.exception", c
172: .toString()));
173: }
174:
175: /**
176: * @see org.continuent.sequoia.controller.connection.AbstractConnectionManager#getXmlImpl()
177: */
178: public String getXmlImpl() {
179: StringBuffer info = new StringBuffer();
180: info.append("<"
181: + DatabasesXmlTags.ELT_FailFastPoolConnectionManager
182: + " " + DatabasesXmlTags.ATT_poolSize + "=\""
183: + poolSize / 1000 + "\"/>");
184: return info.toString();
185: }
186:
187: /**
188: * @see java.lang.Object#clone()
189: */
190: protected Object clone() throws CloneNotSupportedException {
191: return new FailFastPoolConnectionManager(backendUrl,
192: backendName, rLogin, rPassword, driverPath,
193: driverClassName, poolSize);
194: }
195:
196: /**
197: * @see org.continuent.sequoia.controller.connection.AbstractConnectionManager#clone(String,
198: * String)
199: */
200: public AbstractConnectionManager clone(String rLogin,
201: String rPassword) {
202: return new FailFastPoolConnectionManager(backendUrl,
203: backendName, rLogin, rPassword, driverPath,
204: driverClassName, poolSize);
205: }
206:
207: }
|