KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > loadbalancer > tasks > BeginTask


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: sequoia@continuent.org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * Initial developer(s): Emmanuel Cecchet.
20  * Contributor(s): Julie Marguerite.
21  */

22
23 package org.continuent.sequoia.controller.loadbalancer.tasks;
24
25 import java.sql.Connection JavaDoc;
26 import java.sql.SQLException JavaDoc;
27
28 import org.continuent.sequoia.common.exceptions.NoTransactionStartWhenDisablingException;
29 import org.continuent.sequoia.common.exceptions.UnreachableBackendException;
30 import org.continuent.sequoia.common.i18n.Translate;
31 import org.continuent.sequoia.common.log.Trace;
32 import org.continuent.sequoia.controller.backend.DatabaseBackend;
33 import org.continuent.sequoia.controller.connection.AbstractConnectionManager;
34 import org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer;
35 import org.continuent.sequoia.controller.loadbalancer.BackendWorkerThread;
36 import org.continuent.sequoia.controller.requestmanager.TransactionMetaData;
37 import org.continuent.sequoia.controller.requests.AbstractRequest;
38 import org.continuent.sequoia.controller.requests.UnknownReadRequest;
39
40 /**
41  * Task to begin a transaction. Note that this task does not properly set the
42  * transaction isolation but this is not a real issue since it is meant to be
43  * used by the recovery log that does not execute reads and provide its own
44  * serial order.
45  * <p>
46  * <strong>This task is meant to be only used to replay the recovery log</strong>
47  *
48  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
49  * @author <a HREF="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
50  * @version 1.0
51  */

