00001
00025
package org.objectweb.cjdbc.controller.connection;
00026
00027
import java.io.Serializable;
00028
import java.sql.Connection;
00029
import java.util.EmptyStackException;
00030
00031
import org.objectweb.cjdbc.common.exceptions.UnreachableBackendException;
00032
import org.objectweb.cjdbc.common.i18n.Translate;
00033
import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
00034
00045 public class RandomWaitPoolConnectionManager
00046
extends
00047
AbstractPoolConnectionManager implements Serializable
00048 {
00050 private int timeout;
00051
00068 public RandomWaitPoolConnectionManager(String backendUrl, String backendName,
00069 String login, String password, String driverPath, String driverClassName,
00070
int poolSize,
int timeout)
00071 {
00072 super(backendUrl, backendName, login, password, driverPath,
00073 driverClassName, poolSize);
00074
this.timeout = timeout * 1000;
00075 }
00076
00080 protected Object
clone() throws CloneNotSupportedException
00081 {
00082
return new RandomWaitPoolConnectionManager(backendUrl, backendName, rLogin,
00083 rPassword, driverPath, driverClassName, poolSize,
timeout);
00084 }
00085
00091 public int getTimeout()
00092 {
00093
return timeout;
00094 }
00095
00107 public Connection
getConnection() throws
UnreachableBackendException
00108 {
00109
if (!initialized)
00110 {
00111 logger
00112 .
error(
"Requesting a connection from a non-initialized connection manager");
00113
return null;
00114 }
00115
00116
long lTimeout =
timeout;
00117
synchronized (freeConnections)
00118 {
00119
00120
00121
00122
00123
00124
00125
00126
while (freeConnections.isEmpty())
00127 {
00128
00129
try
00130 {
00131
if (lTimeout > 0)
00132 {
00133
long start = System.currentTimeMillis();
00134
00135 freeConnections.wait(timeout);
00136
long end = System.currentTimeMillis();
00137 lTimeout -= end - start;
00138
if (lTimeout <= 0)
00139 {
00140
if (activeConnections.size() == 0)
00141 {
00142
00143 logger.
error(
"Backend " + backendName
00144 +
" is no more accessible.");
00145
throw new UnreachableBackendException();
00146 }
00147
if (logger.
isWarnEnabled())
00148 logger.
warn(
"Timeout expired for connection on backend '"
00149 + backendName
00150 +
"', consider increasing pool size (current size is "
00151 + poolSize +
") or timeout (current timeout is "
00152 + (timeout / 1000) +
" seconds)");
00153
return null;
00154 }
00155 }
00156
else
00157 freeConnections.wait();
00158 }
00159
catch (InterruptedException e)
00160 {
00161 logger
00162 .
error(
"Wait on freeConnections interrupted in RandomWaitPoolConnectionManager: "
00163 + e);
00164
return null;
00165 }
00166 }
00167
00168
try
00169 {
00170 Connection c = (Connection) freeConnections.pop();
00171 activeConnections.add(c);
00172
return c;
00173 }
00174
catch (EmptyStackException e)
00175 {
00176
int missing = poolSize
00177 - (activeConnections.size() + freeConnections.size());
00178
if (missing > 0)
00179 {
00180 logger.
info(
"Trying to reallocate " + missing
00181 +
" missing connections.");
00182 Connection connectionToBeReturned = null;
00183
while (missing > 0)
00184 {
00185 Connection c =
getConnectionFromDriver();
00186
if (c == null)
00187 {
00188
if (missing == poolSize)
00189 {
00190 String msg =
Translate.get(
"loadbalancer.backend.unreacheable",
00191 backendName);
00192 logger.
error(msg);
00193
throw new UnreachableBackendException(msg);
00194 }
00195 logger.
warn(
"Unable to re-allocate " + missing
00196 +
" missing connections.");
00197
break;
00198 }
00199
else
00200 {
00201
if (connectionToBeReturned == null)
00202 connectionToBeReturned = c;
00203
else
00204 freeConnections.add(c);
00205 }
00206 missing--;
00207 }
00208
return connectionToBeReturned;
00209 }
00210
if (logger.
isErrorEnabled())
00211 logger.
error(
"Failed to get a connection on backend '" + backendName
00212 +
"' whereas an idle connection was expected");
00213
return null;
00214 }
00215 }
00216 }
00217
00221 public void releaseConnection(Connection c)
00222 {
00223
if (!initialized)
00224
return;
00225
00226
synchronized (freeConnections)
00227 {
00228
if (activeConnections.remove(c))
00229 {
00230 freeConnections.push(c);
00231 freeConnections.notify();
00232 }
00233
else
00234 logger.
error(
"Failed to release connection " + c
00235 +
" (not found in active pool)");
00236 }
00237 }
00238
00242 public void deleteConnection(Connection c)
00243 {
00244
if (!initialized)
00245
return;
00246
00247
synchronized (freeConnections)
00248 {
00249
if (activeConnections.remove(c))
00250 {
00251 Connection newConnection =
getConnectionFromDriver();
00252
if (newConnection == null)
00253 {
00254
if (logger.
isDebugEnabled())
00255 logger.
error(
"Bad connection " + c
00256 +
" has been removed but cannot be replaced.");
00257 }
00258
else
00259 {
00260 freeConnections.push(newConnection);
00261 freeConnections.notify();
00262
if (logger.
isDebugEnabled())
00263 logger.
debug(
"Bad connection " + c
00264 +
" has been replaced by a new connection.");
00265 }
00266 }
00267
else
00268 logger.
error(
"Failed to release connection " + c
00269 +
" (not found in active pool)");
00270 }
00271 }
00272
00276 public String
getXmlImpl()
00277 {
00278 StringBuffer info =
new StringBuffer();
00279 info.append(
"<" +
DatabasesXmlTags.ELT_RandomWaitPoolConnectionManager
00280 +
" " +
DatabasesXmlTags.ATT_poolSize +
"=\"" + poolSize +
"\" "
00281 +
DatabasesXmlTags.ATT_timeout +
"=\"" +
timeout / 1000 +
"\"/>");
00282
return info.toString();
00283 }
00284
00285 }