1 21 22 package org.continuent.sequoia.controller.virtualdatabase.protocol; 23 24 import java.io.Serializable ; 25 import java.util.ArrayList ; 26 import java.util.Iterator ; 27 import java.util.LinkedList ; 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 57 public class DisableBackendsAndSetCheckpoint 58 extends DistributedVirtualDatabaseMessage 59 { 60 private static final long serialVersionUID = 5296233035014770268L; 61 62 private ArrayList backendInfos; 63 private String checkpointName; 64 private transient LinkedList totalOrderQueue; 65 66 73 public DisableBackendsAndSetCheckpoint( 74 ArrayList backendInfos, String checkpointName) 75 { 76 this.backendInfos = backendInfos; 77 this.checkpointName = checkpointName; 78 } 79 80 84 public Object 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 105 public Serializable handleMessageMultiThreaded( 106 DistributedVirtualDatabase dvdb, Member sender, 107 Object handleMessageSingleThreadedResult) 108 { 109 Trace logger = dvdb.getLogger(); 110 111 boolean found = dvdb.getRequestManager().getLoadBalancer() 113 .waitForTotalOrder(handleMessageSingleThreadedResult, false); 114 115 AbstractScheduler scheduler = dvdb.getRequestManager().getScheduler(); 116 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 scheduler.resumeWritesTransactionsAndPersistentConnections(); 130 return new VirtualDatabaseException(Translate 131 .get("virtualdatabase.no.recovery.log")); 132 } 133 134 try 135 { 136 dvdb.getRequestManager().getRecoveryLog().storeCheckpoint(checkpointName); 138 logger.info(Translate.get("recovery.checkpoint.stored", checkpointName)); 139 140 ControllerException disableStatus = null; 141 if (dvdb.isLocalSender(sender)) 143 { 144 Iterator iter = backendInfos.iterator(); 145 while (iter.hasNext()) 146 { 147 BackendInfo backendInfo = (BackendInfo) iter.next(); 148 149 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; 159 String 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 db.setState(BackendState.DISABLING); 172 logger.info(Translate.get("backend.state.disabling", db.getName())); 173 174 cleanState = (db.getActiveTransactions().size() == 0) 176 && (!db.hasPersistentConnections()); 177 178 if (!cleanState) 179 { 180 String message = "Open transactions or persistent connections detected when disabling backend " 181 + db.getName() + ", switching backend to unknown state"; 182 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 dvdb.getRequestManager().getLoadBalancer().disableBackend(db, false); 196 197 if (cleanState) 198 { 199 db.setLastKnownCheckpoint(checkpointName); 201 logger.info(Translate.get("backend.state.disabled", db.getName())); 202 } 203 } 204 } 205 206 dvdb.handleRemoteDisableBackendsNotification(backendInfos, sender); 208 return disableStatus; 209 } 210 catch (Exception e) 211 { 212 return new ControllerException(e); 213 } 214 } 215 216 221 public String toString() 222 { 223 StringBuffer buff = new StringBuffer ("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 |