KickJava   Java API By Example, From Geeks To Geeks.

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


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

21
22 package org.continuent.sequoia.controller.virtualdatabase.protocol;
23
24 import java.io.Serializable JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedList JavaDoc;
28
29 import org.continuent.hedera.common.Member;
30 import org.continuent.sequoia.common.exceptions.ControllerException;
31 import org.continuent.sequoia.common.exceptions.VirtualDatabaseException;
32 import org.continuent.sequoia.common.i18n.Translate;
33 import org.continuent.sequoia.common.jmx.management.BackendInfo;
34 import org.continuent.sequoia.common.jmx.management.BackendState;
35 import org.continuent.sequoia.common.log.Trace;
36 import org.continuent.sequoia.controller.backend.DatabaseBackend;
37 import org.continuent.sequoia.controller.scheduler.AbstractScheduler;
38 import org.continuent.sequoia.controller.virtualdatabase.DistributedVirtualDatabase;
39 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase;
40
41 /**
42  * This class defines a DisableBackendsAndSetCheckpoint message. Writes,
43  * Transactions and Persistent connections must be suspended before this request
44  * is issued. When executed it does the following things:
45  * <ol>
46  * <li>Set checkpoint
47  * <li>Disable backends if needed
48  * <li>Resume writes, transactions and persistent connections.
49  * </ol>
50  * <p>
51  *
52  * @author <a HREF="mailto:emmanuel.cecchet@continuent.com">Emmanuel Cecchet</a>
53  * @author <a HREF="mailto:damian.arregui@continuent.com">Damian Arregui</a>
54  * @author <a HREF="mailto:ralph.hannus@continuent.com">Ralph hannus</a>
55  * @version 1.0
56  */

