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.GeneratedKeysResult;
032: import org.continuent.sequoia.controller.loadbalancer.AllBackendsFailedException;
033: import org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager;
034: import org.continuent.sequoia.controller.requests.AbstractWriteRequest;
035:
036: /**
037: * Execute a distributed call to Statement.executeUpdate(sql,
038: * Statement.RETURN_GENERATED_KEYS) between several controllers.
039: *
040: * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
041: * @version 1.0
042: */
043: public class DistributedStatementExecuteUpdateWithKeys extends
044: DistributedRequest {
045: private static final long serialVersionUID = -7075254412706395576L;
046:
047: /**
048: * @param request write request to execute
049: */
050: public DistributedStatementExecuteUpdateWithKeys(
051: AbstractWriteRequest request) {
052: super (request);
053: }
054:
055: /**
056: * @see org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedRequest#scheduleRequest(org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager)
057: */
058: public Object scheduleRequest(DistributedRequestManager drm)
059: throws SQLException {
060: LinkedList totalOrderQueue = drm.getVirtualDatabase()
061: .getTotalOrderQueue();
062: synchronized (totalOrderQueue) {
063: totalOrderQueue.addLast(request);
064: }
065: return request;
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: boolean hasBeenScheduled = false;
074:
075: try {
076: drm.getLoadBalancer().waitForSuspendWritesToComplete(
077: request);
078: // This call will trigger a lazyTransactionStart as well
079: drm
080: .scheduleExecWriteRequest((AbstractWriteRequest) request);
081: hasBeenScheduled = true;
082:
083: Serializable execWriteRequestResult = null;
084: execWriteRequestResult = drm
085: .loadBalanceStatementExecuteUpdateWithKeys((AbstractWriteRequest) request);
086: int updateCount = ((GeneratedKeysResult) execWriteRequestResult)
087: .getUpdateCount();
088:
089: drm.storeRequestResult(request, execWriteRequestResult);
090:
091: drm.updateAndNotifyExecWriteRequest(
092: (AbstractWriteRequest) request, updateCount);
093:
094: return execWriteRequestResult;
095: } catch (NoMoreBackendException e) {
096: if (drm.getLogger().isDebugEnabled())
097: drm
098: .getLogger()
099: .debug(
100: Translate
101: .get(
102: "virtualdatabase.distributed.write.logging.only",
103: request
104: .getSqlShortForm(drm
105: .getVirtualDatabase()
106: .getSqlShortFormLength())));
107:
108: // Add to failed list, the scheduler will be notified when the response
109: // will be received from the other controllers.
110: drm.addFailedOnAllBackends(request, hasBeenScheduled);
111: return e;
112: } catch (AllBackendsFailedException e) {
113: // Add to failed list, the scheduler will be notified when the response
114: // will be received from the other controllers.
115: drm.addFailedOnAllBackends(request, hasBeenScheduled);
116: if (drm.getLogger().isDebugEnabled())
117: drm
118: .getLogger()
119: .debug(
120: Translate
121: .get(
122: "virtualdatabase.distributed.write.all.backends.locally.failed",
123: request
124: .getSqlShortForm(drm
125: .getVirtualDatabase()
126: .getSqlShortFormLength())));
127: return e;
128: } catch (SQLException e) {
129: // Something bad more likely happened during the update but the scheduler
130: // has already been notified.
131: drm.addFailedOnAllBackends(request, hasBeenScheduled);
132: drm
133: .getLogger()
134: .warn(
135: Translate
136: .get(
137: "virtualdatabase.distributed.write.sqlexception",
138: e.getMessage()), e);
139: return e;
140: } catch (RuntimeException re) {
141: // Something bad more likely happened during the update but the scheduler
142: // has already been notified.
143: drm.addFailedOnAllBackends(request, hasBeenScheduled);
144: drm
145: .getLogger()
146: .warn(
147: Translate
148: .get(
149: "virtualdatabase.distributed.write.exception",
150: re.getMessage()), re);
151: return new SQLException(re.getMessage());
152: }
153: }
154:
155: /**
156: * @see java.lang.Object#toString()
157: */
158: public String toString() {
159: return "W " + request.getId() + " "
160: + request.getTransactionId() + " "
161: + request.getUniqueKey();
162: }
163:
164: }
|