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: * Contact: sequoia@continuent.org
007: *
008: * Licensed under the Apache License, Version 2.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: * Initial developer(s): Emmanuel Cecchet.
021: * Contributor(s): Jean-Bernard van Zuylen.
022: */package org.continuent.sequoia.controller.scheduler.singledb;
023:
024: import java.sql.SQLException;
025:
026: import org.continuent.sequoia.common.exceptions.RollbackException;
027: import org.continuent.sequoia.common.xml.DatabasesXmlTags;
028: import org.continuent.sequoia.controller.core.ControllerConstants;
029: import org.continuent.sequoia.controller.requestmanager.RAIDbLevels;
030: import org.continuent.sequoia.controller.requests.AbstractWriteRequest;
031: import org.continuent.sequoia.controller.requests.ParsingGranularities;
032: import org.continuent.sequoia.controller.requests.SelectRequest;
033: import org.continuent.sequoia.controller.requests.StoredProcedure;
034: import org.continuent.sequoia.controller.scheduler.AbstractScheduler;
035: import org.continuent.sequoia.controller.scheduler.schema.TransactionExclusiveLock;
036:
037: /**
038: * This scheduler provides transaction level scheduling for a SingleDB. Each
039: * write takes a lock on the whole database. All following writes are blocked
040: * until the transaction of the first write completes.
041: *
042: * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
043: * @version 1.0
044: */
045: public class SingleDBPessimisticTransactionLevelScheduler extends
046: AbstractScheduler {
047:
048: //
049: // How the code is organized ?
050: //
051: // 1. Member variables
052: // 2. Constructor
053: // 3. Request handling
054: // 4. Transaction management
055: // 5. Debug/Monitoring
056: //
057:
058: TransactionExclusiveLock lock = new TransactionExclusiveLock();
059:
060: //
061: // Constructor
062: //
063:
064: /**
065: * Creates a new Pessimistic Transaction Level Scheduler
066: */
067: public SingleDBPessimisticTransactionLevelScheduler() {
068: super (RAIDbLevels.SingleDB, ParsingGranularities.NO_PARSING);
069: }
070:
071: //
072: // Request Handling
073: //
074:
075: /**
076: * Additionally to scheduling the request, this method replaces the SQL Date
077: * macros such as now() with the current date.
078: *
079: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#scheduleNonSuspendedReadRequest(SelectRequest)
080: */
081: public final void scheduleNonSuspendedReadRequest(
082: SelectRequest request) throws SQLException {
083: }
084:
085: /**
086: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#readCompletedNotify(SelectRequest)
087: */
088: public final void readCompletedNotify(SelectRequest request) {
089: }
090:
091: /**
092: * Additionally to scheduling the request, this method replaces the SQL Date
093: * macros such as now() with the current date.
094: *
095: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#scheduleWriteRequest(AbstractWriteRequest)
096: */
097: public void scheduleNonSuspendedWriteRequest(
098: AbstractWriteRequest request) throws SQLException {
099: if (lock.acquire(request)) {
100: if (logger.isDebugEnabled())
101: logger.debug("Request " + request.getId()
102: + " scheduled for write (" + getPendingWrites()
103: + " pending writes)");
104: } else {
105: if (logger.isWarnEnabled())
106: logger
107: .warn("Request " + request.getId()
108: + " timed out (" + request.getTimeout()
109: + " s)");
110: throw new SQLException("Timeout (" + request.getTimeout()
111: + ") for request: " + request.getId());
112: }
113: }
114:
115: /**
116: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#notifyWriteCompleted(AbstractWriteRequest)
117: */
118: public final void notifyWriteCompleted(AbstractWriteRequest request) {
119: // Requests outside transaction delimiters must release the lock
120: // as soon as they have executed
121: if (request.isAutoCommit())
122: releaseLock(request.getTransactionId());
123: }
124:
125: /**
126: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#scheduleNonSuspendedStoredProcedure(org.continuent.sequoia.controller.requests.StoredProcedure)
127: */
128: public final void scheduleNonSuspendedStoredProcedure(
129: StoredProcedure proc) throws SQLException,
130: RollbackException {
131: if (lock.acquire(proc)) {
132: if (logger.isDebugEnabled())
133: logger.debug("Stored procedure " + proc.getId()
134: + " scheduled for write (" + getPendingWrites()
135: + " pending writes)");
136: } else {
137: if (logger.isWarnEnabled())
138: logger.warn("Stored procedure " + proc.getId()
139: + " timed out (" + proc.getTimeout() + " s)");
140: throw new SQLException(
141: "Timeout ("
142: + proc.getTimeout()
143: + ") for request: "
144: + proc
145: .getSqlShortForm(ControllerConstants.SQL_SHORT_FORM_LENGTH));
146: }
147: }
148:
149: /**
150: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#notifyStoredProcedureCompleted(org.continuent.sequoia.controller.requests.StoredProcedure)
151: */
152: public final void notifyStoredProcedureCompleted(
153: StoredProcedure proc) {
154: // Requests outside transaction delimiters must release the lock
155: // as soon as they have executed
156: if (proc.isAutoCommit() && (!proc.isCreate()))
157: releaseLock(proc.getTransactionId());
158: }
159:
160: //
161: // Transaction Management
162: //
163:
164: /**
165: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#commitTransaction(long)
166: */
167: protected final void commitTransaction(long transactionId) {
168: releaseLock(transactionId);
169: }
170:
171: /**
172: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#rollbackTransaction(long)
173: */
174: protected final void rollbackTransaction(long transactionId) {
175: releaseLock(transactionId);
176: }
177:
178: /**
179: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#rollbackTransaction(long,
180: * String)
181: */
182: protected final void rollbackTransaction(long transactionId,
183: String savepointName) {
184: }
185:
186: /**
187: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#setSavepointTransaction(long,
188: * String)
189: */
190: protected final void setSavepointTransaction(long transactionId,
191: String name) {
192: }
193:
194: /**
195: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#releaseSavepointTransaction(long,
196: * String)
197: */
198: protected final void releaseSavepointTransaction(
199: long transactionId, String name) {
200: }
201:
202: /**
203: * Release the locks we may own on the schema.
204: *
205: * @param transactionId id of the transaction that releases the lock
206: */
207: private void releaseLock(long transactionId) {
208: // Are we the lock owner ?
209: if (lock.isLocked()) {
210: if (lock.getLocker() == transactionId)
211: lock.release();
212:
213: // Note that the following warnings could be safely ignored if the
214: // transaction
215: // commiting/rolllbacking (releasing the lock) has not done any
216: // conflicting write
217: else if (logger.isDebugEnabled())
218: logger
219: .debug("Transaction "
220: + transactionId
221: + " wants to release the lock held by transaction "
222: + lock.getLocker());
223: } else if (logger.isDebugEnabled())
224: logger
225: .warn("Transaction "
226: + transactionId
227: + " tries to release a lock that has not been acquired.");
228: }
229:
230: //
231: // Debug/Monitoring
232: //
233:
234: /**
235: * @see org.continuent.sequoia.controller.scheduler.AbstractScheduler#getXmlImpl()
236: */
237: public String getXmlImpl() {
238: return "<" + DatabasesXmlTags.ELT_SingleDBScheduler + " "
239: + DatabasesXmlTags.ATT_level + "=\""
240: + DatabasesXmlTags.VAL_pessimisticTransaction + "\"/>";
241: }
242: }
|