57 public class DisableBackendsAndSetCheckpoint
58     extends DistributedVirtualDatabaseMessage
59 {
60   private static final long serialVersionUID = 5296233035014770268L;
61
62   private ArrayList JavaDoc backendInfos;
63   private String JavaDoc checkpointName;
64   private transient LinkedList JavaDoc totalOrderQueue;
65
66   /**
67    * Creates a new <code>DisableBackendsAndSetCheckpoint</code> object
68    *
69    * @param backendInfos list of Backend Info to be disabled, if the list is
70    * empty no backends are disabled
71    * @param checkpointName name of the checkpoint to be set
72    */

73   public DisableBackendsAndSetCheckpoint(
74       ArrayList JavaDoc/* <BackendInfo> */backendInfos, String JavaDoc checkpointName)
75   {
76     this.backendInfos = backendInfos;
77     this.checkpointName = checkpointName;
78   }
79
80   /**
81    * @see org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedVirtualDatabaseMessage#handleMessageSingleThreaded(org.continuent.sequoia.controller.virtualdatabase.DistributedVirtualDatabase,
82    * org.continuent.hedera.common.Member)
83    */

84   public Object JavaDoc handleMessageSingleThreaded(DistributedVirtualDatabase dvdb,
85       Member sender)
86   {
87     totalOrderQueue = dvdb.getTotalOrderQueue();
88     if (totalOrderQueue == null)
89       return new VirtualDatabaseException(Translate
90           .get("virtualdatabase.no.total.order.queue", dvdb.getVirtualDatabaseName()));
91
92     synchronized (totalOrderQueue)
93     {
94       SuspendWritesMessage request = new SuspendWritesMessage("Disable "
95           + checkpointName);
96       totalOrderQueue.addLast(request);
97       return request;
98     }
99   }
100
101   /**
102    * @see org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedVirtualDatabaseMessage#handleMessageMultiThreaded(org.continuent.sequoia.controller.virtualdatabase.DistributedVirtualDatabase,
103    * org.continuent.hedera.common.Member, java.lang.Object)
104    */

105   public Serializable JavaDoc handleMessageMultiThreaded(
106       DistributedVirtualDatabase dvdb, Member sender,
107       Object JavaDoc handleMessageSingleThreadedResult)
108   {
109     Trace logger = dvdb.getLogger();
110
111     // Wait for our turn to execute
112
boolean found = dvdb.getRequestManager().getLoadBalancer()
113         .waitForTotalOrder(handleMessageSingleThreadedResult, false);
114
115     AbstractScheduler scheduler = dvdb.getRequestManager().getScheduler();
116     // Remove ourselves from the queue to allow others to complete if needed
117
if (!found)
118       logger.error("Disable backend " + backendInfos.toString()
119           + " was not found in total order queue, posting out of order ("
120           + checkpointName + ")");
121     else
122       dvdb.getRequestManager().getLoadBalancer()
123           .removeObjectFromAndNotifyTotalOrderQueue(
124               handleMessageSingleThreadedResult);
125
126     if (!dvdb.hasRecoveryLog())
127     {
128       // Resume transactions, writes and persistent connections
129
scheduler.resumeWritesTransactionsAndPersistentConnections();
130       return new VirtualDatabaseException(Translate
131           .get("virtualdatabase.no.recovery.log"));
132     }
133
134     try
135     {
136       // Insert the checkpoint
137
dvdb.getRequestManager().getRecoveryLog().storeCheckpoint(checkpointName);
138       logger.info(Translate.get("recovery.checkpoint.stored", checkpointName));
139
140       ControllerException disableStatus = null;
141       // Start disabling the backend locally
142
if (dvdb.isLocalSender(sender))
143       {
144         Iterator JavaDoc iter = backendInfos.iterator();
145         while (iter.hasNext())
146         {
147           BackendInfo backendInfo = (BackendInfo) iter.next();
148
149           // Get the real backend instance
150
DatabaseBackend db = dvdb.getAndCheckBackend(backendInfo.getName(),
151               VirtualDatabase.NO_CHECK_BACKEND);
152
153           boolean cleanState = false;
154           if (!(db.isReadEnabled() || db.isWriteEnabled()))
155           {
156             if (db.isDisabled())
157               continue; // Backend already disabled, ignore
158

159             // Else the backend is in a transition state (backuping, ...)
160
String JavaDoc message = "Backend " + db.getName()
161                 + " in transition state ("
162                 + BackendState.description(db.getStateValue())
163                 + "), switching backend to unknown state";
164             disableStatus = new ControllerException(message);
165             logger.error(message);
166             db.setState(BackendState.UNKNOWN);
167           }
168           else
169           {
170             // Signal the backend should not begin any new transaction
171
db.setState(BackendState.DISABLING);
172             logger.info(Translate.get("backend.state.disabling", db.getName()));
173
174             // Sanity checks
175
cleanState = (db.getActiveTransactions().size() == 0)
176                 && (!db.hasPersistentConnections());
177
178             if (!cleanState)
179             {
180               String JavaDoc message = "Open transactions or persistent connections detected when disabling backend "
181                   + db.getName() + ", switching backend to unknown state";
182               // let the user known that the disable was not clean
183
disableStatus = new ControllerException(message);
184               logger.error(message);
185               logger.error(db.getName() + " open transactions: "
186                   + db.getActiveTransactions());
187               logger.error(db.getName() + " open persistent connections: "
188                   + db.hasPersistentConnections());
189               db.setState(BackendState.UNKNOWN);
190             }
191           }
192
193           // Now we can safely disable the backend since all transactions have
194
// completed
195
dvdb.getRequestManager().getLoadBalancer().disableBackend(db, false);
196
197           if (cleanState)
198           {
199             // Update the last known checkpoint
200
db.setLastKnownCheckpoint(checkpointName);
201             logger.info(Translate.get("backend.state.disabled", db.getName()));
202           }
203         }
204       }
205
206       // update remote backend tables
207
dvdb.handleRemoteDisableBackendsNotification(backendInfos, sender);
208       return disableStatus;
209     }
210     catch (Exception JavaDoc e)
211     {
212       return new ControllerException(e);
213     }
214   }
215   
216   /**
217    * For debug only.
218    *
219    * @see java.lang.Object#toString()
220    */

221   public String JavaDoc toString()
222   {
223     StringBuffer JavaDoc buff = new StringBuffer JavaDoc("DisableBackendsAndSetCheckpoint[");
224     buff.append("checkpointName=").append(checkpointName);
225     buff.append(", backendInfos=").append(backendInfos);
226     buff.append("]");
227     return buff.toString();
228   }
229 }
230
Popular Tags