001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.catalog.SPSNameCacheable
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.catalog;
023:
024: import org.apache.derby.iapi.services.cache.Cacheable;
025: import org.apache.derby.iapi.services.cache.CacheManager;
026:
027: import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
028:
029: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
030: import org.apache.derby.iapi.sql.dictionary.SPSDescriptor;
031:
032: import org.apache.derby.iapi.error.StandardException;
033:
034: import org.apache.derby.iapi.services.sanity.SanityManager;
035:
036: /**
037: * This class implements a Cacheable for a DataDictionary cache of
038: * sps descriptors, with the lookup key being the name/schema of the sps.
039: * Assumes client passes in a string that includes the schema name.
040: * <p>
041: * The cache ensures that the class of the target sps is loaded
042: * if the sps is found in cache. This is ensured by calling
043: * loadGeneratedClass() on the sps when it is added to the cache.
044: * Each subsequent user of the sps cache will do its own load/unload
045: * on the class. Because the class manager/loader maintains reference
046: * counts on the classes it is handling, the user load/unload will
047: * just increment/decrement the use count. Only when the sps is
048: * uncached will it be unloaded.
049: */
050: class SPSNameCacheable implements Cacheable {
051: private TableKey identity;
052: private SPSDescriptor spsd;
053: private final DataDictionaryImpl dd;
054:
055: SPSNameCacheable(DataDictionaryImpl dd) {
056: this .dd = dd;
057: }
058:
059: /* Cacheable interface */
060:
061: /** @see Cacheable#clearIdentity */
062: public void clearIdentity() {
063: if (spsd != null) {
064: dd.spsCacheEntryRemoved(spsd);
065:
066: if (SanityManager.DEBUG) {
067: if (SanityManager.DEBUG_ON("SPSNameCacheTrace")) {
068: System.out.println("SPSCACHE: clearIdentity() on "
069: + spsd.getName());
070: }
071: }
072: spsd = null;
073: identity = null;
074: }
075: }
076:
077: /** @see Cacheable#getIdentity */
078: public Object getIdentity() {
079: return identity;
080: }
081:
082: /** @see Cacheable#createIdentity */
083: public Cacheable createIdentity(Object key, Object createParameter) {
084: if (SanityManager.DEBUG) {
085: if (!(key instanceof TableKey)) {
086: SanityManager
087: .THROWASSERT("Key for a SPSNameCacheElement is a "
088: + key.getClass().getName()
089: + " instead of a TableKey");
090: }
091: if (!(createParameter instanceof SPSDescriptor)) {
092: SanityManager
093: .THROWASSERT("Create parameter for a SPSNameCacheElement is a "
094: + createParameter.getClass().getName()
095: + "instead of a SPSDescriptorImpl");
096: }
097: }
098:
099: identity = (TableKey) key;
100: spsd = (SPSDescriptor) createParameter;
101:
102: if (spsd != null) {
103: if (SanityManager.DEBUG) {
104: if (SanityManager.DEBUG_ON("SPSNameCacheTrace")) {
105: System.out.println("SPSCACHE: createIdentity() on "
106: + spsd.getName());
107: }
108: }
109:
110: dd.spsCacheEntryAdded(spsd);
111: try {
112: spsd.loadGeneratedClass();
113: } catch (StandardException e) {
114: /*
115: ** We cannot throw an exception here, and although
116: ** we don't expect a problem, we'll put some debugging
117: ** under sanity just in case. Note that even if we
118: ** do get an exception here, everything else will work
119: ** ok -- subsequent attempts to access the generated
120: ** class for this sps will do a load themselves, and
121: ** they will throw their exception back to the user.
122: */
123: if (SanityManager.DEBUG) {
124: System.out.println("Error loading class for "
125: + spsd.getName());
126: System.out.println(e);
127: e.printStackTrace();
128: }
129: }
130: return this ;
131: } else {
132: return null;
133: }
134: }
135:
136: /**
137: * @see Cacheable#setIdentity
138: *
139: * @exception StandardException Thrown on error
140: */
141: public Cacheable setIdentity(Object key) throws StandardException {
142: if (SanityManager.DEBUG) {
143: if (!(key instanceof TableKey)) {
144: SanityManager
145: .THROWASSERT("Key for a SPSNameCacheable Element is a "
146: + key.getClass().getName()
147: + " instead of a TableKey");
148: }
149: }
150:
151: identity = (TableKey) key;
152: spsd = dd.getUncachedSPSDescriptor(identity);
153: if (spsd != null) {
154: if (SanityManager.DEBUG) {
155: if (SanityManager.DEBUG_ON("SPSNameCacheTrace")) {
156: System.out.println("SPSCACHE: setIdentity() on "
157: + spsd.getName());
158: }
159: }
160:
161: dd.spsCacheEntryAdded(spsd);
162: try {
163: spsd.loadGeneratedClass();
164: } catch (StandardException e) {
165: /*
166: ** We cannot throw an exception here, and although
167: ** we don't expect a problem, we'll put some debugging
168: ** under sanity just in case. Note that even if we
169: ** do get an exception here, everything else will work
170: ** ok -- subsequent attempts to access the generated
171: ** class for this sps will do a load themselves, and
172: ** they will throw their exception back to the user.
173: */
174: if (SanityManager.DEBUG) {
175: System.out.println("Error loading class for "
176: + spsd.getName());
177: System.out.println(e);
178: e.printStackTrace();
179: }
180: }
181: return this ;
182: } else {
183: return null;
184: }
185: }
186:
187: /* Cacheable interface */
188:
189: /** @see Cacheable#clean */
190: public void clean(boolean forRemove) {
191: return;
192: }
193:
194: /** @see Cacheable#isDirty */
195: public boolean isDirty() {
196: return false;
197: }
198:
199: /**
200: * Get the sps descriptor that is associated with this Cacheable
201: */
202: public SPSDescriptor getSPSDescriptor() {
203: return spsd;
204: }
205:
206: /**
207: * Check the consistency of the table descriptor held by this TDCacheable
208: * versus an uncached table descriptor.
209: *
210: * @param uncachedSpsd The uncached descriptor to compare to
211: * @param identity The identity of the table descriptor
212: * @param reportInconsistent A HeaderPrintWriter to send complaints to
213: *
214: * @return true if the descriptors are the same, false if they're different
215: *
216: * @exception StandardException Thrown on error
217: */
218: private boolean checkConsistency(SPSDescriptor uncachedSpsd,
219: Object identity, HeaderPrintWriter reportInconsistent)
220: throws StandardException {
221: boolean retval = true;
222:
223: if (SanityManager.DEBUG) {
224: if (uncachedSpsd == null) {
225: reportInconsistent
226: .println("Inconsistent SPSNameCacheable: identity = "
227: + identity
228: + ", uncached table descriptor not found.");
229: retval = false;
230: } else {
231: if ((!uncachedSpsd.getText().equals(spsd.getText()))
232: || (!uncachedSpsd.getUsingText().equals(
233: spsd.getUsingText()))
234: || (!uncachedSpsd.getQualifiedName().equals(
235: spsd.getQualifiedName()))) {
236: reportInconsistent
237: .println("Inconsistent SPSNameCacheable: identity = "
238: + identity
239: + ", cached SPS = "
240: + spsd
241: + ", uncached SPS = "
242: + uncachedSpsd);
243:
244: retval = false;
245: }
246: }
247: }
248:
249: return retval;
250: }
251: }
|