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.loadbalancer.raidb2;
00026
00027 import java.sql.SQLException;
00028 import java.util.ArrayList;
00029
00030 import org.objectweb.cjdbc.common.exceptions.NoMoreBackendException;
00031 import org.objectweb.cjdbc.common.exceptions.UnreachableBackendException;
00032 import org.objectweb.cjdbc.common.i18n.Translate;
00033 import org.objectweb.cjdbc.common.sql.SelectRequest;
00034 import org.objectweb.cjdbc.common.sql.StoredProcedure;
00035 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
00036 import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
00037 import org.objectweb.cjdbc.controller.cache.metadata.MetadataCache;
00038 import org.objectweb.cjdbc.controller.loadbalancer.policies.WaitForCompletionPolicy;
00039 import org.objectweb.cjdbc.controller.loadbalancer.policies.createtable.CreateTablePolicy;
00040 import org.objectweb.cjdbc.controller.virtualdatabase.ControllerResultSet;
00041 import org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabase;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 public class RAIDb2_LPRF extends RAIDb2
00055 {
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 public RAIDb2_LPRF(VirtualDatabase vdb,
00077 WaitForCompletionPolicy waitForCompletionPolicy,
00078 CreateTablePolicy createTablePolicy) throws Exception
00079 {
00080 super(vdb, waitForCompletionPolicy, createTablePolicy);
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 public ControllerResultSet execReadRequest(SelectRequest request,
00100 MetadataCache metadataCache) throws SQLException
00101 {
00102
00103 try
00104 {
00105 vdb.acquireReadLockBackendLists();
00106 }
00107 catch (InterruptedException e)
00108 {
00109 String msg = Translate.get(
00110 "loadbalancer.backendlist.acquire.readlock.failed", e);
00111 logger.error(msg);
00112 throw new SQLException(msg);
00113 }
00114
00115 DatabaseBackend backend = null;
00116
00117
00118
00119 try
00120 {
00121 ArrayList backends = vdb.getBackends();
00122 int size = backends.size();
00123
00124 if (size == 0)
00125 throw new SQLException(Translate.get(
00126 "loadbalancer.execute.no.backend.available", request.getId()));
00127
00128
00129 int leastRequests = 0;
00130 int enabledBackends = 0;
00131 ArrayList tables = request.getFrom();
00132
00133 for (int i = 0; i < size; i++)
00134 {
00135 DatabaseBackend b = (DatabaseBackend) backends.get(i);
00136 if (b.isReadEnabled())
00137 {
00138 enabledBackends++;
00139 if (b.hasTables(tables))
00140 {
00141 int pending = b.getPendingRequests().size();
00142 if (((backend == null) || (pending < leastRequests)))
00143 {
00144 backend = b;
00145 if (pending == 0)
00146 break;
00147 else
00148 leastRequests = pending;
00149 }
00150 }
00151 }
00152 }
00153
00154 if (backend == null)
00155 {
00156 if (enabledBackends == 0)
00157 throw new NoMoreBackendException(Translate.get(
00158 "loadbalancer.execute.no.backend.enabled", request.getId()));
00159 else
00160 throw new SQLException(Translate.get(
00161 "loadbalancer.backend.no.required.tables", tables.toString()));
00162 }
00163
00164 }
00165 catch (RuntimeException e)
00166 {
00167 String msg = Translate.get("loadbalancer.request.failed.on.backend",
00168 new String[]{request.getSQLShortForm(vdb.getSQLShortFormLength()),
00169 backend.getName(), e.getMessage()});
00170 logger.error(msg, e);
00171 throw new SQLException(msg);
00172 }
00173 finally
00174 {
00175 vdb.releaseReadLockBackendLists();
00176 }
00177
00178
00179 ControllerResultSet rs = null;
00180 try
00181 {
00182 rs = executeRequestOnBackend(request, backend, metadataCache);
00183 }
00184 catch (UnreachableBackendException se)
00185 {
00186
00187 return execReadRequest(request, metadataCache);
00188 }
00189 catch (SQLException se)
00190 {
00191 String msg = Translate.get("loadbalancer.request.failed", new String[]{
00192 String.valueOf(request.getId()), se.getMessage()});
00193 if (logger.isInfoEnabled())
00194 logger.info(msg);
00195 throw new SQLException(msg);
00196 }
00197 catch (RuntimeException e)
00198 {
00199 String msg = Translate.get("loadbalancer.request.failed.on.backend",
00200 new String[]{request.getSQLShortForm(vdb.getSQLShortFormLength()),
00201 backend.getName(), e.getMessage()});
00202 logger.error(msg, e);
00203 throw new SQLException(msg);
00204 }
00205
00206 return rs;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 public ControllerResultSet execReadOnlyReadStoredProcedure(
00218 StoredProcedure proc, MetadataCache metadataCache) throws SQLException
00219 {
00220
00221 try
00222 {
00223 vdb.acquireReadLockBackendLists();
00224 }
00225 catch (InterruptedException e)
00226 {
00227 String msg = Translate.get(
00228 "loadbalancer.backendlist.acquire.readlock.failed", e);
00229 logger.error(msg);
00230 throw new SQLException(msg);
00231 }
00232
00233 DatabaseBackend backend = null;
00234
00235
00236
00237 try
00238 {
00239 DatabaseBackend failedBackend = null;
00240 SQLException failedException = null;
00241 ControllerResultSet rs = null;
00242 do
00243 {
00244 ArrayList backends = vdb.getBackends();
00245 int size = backends.size();
00246
00247 if (size == 0)
00248 throw new SQLException(Translate.get(
00249 "loadbalancer.execute.no.backend.available", proc.getId()));
00250
00251
00252 int leastRequests = 0;
00253 int enabledBackends = 0;
00254
00255 for (int i = 0; i < size; i++)
00256 {
00257 DatabaseBackend b = (DatabaseBackend) backends.get(i);
00258 if (b.isReadEnabled())
00259 {
00260 enabledBackends++;
00261 if (b.hasStoredProcedure(proc.getProcedureName()))
00262 {
00263 int pending = b.getPendingRequests().size();
00264 if ((b != failedBackend)
00265 && ((backend == null) || (pending < leastRequests)))
00266 {
00267 backend = b;
00268 if (pending == 0)
00269 break;
00270 else
00271 leastRequests = pending;
00272 }
00273 }
00274 }
00275 }
00276
00277 if (backend == null)
00278 {
00279 if (enabledBackends == 0)
00280 throw new SQLException(Translate
00281 .get("loadbalancer.storedprocedure.backend.no.enabled", proc
00282 .getId()));
00283 else if (failedBackend == null)
00284 throw new SQLException(Translate.get(
00285 "loadbalancer.backend.no.required.storedprocedure", proc
00286 .getProcedureName()));
00287 else
00288
00289 throw failedException;
00290 }
00291
00292
00293 boolean toDisable = false;
00294 try
00295 {
00296 rs = executeStoredProcedureOnBackend(proc, backend, metadataCache);
00297 if (failedBackend != null)
00298 {
00299 if (logger.isWarnEnabled())
00300 logger.warn(Translate.get("loadbalancer.storedprocedure.status",
00301 new String[]{String.valueOf(proc.getId()), backend.getName(),
00302 failedBackend.getName()}));
00303 toDisable = true;
00304 }
00305 }
00306 catch (UnreachableBackendException se)
00307 {
00308
00309 continue;
00310 }
00311 catch (SQLException se)
00312 {
00313 if (failedBackend != null)
00314 {
00315 String msg = Translate.get(
00316 "loadbalancer.storedprocedure.failed.twice", new String[]{
00317 String.valueOf(proc.getId()), se.getMessage()});
00318 if (logger.isInfoEnabled())
00319 logger.info(msg);
00320 throw new SQLException(msg);
00321 }
00322 else
00323 {
00324 failedBackend = backend;
00325 failedException = se;
00326 if (logger.isInfoEnabled())
00327 logger.info(Translate.get(
00328 "loadbalancer.storedprocedure.failed.on.backend",
00329 new String[]{
00330 proc.getSQLShortForm(vdb.getSQLShortFormLength()),
00331 backend.getName(), se.getMessage()}));
00332 continue;
00333 }
00334 }
00335
00336 if (toDisable)
00337 {
00338
00339 try
00340 {
00341 if (logger.isWarnEnabled())
00342 logger.warn(Translate.get("loadbalancer.backend.disabling",
00343 failedBackend.getName()));
00344 disableBackend(failedBackend);
00345 }
00346 catch (SQLException ignore)
00347 {
00348 }
00349 finally
00350 {
00351 failedBackend = null;
00352 }
00353 }
00354 }
00355 while (failedBackend != null);
00356 return rs;
00357 }
00358 catch (RuntimeException e)
00359 {
00360 String msg = Translate.get(
00361 "loadbalancer.storedprocedure.failed.on.backend", new String[]{
00362 proc.getSQLShortForm(vdb.getSQLShortFormLength()),
00363 backend.getName(), e.getMessage()});
00364 logger.fatal(msg, e);
00365 throw new SQLException(msg);
00366 }
00367 finally
00368 {
00369 vdb.releaseReadLockBackendLists();
00370 }
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 public String getInformation()
00383 {
00384
00385 int size = vdb.getBackends().size();
00386
00387 if (size == 0)
00388 return "RAIDb-2 Least Pending Requests First load balancer: !!!Warning!!! No backend nodes found\n";
00389 else
00390 return "RAIDb-2 Least Pending Requests First load balancer (" + size
00391 + " backends)\n";
00392 }
00393
00394
00395
00396
00397 public String getRaidb2Xml()
00398 {
00399 return "<" + DatabasesXmlTags.ELT_RAIDb_2_LeastPendingRequestsFirst + "/>";
00400 }
00401 }