KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > virtualdatabase > protocol > DistributedAbort


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

23
24 package org.continuent.sequoia.controller.virtualdatabase.protocol;
25
26 import java.io.Serializable JavaDoc;
27 import java.sql.SQLException JavaDoc;
28 import java.util.LinkedList JavaDoc;
29
30 import org.continuent.sequoia.common.exceptions.NoMoreBackendException;
31 import org.continuent.sequoia.common.i18n.Translate;
32 import org.continuent.sequoia.common.log.Trace;
33 import org.continuent.sequoia.controller.requestmanager.TransactionMetaData;
34 import org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager;
35 import org.continuent.sequoia.controller.requests.AbstractRequest;
36 import org.continuent.sequoia.controller.requests.UnknownWriteRequest;
37 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabaseWorkerThread;
38
39 /**
40  * Execute a distributed abort.
41  *
42  * @author <a HREF="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet
43  * </a>
44  * @version 1.0
45  */

46 public class DistributedAbort extends DistributedTransactionMarker
47 {
48   private static final long serialVersionUID = -8954391235872189513L;
49
50   private transient Long JavaDoc tid;
51   // Login that rollbacks the transaction. This is used in case the remote
52
// controller has to log the commit but didn't see the begin in which case it
53
// will not be able to retrieve the transaction marker metadata
54
private String JavaDoc login;
55
56   private DistributedRollback totalOrderAbort;
57
58   /**
59    * Creates a new <code>Abort</code> message.
60    *
61    * @param login login that rollback the transaction
62    * @param transactionId id of the transaction to commit
63    */

64   public DistributedAbort(String JavaDoc login, long transactionId)
65   {
66     super(transactionId);
67     this.login = login;
68   }
69
70   /**
71    * @see org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedTransactionMarker#scheduleCommand(org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager)
72    */

73   public Object JavaDoc scheduleCommand(DistributedRequestManager drm)
74       throws SQLException JavaDoc
75   {
76     LinkedList JavaDoc totalOrderQueue = drm.getVirtualDatabase().getTotalOrderQueue();
77     if (totalOrderQueue != null)
78     {
79       synchronized (totalOrderQueue)
80       {
81         totalOrderAbort = new DistributedRollback(login, transactionId);
82         totalOrderQueue.addLast(totalOrderAbort);
83       }
84     }
85     return totalOrderAbort;
86   }
87
88   /**
89    * Execution of a distributed rollback command on the specified
90    * <code>DistributedRequestManager</code>
91    *
92    * @param drm the DistributedRequestManager that will execute the rollback
93    * @return Boolean.TRUE if everything went fine or a SQLException if an error
94    * occured
95    * @throws SQLException if an error occurs
96    */

97   public Serializable JavaDoc executeCommand(DistributedRequestManager drm)
98       throws SQLException JavaDoc
99   {
100     Trace logger = drm.getLogger();
101
102     boolean transactionStartedOnThisController = true;
103     tid = new Long JavaDoc(transactionId);
104     TransactionMetaData tm;
105     try
106     {
107       tm = drm.getTransactionMetaData(tid);
108     }
109     catch (SQLException JavaDoc ignore)
110     {
111       // The transaction was started before the controller joined the
112
// cluster, build a fake tm so that we will be able to log it.
113
transactionStartedOnThisController = false;
114       tm = new TransactionMetaData(transactionId, 0, login, false, 0);
115     }
116
117     VirtualDatabaseWorkerThread vdbwt = drm.getVirtualDatabase()
118         .getVirtualDatabaseWorkerThreadForTransaction(transactionId);
119     if (vdbwt != null)
120       vdbwt.notifyAbort(transactionId);
121
122     boolean hasBeenScheduled = false;
123     try
124     {
125       if (transactionStartedOnThisController)
126       { // Rollback would fail on a fake tm so skip it
127
drm.getScheduler().rollback(tm, totalOrderAbort);
128         hasBeenScheduled = true;
129       }
130
131       if (logger.isDebugEnabled())
132         logger.debug(Translate.get("transaction.aborting", tid));
133
134       // Send to load balancer
135
drm.getLoadBalancer().abort(tm);
136
137       // Update recovery log
138
drm.getRecoveryLog().logRequestCompletion(tm.getLogId(), true, 0);
139
140       // Invalidate the query result cache if this transaction has updated the
141
// cache or altered the schema
142
if ((drm.getResultCache() != null)
143           && (tm.altersQueryResultCache() || tm.altersDatabaseSchema()))
144         drm.getResultCache().rollback(transactionId);
145
146       // Check for schema modifications that need to be rollbacked
147
if (tm.altersDatabaseSchema())
148       {
149         if (drm.getMetadataCache() != null)
150           drm.getMetadataCache().flushCache();
151         drm.setSchemaIsDirty(true);
152       }
153
154       if (hasBeenScheduled) // skipped if tm was fake
155
{
156         // Notify scheduler for completion
157
drm.getScheduler().rollbackCompleted(tm, true);
158       }
159     }
160     catch (NoMoreBackendException e)
161     {
162       if (logger.isDebugEnabled())
163         logger.debug(Translate.get(
164             "virtualdatabase.distributed.abort.logging.only", transactionId));
165
166       addAbortFailureOnAllBackends(drm, hasBeenScheduled, tm);
167       throw e;
168     }
169     catch (SQLException JavaDoc e)
170     {
171       logger.warn(Translate
172           .get("virtualdatabase.distributed.abort.sqlexception"), e);
173       addAbortFailureOnAllBackends(drm, hasBeenScheduled, tm);
174       return e;
175     }
176     catch (RuntimeException JavaDoc re)
177     {
178       logger.warn(Translate
179           .get("virtualdatabase.distributed.rollback.exception"), re);
180       addAbortFailureOnAllBackends(drm, hasBeenScheduled, tm);
181       throw new SQLException JavaDoc(re.getMessage());
182     }
183     finally
184     {
185       if (!hasBeenScheduled)
186       {
187         // Query has not been scheduled, we have to remove the entry from the
188
// total order queue (wait to be sure that we do it in the proper order)
189
if (drm.getLoadBalancer().waitForTotalOrder(totalOrderAbort, false))
190           drm.getLoadBalancer().removeObjectFromAndNotifyTotalOrderQueue(
191               totalOrderAbort);
192       }
193
194       if (transactionStartedOnThisController)
195       {
196         drm.completeTransaction(tid);
197       }
198
199       if (logger.isDebugEnabled())
200         logger.debug(Translate.get("transaction.aborted", tid));
201     }
202     return Boolean.TRUE;
203   }
204
205   private void addAbortFailureOnAllBackends(DistributedRequestManager drm,
206       boolean hasBeenScheduled, TransactionMetaData tm)
207   {
208     AbstractRequest abortRequest = new UnknownWriteRequest("abort", false, 0,
209         "\n");
210     abortRequest.setLogin(login);
211     abortRequest.setTransactionId(transactionId);
212     abortRequest.setIsAutoCommit(false);
213     abortRequest.setLogId(tm.getLogId());
214     drm.addFailedOnAllBackends(abortRequest, hasBeenScheduled);
215   }
216
217   /**
218    * @see java.lang.Object#toString()
219    */

220   public String JavaDoc toString()
221   {
222     return "Abort transaction " + transactionId;
223   }
224 }
Popular Tags