KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > controller > loadbalancer > raidb1 > RAIDb1_RR


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Julie Marguerite.
23  */

24
25 package org.objectweb.cjdbc.controller.loadbalancer.raidb1;
26
27 import java.sql.SQLException JavaDoc;
28 import java.util.ArrayList JavaDoc;
29
30 import org.objectweb.cjdbc.common.exceptions.NoMoreBackendException;
31 import org.objectweb.cjdbc.common.exceptions.UnreachableBackendException;
32 import org.objectweb.cjdbc.common.i18n.Translate;
33 import org.objectweb.cjdbc.common.sql.AbstractRequest;
34 import org.objectweb.cjdbc.common.sql.SelectRequest;
35 import org.objectweb.cjdbc.common.sql.StoredProcedure;
36 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
37 import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
38 import org.objectweb.cjdbc.controller.cache.metadata.MetadataCache;
39 import org.objectweb.cjdbc.controller.loadbalancer.policies.WaitForCompletionPolicy;
40 import org.objectweb.cjdbc.controller.virtualdatabase.ControllerResultSet;
41 import org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabase;
42
43 /**
44  * RAIDb-1 Round Robin load balancer
45  * <p>
46  * The read requests coming from the Request Manager are sent in a round robin
47  * to the backend nodes. Write requests are broadcasted to all backends.
48  *
49  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
50  * @author <a HREF="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
51  * @version 1.0
52  */

