00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 public class RandomWaitPoolConnectionManager
00046 extends
00047 AbstractPoolConnectionManager implements Serializable
00048 {
00049
00050 private int timeout;
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
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
00077
00078
00079
00080 protected Object clone() throws CloneNotSupportedException
00081 {
00082 return new RandomWaitPoolConnectionManager(backendUrl, backendName, rLogin,
00083 rPassword, driverPath, driverClassName, poolSize,timeout);
00084 }
00085
00086
00087
00088
00089
00090
00091 public int getTimeout()
00092 {
00093 return timeout;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
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
00218
00219
00220
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
00239
00240
00241
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
00273
00274
00275
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 }