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

RAIDb2PessimisticTransactionLevelScheduler.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.raidb2;
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.xml.DatabasesXmlTags;
00033 import org.objectweb.cjdbc.controller.requestmanager.RAIDbLevels;
00034 import org.objectweb.cjdbc.controller.scheduler.AbstractScheduler;
00035 import org.objectweb.cjdbc.controller.scheduler.schema.TransactionExclusiveLock;
00036 
00037 /**
00038  * This scheduler provides transaction level scheduling for RAIDb-2 controllers.
00039  * Each write takes a lock on the whole database. All following writes are
00040  * blocked until the transaction of the first write completes.
00041  * 
00042  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00043  * @version 1.0
00044  */
00045 public class RAIDb2PessimisticTransactionLevelScheduler
00046     extends AbstractScheduler
00047 {
00048 
00049   //
00050   // How the code is organized ?
00051   //
00052   // 1. Member variables
00053   // 2. Constructor
00054   // 3. Request handling
00055   // 4. Transaction management
00056   // 5. Debug/Monitoring
00057   //
00058 
00059   private long                     requestId;
00060   private TransactionExclusiveLock lock = new TransactionExclusiveLock();
00061 
00062   //
00063   // Constructor
00064   //
00065 
00066   /**
00067    * Creates a new Pessimistic Transaction Level Scheduler
00068    */
00069   public RAIDb2PessimisticTransactionLevelScheduler()
00070   {
00071     super(RAIDbLevels.RAIDb2, ParsingGranularities.NO_PARSING);
00072   }
00073 
00074   //
00075   // Request Handling
00076   //
00077 
00078   /**
00079    * Additionally to scheduling the request, this method replaces the SQL Date
00080    * macros such as now() with the current date.
00081    * 
00082    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#scheduleReadRequest(SelectRequest)
00083    */
00084   public final void scheduleReadRequest(SelectRequest request)
00085       throws SQLException
00086   {
00087     synchronized (this)
00088     {
00089       request.setId(requestId++);
00090     }
00091   }
00092 
00093   /**
00094    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#readCompletedNotify(SelectRequest)
00095    */
00096   public final void readCompletedNotify(SelectRequest request)
00097   {
00098   }
00099 
00100   /**
00101    * Note that CREATE statements are not synchronized.
00102    * 
00103    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#scheduleWriteRequest(AbstractWriteRequest)
00104    */
00105   public void scheduleNonSuspendedWriteRequest(AbstractWriteRequest request)
00106       throws SQLException
00107   {
00108     if (request.isCreate())
00109     {
00110       synchronized (this)
00111       {
00112         request.setId(requestId++);
00113       }
00114       return;
00115     }
00116 
00117     if (lock.acquire(request))
00118     {
00119       synchronized (this)
00120       {
00121         request.setId(requestId++);
00122       }
00123       if (logger.isDebugEnabled())
00124         logger.debug("Request " + request.getId() + " scheduled for write ("
00125             + getPendingWrites() + " pending writes)");
00126     }
00127     else
00128     {
00129       if (logger.isWarnEnabled())
00130         logger.warn("Request " + request.getId() + " timed out ("
00131             + request.getTimeout() + " s)");
00132       throw new SQLException("Timeout (" + request.getTimeout()
00133           + ") for request: " + request.getId());
00134     }
00135   }
00136 
00137   /**
00138    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#notifyWriteCompleted(AbstractWriteRequest)
00139    */
00140   public final synchronized void notifyWriteCompleted(
00141       AbstractWriteRequest request)
00142   {
00143     // Requests outside transaction delimiters must release the lock
00144     // as soon as they have executed
00145     if (request.isAutoCommit() && (!request.isCreate()))
00146       releaseLock(request.getTransactionId());
00147   }
00148 
00149   //
00150   // Transaction Management
00151   //
00152 
00153   /**
00154    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#commitTransaction(long)
00155    */
00156   protected final void commitTransaction(long transactionId)
00157   {
00158     if (lock.isLocked())
00159       releaseLock(transactionId);
00160     // else this was an empty or read-only transaction
00161   }
00162 
00163   /**
00164    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#rollbackTransaction(long)
00165    */
00166   protected final void rollbackTransaction(long transactionId)
00167   {
00168     if (lock.isLocked())
00169       releaseLock(transactionId);
00170     // else this was an empty or read-only transaction
00171   }
00172 
00173   /**
00174    * Release the locks we may own on the schema.
00175    * 
00176    * @param transactionId id of the transaction that releases the lock
00177    */
00178   private void releaseLock(long transactionId)
00179   {
00180     // Are we the lock owner ?
00181     if (lock.isLocked())
00182     {
00183       if (lock.getLocker() == transactionId)
00184         lock.release();
00185 
00186       // Note that the following warnings could be safely ignored if the
00187       // transaction commiting/rollbacking (releasing the lock) has not done any
00188       // conflicting write
00189       else if (logger.isDebugEnabled())
00190         logger.debug("Transaction " + transactionId
00191             + " wants to release the lock held by transaction "
00192             + lock.getLocker());
00193     }
00194     else if (logger.isDebugEnabled())
00195       logger.warn("Transaction " + transactionId
00196           + " tries to release a lock that has not been acquired.");
00197   }
00198 
00199   //
00200   // Debug/Monitoring
00201   //
00202 
00203   /**
00204    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#getXmlImpl()
00205    */
00206   public String getXmlImpl()
00207   {
00208     return "<" + DatabasesXmlTags.ELT_RAIDb2Scheduler + " "
00209         + DatabasesXmlTags.ATT_level + "=\""
00210         + DatabasesXmlTags.VAL_pessimisticTransaction + "\"/>";
00211   }
00212 
00213 }

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