001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.cache;
006:
007: import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
008:
009: import com.tc.lang.TCThreadGroup;
010: import com.tc.lang.ThrowableHandler;
011: import com.tc.logging.TCLogging;
012: import com.tc.test.TCTestCase;
013: import com.tc.util.concurrent.ThreadUtil;
014:
015: import java.util.ArrayList;
016: import java.util.Date;
017: import java.util.Random;
018: import java.util.Vector;
019:
020: public class CacheManagerTest extends TCTestCase implements Evictable {
021:
022: private static final int BYTES_SIZE = 10240;
023: int usedT = 50;
024: int usedCritialT = 90;
025: long sleepInterval = 500;
026: int lc = 2;
027: int percentage2Evict = 10;
028: SynchronizedInt callCount = new SynchronizedInt(0);
029:
030: Vector v = new Vector();
031:
032: public void test() throws Exception {
033: CacheManager cm = new CacheManager(this , new TestCacheConfig(),
034: new TCThreadGroup(new ThrowableHandler(TCLogging
035: .getLogger(CacheManagerTest.class))));
036: log("Cache Manager Created : " + cm);
037: hogMemory();
038: assertTrue(callCount.get() > 0);
039: }
040:
041: private void log(String message) {
042: System.err.println(time() + " - " + thread() + " : " + message);
043: }
044:
045: private String time() {
046: return new Date().toString();
047: }
048:
049: private String thread() {
050: return Thread.currentThread().getName();
051: }
052:
053: private void hogMemory() {
054: for (int i = 1; i < 300000; i++) {
055: byte[] b = new byte[BYTES_SIZE];
056: v.add(b);
057: if (i == 100) {
058: // Sometimes in some platforms the memory manager thread is not given any time to start up, so
059: ThreadUtil.reallySleep(2000);
060: } else if (i % 10000 == 0) {
061: log("Created " + i
062: + " byte arrays - currently in vector = "
063: + v.size());
064: ThreadUtil.reallySleep(500);
065: } else if (i % 50 == 0) {
066: ThreadUtil.reallySleep(1);
067: } else if (i % 100 == 1) {
068: waitTillNotifiedIfCritical();
069: }
070: }
071: }
072:
073: private void waitTillNotifiedIfCritical() {
074: synchronized (v) {
075: Runtime runtime = Runtime.getRuntime();
076: long max = runtime.maxMemory();
077: long total = runtime.totalMemory();
078: long free = runtime.freeMemory();
079: // XXX::Explicitly not doing a spin lock
080: if (total >= max * 0.97 && free < max * 0.05) {
081: // free memory is less than 5 % of max memory
082: log("WARNING :: Vector Size reached "
083: + v.size()
084: + " and free = "
085: + free
086: + " max = "
087: + max
088: + " total = "
089: + total
090: + ". Pathway to OOME. Waiting for 5O msec or until reaping.");
091: try {
092: v.wait(50);
093: } catch (InterruptedException e) {
094: throw new RuntimeException(e);
095: }
096: }
097: }
098:
099: }
100:
101: public void evictCache(CacheStats stat) {
102: synchronized (v) {
103: int toEvict = stat.getObjectCountToEvict(v.size());
104: int evicted = 0;
105: ArrayList targetObjects4GC = new ArrayList();
106: if (toEvict >= v.size()) {
107: evicted = v.size();
108: targetObjects4GC.addAll(v);
109: v.clear();
110: } else {
111: for (int i = 0; i < toEvict; i++) {
112: targetObjects4GC.add(v.remove(rnd(v.size())));
113: evicted++;
114: }
115: }
116: stat.objectEvicted(evicted, v.size(), targetObjects4GC);
117: if (callCount.increment() % 10 == 1) {
118: log(stat.toString());
119: log("Asked to evict - " + toEvict + " Evicted : "
120: + evicted + " Vector Size : " + v.size());
121: }
122: v.notifyAll();
123: }
124: }
125:
126: Random r = new Random();
127:
128: private int rnd(int max) {
129: return r.nextInt(max);
130: }
131:
132: public class TestCacheConfig implements CacheConfig {
133:
134: public int getUsedCriticalThreshold() {
135: return usedCritialT;
136: }
137:
138: public int getUsedThreshold() {
139: return usedT;
140: }
141:
142: public int getLeastCount() {
143: return lc;
144: }
145:
146: public int getPercentageToEvict() {
147: return percentage2Evict;
148: }
149:
150: public long getSleepInterval() {
151: return sleepInterval;
152: }
153:
154: public boolean isOnlyOldGenMonitored() {
155: return true;
156: }
157:
158: public boolean isLoggingEnabled() {
159: return false;
160: }
161:
162: public int getObjectCountCriticalThreshold() {
163: return -1;
164: }
165:
166: }
167:
168: }
|