001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2002-2004 French National Institute For Research In Computer
004: * Science And Control (INRIA).
005: * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
006: * Copyright (C) 2005-2006 Continuent, Inc.
007: * Contact: sequoia@continuent.org
008: *
009: * Licensed under the Apache License, Version 2.0 (the "License");
010: * you may not use this file except in compliance with the License.
011: * You may obtain a copy of the License at
012: *
013: * http://www.apache.org/licenses/LICENSE-2.0
014: *
015: * Unless required by applicable law or agreed to in writing, software
016: * distributed under the License is distributed on an "AS IS" BASIS,
017: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018: * See the License for the specific language governing permissions and
019: * limitations under the License.
020: *
021: * Initial developer(s): Emmanuel Cecchet.
022: * Contributor(s): ______________________.
023: */package org.continuent.sequoia.controller.virtualdatabase.protocol;
024:
025: import java.io.Serializable;
026: import java.sql.SQLException;
027: import java.util.LinkedList;
028:
029: import org.continuent.sequoia.common.exceptions.NoMoreBackendException;
030: import org.continuent.sequoia.common.i18n.Translate;
031: import org.continuent.sequoia.controller.backend.result.ExecuteUpdateResult;
032: import org.continuent.sequoia.controller.loadbalancer.AllBackendsFailedException;
033: import org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager;
034: import org.continuent.sequoia.controller.requests.StoredProcedure;
035: import org.continuent.sequoia.controller.requests.StoredProcedureCallResult;
036:
037: /**
038: * This execute a write stored procedure on multiple controllers.
039: *
040: * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
041: * @version 1.0
042: */
043: public class DistributedCallableStatementExecuteUpdate extends
044: DistributedRequest {
045: private static final long serialVersionUID = 3550127604843949629L;
046:
047: /**
048: * Execute a write stored procedure on multiple controllers.
049: *
050: * @param proc the stored procedure to execute
051: */
052: public DistributedCallableStatementExecuteUpdate(
053: StoredProcedure proc) {
054: super (proc);
055: }
056:
057: /**
058: * @see org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedRequest#scheduleRequest(org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager)
059: */
060: public Object scheduleRequest(DistributedRequestManager drm)
061: throws SQLException {
062: LinkedList totalOrderQueue = drm.getVirtualDatabase()
063: .getTotalOrderQueue();
064: synchronized (totalOrderQueue) {
065: totalOrderQueue.addLast(request);
066: }
067: return request;
068: }
069:
070: /**
071: * @see org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedRequest#executeScheduledRequest(org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager)
072: */
073: public Serializable executeScheduledRequest(
074: DistributedRequestManager drm) throws SQLException {
075: Serializable execWriteStoredProcedure = null;
076: StoredProcedure proc = (StoredProcedure) request;
077: boolean hasBeenScheduled = false;
078: try {
079: drm.getLoadBalancer().waitForSuspendWritesToComplete(
080: request);
081:
082: // Even if we do not execute this query, we have to log the begin if any
083: drm.lazyTransactionStart(request);
084: drm.scheduleStoredProcedure((StoredProcedure) request);
085: hasBeenScheduled = true;
086:
087: if (drm.getLogger().isDebugEnabled())
088: drm
089: .getLogger()
090: .debug(
091: Translate
092: .get(
093: "requestmanager.write.stored.procedure",
094: new String[] {
095: String
096: .valueOf(request
097: .getId()),
098: request
099: .getSqlShortForm(drm
100: .getVirtualDatabase()
101: .getSqlShortFormLength()) }));
102:
103: StoredProcedureCallResult storedProcedureCallResult = new StoredProcedureCallResult(
104: proc,
105: drm.loadBalanceCallableStatementExecuteUpdate(proc));
106:
107: execWriteStoredProcedure = storedProcedureCallResult;
108:
109: if (drm.storeRequestResult(request,
110: execWriteStoredProcedure)
111: && !(storedProcedureCallResult.getResult() instanceof ExecuteUpdateResult))
112: execWriteStoredProcedure = DistributedRequestManager.SUCCESSFUL_COMPLETION;
113:
114: drm.updateRecoveryLogFlushCacheAndRefreshSchema(proc);
115:
116: // Notify scheduler of completion
117: drm.getScheduler().storedProcedureCompleted(proc);
118:
119: return execWriteStoredProcedure;
120: } catch (NoMoreBackendException e) {
121: if (drm.getLogger().isDebugEnabled())
122: drm
123: .getLogger()
124: .debug(
125: Translate
126: .get(
127: "virtualdatabase.distributed.write.procedure.logging.only",
128: request
129: .getSqlShortForm(drm
130: .getVirtualDatabase()
131: .getSqlShortFormLength())));
132:
133: // Add to failed list, the scheduler will be notified when the response
134: // will be received from the other controllers.
135: drm.addFailedOnAllBackends(request, hasBeenScheduled);
136: return e;
137: } catch (AllBackendsFailedException e) {
138: // Add to failed list, the scheduler will be notified when the response
139: // will be received from the other controllers.
140: drm.addFailedOnAllBackends(request, hasBeenScheduled);
141: if (drm.getLogger().isDebugEnabled())
142: drm
143: .getLogger()
144: .debug(
145: Translate
146: .get(
147: "virtualdatabase.distributed.write.procedure.all.backends.locally.failed",
148: request
149: .getSqlShortForm(drm
150: .getVirtualDatabase()
151: .getSqlShortFormLength())));
152: return e;
153: } catch (SQLException e) {
154: // Something bad more likely happened during the notification. Let's
155: // notify the scheduler (possibly again) to be safer.
156: drm.addFailedOnAllBackends(request, hasBeenScheduled);
157: drm
158: .getLogger()
159: .warn(
160: Translate
161: .get(
162: "virtualdatabase.distributed.write.procedure.sqlexception",
163: e.getMessage()), e);
164: return e;
165: } catch (RuntimeException re) {
166: // Something bad more likely happened during the notification. Let's
167: // notify the scheduler (possibly again) to be safer.
168: drm.addFailedOnAllBackends(request, hasBeenScheduled);
169: drm
170: .getLogger()
171: .warn(
172: Translate
173: .get(
174: "virtualdatabase.distributed.write.procedure.exception",
175: re.getMessage()), re);
176: return new SQLException(re.getMessage());
177: }
178: }
179:
180: /**
181: * @see java.lang.Object#toString()
182: */
183: public String toString() {
184: return "W " + request.getId() + " "
185: + request.getTransactionId() + " "
186: + request.getUniqueKey();
187: }
188:
189: }
|