53 public class RAIDb1_RR extends RAIDb1
54 {
55   /*
56    * How the code is organized ? 1. Member variables 2. Constructor(s) 3.
57    * Request handling 4. Debug/Monitoring
58    */

59
60   private int index; // index in the backend vector the Round-Robin
61

62   /*
63    * Constructors
64    */

65
66   /**
67    * Creates a new RAIDb-1 Round Robin request load balancer.
68    *
69    * @param vdb the virtual database this load balancer belongs to.
70    * @param waitForCompletionPolicy How many backends must complete before
71    * returning the result?
72    * @throws Exception if an error occurs
73    */

74   public RAIDb1_RR(VirtualDatabase vdb,
75       WaitForCompletionPolicy waitForCompletionPolicy) throws Exception JavaDoc
76   {
77     super(vdb, waitForCompletionPolicy);
78     index = -1;
79   }
80
81   /*
82    * Request Handling
83    */

84
85   /**
86    * Selects the backend using a simple round-robin algorithm and executes the
87    * read request.
88    *
89    * @see org.objectweb.cjdbc.controller.loadbalancer.raidb1.RAIDb1#execReadRequest(SelectRequest,
90    * MetadataCache)
91    */

92   public ControllerResultSet execReadRequest(SelectRequest request,
93       MetadataCache metadataCache) throws SQLException JavaDoc
94   {
95     return executeRoundRobinRequest(request, true, "Request ", metadataCache);
96   }
97
98   /**
99    * Selects the backend using a simple round-robin algorithm and executes the
100    * read request.
101    *
102    * @see org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer#execReadOnlyReadStoredProcedure(StoredProcedure,
103    * MetadataCache)
104    */

105   public ControllerResultSet execReadOnlyReadStoredProcedure(
106       StoredProcedure proc, MetadataCache metadataCache) throws SQLException JavaDoc
107   {
108     return executeRoundRobinRequest(proc, false, "Stored procedure ",
109         metadataCache);
110   }
111
112   /**
113    * Common code to execute a SelectRequest or a StoredProcedure on a backend
114    * chosen using a round-robin algorithm.
115    *
116    * @param request a <code>SelectRequest</code> or
117    * <code>StoredProcedure</code>
118    * @param isSelect true if it is a <code>SelectRequest</code>, false if it
119    * is a <code>StoredProcedure</code>
120    * @param errorMsgPrefix the error message prefix, usually "Request " or
121    * "Stored procedure " ... failed because ...
122    * @param metadataCache a metadataCache if any or null
123    * @return a <code>ResultSet</code>
124    * @throws SQLException if an error occurs
125    */

126   private ControllerResultSet executeRoundRobinRequest(AbstractRequest request,
127       boolean isSelect, String JavaDoc errorMsgPrefix, MetadataCache metadataCache)
128       throws SQLException JavaDoc
129   {
130     // Choose a backend
131
try
132     {
133       vdb.acquireReadLockBackendLists();
134     }
135     catch (InterruptedException JavaDoc e)
136     {
137       String JavaDoc msg = Translate.get(
138           "loadbalancer.backendlist.acquire.readlock.failed", e);
139       logger.error(msg);
140       throw new SQLException JavaDoc(msg);
141     }
142
143     DatabaseBackend backend = null; // The
144
// backend
145
// that
146
// will
147
// execute
148
// the
149
// query
150

151     // Note that vdb lock is released in the finally clause of this try/catch
152
// block
153
try
154     {
155       ArrayList JavaDoc backends = vdb.getBackends();
156       int size = backends.size();
157
158       if (size == 0)
159         throw new SQLException JavaDoc(Translate.get(
160             "loadbalancer.execute.no.backend.available", request.getId()));
161
162       // Take the next backend
163
int maxTries = size;
164       synchronized (this)
165       {
166         do
167         {
168           index = (index + 1) % size;
169           backend = (DatabaseBackend) backends.get(index);
170           maxTries--;
171         }
172         while ((!backend.isReadEnabled() && maxTries >= 0));
173       }
174
175       if (maxTries < 0)
176         throw new NoMoreBackendException(Translate.get(
177             "loadbalancer.execute.no.backend.enabled", request.getId()));
178     }
179     catch (RuntimeException JavaDoc e)
180     {
181       String JavaDoc msg = Translate.get("loadbalancer.execute.find.backend.failed",
182           new String JavaDoc[]{request.getSQLShortForm(vdb.getSQLShortFormLength()),
183               e.getMessage()});
184       logger.error(msg, e);
185       throw new SQLException JavaDoc(msg);
186     }
187     finally
188     {
189       vdb.releaseReadLockBackendLists();
190     }
191
192     ControllerResultSet rs = null;
193     // Execute the request on the chosen backend
194
try
195     {
196       if (isSelect)
197         rs = executeRequestOnBackend((SelectRequest) request, backend,
198             metadataCache);
199       else
200         rs = executeStoredProcedureOnBackend((StoredProcedure) request,
201             backend, metadataCache);
202     }
203     catch (UnreachableBackendException urbe)
204     {
205       // Try to execute query on different backend
206
return executeRoundRobinRequest(request, isSelect, errorMsgPrefix,
207           metadataCache);
208     }
209     catch (SQLException JavaDoc se)
210     {
211       String JavaDoc msg = Translate.get("loadbalancer.something.failed", new String JavaDoc[]{
212           errorMsgPrefix, String.valueOf(request.getId()), se.getMessage()});
213       if (logger.isInfoEnabled())
214         logger.info(msg);
215       throw se;
216     }
217     catch (RuntimeException JavaDoc e)
218     {
219       String JavaDoc msg = Translate.get("loadbalancer.something.failed.on",
220           new String JavaDoc[]{errorMsgPrefix,
221               request.getSQLShortForm(vdb.getSQLShortFormLength()),
222               backend.getName(), e.getMessage()});
223       logger.error(msg, e);
224       throw new SQLException JavaDoc(msg);
225     }
226
227     return rs;
228   }
229
230   /*
231    * Debug/Monitoring
232    */

233
234   /**
235    * Gets information about the request load balancer.
236    *
237    * @return <code>String</code> containing information
238    */

239   public String JavaDoc getInformation()
240   {
241     // We don't lock since we don't need a top accurate value
242
int size = vdb.getBackends().size();
243
244     if (size == 0)
245       return "RAIDb-1 Round-Robin Request load balancer: !!!Warning!!! No backend nodes found\n";
246     else
247       return "RAIDb-1 Round-Robin Request load balancer (" + size
248           + " backends)\n";
249   }
250
251   /**
252    * @see org.objectweb.cjdbc.controller.loadbalancer.raidb1.RAIDb1#getRaidb1Xml
253    */

254   public String JavaDoc getRaidb1Xml()
255   {
256     return "<" + DatabasesXmlTags.ELT_RAIDb_1_RoundRobin + "/>";
257   }
258
259 }
Popular Tags