001: /**
002: * Copyright (C) 2001 Yasna.com. All rights reserved.
003: *
004: * ===================================================================
005: * The Apache Software License, Version 1.1
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution,
020: * if any, must include the following acknowledgment:
021: * "This product includes software developed by
022: * Yasna.com (http://www.yasna.com)."
023: * Alternately, this acknowledgment may appear in the software itself,
024: * if and wherever such third-party acknowledgments normally appear.
025: *
026: * 4. The names "Yazd" and "Yasna.com" must not be used to
027: * endorse or promote products derived from this software without
028: * prior written permission. For written permission, please
029: * contact yazd@yasna.com.
030: *
031: * 5. Products derived from this software may not be called "Yazd",
032: * nor may "Yazd" appear in their name, without prior written
033: * permission of Yasna.com.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL YASNA.COM OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of Yasna.com. For more information
051: * on Yasna.com, please see <http://www.yasna.com>.
052: */
053:
054: /**
055: * Copyright (C) 2000 CoolServlets.com. All rights reserved.
056: *
057: * ===================================================================
058: * The Apache Software License, Version 1.1
059: *
060: * Redistribution and use in source and binary forms, with or without
061: * modification, are permitted provided that the following conditions
062: * are met:
063: *
064: * 1. Redistributions of source code must retain the above copyright
065: * notice, this list of conditions and the following disclaimer.
066: *
067: * 2. Redistributions in binary form must reproduce the above copyright
068: * notice, this list of conditions and the following disclaimer in
069: * the documentation and/or other materials provided with the
070: * distribution.
071: *
072: * 3. The end-user documentation included with the redistribution,
073: * if any, must include the following acknowledgment:
074: * "This product includes software developed by
075: * CoolServlets.com (http://www.coolservlets.com)."
076: * Alternately, this acknowledgment may appear in the software itself,
077: * if and wherever such third-party acknowledgments normally appear.
078: *
079: * 4. The names "Jive" and "CoolServlets.com" must not be used to
080: * endorse or promote products derived from this software without
081: * prior written permission. For written permission, please
082: * contact webmaster@coolservlets.com.
083: *
084: * 5. Products derived from this software may not be called "Jive",
085: * nor may "Jive" appear in their name, without prior written
086: * permission of CoolServlets.com.
087: *
088: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
089: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
090: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
091: * DISCLAIMED. IN NO EVENT SHALL COOLSERVLETS.COM OR
092: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
093: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
094: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
095: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
096: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
097: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
098: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
099: * SUCH DAMAGE.
100: * ====================================================================
101: *
102: * This software consists of voluntary contributions made by many
103: * individuals on behalf of CoolServlets.com. For more information
104: * on CoolServlets.com, please see <http://www.coolservlets.com>.
105: */package com.Yasna.forum.database;
106:
107: import com.Yasna.util.*;
108:
109: /**
110: * Central cache management of all caches used by Yazd.
111: */
112: public class DbCacheManager {
113:
114: public static int USER_CACHE = 0;
115: public static int USER_ID_CACHE = 1;
116: public static int GROUP_CACHE = 2;
117: public static int GROUP_ID_CACHE = 3;
118: public static int FORUM_CACHE = 4;
119: public static int FORUM_ID_CACHE = 5;
120: public static int THREAD_CACHE = 6;
121: public static int MESSAGE_CACHE = 7;
122: public static int USER_PERMS_CACHE = 8;
123: public static int CATEGORY_CACHE = 9;
124: public static int CATEGORY_ID_CACHE = 10;
125: public static int FORUM_GROUP_CACHE = 11;
126: public static int THREAD_TYPE_ID_CACHE = 12;
127:
128: protected Cache[] caches;
129:
130: private boolean cacheEnabled = true;
131:
132: public DbCacheManager() {
133: int MINUTE = 1000 * 60;
134: int HOUR = MINUTE * 60;
135:
136: caches = new Cache[13];
137:
138: //Initialize all cache structures
139: caches[USER_CACHE] = new Cache(256 * 1024, 10 * MINUTE);
140: caches[USER_ID_CACHE] = new Cache(128 * 1024, 10 * MINUTE);
141: caches[GROUP_CACHE] = new Cache(128 * 1024, 1 * HOUR);
142: caches[GROUP_ID_CACHE] = new Cache(128 * 1024, 1 * HOUR);
143: caches[FORUM_CACHE] = new Cache(128 * 1024, 20 * MINUTE);
144: caches[FORUM_ID_CACHE] = new Cache(128 * 1024, 20 * MINUTE);
145: caches[THREAD_CACHE] = new Cache(128 * 1024, 20 * MINUTE);
146: caches[MESSAGE_CACHE] = new Cache(512 * 1024, 1 * HOUR);
147: caches[CATEGORY_CACHE] = new Cache(128 * 1024, 1 * HOUR);
148: caches[CATEGORY_ID_CACHE] = new Cache(128 * 1024, 1 * HOUR);
149: caches[FORUM_GROUP_CACHE] = new Cache(128 * 1024, 1 * HOUR);
150: //The user permissions cache is a special one. It's actually a Cache
151: //of Cache objects. Each of the cache objects in the main cache
152: //corresponds to a particular forum, and is used to cache the
153: //permissions that a user has for a forum. In order to handle this
154: //requirement, we use a special subclass of Cache.
155: caches[USER_PERMS_CACHE] = new UserPermsCache(256 * 1024,
156: 2 * HOUR);
157: caches[THREAD_TYPE_ID_CACHE] = new Cache(128 * 1024, 1 * HOUR);
158: }
159:
160: public Cache getCache(int cacheType) {
161: return caches[cacheType];
162: }
163:
164: public void add(int cacheType, Object key, Cacheable object) {
165: caches[cacheType].add(key, object);
166: }
167:
168: public Cacheable get(int cacheType, Object key) {
169: if (!cacheEnabled) {
170: return null;
171: }
172: return caches[cacheType].get(key);
173: }
174:
175: public void remove(int cacheType, Object key) {
176: caches[cacheType].remove(key);
177: //when cache becomes distributed, we'd send out an expire message
178: //here to all other yazd servers.
179: }
180:
181: public void removeUserPerm(Object userID) {
182: Object[] values = caches[USER_PERMS_CACHE].values().toArray();
183: for (int i = 0; i < values.length; i++) {
184: Cache cache = (Cache) ((CacheObject) values[i]).object;
185: cache.remove(userID);
186: }
187: //when cache becomes distributed, we'd send out an expire message
188: //here to all other yazd servers.
189: }
190:
191: public void removeUserPerm(Object userID, Object forumID) {
192: Cache cache = (Cache) caches[USER_PERMS_CACHE].get(forumID);
193: if (cache != null) {
194: cache.remove(userID);
195: }
196: //when cache becomes distributed, we'd send out an expire message
197: //here to all other yazd servers.
198: }
199:
200: public void clear(int cacheType) {
201: caches[cacheType].clear();
202: //when cache becomes distributed, we'd send out an expire message
203: //here to all other yazd servers.
204: }
205:
206: public boolean isCacheEnabled() {
207: return cacheEnabled;
208: }
209:
210: public void setCacheEnabled(boolean cacheEnabled) {
211: this .cacheEnabled = cacheEnabled;
212: }
213: }
214:
215: /**
216: * Special purpose Cache to hold all of the different user permission cache
217: * objects. The main feature is that new caches are automatically created so
218: * that calling get() never returns null.
219: */
220: class UserPermsCache extends Cache {
221:
222: public UserPermsCache(int size, long expireTime) {
223: super (size, expireTime);
224: }
225:
226: public synchronized Cacheable get(Object key) {
227: Cache subCache = (Cache) super .get(key);
228: if (subCache == null) {
229: //cache has expired, or is not there, so put a new one in there.
230: //Cache objects only need to last as long as a user's session
231: //does. Half an hour is a reasonable amount of time for this.
232: subCache = new Cache(2 * 1024, 30 * 1000 * 60);
233: add(key, subCache);
234: }
235: return subCache;
236: }
237:
238: public synchronized void remove(Object key) {
239: CacheObject cacheObject = (CacheObject) cachedObjectsHash
240: .get(key);
241: //If the object is not in cache, stop trying to remove it.
242: if (cacheObject == null) {
243: return;
244: }
245: //remove from the hash map
246: cachedObjectsHash.remove(key);
247: //remove from the cache order list
248: cacheObject.lastAccessedListNode.remove();
249: cacheObject.ageListNode.remove();
250: //remove references to linked list nodes
251: cacheObject.ageListNode = null;
252: cacheObject.lastAccessedListNode = null;
253: //removed the object, so subtract its size from the total.
254: size -= cacheObject.size;
255:
256: //Finally, clear the sub-cache to make sure memory is released.
257: ((Cache) cacheObject.object).clear();
258: }
259:
260: /**
261: * Returns the current size in bytes of the cache. The base getSize() method
262: * does not work correctly because the sub-caches are empty when we first
263: * add them rather than the normal cache assumption that objects are near
264: * the size that they will always be.
265: *
266: * @return the size of the cache in bytes.
267: */
268: public int getSize() {
269: int size = 0;
270: Object[] values = values().toArray();
271: for (int i = 0; i < values.length; i++) {
272: Cache cache = (Cache) values[i];
273: size += cache.getSize();
274: }
275: return size;
276: }
277: }
|