KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > cofax > CofaxCache


1 /*
2  * CofaxCache is part of the Cofax content management system library.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Please see http://www.cofax.org for contact information and other related informaion.
19  *
20  * $Header: /cvsroot/cofax/cofax/src/org/cofax/CofaxCache.java,v 1.10.2.1 2006/12/11 16:28:43 fxrobin Exp $
21  */

22
23 package org.cofax;
24
25 import java.util.*;
26
27 import org.cofax.CofaxUtil;
28
29 /**
30  * Provides caching services for Cofax.
31  *
32  * @author Rajiv Pant
33  * @author Karl Martino
34  * @author Sam Cohen
35  * @author Hung Dao
36  * @created April 19, 2002
37  */

38
39 public final class CofaxCache {
40
41     /** Used to store the last error */
42     private String JavaDoc lastError;
43
44     /** Hash to store cached and tracked pages */
45     private HashMap cacheHash = new HashMap();
46
47     /** Hash to store dirty cached pages */
48     private HashMap dirtyHash = new HashMap();
49
50     /** Maximum numer of URLs to keep a count for */
51     private int maxURLsToCount = 0;
52
53     /** Maximum numer of URLs to cache */
54     private int maxURLsToStore = 0;
55
56     /** Current lowest hit count of tracked items */
57     private int curLowTrack = 0;
58
59     /** Current lowest hit count of cached items */
60     private int curLowCache = 0;
61
62     /** Time interval to allow dirty cache reads after last build started */
63     private int dirtyReadTime = 0;
64
65     /** Current lowest hit URL of tracked items */
66     private String JavaDoc curLowTrackURL;
67
68     /** Current lowest hit URL of cached items */
69     private String JavaDoc curLowCacheURL;
70
71     /** The oldest URL being cached */
72     private String JavaDoc curOldCacheURL;
73
74     /** Time interval to refresh CofaxCache */
75     private long timeToRefresh = 0;
76
77     /** The number of times cache has been looked at */
78     private long cacheRequests = 0;
79
80     /** The number of times something has been pulled from cache */
81     private long cacheHits = 0;
82
83     /** The number of times something has been pulled from dirty cache */
84     private long dirtyHits = 0;
85
86     /** The curent number of items being cached */
87     private long curCacheCount = 0;
88
89     /** The current number of items being tracked */
90     private long curTrackCount = 0;
91
92     /** Time to die in cache */
93     private long cacheTimeToDie = 0;
94
95     /** Current age of oldest item in cache */
96     private long curOldCache = 0;
97
98     private Date clearedTimeTotal;
99
100     private Date maxTrackReached;
101
102     private Date maxStoreReached;
103
104     private boolean isMaxTrackReached;
105
106     private boolean isMaxStoreReached;
107
108     private boolean isCleaning = false; // FX : boolean to store the cleaning
109

110     // status
111

112     /**
113      * Provides Cofax with it's caching needs. Caches the most hit n number of
114      * pages out of the number being counted.
115      *
116      * @param maxUrlsToCount
117      * The total number of url's to track
118      * @param maxUrlsToCache
119      * The total number of url's to cache
120      * @param refreshCacheInterval
121      * The amount of time a cached URL is good before forcing a
122      * reload
123      * @param dirtyReadInterval
124      * The amount of time after a page is being built that will allow
125      * dirty cache hits.
126      */

127     public CofaxCache(int maxUrlsToCount, int maxUrlsToCache, int refreshCacheInterval, int dirtyReadInterval) {
128
129         this.maxURLsToCount = maxUrlsToCount;
130         this.maxURLsToStore = maxUrlsToCache;
131         this.timeToRefresh = refreshCacheInterval * CofaxUtil.MILLISECONDS_PER_MINUTE;
132         // 1 minute = 60 seconds x 1000 miliseconds
133
this.cacheTimeToDie = (refreshCacheInterval * CofaxUtil.MILLISECONDS_PER_MINUTE * 2);
134         // double the refresh time
135
this.dirtyReadTime = dirtyReadInterval * CofaxUtil.MILLISECONDS_PER_SECOND;
136         this.clearedTimeTotal = new Date();
137         this.isMaxTrackReached = false;
138         this.isMaxStoreReached = false;
139         this.isCleaning = false; // FX : default value;
140
}
141
142     /**
143      * Gets the trackedCount attribute of the CofaxCache object
144      *
145      * @return The trackedCount value
146      */

147     public long getTrackedCount() {
148         // returns the number of pages being tracked
149

150         return curTrackCount;
151     }
152
153     /**
154      * Gets the cachedCount attribute of the CofaxCache object
155      *
156      * @return The cachedCount value
157      */

158     public long getCachedCount() {
159         // returns the number of pages being cached
160

161         return curCacheCount;
162     }
163
164     /**
165      * Gets the maxTrack attribute of the CofaxCache object
166      *
167      * @return The maxTrack value
168      */

169     public int getMaxTrack() {
170         // return the maximum number of pages that will be tracked
171

172         return maxURLsToCount;
173     }
174
175     /**
176      * Sets the maxTrack attribute of the CofaxCache object
177      *
178      * @param inMaxURLsToCount
179      * The new maxTrack value
180      */

181     public void setMaxTrack(int inMaxURLsToCount) {
182
183         maxURLsToCount = inMaxURLsToCount;
184
185     }
186
187     /**
188      * Gets the maxStore attribute of the CofaxCache object
189      *
190      * @return The maxStore value
191      */

192     public int getMaxStore() {
193         // returns the maximum number of pages that will be cached
194

195         return maxURLsToStore;
196     }
197
198     /**
199      * Sets the maxStore attribute of the CofaxCache object
200      *
201      * @param inMaxURLsToStore
202      * The new maxStore value
203      */

204     public void setMaxStore(int inMaxURLsToStore) {
205
206         maxURLsToStore = inMaxURLsToStore;
207
208     }
209
210     /**
211      * Gets the refreshInterval attribute of the CofaxCache object
212      *
213      * @return The refreshInterval value
214      */

215     public long getRefreshInterval() {
216         // returns the amount of time before a page will be fored to reload in
217
// cache
218

219         return timeToRefresh;
220     }
221
222     /**
223      * Sets the refreshInterval attribute of the CofaxCache object
224      *
225      * @param inTimeToRefresh
226      * The new refreshInterval value
227      */

228     public void setRefreshInterval(int inTimeToRefresh) {
229
230         timeToRefresh = inTimeToRefresh;
231
232     }
233
234     /**
235      * Gets the dirtyRead attribute of the CofaxCache object
236      *
237      * @return The dirtyRead value
238      */

239     public int getDirtyRead() {
240
241         return dirtyReadTime;
242     }
243
244     /**
245      * Sets the dirtyRead attribute of the CofaxCache object
246      *
247      * @param inDirtyRead
248      * The new dirtyRead value
249      */

250     public void setDirtyRead(int inDirtyRead) {
251
252         dirtyReadTime = inDirtyRead;
253
254     }
255
256     /**
257      * Gets the cacheHash attribute of the CofaxCache object
258      *
259      * @return The cacheHash value
260      */

261     public HashMap getCacheHash() {
262         // returns the whole cache pages hash table ??? sam asks why would you
263
// do this?
264

265         return cacheHash;
266     }
267
268     /**
269      * Gets the clearedTimeTotal attribute of the CofaxCache object
270      *
271      * @return The clearedTimeTotal value
272      */

273     public Date getClearedTimeTotal() {
274
275         return clearedTimeTotal;
276     }
277
278     /**
279      * Gets the cacheRequests attribute of the CofaxCache object
280      *
281      * @return The cacheRequests value
282      */

283     public long getCacheRequests() {
284
285         return cacheRequests;
286     }
287
288     /**
289      * Gets the cacheHits attribute of the CofaxCache object
290      *
291      * @return The cacheHits value
292      */

293     public long getCacheHits() {
294
295         return cacheHits;
296     }
297
298     /**
299      * Gets the dirtyCacheHits attribute of the CofaxCache object
300      *
301      * @return The dirtyCacheHits value
302      */

303     public long getDirtyCacheHits() {
304
305         return dirtyHits;
306     }
307
308     /**
309      * Gets the maxTrackReached attribute of the CofaxCache object
310      *
311      * @return The maxTrackReached value
312      */

313     public Date getMaxTrackReached() {
314
315         return maxTrackReached;
316     }
317
318     /**
319      * Gets the maxStoreReached attribute of the CofaxCache object
320      *
321      * @return The maxStoreReached value
322      */

323     public Date getMaxStoreReached() {
324
325         return maxStoreReached;
326     }
327
328     /**
329      * Gets the isMaxTrackReached attribute of the CofaxCache object
330      *
331      * @return The isMaxTrackReached value
332      */

333     public boolean getIsMaxTrackReached() {
334
335         return isMaxTrackReached;
336     }
337
338     /**
339      * Gets the isMaxStoreReached attribute of the CofaxCache object
340      *
341      * @return The isMaxStoreReached value
342      */

343     public boolean getIsMaxStoreReached() {
344
345         return isMaxStoreReached;
346     }
347
348     /**
349      * Gets the maxTrackTurnOver attribute of the CofaxCache object
350      *
351      * @return The maxTrackTurnOver value
352      */

353     public int getMaxTrackTurnOver() {
354
355         return 0;
356         // return maxTrackTurnOver ;
357

358     }
359
360     /**
361      * Removes all items from cache and tracking.
362      */

363     public synchronized void clear() {
364         // removes all items for cache and tracking hash tables
365

366         this.cacheHash.clear();
367         this.curCacheCount = 0;
368         this.curTrackCount = 0;
369         clearedTimeTotal = new Date();
370         isMaxStoreReached = false;
371         isMaxTrackReached = false;
372
373     }
374
375     /**
376      * Determines if the passed in url is a page which is stored in cache
377      * already and if the page is stored that it will be returned from memory.
378      * If the page is stored but is too old it will be removed from memory.
379      * Either way the number of times this particular page has been requested
380      * will be incremented. Args: id - a string URL that will identify this page
381      * Revision History: 9/25/2001- Sam Cohen - Added dirty read functionality,
382      * this will let first request for expired page place the page in a dirty
383      * cache then allow other threads to read from the dirty cache while the 1st
384      * builds the page.
385      *
386      * @param id
387      * A string URL that will identify this page.
388      * @return True if the page is is in cache and can be returned, false if the
389      * page is not in memory or needed to be refreshed.
390      */

391     public synchronized boolean isPageCached(String JavaDoc id) {
392
393         CofaxPage page = new CofaxPage();
394         long curTime = new Date().getTime();
395         // current system miliseconds
396
cacheRequests++;
397         // increment the total requests counter
398

399         if (cacheHash.containsKey(id)) {
400             // if the page is being tracked
401
if (cacheHash.get(id) instanceof CofaxPage) {
402                 page = (CofaxPage) cacheHash.get(id);
403                 // load the page from the hash table
404
if (page.isPageCached()) {
405                     // if the page is in cache
406
if ((curTime - page.getLastModified()) < timeToRefresh) {
407                         // if the page is new enough
408
return true;
409                     } else {
410                         // else the page is too old so remove it, but keep
411
// tracking it
412
Integer JavaDoc x = new Integer JavaDoc(page.getHitCount());
413                         this.removeFromCache(id);
414                         if (curTrackCount >= maxURLsToCount) {
415                             // if we dont have room make some
416
this.dumpLowestTrackedHitCount();
417                         }
418                         this.addPageToCache(id, x);
419                         page.setStartBuildTime();
420                         // let others know that someone else is about to build
421
// this page
422
this.dirtyHash.put(id, page);
423                     }
424                 }
425             } else if (isPageDirtyCached(id)) {
426                 return true;
427             }
428         } else if (isPageDirtyCached(id)) {
429             return true;
430         }
431         return false;
432         // page was not in or expired
433

434     }
435
436     /**
437      * Determines if the passed in url is a page which is stored in dirty cache
438      * and if it is new enough to return. Args: id - Returns: true - if the page
439      * is in dirty cache and is fresh enough to be returned from memory false -
440      * if the page is not in dirty cache or is too old Author: Sam Cohen
441      * Created: 9/24/2001 Revision History:
442      *
443      * @param id
444      * A string URL that will identify this page
445      * @return True, if the page is in dirty cache and is fresh enough to be
446      * returned from memory, false if the page is not in dirty cache or
447      * is too old.
448      */

449     public synchronized boolean isPageDirtyCached(String JavaDoc id) {
450
451         if (dirtyHash.containsKey(id)) {
452             CofaxPage page = new CofaxPage();
453             page = (CofaxPage) dirtyHash.get(id);
454             // load the page from the hash table
455
long curTime = new Date().getTime();
456             // current system miliseconds
457
if ((curTime - page.getStartBuildTime()) < dirtyReadTime) {
458                 // if the page is beig built by someone else
459
return true;
460             }
461         }
462         return false;
463     }
464
465     /**
466      * Clears a cached page out of the cache hash table. Author: Sam Cohen
467      * Created: 6/28/2001 Revision History:
468      *
469      * @param id
470      * A string URL that will identify the page
471      * @return True if the page was removed, false if the page was not removed
472      */

473     public synchronized boolean removeFromCache(String JavaDoc id) {
474
475         if (cacheHash.containsKey(id)) {
476             // if the object is currently being cached or tracked
477
if (cacheHash.get(id) instanceof CofaxPage) {
478                 this.curCacheCount--;
479             } else if (cacheHash.get(id) instanceof Integer JavaDoc) {
480                 this.curTrackCount--;
481             }
482             cacheHash.remove(id);
483             this.generateLowTrackCount();
484             this.generateLowCacheCount();
485             this.generateOldCache();
486             return (true);
487         }
488         return false;
489     }
490
491     /**
492      * Forces the page to be expired in 1 minute. This semi-hack is desinged for
493      * the tools to call and to allow for replication to take place in the db's
494      * then have cached items update 1 minute later. "Don't ask don't tell"
495      * policy in effect here -SAC Author: Sam Cohen Created: 9/24/2001 Revision
496      * History:
497      *
498      * @param id
499      * A string URL that will identify the page.
500      * @return True if the page was set to expire, false if the page could not
501      * be set.
502      */

503     public synchronized boolean expireInCache(String JavaDoc id) {
504
505         if (cacheHash.containsKey(id)) {
506             // if the object is currently being cached or tracked
507
if (cacheHash.get(id) instanceof CofaxPage) {
508                 CofaxPage page = (CofaxPage) cacheHash.get(id);
509                 Date curDate = new Date();
510                 long expInOneMinute = curDate.getTime() - timeToRefresh + CofaxUtil.MILLISECONDS_PER_MINUTE;
511                 page.setLastModified(expInOneMinute);
512                 page.setPageCached(true);
513                 page.setCachedTime(expInOneMinute);
514                 return (true);
515             }
516         }
517         return (false);
518     }
519
520     /**
521      * Prints to standard out the current statistics of the cache.
522      */

523     private void printStats() {
524
525         long fOldCAge = curOldCache / CofaxUtil.MILLISECONDS_PER_MINUTE;
526         System.out.println("Cache Stats:");
527         System.out.println(" Current Cached Pages: " + curCacheCount + " Max to cache: " + maxURLsToStore);
528         System.out.println(" Current Tracked Pages: " + curTrackCount + " Max to track: " + maxURLsToCount);
529         System.out.println(" Current Low Cache hits: " + curLowCache + " page: " + curLowCacheURL);
530         System.out.println(" Current Low Tracked hits: " + curLowTrack + " page: " + curLowTrackURL);
531         System.out.println(" Current Oldest Cache Age: " + fOldCAge + " page: " + curOldCacheURL);
532
533     }
534
535     /**
536      * Increments the hit count of a page object in the cache hash table.
537      * Author: Sam Cohen Created: 6/28/2001 Revision History:
538      *
539      * @param id
540      * A string URL that will identify the page.
541      * @return True if the page count was incremented, false if the page count
542      * was not incremented.
543      */

544     public synchronized boolean incrementHitCount(String JavaDoc id) {
545
546         boolean toReturn = false;
547         CofaxPage curPage = new CofaxPage();
548
549         if (cacheHash.containsKey(id)) {
550             if (cacheHash.get(id) instanceof CofaxPage) {
551                 curPage = (CofaxPage) cacheHash.get(id);
552                 curPage.incrementHitCount();
553                 toReturn = true;
554             } else if (cacheHash.get(id) instanceof Integer JavaDoc) {
555                 Integer JavaDoc x = new Integer JavaDoc(0);
556                 x = (Integer JavaDoc) cacheHash.get(id);
557                 int y = x.intValue();
558                 y++;
559                 x = new Integer JavaDoc(y);
560                 cacheHash.put(id, x);
561                 toReturn = true;
562             }
563             // if the URL we are incrementing is one of our lowest ones the
564
// re-run the low generator
565
if (id.equals(curLowTrackURL)) {
566                 this.generateLowTrackCount();
567             }
568
569             if (id.equals(curLowCacheURL)) {
570                 this.generateLowCacheCount();
571             }
572         }
573         return toReturn;
574     }
575
576     /**
577      * Removes the url from the tracked hash table which has been hit the least
578      * number of times. Author: Sam Cohen Created: 6/28/2001 Revision History:
579      *
580      * @return True if a url was removed, false if a url was not removed.
581      */

582     private boolean dumpLowestTrackedHitCount() {
583
584         if (curTrackCount == 0) {
585             return false;
586         }
587
588         this.removeFromCache(curLowTrackURL);
589         return true;
590     }
591
592     /**
593      * Returns the hit count of a page in the cache hash table. Author: Sam
594      * Cohen Created: 6/28/2001 Revision History:
595      *
596      * @param id
597      * A string URL that will identify the page.
598      * @return The hit count of the page or -1 if page not found or error.
599      */

600     public int getHitCount(String JavaDoc id) {
601
602         if (cacheHash.containsKey(id)) {
603             if (cacheHash.get(id) instanceof CofaxPage) {
604                 CofaxPage testPage = new CofaxPage();
605                 testPage = (CofaxPage) cacheHash.get(id);
606                 return testPage.getHitCount();
607             } else if (cacheHash.get(id) instanceof Integer JavaDoc) {
608                 Integer JavaDoc x = new Integer JavaDoc(0);
609                 x = (Integer JavaDoc) cacheHash.get(id);
610                 return x.intValue();
611             }
612         }
613         return -1;
614     }
615
616     /**
617      * Takes a CofaxPage item and places it in the cacheHash. Author: Sam Cohen
618      * Created: 6/28/2001 Revision History:
619      *
620      * @param id
621      * A string URL that will identify the page.
622      * @param item
623      * The CofaxPage to add to cache,
624      * @param hitCount
625      * The number of times this page has been hit.
626      * @return True, if the the page was added, false if the page was not added.
627      */

628     private synchronized boolean placePageInCache(String JavaDoc id, Object JavaDoc item, int hitCount) {
629
630         try {
631             Date curDate = new Date();
632             CofaxPage page = new CofaxPage();
633             page = (CofaxPage) item;
634             page.setLastModified(curDate.getTime());
635             page.setPageCached(true);
636             page.setCachedTime(curDate.getTime());
637             page.setHitCount(hitCount);
638             this.cacheHash.put(id, page);
639             this.curCacheCount++;
640             this.generateLowTrackCount();
641             this.generateLowCacheCount();
642             return true;
643         } catch (Exception JavaDoc e) {
644             lastError = e.toString();
645             return false;
646         }
647
648     }
649
650     /**
651      * Takes an integer and places it and its url into tracking Args: item -
652      * Integer representing the number of time the url has been hit Returns:
653      * true - the the url was added false - if the url was not added Author: Sam
654      * Cohen Created: 6/28/2001 Revisions:
655      *
656      * @param id
657      * A string URL that will identify the page
658      * @param item
659      * Integer representing the number of time the url has been hit.
660      * @return True, the the url was added, false if the url was not added.
661      */

662     private synchronized boolean placeTrackInCache(String JavaDoc id, Object JavaDoc item) {
663
664         try {
665             this.cacheHash.put(id, item);
666             this.curTrackCount++;
667             this.generateLowTrackCount();
668             return true;
669         } catch (Exception JavaDoc e) {
670             lastError = e.toString();
671             return false;
672         }
673
674     }
675
676     /**
677      * Adds a new page to the cache hash table. Notes: this function can be
678      * passed a CofaxPage or an Integer if we are passed a CofaxPage then we
679      * want to cache it if we get an integer then we are just tracking the url
680      * for now Author: Sam Cohen Created: 6/28/2001 Revision History: 9/25/2001-
681      * Added the remove from diryHash line to clear out anything that was
682      * temporarily being stored in diry cache
683      *
684      * @param id
685      * A string URL that will identify the page item.
686      * @param item
687      * Either a page to cache or a hit count to start.
688      * @return True if the new page was added to the hash table, false if the
689      * new page was not.
690      */

691     public synchronized boolean addPageToCache(String JavaDoc id, Object JavaDoc item) {
692
693         try {
694             if (cacheHash.containsKey(id)) {
695                 // is this page already being tracked or cached?
696
if (cacheHash.get(id) instanceof Integer JavaDoc) {
697                     // are we tracking this page?
698
Integer JavaDoc x = new Integer JavaDoc(0);
699                     x = (Integer JavaDoc) cacheHash.get(id);
700                     this.removeFromCache(id);
701                     // lets get rid of it, so counters get updated
702
if (item instanceof CofaxPage) {
703                         this.placePageInCache(id, item, x.intValue());
704                     } else if (item instanceof Integer JavaDoc) {
705                         this.placeTrackInCache(id, item);
706                     }
707                 } else if (cacheHash.get(id) instanceof CofaxPage) {
708                     // is this already cached? dont ask dont tell
709
this.removeFromCache(id);
710                     // lets get rid of it, so counters get updated
711
if (item instanceof CofaxPage) {
712                         this.placePageInCache(id, item, 1);
713                     } else if (item instanceof Integer JavaDoc) {
714                         this.placeTrackInCache(id, item);
715                     }
716                 }
717             } else {
718                 // the page is not being tracked or cached
719
if (item instanceof CofaxPage) {
720                     this.placePageInCache(id, item, 1);
721                 } else if (item instanceof Integer JavaDoc) {
722                     this.placeTrackInCache(id, item);
723                 }
724             }
725         } catch (Exception JavaDoc e) {
726             lastError = e.toString();
727             return false;
728         }
729         this.dirtyHash.remove(id);
730         this.generateOldCache();
731         return true;
732     }
733
734     /**
735      * Removes all pages from cache whos urls match the passed in url. Author:
736      * Sam Cohen Created: 6/28/2001 Revision History:
737      *
738      * @param partialUrl
739      * A string representing a url or partial URL.
740      * @return The list of URLs which were removed
741      */

742     public synchronized ArrayList removeByPartialUrl(String JavaDoc partialUrl) {
743
744         ArrayList list = new ArrayList();
745
746         for (Iterator i = cacheHash.keySet().iterator(); i.hasNext();) {
747             String JavaDoc url = (String JavaDoc) i.next();
748             if (url.indexOf(partialUrl) > -1) {
749                 this.removeFromCache(url);
750                 list.add(url);
751             }
752         }
753         return list;
754     }
755
756     /**
757      * Expires all pages from cache whos urls match the passed in url. Author:
758      * Sam Cohen Created: 9/24/2001 Revision History:
759      *
760      * @param partialUrl
761      * A string representing a url or partial URL.
762      * @return The list of URLs which were removed.
763      */

764     public synchronized ArrayList expireByPartialUrl(String JavaDoc partialUrl) {
765
766         ArrayList list = new ArrayList();
767
768         for (Iterator i = cacheHash.keySet().iterator(); i.hasNext();) {
769             String JavaDoc url = (String JavaDoc) i.next();
770             if (url.indexOf(partialUrl) > -1) {
771                 this.expireInCache(url);
772                 list.add(url);
773             }
774         }
775         return list;
776     }
777
778     /**
779      * Returns a page from the cache hash table. Author: Sam Cohen Created:
780      * 6/28/2001 Revision History: 9/25/2001- Added function to return a dirty
781      * page if there 20/10/2005 - FX: adding synchronized header.
782      *
783      * @param id
784      * A string URL that will identify the page.
785      * @return The page dentified by id.
786      */

787     public synchronized CofaxPage getPage(String JavaDoc id) {
788         // fx: getting the page only once
789
Object JavaDoc _o = cacheHash.get(id);
790         CofaxPage _p = null;
791
792         if (_o instanceof CofaxPage)
793             _p = (CofaxPage) _o;
794
795         if (_p != null) {
796             cacheHits++;
797             return _p;
798         } else {
799             _o = dirtyHash.get(id);
800             if (_o instanceof CofaxPage)
801                 _p = (CofaxPage) _o;
802             if (_p != null) {
803                 dirtyHits++;
804                 return _p;
805             } else {
806                 // return (CofaxPage) new CofaxPage();
807
return null; // FX : instead of returning a blank page.
808
}
809         }
810
811     }
812
813     /**
814      * Removes least hit URL from cache hash. Author: Sam Cohen Created:
815      * 6/28/2001 Revision History:
816      *
817      * @return True if the page was removed, false if the the page could not be
818      * removed.
819      */

820     private synchronized boolean dumpLowestCachedURL() {
821
822         String JavaDoc uHold = curLowCacheURL;
823         Integer JavaDoc cHold = new Integer JavaDoc(curLowCache);
824         this.removeFromCache(curLowCacheURL);
825         if (curTrackCount < maxURLsToCount) {
826             // is there still room to track this
827
this.addPageToCache(uHold, cHold);
828         }
829         this.generateOldCache();
830         return true;
831     }
832
833     /**
834      * Removes oldest URL from cache hash. Author: Sam Cohen Created: 7/10/2001
835      * Revision History:
836      *
837      * @return True if the page was removed, false if the the page could not be
838      * removed.
839      */

840     private synchronized boolean dumpOldestCachedURL() {
841
842         CofaxPage lPage = new CofaxPage();
843         String JavaDoc uHold = curOldCacheURL;
844         Integer JavaDoc cHold;
845
846         if (this.cacheHash.containsKey(uHold)) {
847             lPage = (CofaxPage) this.cacheHash.get(uHold);
848             cHold = new Integer JavaDoc(lPage.getHitCount());
849         } else {
850             cHold = new Integer JavaDoc(1);
851         }
852         this.removeFromCache(curOldCacheURL);
853         if (curTrackCount < maxURLsToCount) {
854             // is there still room to track this
855
this.addPageToCache(uHold, cHold);
856         }
857         return true;
858     }
859
860     /**
861      * Decides if a given url should be stored in the cache. Author: Sam Cohen
862      * Created: 6/28/2001 Revision History:
863      *
864      * @param id
865      * A string URL that will identify the page.
866      * @return True if the url in question should be cached, false if the url in
867      * question should not be cached.
868      */

869     public synchronized boolean shouldPageBeCached(String JavaDoc id) {
870
871         try {
872             CofaxPage testPage = new CofaxPage();
873             if (cacheHash.containsKey(id)) {
874                 // is the page already being tracked or cached
875
if (cacheHash.get(id) instanceof CofaxPage) {
876                     // is it cached?
877
testPage = (CofaxPage) cacheHash.get(id);
878                     if (testPage.isPageCached()) {
879                         return false;
880                     }
881                 } else if (cacheHash.get(id) instanceof Integer JavaDoc) {
882                     // is it being tracked?
883
Integer JavaDoc x = new Integer JavaDoc(0);
884                     x = (Integer JavaDoc) cacheHash.get(id);
885                     if (curCacheCount < maxURLsToStore) {
886                         // should we cache because we have room
887
return true;
888                     } else if (x.intValue() > curLowCache) {
889                         // should we cache because this is more popular
890
this.dumpLowestCachedURL();
891                         return true;
892                     } else if (this.curOldCache > this.cacheTimeToDie) {
893                         // should we cache because something is too old
894
this.dumpOldestCachedURL();
895                         return true;
896                     }
897                 }
898             } else {
899                 // it is not yet being tracked or cached
900
if (curCacheCount < maxURLsToStore) {
901                     // should we cache because we have room?
902
return true;
903                 } else if (this.curOldCache > this.cacheTimeToDie) {
904                     // should we cache because something is too old
905
this.dumpOldestCachedURL();
906                     return true;
907                 } else {
908                     // we will track this url
909
if (curTrackCount < maxURLsToCount) {
910                         // if we have room then add to track
911
this.addPageToCache(id, new Integer JavaDoc(1));
912                     } else {
913                         // dump the lowest tracked page
914
this.dumpLowestTrackedHitCount();
915                         this.addPageToCache(id, new Integer JavaDoc(1));
916                     }
917                     return false;
918                 }
919             }
920         } catch (Exception JavaDoc e) {
921             lastError = e.toString();
922             return false;
923         }
924         return false;
925     }
926
927     /**
928      * Returns the total number of hits for all the URLs being tracked. Author:
929      * Sam Cohen Created: 6/28/2001 Revision History:
930      *
931      * @return The total number of hits to all URLs being tracked.
932      */

933     public int getTrackedTotal() {
934
935         Iterator URLs = cacheHash.keySet().iterator();
936         String JavaDoc url;
937         Integer JavaDoc x;
938         Integer JavaDoc y;
939         int totalCount = 0;
940         CofaxPage loopPage = new CofaxPage();
941
942         while (URLs.hasNext()) {
943             url = (String JavaDoc) URLs.next();
944             if (cacheHash.get(url) instanceof Integer JavaDoc) {
945                 x = (Integer JavaDoc) cacheHash.get(url);
946             } else {
947                 loopPage = (CofaxPage) cacheHash.get(url);
948                 y = new Integer JavaDoc(loopPage.getHitCount());
949                 x = y;
950             }
951             totalCount += x.intValue();
952         }
953         return totalCount;
954     }
955
956     /**
957      * Re-calculates the current lowest hit url being tracked. Author: Sam Cohen
958      * Created: 6/28/2001 Revision History:
959      *
960      * @return True if the re-calc works, false if the re-calc fails.
961      */

962     private synchronized boolean generateLowTrackCount() {
963
964         Iterator URLs = cacheHash.keySet().iterator();
965         String JavaDoc url;
966         String JavaDoc lUrl = "";
967         Integer JavaDoc x;
968         int lCount = -1;
969         boolean gotLow = false;
970
971         if (curTrackCount == 0) {
972             return false;
973         }
974
975         while (URLs.hasNext()) {
976             url = (String JavaDoc) URLs.next();
977             if (cacheHash.get(url) instanceof Integer JavaDoc) {
978                 x = (Integer JavaDoc) cacheHash.get(url);
979                 if (x.intValue() < lCount || lCount == -1) {
980                     lCount = x.intValue();
981                     lUrl = url;
982                     gotLow = true;
983                 }
984             }
985         }
986         if (gotLow) {
987             curLowTrack = lCount;
988             curLowTrackURL = lUrl;
989             return true;
990         } else {
991             return false;
992         }
993
994     }
995
996     /**
997      * Re-calculates the current lowest hit url being cached. Author: Sam Cohen
998      * Created: 6/28/2001 Revision History:
999      *
1000     * @return True if the re-calc works, false if the the re-calc fails.
1001     */

1002    private synchronized boolean generateLowCacheCount() {
1003
1004        Iterator URLs = cacheHash.keySet().iterator();
1005        String JavaDoc url;
1006        String JavaDoc lUrl = "";
1007        Integer JavaDoc x;
1008        int lCount = -1;
1009        boolean gotLow = false;
1010        CofaxPage lPage = new CofaxPage();
1011
1012        if (curCacheCount == 0) {
1013            return false;
1014        }
1015
1016        while (URLs.hasNext()) {
1017            url = (String JavaDoc) URLs.next();
1018            if (cacheHash.get(url) instanceof CofaxPage) {
1019                lPage = (CofaxPage) cacheHash.get(url);
1020                if (lPage.getHitCount() < lCount || lCount == -1) {
1021                    lCount = lPage.getHitCount();
1022                    lUrl = url;
1023                    gotLow = true;
1024                }
1025            }
1026        }
1027        if (gotLow) {
1028            this.curLowCache = lCount;
1029            this.curLowCacheURL = lUrl;
1030            return true;
1031        } else {
1032            return false;
1033        }
1034
1035    }
1036
1037    /**
1038     * Re-calculates the current oldest url being cached. Author: Sam Cohen
1039     * Created: 7/10/2001 Revision History:
1040     *
1041     * @return True if the re-calc works, false if the the re-calc fails.
1042     */

1043    private synchronized boolean generateOldCache() {
1044
1045        Iterator URLs = cacheHash.keySet().iterator();
1046        String JavaDoc url = "";
1047        String JavaDoc lUrl = "";
1048        long lCount = -1;
1049        boolean gotOld = false;
1050        CofaxPage lPage = new CofaxPage();
1051
1052        if (curCacheCount == 0) {
1053            return false;
1054        }
1055
1056        Date currDate = new Date();
1057        long currSecs = currDate.getTime();
1058        long cacheAge = 0;
1059        long cachedTime = 0;
1060
1061        while (URLs.hasNext()) {
1062            url = (String JavaDoc) URLs.next();
1063            if (cacheHash.get(url) instanceof CofaxPage) {
1064                lPage = (CofaxPage) cacheHash.get(url);
1065                cachedTime = lPage.getLastModified();
1066                cacheAge = currSecs - cachedTime;
1067                if (cacheAge > lCount || lCount == -1) {
1068                    lCount = cacheAge;
1069                    lUrl = url;
1070                    gotOld = true;
1071                }
1072            }
1073        }
1074        if (gotOld) {
1075            this.curOldCache = lCount;
1076            this.curOldCacheURL = lUrl;
1077            return true;
1078        } else {
1079            return false;
1080        }
1081
1082    }
1083
1084    /**
1085     * Returns configuration data for this Cache object
1086     */

1087    public String JavaDoc toString() {
1088        return "Instance Of: " + getClass().getName() + "\n" + "maxURLsToCount: " + maxURLsToCount + "\n" + "maxUrlsToStore: " + maxURLsToStore + "\n"
1089                + "timeToRefresh: " + timeToRefresh + "\n" + "cacheTimeToDie: " + cacheTimeToDie + "\n" + "dirtyReadTime: " + dirtyReadTime;
1090    }
1091
1092    // FX : cleaning the cache with old pages
1093
// this method ONLY remove the content date of a page but does not remove
1094
// the entry of the page in the cache
1095
// this makes free memory in the JVM.
1096
public synchronized boolean CleanIfPossible() {
1097        // org.cofax.cds.CDSServlet.cofaxLog("Should I clean ?");
1098
if (isCleaning) {
1099            // org.cofax.cds.CDSServlet.cofaxLog("don't clean");
1100
return false; // already cleaning in another thread;
1101
}
1102
1103        isCleaning = true;
1104        // org.cofax.cds.CDSServlet.cofaxLog("Starting cleaning cache ...");
1105

1106        try {
1107            HashMap _pages = getCacheHash();
1108            Iterator objects = _pages.keySet().iterator();
1109
1110            long curTime = System.currentTimeMillis();
1111            // org.cofax.cds.CDSServlet.cofaxLog("Number of pages to scan :
1112
// "+_pages.size());
1113

1114            // display all the cached pages
1115

1116            while (objects.hasNext()) {
1117                String JavaDoc id = (String JavaDoc) objects.next();
1118                if (_pages.get(id) instanceof CofaxPage) {
1119                    // if we are dealing with a cached page
1120
CofaxPage _p = (CofaxPage) _pages.get(id);
1121                    if (_p != null && _p.getContentsLength() > 0 && (curTime - _p.getLastModified()) > timeToRefresh) {
1122                        // if the page is too old enough, resetting the data
1123
_p.reset();
1124                        org.cofax.cds.CDSServlet.cofaxLog("Cleaning this page : " + _p.getPageId());
1125                    }
1126                }
1127            }
1128        } catch (Exception JavaDoc ex) {
1129            org.cofax.cds.CDSServlet.cofaxLog("Error while cleaning : " + ex);
1130        }
1131
1132        isCleaning = false; // releasing the flag.
1133
// org.cofax.cds.CDSServlet.cofaxLog("Cleaning done");
1134
return true;
1135    }
1136
1137}
1138
Popular Tags