001: // Space4J(TM) - Object Persistence in RAM
002: // Copyright (C) 2003 Sergio Oliveira Junior
003: // This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
004:
005: package org.space4j.passivation;
006:
007: import java.io.*;
008: import java.util.*;
009: import java.nio.channels.*;
010:
011: import org.space4j.*;
012:
013: /**
014: * The PassivationMap stores its values in PassivationObjs.<br>
015: * It creates a PassivationObj for all objects it receives through the put method.<br>
016: * PassivationMap returns PassivationObjs through its get method.<br>
017: * It is able to passivate objects to save memory based on its last access time.<br>
018: * This will be useful when you have too many objects and there is not enough RAM.<br>
019: * Let's say you have 3 million registered users for your application.<br>
020: * It's not a good idea to keep all 3 million users in memory.<br>
021: * Among these 3 million users, how many are ACTIVE users ???<br>
022: * The goal of the PassivationMap is to keep only active objects in memory.<br>
023: * <b>Note: Passivation does not generate commands and it is only reflected by snapshots.</b>
024: */
025: public class PassivationMap implements Map, Runnable, Serializable {
026:
027: private final static boolean DEBUG = true;
028:
029: final static String DIR = "space4j_pv";
030: final static String PV_PREFIX = ".pv";
031: private static int SLEEPTIME = 1 * 60000; // minutes
032: private static int PASSIVATETIME = 15 * 1000; // seconds
033:
034: private Map map = null;
035: private String dirname = null;
036: private transient Thread thread = null;
037: private boolean bThread = false;
038:
039: /**
040: * Creates a PassivationMap
041: * @param space4j The space4j containing this map.
042: */
043: public PassivationMap(Space4J space4j) {
044: map = new HashMap();
045: init(space4j);
046: }
047:
048: /**
049: * Creates a PassivationMap with sleeptime and mininterval.
050: * @param space4j The space4j containing this map.
051: * @param sleeptime The monitor will wake up every sleeptime.
052: * @param mininterval The min interval before an object can be passivated.
053: */
054: public PassivationMap(Space4J space4j, int sleeptime,
055: int mininterval) {
056: this (space4j);
057: SLEEPTIME = sleeptime;
058: PASSIVATETIME = mininterval;
059: }
060:
061: /**
062: * Creates a PassivationMap.
063: * @param space4j The space4j containing this map.
064: * @param map The internal map to use.
065: */
066: public PassivationMap(Space4J space4j, Map map) {
067: this .map = map;
068: init(space4j);
069: }
070:
071: // Cool !!! This is a Java hack !!! It works !!!
072: // When the VM brings back this object from serialization, it will call this function.
073: private void readObject(ObjectInputStream stream)
074: throws ClassNotFoundException, IOException {
075: stream.defaultReadObject();
076: startMonitor();
077: }
078:
079: private void init(Space4J space4j) {
080: this .dirname = space4j.getDirName();
081: startMonitor();
082: }
083:
084: private void startMonitor() {
085: thread = new Thread(this );
086: thread.setDaemon(true);
087: thread.setPriority(Thread.NORM_PRIORITY - 1);
088: bThread = true;
089: thread.start();
090: }
091:
092: /**
093: * Return a thread-safe Iterator with the keys of this Map.
094: * @return Thread-safe iterator with keys.
095: */
096: public synchronized Iterator getSafeKeyIterator() {
097: Object[] array = map.keySet().toArray();
098: ArrayList list = new ArrayList(array.length);
099: for (int i = 0; i < array.length; i++)
100: list.add(array[i]);
101: return list.iterator();
102: }
103:
104: public void run() {
105: try {
106: if (DEBUG)
107: System.out.println("Monitor started !!!");
108: while (bThread) {
109: Thread.sleep(SLEEPTIME);
110: if (DEBUG)
111: System.out.println("Monitor acordado !!!");
112: Iterator iter = getSafeKeyIterator();
113: while (iter.hasNext() && bThread) {
114: Object key = iter.next();
115: PassivationObj po = (PassivationObj) map.get(key);
116: if (po != null && !po.isPassivated()
117: && po.canPassivate(PASSIVATETIME)) {
118: po.passivate();
119: }
120: }
121: }
122: } catch (Exception e) {
123: e.printStackTrace();
124: }
125: }
126:
127: public synchronized void clear() {
128: map.clear();
129: }
130:
131: public synchronized boolean containsKey(Object key) {
132: return map.containsKey(key);
133: }
134:
135: public boolean containsValue(Object value) {
136: return map.containsValue(value);
137: }
138:
139: public Set entrySet() {
140: return map.entrySet();
141: }
142:
143: public boolean equals(Object obj) {
144: if (obj == this )
145: return true;
146: return false;
147: }
148:
149: public int hashCode() {
150: return this .hashCode();
151: }
152:
153: public synchronized boolean isEmpty() {
154: return map.isEmpty();
155: }
156:
157: public synchronized Set keySet() {
158: return map.keySet();
159: }
160:
161: /**
162: * Every object put here will become a PassivationObj.
163: */
164: public void putAll(Map m) {
165: Iterator iter = m.keySet().iterator();
166: while (iter.hasNext()) {
167: Object key = iter.next();
168: Object value = m.get(key);
169: PassivationObj po = new PassivationObj(value);
170: map.put(key, po);
171: }
172: }
173:
174: public synchronized Object remove(Object key) {
175: return map.remove(key);
176: }
177:
178: public synchronized int size() {
179: return map.size();
180: }
181:
182: public Collection values() {
183: return map.values();
184: }
185:
186: /**
187: * Every object put here will become a PassivationObj.
188: */
189: public synchronized Object put(Object key, Object value) {
190: PassivationObj po = new PassivationObj(value);
191: return map.put(key, po);
192: }
193:
194: /**
195: * This will only return PassivationObjs.
196: */
197: public synchronized Object get(Object key) {
198: return map.get(key);
199: }
200: }
|