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