001: /*
002: * $Id: UserProfileGatewayCache.java,v 1.6 2006/08/14 09:46:47 vp154433 Exp $
003: * $Source: /m/portal/ps/srap/src/com/sun/portal/rproxy/configservlet/client/UserProfileGatewayCache.java,v $
004: * $Log: UserProfileGatewayCache.java,v $
005: * Revision 1.6 2006/08/14 09:46:47 vp154433
006: * CR 6439602 - Fixed bug for 0/0 error
007: *
008: * Revision 1.5 2005/03/01 10:27:23 np145014
009: * CR 6224556
010: *
011: * Revision 1.4 2005/03/01 10:22:37 np145014
012: * CR 6224556
013: *
014: * Revision 1.3 2005/02/23 09:14:06 ss150821
015: * RFE 6223490 - SRA Should use JDK based logging
016: *
017: * Revision 1.2 2005/02/23 09:13:05 ss150821
018: * RFE 6223490 - SRA Should use JDK based logging
019: *
020: * Revision 1.1 2002/06/14 09:53:49 rt130506
021: * SRAP rebranding
022: *
023: * Revision 1.6 2002/06/12 07:56:00 bv131302
024: * more rebranding - filenames
025: *
026: * Revision 1.5 2002/06/11 16:02:10 bv131302
027: * new branded
028: *
029: * Revision 1.4 2002/05/28 13:34:38 mm132998
030: * Bug id : 4640268 - RProxy migration to iDSAME
031: *
032: * Revision 1.2 2002/02/21 11:02:51 mm132998
033: * Checkin for Bug id : 4640268 - RProxy migration to iDSAME
034: *
035: * Revision 1.1 2002/02/21 06:04:11 mm132998
036: * Checkin for Bug id : 4640268 - RProxy migration to iDSAME
037: *
038: *
039: */
040: /*
041: * UserProfileGatewayCache.java
042: *
043: * Created on February 20, 2002, 12:14 PM
044: */
045:
046: package com.sun.portal.rproxy.configservlet.client;
047:
048: import java.util.HashMap;
049: import java.util.Iterator;
050: import java.util.Map;
051: import java.util.Set;
052:
053: import com.sun.portal.rproxy.configservlet.Request;
054: import com.sun.portal.rproxy.configservlet.Response;
055: import com.sun.portal.rproxy.monitoring.util.RProxyEvent;
056: import com.sun.portal.rproxy.monitoring.MonitoringSubsystem;
057: import com.sun.portal.util.SystemProperties;
058:
059: /*
060: * Maintains a UserProfile cache at the Gateway to reduce traffic to backend
061: * servlet.
062: *
063: * @author Mridul Muralidharan
064: */
065: public class UserProfileGatewayCache implements Runnable {
066:
067: private HashMap cache = null;
068:
069: private static UserProfileGatewayCache instance = null;
070:
071: private static final String GET_REQUEST = "GET_USERS";
072:
073: private static final String SET_USER_ATTRIBUTES = "SET_USER_ATTRIBUTES";
074:
075: private int numCacheEntries = 0;
076: private int numberOfHits = 0;
077: private int numberOfCacheHits = 0;
078: // Maximum number of entries in cache
079: // private static final int MAX_CACHE_SIZE = 1024;
080: private static int MAX_CACHE_SIZE;
081:
082: // Sleep time of one min
083: private static long CACHE_SLEEP_TIME;
084:
085: // Maximum time for which an entry can exist in Cache - 5 mins.
086: private static long CLEANUP_TIME;
087:
088: static {
089: try {
090: MAX_CACHE_SIZE = Integer.parseInt(SystemProperties.get(
091: "gateway.userProfile.cacheSize", "1024"));
092: } catch (Exception ex) {
093: MAX_CACHE_SIZE = 1024;
094: }
095: try {
096: CACHE_SLEEP_TIME = Integer.parseInt(SystemProperties.get(
097: "gateway.userProfile.cacheSleepTime", "60000"));
098: } catch (Exception ex) {
099: CACHE_SLEEP_TIME = 60000;
100: }
101: try {
102: CLEANUP_TIME = Integer.parseInt(SystemProperties.get(
103: "gateway.userProfile.cacheCleanupTime", "300000"));
104: } catch (Exception ex) {
105: CLEANUP_TIME = 300000;
106: }
107: }
108:
109: private int numOfCleanCacheSkips = 0;
110:
111: static {
112: instance = new UserProfileGatewayCache();
113: // Since this is not a thread that will ever exit , not running this
114: // in GWThreadPool but in its own thread.
115: // GWThreadPool.run(instance);
116: Thread thr = new Thread(instance);
117: thr.start();
118: }
119:
120: private UserProfileGatewayCache() {
121: cache = new HashMap();
122: }
123:
124: public static Map getResponse(String sessionId)
125: throws SendRequestException, GetResponseException {
126: instance.numberOfHits++;
127:
128: UserProfileGatewayCacheEntry entry = (UserProfileGatewayCacheEntry) instance
129: .getEntry(sessionId);
130:
131: if (entry == null) {
132: entry = instance.addEntry(sessionId);
133: if (entry == null) {
134: return new HashMap();
135: }
136: } else {
137: instance.numberOfCacheHits++;
138: }
139:
140: return entry.getValue();
141: }
142:
143: private synchronized Object getEntry(String sessid) {
144: return cache.get(sessid);
145: }
146:
147: private synchronized void addNewEntry(Object key, Object value) {
148: if (numCacheEntries >= MAX_CACHE_SIZE) {
149: cleanCache(System.currentTimeMillis(), true);
150: }
151: cache.put(key, value);
152: numCacheEntries++;
153: }
154:
155: private UserProfileGatewayCacheEntry addEntry(String sessid)
156: throws SendRequestException, GetResponseException {
157:
158: UserProfileGatewayCacheEntry newEntry = null;
159: Request request = new Request(sessid, null, GET_REQUEST);
160: MonitoringSubsystem
161: .handleEvent(RProxyEvent.GET_USER_PROFILE_START);
162: Response response = SrapClient.execute(request);
163: MonitoringSubsystem
164: .handleEvent(RProxyEvent.GET_USER_PROFILE_END);
165: if (response != null) {
166: Map result = (Map) response.getReturnedObject();
167: if (result == null) {
168: return null;
169: }
170: newEntry = new UserProfileGatewayCacheEntry(result);
171: addNewEntry(sessid, newEntry);
172: }
173: return newEntry;
174: }
175:
176: public static void setAttribute(String sessionId, String attribute,
177: Set value) throws SendRequestException,
178: GetResponseException {
179:
180: // Send request to Servlet to set Attribute
181: Request request = new Request(sessionId, null,
182: SET_USER_ATTRIBUTES, attribute, new Object[] { value });
183: Response resp = SrapClient.execute(request);
184:
185: UserProfileGatewayCacheEntry entry = (UserProfileGatewayCacheEntry) instance
186: .getEntry(sessionId);
187:
188: if (entry != null) {
189: Map map = entry.getValue();
190: map.put(attribute, value);
191: }
192: }
193:
194: public void run() {
195:
196: long currtime;
197: while (true) {
198: try {
199: Thread.currentThread().sleep(CACHE_SLEEP_TIME);
200: currtime = System.currentTimeMillis();
201: // This ensures that atleast once in every 10*CACHE_SLEEP_TIME
202: // millisecs
203: // The cache gets cleaned up.
204: if (numOfCleanCacheSkips >= 10) {
205: cleanCache(currtime, true);
206: } else {
207: numOfCleanCacheSkips++;
208: cleanCache(currtime, false);
209: }
210: } catch (Throwable t) {
211: }
212: }
213: }
214:
215: /*
216: * This method cleans up the cache. If number of entries in cache is low
217: * then the cache gets cleaned up depending on whether force is true or
218: * false The upper size limit is not a hard limit and the number of entries
219: * may exceed it in case no entries get cleaned up.
220: */
221: private synchronized void cleanCache(long time, boolean force) {
222:
223: if (force || numCacheEntries >= MAX_CACHE_SIZE) {
224: numOfCleanCacheSkips = 0;
225: Set keys = cache.keySet();
226: Iterator iter = keys.iterator();
227: UserProfileGatewayCacheEntry entry;
228: Object key;
229:
230: while (iter.hasNext()) {
231: key = iter.next();
232: entry = (UserProfileGatewayCacheEntry) cache.get(key);
233: if (time - entry.getTime() > CLEANUP_TIME) {
234: // cache.remove(key);
235: iter.remove();
236: numCacheEntries--;
237: }
238: }
239: }
240: return;
241: }
242:
243: public static long getMaxCacheSize() {
244: return MAX_CACHE_SIZE;
245: }
246:
247: private class UserProfileGatewayCacheEntry {
248:
249: private Map value = null;
250:
251: private long timestamp;
252:
253: public UserProfileGatewayCacheEntry(Map value) {
254: this .value = value;
255: timestamp = System.currentTimeMillis();
256: }
257:
258: public Map getValue() {
259: return value;
260: }
261:
262: public long getTime() {
263: return timestamp;
264: }
265: }
266:
267: public static int getNumCacheEntries() {
268: return instance.numCacheEntries;
269: }
270:
271: public static int getCacheHitRate() {
272: int hitRate = 0;
273: if (instance.numberOfHits != 0)
274: hitRate = instance.numberOfCacheHits
275: / instance.numberOfHits;
276: return hitRate;
277: }
278:
279: }
|