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