00001
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
00053 public class RAIDb2_RR extends RAIDb2
00054 {
00055
00056
00057
00058
00059
00060 private int index;
00061
00062
00063
00064
00065
00076 public RAIDb2_RR(
VirtualDatabase vdb,
00077
WaitForCompletionPolicy waitForCompletionPolicy,
00078
CreateTablePolicy createTablePolicy)
throws SQLException
00079 {
00080 super(vdb, waitForCompletionPolicy, createTablePolicy);
00081
index = -1;
00082 }
00083
00084
00085
00086
00087
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
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 failedBackend.
disable();
00336 failedBackend.finalizeConnections();
00337 }
00338
catch (SQLException ignore)
00339 {
00340 }
00341 finally
00342 {
00343 failedBackend = null;
00344 }
00345 }
00346 }
00347
while (failedBackend != null);
00348
return rs;
00349 }
00350
catch (RuntimeException e)
00351 {
00352 String msg = Translate.get(
00353
"loadbalancer.storedprocedure.failed.on.backend",
new String[]{
00354 proc.getSQLShortForm(vdb.getSQLShortFormLength()),
00355 backend.getName(), e.getMessage()});
00356 logger.fatal(msg, e);
00357
throw new SQLException(msg);
00358 }
00359 finally
00360 {
00361 vdb.releaseReadLockBackendLists();
00362 }
00363 }
00364
00365
00366
00367
00368
00374 public String getInformation()
00375 {
00376
00377
int size = vdb.getBackends().size();
00378
00379
if (size == 0)
00380
return "RAIDb-2 Round-Robin Request load balancer: !!!Warning!!! No backend nodes found\n";
00381
else
00382
return "RAIDb-2 Round-Robin Request load balancer (" + size
00383 +
" backends)\n";
00384 }
00385
00389 public String getRaidb2Xml()
00390 {
00391
return "<" +
DatabasesXmlTags.ELT_RAIDb_2_RoundRobin +
"/>";
00392 }
00393 }