Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

RAIDb1PessimisticTransactionLevelScheduler.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Emmanuel Cecchet. 
00022  * Contributor(s): _________________________.
00023  */
00024 
00025 package org.objectweb.cjdbc.controller.scheduler.raidb1;
00026 
00027 import java.sql.SQLException;
00028 
00029 import org.objectweb.cjdbc.common.sql.AbstractWriteRequest;
00030 import org.objectweb.cjdbc.common.sql.ParsingGranularities;
00031 import org.objectweb.cjdbc.common.sql.SelectRequest;
00032 import org.objectweb.cjdbc.common.util.Constants;
00033 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
00034 import org.objectweb.cjdbc.controller.requestmanager.RAIDbLevels;
00035 import org.objectweb.cjdbc.controller.scheduler.AbstractScheduler;
00036 import org.objectweb.cjdbc.controller.scheduler.schema.TransactionExclusiveLock;
00037 
00038 /**
00039  * This scheduler provides transaction level scheduling for RAIDb-1 controllers.
00040  * Each write takes a lock on the whole database. All following writes are
00041  * blocked until the transaction of the first write completes.
00042  * 
00043  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00044  * @version 1.0
00045  */
00046 public class RAIDb1PessimisticTransactionLevelScheduler
00047     extends AbstractScheduler
00048 {
00049 
00050   //
00051   // How the code is organized ?
00052   //
00053   // 1. Member variables
00054   // 2. Constructor
00055   // 3. Request handling
00056   // 4. Transaction management
00057   // 5. Debug/Monitoring
00058   //
00059 
00060   private long             requestId;
00061 
00062   TransactionExclusiveLock lock = new TransactionExclusiveLock();
00063 
00064   //
00065   // Constructor
00066   //
00067 
00068   /**
00069    * Creates a new Pessimistic Transaction Level Scheduler
00070    */
00071   public RAIDb1PessimisticTransactionLevelScheduler()
00072   {
00073     super(RAIDbLevels.RAIDb1, ParsingGranularities.NO_PARSING);
00074   }
00075 
00076   //
00077   // Request Handling
00078   //
00079 
00080   /**
00081    * Additionally to scheduling the request, this method replaces the SQL Date
00082    * macros such as now() with the current date.
00083    * 
00084    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#scheduleReadRequest(SelectRequest)
00085    */
00086   public final void scheduleReadRequest(SelectRequest request)
00087       throws SQLException
00088   {
00089     synchronized (this)
00090     {
00091       request.setId(requestId++);
00092     }
00093   }
00094 
00095   /**
00096    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#readCompletedNotify(SelectRequest)
00097    */
00098   public final void readCompletedNotify(SelectRequest request)
00099   {
00100   }
00101 
00102   /**
00103    * Note that CREATE statements are not synchronized.
00104    * 
00105    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#scheduleNonSuspendedWriteRequest(AbstractWriteRequest)
00106    */
00107   public void scheduleNonSuspendedWriteRequest(AbstractWriteRequest request)
00108       throws SQLException
00109   {
00110     if (request.isCreate())
00111     {
00112       synchronized (this)
00113       {
00114         request.setId(requestId++);
00115       }
00116       return;
00117     }
00118 
00119     if (lock.acquire(request))
00120     {
00121       synchronized (this)
00122       {
00123         request.setId(requestId++);
00124       }
00125       if (logger.isDebugEnabled())
00126         logger.debug("Request " + request.getId() + " scheduled for write ("
00127             + getPendingWrites() + " pending writes)");
00128     }
00129     else
00130     {
00131       if (logger.isWarnEnabled())
00132         logger.warn("Request " + request.getId() + " timed out ("
00133             + request.getTimeout() + " s)");
00134       throw new SQLException("Timeout (" + request.getTimeout()
00135           + ") for request: "
00136           + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH));
00137     }
00138   }
00139 
00140   /**
00141    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#notifyWriteCompleted(AbstractWriteRequest)
00142    */
00143   public final synchronized void notifyWriteCompleted(
00144       AbstractWriteRequest request)
00145   {
00146     // Requests outside transaction delimiters must release the lock
00147     // as soon as they have executed
00148     if (request.isAutoCommit() && (!request.isCreate()))
00149       releaseLock(request.getTransactionId());
00150   }
00151 
00152   //
00153   // Transaction Management
00154   //
00155 
00156   /**
00157    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#commitTransaction(long)
00158    */
00159   protected final void commitTransaction(long transactionId)
00160   {
00161     if (lock.isLocked())
00162       releaseLock(transactionId);
00163     // else this was an empty or read-only transaction
00164   }
00165 
00166   /**
00167    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#rollbackTransaction(long)
00168    */
00169   protected final void rollbackTransaction(long transactionId)
00170   {
00171     if (lock.isLocked())
00172       releaseLock(transactionId);
00173     // else this was an empty or read-only transaction
00174   }
00175 
00176   /**
00177    * Release the locks we may own on the schema.
00178    * 
00179    * @param transactionId id of the transaction that releases the lock
00180    */
00181   private void releaseLock(long transactionId)
00182   {
00183     // Are we the lock owner ?
00184     if (lock.isLocked())
00185     {
00186       if (lock.getLocker() == transactionId)
00187         lock.release();
00188 
00189       // Note that the following warnings could be safely ignored if the
00190       // transaction commiting/rollbacking (releasing the lock) has not done any
00191       // conflicting write
00192       else if (logger.isDebugEnabled())
00193         logger.debug("Transaction " + transactionId
00194             + " wants to release the lock held by transaction "
00195             + lock.getLocker());
00196     }
00197     else if (logger.isDebugEnabled())
00198       logger.warn("Transaction " + transactionId
00199           + " tries to release a lock that has not been acquired.");
00200   }
00201 
00202   //
00203   // Debug/Monitoring
00204   //
00205   /**
00206    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#getXmlImpl()
00207    */
00208   public String getXmlImpl()
00209   {
00210     return "<" + DatabasesXmlTags.ELT_RAIDb1Scheduler + " "
00211         + DatabasesXmlTags.ATT_level + "=\""
00212         + DatabasesXmlTags.VAL_pessimisticTransaction + "\"/>";
00213   }
00214 
00215 }

Generated on Mon Apr 11 22:01:33 2005 for C-JDBC by  doxygen 1.3.9.1