KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > cache > CacheManager


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tc.object.cache;
6
7 import com.tc.logging.TCLogger;
8 import com.tc.logging.TCLogging;
9 import com.tc.runtime.MemoryEventType;
10 import com.tc.runtime.MemoryEventsListener;
11 import com.tc.runtime.MemoryUsage;
12 import com.tc.runtime.TCMemoryManagerImpl;
13 import com.tc.util.Assert;
14 import com.tc.util.State;
15
16 import java.util.List JavaDoc;
17
18 public class CacheManager implements MemoryEventsListener {
19
20   private static final TCLogger logger = TCLogging.getLogger(CacheManager.class);
21
22   private static final State INIT = new State("INIT");
23   private static final State PROCESSING = new State("PROCESSING");
24   private static final State COMPLETE = new State("COMPLETE");
25
26   private final Evictable evictable;
27   private final CacheConfig config;
28   private final TCMemoryManagerImpl memoryManager;
29
30   private int calculatedCacheSize = 0;
31   private CacheStatistics lastStat = null;
32
33   public CacheManager(Evictable evictable, CacheConfig config) {
34     this.evictable = evictable;
35     this.config = config;
36     this.memoryManager = new TCMemoryManagerImpl(config.getUsedThreshold(), config.getUsedCriticalThreshold(), config
37         .getSleepInterval(), config.getLeastCount(), config.isOnlyOldGenMonitored());
38     this.memoryManager.registerForMemoryEvents(this);
39   }
40
41   public void memoryUsed(MemoryEventType type, MemoryUsage usage) {
42     CacheStatistics cp = new CacheStatistics(type, usage);
43     evictable.evictCache(cp);
44     cp.validate();
45     addLastStat(cp);
46   }
47
48   // currently we only maintain 1 last stat
49
private void addLastStat(CacheStatistics cp) {
50     this.lastStat = cp;
51   }
52
53   private final class CacheStatistics implements CacheStats {
54     private final MemoryEventType type;
55     private final MemoryUsage usage;
56
57     private int countBefore;
58     private int countAfter;
59     private int evicted;
60     private boolean objectsGCed = false;
61     private int toEvict;
62     private long startTime;
63     private State state = INIT;
64
65     public CacheStatistics(MemoryEventType type, MemoryUsage usage) {
66       this.type = type;
67       this.usage = usage;
68     }
69
70     public void validate() {
71       if (state == PROCESSING) {
72         // This might be ignored by the memory manager thread. TODO:: exit VM !!!
73
throw new AssertionError JavaDoc(this + " : Object Evicted is not called. This indicates a bug in the software !");
74       }
75     }
76
77     public int getObjectCountToEvict(int currentCount) {
78       startTime = System.currentTimeMillis();
79       countBefore = currentCount;
80       adjustCachedObjectCount(currentCount);
81       toEvict = computeObjects2Evict(currentCount);
82       if (toEvict < 0 || toEvict > currentCount) {
83         //
84
throw new AssertionError JavaDoc("Computed Object to evict is out of range : toEvict = " + toEvict + " currentCount = "
85                                  + currentCount + " " + this);
86       }
87       if (toEvict > 0) {
88         state = PROCESSING;
89       }
90       if (config.isLoggingEnabled()) {
91         logger.info("Asking to evict " + toEvict + " current size = " + currentCount + " calculated cache size = "
92                     + calculatedCacheSize + " heap used = " + usage.getUsedPercentage() + " % gc count = "
93                     + usage.getCollectionCount());
94       }
95       return this.toEvict;
96     }
97
98     //
99
// We recalibrate the calculatedCacheSize based on the current known details if one of the following is true.
100
// 0) Usage goes below threshold or
101
// 1) This is the first threshold crossing alarm or
102
// 2) A GC has taken place since the last time (we either base in on the collection count which is accurate in 1.5
103
// or in 1.4 we check to see if the usedMemory has gone down which is an indication of gc (not foolprove though)
104
//
105
private void adjustCachedObjectCount(int currentCount) {
106       if (type == MemoryEventType.BELOW_THRESHOLD || lastStat == null
107           || lastStat.usage.getCollectionCount() < usage.getCollectionCount()
108           || (usage.getCollectionCount() < 0 && lastStat.usage.getUsedMemory() > usage.getUsedMemory())) {
109         double used = usage.getUsedPercentage();
110         double threshold = config.getUsedThreshold();
111         Assert.assertTrue((type == MemoryEventType.BELOW_THRESHOLD && threshold >= used) || threshold <= used);
112         if (used > 0) calculatedCacheSize = (int) (currentCount * (threshold / used));
113       }
114     }
115
116     public void objectEvicted(int evictedCount, int currentCount, List JavaDoc targetObjects4GC) {
117       this.evicted = evictedCount;
118       this.countAfter = currentCount;
119       state = COMPLETE;
120       // TODO:: add reference queue
121
if (config.isLoggingEnabled()) {
122         logger.info("Evicted " + evictedCount + " current Size = " + currentCount + " new objects created = "
123                     + getNewObjectsCount() + " time taken = " + (System.currentTimeMillis() - startTime) + " ms");
124       }
125     }
126
127     private int getNewObjectsCount() {
128       return countAfter - (countBefore - evicted);
129     }
130
131     // TODO:: This need to be more intellegent. It should also check if a GC actually happened after eviction. Use
132
// Reference Queue
133
private int computeObjects2Evict(int currentCount) {
134       if (type == MemoryEventType.BELOW_THRESHOLD || calculatedCacheSize > currentCount) { return 0; }
135       int overshoot = currentCount - calculatedCacheSize;
136       if (overshoot <= 0) return 0;
137       int objects2Evict = overshoot + ((calculatedCacheSize * config.getPercentageToEvict()) / 100);
138       return objects2Evict;
139     }
140
141     public String JavaDoc toString() {
142       return "CacheStats[ type = " + type + ",\n\t usage = " + usage + ",\n\t countBefore = " + countBefore
143              + ", toEvict = " + toEvict + ", evicted = " + evicted + ", countAfter = " + countAfter
144              + ", objectsGCed = " + objectsGCed + ",\n\t state = " + state + "]";
145     }
146   }
147
148 }
149
Popular Tags