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

ResultCacheColumnUnique.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): Nicolas Modrzyk.
00023  */
00024 
00025 package org.objectweb.cjdbc.controller.cache.result;
00026 
00027 import java.util.ArrayList;
00028 import java.util.Iterator;
00029 
00030 import org.objectweb.cjdbc.common.sql.AbstractWriteRequest;
00031 import org.objectweb.cjdbc.common.sql.DeleteRequest;
00032 import org.objectweb.cjdbc.common.sql.ParsingGranularities;
00033 import org.objectweb.cjdbc.common.sql.RequestType;
00034 import org.objectweb.cjdbc.common.sql.SelectRequest;
00035 import org.objectweb.cjdbc.common.sql.UpdateRequest;
00036 import org.objectweb.cjdbc.common.sql.schema.TableColumn;
00037 import org.objectweb.cjdbc.controller.cache.result.entries.CacheEntry;
00038 import org.objectweb.cjdbc.controller.cache.result.entries.ResultCacheEntry;
00039 import org.objectweb.cjdbc.controller.cache.result.schema.CacheDatabaseColumn;
00040 import org.objectweb.cjdbc.controller.cache.result.schema.CacheDatabaseTable;
00041 import org.objectweb.cjdbc.controller.virtualdatabase.ControllerResultSet;
00042 
00043 /**
00044  * This is a query cache implementation with a column unique granularity:
00045  * <ul>
00046  * <li><code>COLUMN_UNIQUE</code>: same as <code>COLUMN</code> except that
00047  * <code>UNIQUE</code> queries that selects a single row based on a key are
00048  * invalidated only when needed.
00049  * </ul>
00050  * 
00051  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00052  * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
00053  * @version 1.0
00054  */
00055 public class ResultCacheColumnUnique extends ResultCache
00056 {
00057 
00058   /**
00059    * Builds a new ResultCache with a column unique granularity.
00060    * 
00061    * @param maxEntries maximum number of entries
00062    * @param pendingTimeout pending timeout for concurrent queries
00063    */
00064   public ResultCacheColumnUnique(int maxEntries, int pendingTimeout)
00065   {
00066     super(maxEntries, pendingTimeout);
00067     parsingGranularity = ParsingGranularities.COLUMN_UNIQUE;
00068   }
00069 
00070   /**
00071    * @see org.objectweb.cjdbc.controller.cache.result.ResultCache#processAddToCache(CacheEntry)
00072    */
00073   public void processAddToCache(CacheEntry qe)
00074   {
00075     SelectRequest request = qe.getRequest();
00076     ArrayList selectedColumns = request.getSelect();
00077     //  Update the tables columns dependencies
00078     if (selectedColumns == null || selectedColumns.isEmpty())
00079     {
00080       logger
00081           .warn("No parsing of select clause found - Fallback to table granularity");
00082       for (Iterator i = request.getFrom().iterator(); i.hasNext();)
00083       {
00084         CacheDatabaseTable table = cdbs.getTable((String) i.next());
00085         table.addCacheEntry(qe);
00086         // Add all columns, entries will be added below.
00087         ArrayList columns = table.getColumns();
00088         for (int j = 0; j < columns.size(); j++)
00089         {
00090           ((CacheDatabaseColumn) columns.get(j)).addCacheEntry(qe);
00091         }
00092         return;
00093       }
00094     }
00095     for (Iterator i = request.getSelect().iterator(); i.hasNext();)
00096     {
00097       TableColumn tc = (TableColumn) i.next();
00098       cdbs.getTable(tc.getTableName()).getColumn(tc.getColumnName())
00099           .addCacheEntry(qe);
00100     }
00101     if (request.getWhere() != null)
00102     { // Add all columns dependencies
00103       for (Iterator i = request.getWhere().iterator(); i.hasNext();)
00104       {
00105         TableColumn tc = (TableColumn) i.next();
00106         cdbs.getTable(tc.getTableName()).getColumn(tc.getColumnName())
00107             .addCacheEntry(qe);
00108       }
00109       if (request.getCacheAbility() == RequestType.UNIQUE_CACHEABLE)
00110       { // Add a specific entry for this pk
00111         String tableName = (String) request.getFrom().get(0);
00112         ResultCacheEntry entry = cdbs.getTable(tableName)
00113             .getPkResultCacheEntry(request.getPkValue());
00114         if (entry != null)
00115         {
00116           if (entry.isValid())
00117           { // Do not add an entry which has a lower selection than the current
00118             // one
00119             if (entry.getRequest().getSelect().size() >= request.getSelect()
00120                 .size())
00121               return;
00122           }
00123         }
00124         cdbs.getTable(tableName).addPkCacheEntry(request.getPkValue(), qe);
00125       }
00126     }
00127   }
00128 
00129   /**
00130    * @see org.objectweb.cjdbc.controller.cache.result.AbstractResultCache#isUpdateNecessary(org.objectweb.cjdbc.common.sql.UpdateRequest)
00131    */
00132   public boolean isUpdateNecessary(UpdateRequest request)
00133   {
00134     if (request.getCacheAbility() != RequestType.UNIQUE_CACHEABLE)
00135       return true;
00136     CacheDatabaseTable cacheTable = cdbs.getTable(request.getTableName());
00137     if (request.getColumns() == null)
00138       return true;
00139     String pk = request.getPk();
00140     ResultCacheEntry qce = cacheTable.getPkResultCacheEntry(pk);
00141     if (qce != null)
00142     {
00143       if (!qce.isValid())
00144         return true;
00145       ControllerResultSet rs = qce.getResult();
00146       if (rs == null)
00147         return true;
00148       else
00149         return needInvalidate(rs, request)[1];
00150     }
00151     else
00152       return true;
00153   }
00154 
00155   /**
00156    * @see org.objectweb.cjdbc.controller.cache.result.ResultCache#processWriteNotify(org.objectweb.cjdbc.common.sql.AbstractWriteRequest)
00157    */
00158   protected void processWriteNotify(AbstractWriteRequest request)
00159   {
00160     // Sanity check
00161     CacheDatabaseTable cacheTable = cdbs.getTable(request.getTableName());
00162     if (request.getColumns() == null)
00163     {
00164       logger.warn("No column parsing found - Fallback to table granularity ("
00165           + request.getSQL() + ")");
00166       cacheTable.invalidateAll();
00167       return;
00168     }
00169     if (request.isInsert())
00170     {
00171       for (Iterator i = request.getColumns().iterator(); i.hasNext();)
00172       {
00173         TableColumn tc = (TableColumn) i.next();
00174         cdbs.getTable(tc.getTableName()).getColumn(tc.getColumnName())
00175             .invalidateAllNonUnique();
00176       }
00177     }
00178     else
00179     {
00180       if (request.getCacheAbility() == RequestType.UNIQUE_CACHEABLE)
00181       {
00182         if (request.isUpdate())
00183         {
00184           String pk = ((UpdateRequest) request).getPk();
00185           ResultCacheEntry qce = cacheTable.getPkResultCacheEntry(pk);
00186           if (qce != null)
00187           {
00188             boolean[] invalidate = needInvalidate(qce.getResult(),
00189                 (UpdateRequest) request);
00190             if (invalidate[0])
00191             { // We must invalidate this entry
00192               cacheTable.removePkResultCacheEntry(pk);
00193               return;
00194             }
00195             else
00196             {
00197               if (logger.isDebugEnabled())
00198                 logger.debug("No invalidate needed for request:"
00199                     + request.getSQLShortForm(20));
00200               return; // We don't need to invalidate
00201             }
00202           }
00203         }
00204         else if (request.isDelete())
00205         { // Invalidate the corresponding cache entry
00206           cacheTable
00207               .removePkResultCacheEntry(((DeleteRequest) request).getPk());
00208           return;
00209         }
00210       }
00211       // At this point this is a non unique write query or a request
00212       // we didn't handle properly (unknown request for example)
00213       for (Iterator i = request.getColumns().iterator(); i.hasNext();)
00214       {
00215         TableColumn tc = (TableColumn) i.next();
00216         CacheDatabaseTable table = cdbs.getTable(tc.getTableName());
00217         table.invalidateAll(); // Pk are associated to tables
00218         if (!request.isAlter())
00219           table.getColumn(tc.getColumnName()).invalidateAll();
00220       }
00221     }
00222   }
00223 
00224   /**
00225    * @see org.objectweb.cjdbc.controller.cache.result.ResultCache#getName()
00226    */
00227   public String getName()
00228   {
00229     return "columnUnique";
00230   }
00231 
00232 }

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