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

SingleDBPessimisticTransactionLevelScheduler.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.singledb;
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 a SingleDB. Each
00039  * write takes a lock on the whole database. All following writes are blocked
00040  * 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 SingleDBPessimisticTransactionLevelScheduler
00046     extends
00047       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   TransactionExclusiveLock lock = new TransactionExclusiveLock();
00062 
00063   //
00064   // Constructor
00065   //
00066 
00067   /**
00068    * Creates a new Pessimistic Transaction Level Scheduler
00069    */
00070   public SingleDBPessimisticTransactionLevelScheduler()
00071   {
00072     super(RAIDbLevels.SingleDB, ParsingGranularities.NO_PARSING);
00073   }
00074 
00075   //
00076   // Request Handling
00077   //
00078 
00079   /**
00080    * Additionally to scheduling the request, this method replaces the SQL Date
00081    * macros such as now() with the current date.
00082    * 
00083    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#scheduleReadRequest(SelectRequest)
00084    */
00085   public final synchronized void scheduleReadRequest(SelectRequest request)
00086       throws SQLException
00087   {
00088     request.setId(requestId++);
00089   }
00090 
00091   /**
00092    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#readCompletedNotify(SelectRequest)
00093    */
00094   public final void readCompletedNotify(SelectRequest request)
00095   {
00096   }
00097 
00098   /**
00099    * Additionally to scheduling the request, this method replaces the SQL Date
00100    * macros such as now() with the current date.
00101    * 
00102    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#scheduleWriteRequest(AbstractWriteRequest)
00103    */
00104   public void scheduleNonSuspendedWriteRequest(AbstractWriteRequest request)
00105       throws SQLException
00106   {
00107     if (lock.acquire(request))
00108     {
00109       synchronized (this)
00110       {
00111         request.setId(requestId++);
00112       }
00113       if (logger.isDebugEnabled())
00114         logger.debug("Request " + request.getId() + " scheduled for write ("
00115             + getPendingWrites() + " pending writes)");
00116     }
00117     else
00118     {
00119       if (logger.isWarnEnabled())
00120         logger.warn("Request " + request.getId() + " timed out ("
00121             + request.getTimeout() + " s)");
00122       throw new SQLException("Timeout (" + request.getTimeout()
00123           + ") for request: " + request.getId());
00124     }
00125   }
00126 
00127   /**
00128    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#notifyWriteCompleted(AbstractWriteRequest)
00129    */
00130   public final synchronized void notifyWriteCompleted(
00131       AbstractWriteRequest request)
00132   {
00133     // Requests outside transaction delimiters must release the lock
00134     // as soon as they have executed
00135     if (request.isAutoCommit())
00136       releaseLock(request.getTransactionId());
00137   }
00138 
00139   //
00140   // Transaction Management
00141   //
00142 
00143   /**
00144    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#commitTransaction(long)
00145    */
00146   protected final void commitTransaction(long transactionId)
00147   {
00148     releaseLock(transactionId);
00149   }
00150 
00151   /**
00152    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#rollbackTransaction(long)
00153    */
00154   protected final void rollbackTransaction(long transactionId)
00155   {
00156     releaseLock(transactionId);
00157   }
00158 
00159   /**
00160    * Release the locks we may own on the schema.
00161    * 
00162    * @param transactionId id of the transaction that releases the lock
00163    */
00164   private void releaseLock(long transactionId)
00165   {
00166     // Are we the lock owner ?
00167     if (lock.isLocked())
00168     {
00169       if (lock.getLocker() == transactionId)
00170         lock.release();
00171 
00172       // Note that the following warnings could be safely ignored if the
00173       // transaction
00174       // commiting/rolllbacking (releasing the lock) has not done any
00175       // conflicting write
00176       else if (logger.isDebugEnabled())
00177         logger.debug("Transaction " + transactionId
00178             + " wants to release the lock held by transaction "
00179             + lock.getLocker());
00180     }
00181     else if (logger.isDebugEnabled())
00182       logger.warn("Transaction " + transactionId
00183           + " tries to release a lock that has not been acquired.");
00184   }
00185 
00186   //
00187   // Debug/Monitoring
00188   //
00189 
00190   /**
00191    * @see org.objectweb.cjdbc.controller.scheduler.AbstractScheduler#getXmlImpl()
00192    */
00193   public String getXmlImpl()
00194   {
00195     return "<" + DatabasesXmlTags.ELT_SingleDBScheduler + " "
00196         + DatabasesXmlTags.ATT_level + "=\""
00197         + DatabasesXmlTags.VAL_pessimisticTransaction + "\"/>";
00198   }
00199 
00200 }

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