52 public class BeginTask extends AbstractTask
53 {
54   // Transaction metadata (login, transaction id, timeout)
55
private TransactionMetaData tm;
56   private AbstractRequest request;
57   static Trace endUserLogger = Trace
58                                                 .getLogger("org.continuent.sequoia.enduser");
59
60   /**
61    * Begins a new transaction given a login and a transaction id.
62    *
63    * @param nbToComplete number of threads that must succeed before returning
64    * @param totalNb total number of threads
65    * @param tm transaction metadata
66    * @throws NullPointerException if tm is null
67    */

68   public BeginTask(int nbToComplete, int totalNb, TransactionMetaData tm)
69       throws NullPointerException JavaDoc
70   {
71     super(nbToComplete, totalNb, tm.isPersistentConnection(), tm
72         .getPersistentConnectionId());
73     if (tm == null)
74       throw new NullPointerException JavaDoc("Unexpected null metadata in BeginTask");
75     this.tm = tm;
76     this.request = new UnknownReadRequest("begin", false, 0, "");
77     request.setLogin(tm.getLogin());
78     request.setIsAutoCommit(false);
79     request.setTransactionId(tm.getTransactionId());
80     request.setPersistentConnection(tm.isPersistentConnection());
81     request.setPersistentConnectionId(tm.getPersistentConnectionId());
82     request
83         .setTransactionIsolation(org.continuent.sequoia.driver.Connection.DEFAULT_TRANSACTION_ISOLATION_LEVEL);
84   }
85
86   /**
87    * Begins a new transaction with the given backend thread.
88    *
89    * @param backendThread the backend thread that will execute the task
90    * @exception SQLException if an error occurs
91    */

92   public void executeTask(BackendWorkerThread backendThread)
93       throws SQLException JavaDoc
94   {
95     DatabaseBackend backend = backendThread.getBackend();
96     if (!backend.isReplaying())
97       throw new SQLException JavaDoc(
98           "BeginTask should only be used for recovery purposes. Detected incorrect backend state:"
99               + backend.getState());
100
101     try
102     {
103       AbstractConnectionManager cm = backend
104           .getConnectionManager(tm.getLogin());
105       if (cm == null)
106       {
107         SQLException JavaDoc se = new SQLException JavaDoc(
108             "No Connection Manager for Virtual Login:" + tm.getLogin());
109         try
110         {
111           notifyFailure(backendThread, 1, se);
112         }
113         catch (SQLException JavaDoc ignore)
114         {
115
116         }
117         throw se;
118       }
119
120       Connection JavaDoc c;
121       Long JavaDoc lTid = new Long JavaDoc(tm.getTransactionId());
122       Trace logger = backendThread.getLogger();
123
124       try
125       {
126         c = AbstractLoadBalancer.getConnectionAndBeginTransaction(backend, cm,
127             request);
128         backend.startTransaction(lTid);
129       }
130       catch (UnreachableBackendException ube)
131       {
132         SQLException JavaDoc se = new SQLException JavaDoc("Backend " + backend.getName()
133             + " is no more reachable.");
134         try
135         {
136           notifyFailure(backendThread, -1, se);
137         }
138         catch (SQLException JavaDoc ignore)
139         {
140         }
141         // Disable this backend (it is no more in sync) by killing the backend
142
// thread
143
backendThread.getLoadBalancer().disableBackend(backend, true);
144         String JavaDoc msg = Translate.get(
145             "loadbalancer.backend.disabling.unreachable", backend.getName());
146         logger.error(msg);
147         endUserLogger.error(msg);
148         throw se;
149       }
150       catch (NoTransactionStartWhenDisablingException e)
151       {
152         // Backend is disabling, we do not execute queries except the one in the
153
// transaction we already started. Just notify the completion for the
154
// others.
155
notifyCompletion(backendThread);
156         return;
157       }
158       catch (SQLException JavaDoc e1)
159       {
160         SQLException JavaDoc se = new SQLException JavaDoc(
161             "Unable to get connection for transaction " + lTid);
162         try
163         { // All backends failed, just ignore
164
if (!notifyFailure(backendThread, tm.getTimeout(), se))
165             return;
166         }
167         catch (SQLException JavaDoc ignore)
168         {
169         }
170         // Disable this backend (it is no more in sync) by killing the
171
// backend thread
172
backendThread.getLoadBalancer().disableBackend(backend, true);
173         String JavaDoc msg = "Begin of transaction " + tm.getTransactionId()
174             + " failed on backend " + backend.getName() + " but "
175             + getSuccess() + " succeeded (" + se + ")";
176         logger.error(msg);
177         endUserLogger.error(Translate.get(
178             "loadbalancer.backend.disabling", backend.getName()));
179         throw new SQLException JavaDoc(msg);
180       }
181
182       // Sanity check
183
if (c == null)
184       { // Bad connection
185
SQLException JavaDoc se = new SQLException JavaDoc(
186             "No more connection to start a new transaction.");
187         try
188         { // All backends failed, just ignore
189
if (!notifyFailure(backendThread, tm.getTimeout(), se))
190             return;
191         }
192         catch (SQLException JavaDoc ignore)
193         {
194         }
195       }
196       else
197       {
198         notifySuccess(backendThread);
199       }
200     }
201     catch (Exception JavaDoc e)
202     {
203       try
204       {
205         if (!notifyFailure(backendThread, tm.getTimeout(), new SQLException JavaDoc(e
206             .getMessage())))
207           return;
208       }
209       catch (SQLException JavaDoc ignore)
210       {
211       }
212       String JavaDoc msg = "Failed to begin transaction " + tm.getTransactionId()
213           + " on backend " + backend.getName() + " (" + e + ")";
214       backendThread.getLogger().error(msg);
215       throw new SQLException JavaDoc(msg);
216     }
217   }
218
219   /**
220    * @see org.continuent.sequoia.controller.loadbalancer.tasks.AbstractTask#getRequest()
221    */

222   public AbstractRequest getRequest()
223   {
224     return request;
225   }
226
227   /**
228    * @see org.continuent.sequoia.controller.loadbalancer.tasks.AbstractTask#getTransactionId()
229    */

230   public long getTransactionId()
231   {
232     return tm.getTransactionId();
233   }
234
235   /**
236    * @see org.continuent.sequoia.controller.loadbalancer.tasks.AbstractTask#isAutoCommit()
237    */

238   public boolean isAutoCommit()
239   {
240     return false;
241   }
242
243   /**
244    * @see java.lang.Object#equals(java.lang.Object)
245    */

246   public boolean equals(Object JavaDoc other)
247   {
248     if ((other == null) || !(other instanceof BeginTask))
249       return false;
250
251     BeginTask begin = (BeginTask) other;
252     return this.getTransactionId() == begin.getTransactionId();
253   }
254
255   /**
256    * @see java.lang.Object#hashCode()
257    */

258   public int hashCode()
259   {
260     return (int) this.getTransactionId();
261   }
262
263   /**
264    * @see java.lang.Object#toString()
265    */

266   public String JavaDoc toString()
267   {
268     return "BeginTask (" + tm.getLogin() + "," + tm.getTransactionId() + ")";
269   }
270
271 }
Popular Tags