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
00054 public class RAIDb2_LPRF extends RAIDb2
00055 {
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00076 public RAIDb2_LPRF(
VirtualDatabase vdb,
00077
WaitForCompletionPolicy waitForCompletionPolicy,
00078
CreateTablePolicy createTablePolicy)
throws SQLException
00079 {
00080 super(vdb, waitForCompletionPolicy, createTablePolicy);
00081 }
00082
00083
00084
00085
00086
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
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 failedBackend.
disable();
00345 failedBackend.finalizeConnections();
00346 }
00347
catch (SQLException ignore)
00348 {
00349 }
00350 finally
00351 {
00352 failedBackend = null;
00353 }
00354 }
00355 }
00356
while (failedBackend != null);
00357
return rs;
00358 }
00359
catch (RuntimeException e)
00360 {
00361 String msg = Translate.get(
00362
"loadbalancer.storedprocedure.failed.on.backend",
new String[]{
00363 proc.getSQLShortForm(vdb.getSQLShortFormLength()),
00364 backend.getName(), e.getMessage()});
00365 logger.fatal(msg, e);
00366
throw new SQLException(msg);
00367 }
00368 finally
00369 {
00370 vdb.releaseReadLockBackendLists();
00371 }
00372 }
00373
00374
00375
00376
00377
00383 public String getInformation()
00384 {
00385
00386
int size = vdb.getBackends().size();
00387
00388
if (size == 0)
00389
return "RAIDb-2 Least Pending Requests First load balancer: !!!Warning!!! No backend nodes found\n";
00390
else
00391
return "RAIDb-2 Least Pending Requests First load balancer (" + size
00392 +
" backends)\n";
00393 }
00394
00398 public String getRaidb2Xml()
00399 {
00400
return "<" +
DatabasesXmlTags.ELT_RAIDb_2_LeastPendingRequestsFirst +
"/>";
00401 }
00402 }