Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/derby/impl/services/cache/CachedItem.java


1   /*
2   
3      Derby - Class org.apache.derby.impl.services.cache.CachedItem
4   
5      Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6   
7      Licensed under the Apache License, Version 2.0 (the "License");
8      you may not use this file except in compliance with the License.
9      You may obtain a copy of the License at
10  
11        http://www.apache.org/licenses/LICENSE-2.0
12  
13     Unless required by applicable law or agreed to in writing, software
14     distributed under the License is distributed on an "AS IS" BASIS,
15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16     See the License for the specific language governing permissions and
17     limitations under the License.
18  
19   */
20  
21  package org.apache.derby.impl.services.cache;
22  
23  import org.apache.derby.iapi.services.cache.Cacheable;
24  import org.apache.derby.iapi.services.cache.CacheableFactory;
25  import org.apache.derby.iapi.services.cache.CacheManager;
26  import org.apache.derby.iapi.error.StandardException;
27  
28  import org.apache.derby.iapi.services.sanity.SanityManager;
29  import org.apache.derby.iapi.services.context.ContextService;
30  
31  /**
32    A generic class to represent the cache related infomation of a cached object (Cacheable).
33    <P><PRE>
34    The relationship between isValid and settingIdentity can be explain by the
35    following life cycle of a cached item.
36  
37    Stage       1  2  3
38    ----------------------
39    isValid          F  T  T  
40    settingIdentity  X  T  F
41  
42    In Stage 1, the CachedItem is created but it is invalid and has an entry
43    that is just a holder object with no identity.
44  
45    In Stage 2, the identity has been set and the item is being created or
46    being faulted into the cache.
47  
48    In Stage 3, the item found in the CachedItem entry
49    </PRE> <P>
50    Remove is set if this item is being removed out of existance, not just
51    being evicted from the cache.  When the last referece to it release it from
52    the cache, it will be removed.
53    <BR>
54    RecentlyUsed is set whenever this item is accessed (via a keep() call).
55    It is reset by the clockHand as it sweeps around the cache looking for
56    victims to evict.
57  
58    <P>MT - must be MT-safe and work with cache manager.  Every method that
59    access (set or get) instance variables is synchronized on the cached item
60    object.  The following method waits so it should not be called by the cache
61    manager inside a sync block: clean(), waitFor(), create(), remove().
62    (RESOLVE: need to move these from the cache manager to here)
63  
64    @see org.apache.derby.impl.services.cache
65    @see Cacheable
66  */
67  public final class CachedItem {
68  
69    private static final int VALID            = 0x00000001;
70    private static final int REMOVE_REQUESTED = 0x00000002;
71    private static final int SETTING_IDENTITY = 0x00000004;
72    private static final int REMOVE_OK        = 0x00000008;
73  
74    private static final int RECENTLY_USED    = 0x00000010;
75  
76    /*
77    ** Fields
78    */
79  
80    /**
81      Does entry (the Cacheable) have an identity.
82  
83      <BR> MT - single thread required : synchronization provided by cache manager.
84    */
85    private int state;
86  
87    /**
88      The current keep count on the entry.
89  
90      <BR> MT - single thread required : synchronization provided by cache manager.
91  
92    */
93    private int  keepCount;
94  
95    /**
96      The Cacheable object being represented.
97  
98      <BR> Mutable - content dynamic
99    */
100   private Cacheable  entry;
101     
102   /**
103     Create a CachedItem in the not valid state.
104   */
105   public CachedItem() {
106   }
107 
108   /**
109     Keep the cached object after a search.
110 
111   */
112   public void keepAfterSearch() {
113     keepCount++;
114     setUsed(true);
115   }
116 
117   public void keepForCreate() {
118     if (SanityManager.DEBUG) {
119       SanityManager.ASSERT(!isKept());
120       SanityManager.ASSERT(!isValid());
121     }
122     keepCount = 1;
123     state |= SETTING_IDENTITY;
124   }
125 
126     public void unkeepForCreate( )
127     {
128         settingIdentityComplete();
129         unkeep();
130     }
131 
132   public void keepForClean() {
133     if (SanityManager.DEBUG) {
134       SanityManager.ASSERT(isValid());
135     }
136     keepCount++;
137   }
138 
139 
140 
141   /**
142     Unkeep the cached object.
143 
144     <P>MT - not synchronized, only modified single threaded by the cache manager
145 
146     @return if the object is still kept after this call. 
147   */
148   public synchronized boolean unkeep() {
149     boolean unkept = --keepCount == 0;
150 
151     if (SanityManager.DEBUG) {
152       SanityManager.ASSERT(keepCount >= 0);
153     }
154     return unkept && ((state & REMOVE_REQUESTED) != 0);
155   }
156 
157   /**
158     Is the cached object kept?
159 
160     <P>MT - not synchronized, only accessed single threaded by the cache manager
161   */
162   public final boolean isKept() {
163 
164     return keepCount != 0;
165   }
166 
167   /**
168     Clean the cached object
169 
170     <P>MT -    <BR>
171     The wait will not release the lock on the cache manager, so the
172     cache manager should not waitfor clean inside a sync block or
173     the whole cache will freeze
174 
175     @param forRemove if true, get rid of the backend persistent store object
176     @exception StandardException error thrown while writing cacheable
177     object to disk
178   */
179   public void clean(boolean forRemove) throws StandardException
180   {
181     entry.clean(forRemove);
182   }
183 
184   /**
185     Set the state of the to-be removed flag.
186   */
187   public synchronized void setRemoveState() {
188     state |= REMOVE_REQUESTED;
189   }
190 
191   /**
192     Does the cached object have a valid identity.
193   */
194   public final synchronized boolean isValid() {
195     return (state & VALID) != 0;
196   }
197 
198   /**
199     Set the valid state of the cached object.
200   */
201   public synchronized void setValidState(boolean flag) {
202 
203     if (flag)
204       state |= VALID;
205     else
206       state &= ~VALID;
207 
208     state &= ~(REMOVE_REQUESTED | REMOVE_OK);
209 
210     setUsed(flag);
211   }
212 
213   /**
214     Get the cached object.
215   */
216   public Cacheable getEntry() {
217     return entry;
218   }
219 
220   /**
221     Make entry (the Cacheable) take on a new identity.
222   */
223   public Cacheable takeOnIdentity(CacheManager cm, CacheableFactory holderFactory,
224     Object key, boolean forCreate, Object createParameter)
225     throws StandardException {
226 
227     // tell the object it needs to create itself
228     Cacheable oldEntry = entry;
229     if (oldEntry == null)
230       oldEntry = holderFactory.newCacheable(cm);
231 
232     if (forCreate) {
233       entry = oldEntry.createIdentity(key, createParameter);
234     } else {
235       entry = oldEntry.setIdentity(key);
236     }
237 
238     if (entry != null) {
239       // item was found or created
240       if (SanityManager.DEBUG) {
241         SanityManager.ASSERT(entry.getIdentity().equals(key));
242       }
243 
244       return entry;
245     }
246 
247     entry = oldEntry;
248     return null;
249   }
250 
251   public synchronized void settingIdentityComplete() {
252     // notify all waiters that this item has finished setting its identity,
253     // successfully or not.
254     state &= ~SETTING_IDENTITY;
255         
256     notifyAll();
257   }
258 
259   /**
260     Allow use of the cacheable entry. 
261   */
262 
263   public synchronized Cacheable use() throws StandardException {
264 
265     while ((state & SETTING_IDENTITY) != 0) {
266       try {
267         if (SanityManager.DEBUG) {
268           SanityManager.DEBUG("CacheTrace", 
269                         "trying to use a cached item that is taking on an identity");
270         }
271 
272         wait();
273 
274       } catch (InterruptedException ie) {
275         throw StandardException.interrupt(ie);
276       }
277     }
278 
279     // see if the setting of this identity failed ...
280     if (!isValid())
281       return null;
282 
283     if (SanityManager.DEBUG)
284         {
285             if (SanityManager.DEBUG_ON("CacheTrace"))
286                 SanityManager.DEBUG(
287                     "CacheTrace", "item keep count is " + keepCount);
288     }
289 
290 
291     return entry;
292   }
293 
294   /**
295   */
296   public void remove(boolean removeNow) throws StandardException {
297 
298     if (!removeNow) {
299 
300       synchronized (this) {
301         while ((state & REMOVE_OK) == 0) {
302           try {
303             wait();
304           } catch (InterruptedException ie) {
305             throw StandardException.interrupt(ie);
306           }
307         }
308       }
309     }
310     
311     clean(true);
312   }
313 
314   public synchronized void notifyRemover() {
315 
316     if (SanityManager.DEBUG) {
317       SanityManager.ASSERT((state & REMOVE_REQUESTED) != 0);
318       SanityManager.ASSERT(isKept());
319     }
320 
321     state |= REMOVE_OK;
322     notifyAll();
323   }
324 
325   /**
326     The clock hand has swept past this entry.
327   */
328   public synchronized void setUsed(boolean flag)
329   {
330     if (flag)
331       state |= RECENTLY_USED;
332     else
333       state &= ~RECENTLY_USED;
334   }
335 
336   /**
337     Has the cached object been referenced (kept) since the last sweep of
338     the clock hand?
339   */
340   public synchronized boolean recentlyUsed() {
341     return (state & RECENTLY_USED) != 0;
342   }
343 }
344 
345   
346