KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > controller > cache > metadata > MetadataCache


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): ______________________________________.
23  */

24
25 package org.objectweb.cjdbc.controller.cache.metadata;
26
27 import java.util.Hashtable JavaDoc;
28
29 import org.objectweb.cjdbc.common.i18n.Translate;
30 import org.objectweb.cjdbc.common.log.Trace;
31 import org.objectweb.cjdbc.common.sql.AbstractRequest;
32 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
33 import org.objectweb.cjdbc.driver.Field;
34
35 /**
36  * This class implements a ResultSet metadata cache.
37  * <p>
38  * ResultSet Fields are kept here to prevent recomputing them and allocating
39  * them each time a query is executed.
40  *
41  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
42  * @version 1.0
43  */

44 public class MetadataCache
45 {
46   private static Trace logger = Trace.getLogger(MetadataCache.class.getName());
47
48   // SQL -> Field[]
49
private Hashtable JavaDoc metadataCache;
50
51   // Schema.Table.Column name -> Field
52
private Hashtable JavaDoc fieldCache;
53   private int maxNbOfMetadata;
54   private int maxNbOfField;
55
56   /**
57    * Constructor for MetadataCache.
58    *
59    * @param maxNbOfMetadata maximum nb of entries in metadata cache
60    * @param maxNbOfField maximum nb of entries in field cache
61    */

62   public MetadataCache(int maxNbOfMetadata, int maxNbOfField)
63   {
64     metadataCache = new Hashtable JavaDoc(maxNbOfMetadata == 0
65         ? 10000
66         : maxNbOfMetadata);
67     fieldCache = new Hashtable JavaDoc(maxNbOfField == 0 ? 100 : maxNbOfField);
68     if (maxNbOfMetadata < 0)
69       throw new RuntimeException JavaDoc(Translate.get("cache.metadata.invalid.size",
70           maxNbOfMetadata));
71     if (maxNbOfMetadata == 0)
72       this.maxNbOfMetadata = Integer.MAX_VALUE;
73     else
74       this.maxNbOfMetadata = maxNbOfMetadata;
75     if (maxNbOfField < 0)
76       throw new RuntimeException JavaDoc(Translate.get("cache.metadata.invalid.size",
77           maxNbOfField));
78     if (maxNbOfField == 0)
79       this.maxNbOfField = Integer.MAX_VALUE;
80     else
81       this.maxNbOfField = maxNbOfField;
82   }
83
84   /**
85    * Flush the cache
86    */

87   public void flushCache()
88   {
89     synchronized (metadataCache)
90     {
91       metadataCache.clear();
92     }
93     synchronized (fieldCache)
94     {
95       fieldCache.clear();
96     }
97   }
98
99   /**
100    * Get metadata associated to a request.
101    * <p>
102    * Returns null if the cache contains no metadata for the given request.
103    *
104    * @param request the request we look for
105    * @return the metadata or null if not in cache
106    */

107   public Field[] getMetadata(AbstractRequest request)
108   {
109     String JavaDoc sqlSkeleton = request.getSqlSkeleton();
110     if (sqlSkeleton != null)
111       return (Field[]) metadataCache.get(sqlSkeleton);
112     else
113       return (Field[]) metadataCache.get(request.getSQL());
114   }
115
116   /**
117    * Add a metadata entry to the cache and associate it to the given request.
118    *
119    * @param request request to which the metadata belong
120    * @param metadata metadata to cache
121    */

122   public void addMetadata(AbstractRequest request, Field[] metadata)
123   {
124     // Note that the underlying cache Hashtable is synchronized and we usually
125
// do not need to synchronize on it.
126
// As we will have to add a cache entry, check if the cache size is ok
127
// else remove the first entry of the hashtable.
128
while (metadataCache.size() > maxNbOfMetadata)
129     { // Remove first entry from Hashtable. We need to synchronize here to be
130
// sure that we are not trying to concurrently remove the first cache
131
// entry.
132
synchronized (metadataCache)
133       {
134         try
135         {
136           metadataCache.remove(metadataCache.keys().nextElement());
137         }
138         catch (Exception JavaDoc ignore)
139         {
140           break;
141         }
142       }
143     }
144
145     // Add to cache
146
try
147     {
148       String JavaDoc sqlSkeleton = request.getSqlSkeleton();
149       if (sqlSkeleton != null)
150         metadataCache.put(sqlSkeleton, metadata);
151       else
152         metadataCache.put(request.getSQL(), metadata);
153     }
154     catch (OutOfMemoryError JavaDoc oome)
155     {
156       flushCache();
157       System.gc();
158       logger.warn(Translate.get("cache.memory.error.cache.flushed", this
159           .getClass()));
160     }
161   }
162
163   /**
164    * Get the field corresponding to a column name.
165    * <p>
166    * Returns null if the cache contains no field for the given name.
167    *
168    * @param fullyQualifiedFieldName the field name (table.column) to look for
169    * @return the corresponding Field or null if not in cache
170    */

171   public Field getField(String JavaDoc fullyQualifiedFieldName)
172   {
173     return (Field) fieldCache.get(fullyQualifiedFieldName);
174   }
175
176   /**
177    * Add a Field entry to the cache and associate it to the given name.
178    *
179    * @param fullyQualifiedFieldName table.column name that uniquely identifies
180    * the field
181    * @param field field to cache
182    */

183   public void addField(String JavaDoc fullyQualifiedFieldName, Field field)
184   {
185     // Note that the underlying cache Hashtable is synchronized and we usually
186
// do not need to synchronize on it.
187
// As we will have to add a cache entry, check if the cache size is ok
188
// else remove the first entry of the hashtable.
189
while (fieldCache.size() > maxNbOfField)
190     { // Remove first entry from Hashtable. We need to synchronize here to be
191
// sure that we are not trying to concurrently remove the first cache
192
// entry.
193
synchronized (fieldCache)
194       {
195         try
196         {
197           fieldCache.remove(fieldCache.keys().nextElement());
198         }
199         catch (Exception JavaDoc ignore)
200         {
201           break;
202         }
203       }
204     }
205     // Add to cache
206
try
207     {
208       fieldCache.put(fullyQualifiedFieldName, field);
209     }
210     catch (OutOfMemoryError JavaDoc oome)
211     {
212       flushCache();
213       System.gc();
214       logger.warn(Translate.get("cache.memory.error.cache.flushed", this
215           .getClass()));
216     }
217   }
218
219   /**
220    * Get xml information about this ParsingCache
221    *
222    * @return <code>String</code> in xml formatted text
223    */

224   public String JavaDoc getXml()
225   {
226     return "<" + DatabasesXmlTags.ELT_MetadataCache + " "
227         + DatabasesXmlTags.ATT_maxNbOfMetadata + "=\"" + maxNbOfMetadata
228         + "\" " + DatabasesXmlTags.ATT_maxNbOfField + "=\""
229         + (maxNbOfField == Integer.MAX_VALUE ? 0 : maxNbOfField) + "\"/>";
230   }
231
232 }
Popular Tags