001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: Swapper.java 9860 2006-11-23 16:40:22Z durieuxp $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas_ejb.container;
025:
026: import java.util.LinkedList;
027: import java.util.NoSuchElementException;
028:
029: import org.objectweb.util.monolog.api.BasicLevel;
030:
031: /**
032: * This class is responsible for swapping bean instances to keep memory usage
033: * low enough, according to entity max-cache-size and inactivity-timeout values
034: * and to passivate instances on timeout when used outside transactions.
035: * There is 1 swapper per Container.
036: * @author Philippe Durieux
037: */
038: class Swapper extends Thread {
039:
040: /**
041: * My container
042: */
043: private JContainer container;
044:
045: /**
046: * true if still valid. Will be set to false when the container is unloaded.
047: */
048: private boolean valid;
049:
050: /**
051: * list of BeanFactory used to sync dirty instances
052: * This is "CS policy" specific
053: */
054: private LinkedList bfsList = new LinkedList();
055:
056: /**
057: * Value of the timeout to sync bean instances. (in sec.)
058: * default timeout value when no action required = 15 mn.
059: * never go under 1 mn.
060: */
061: private static final long SYNC_TIMEOUT = 30 * 1000;
062: private static final long MIN_SWAP_TIMEOUT = 60 * 1000;
063: private static final long MAX_SWAP_TIMEOUT = 15 * 60 * 1000;
064: private long swapTimeout = MAX_SWAP_TIMEOUT;
065: private long nextSync;
066: private boolean waiting;
067:
068: /**
069: * constructor
070: * @param cont The Container
071: */
072: public Swapper(JContainer cont) {
073: super ("JonasSwapper-" + cont.getName());
074: valid = true;
075: container = cont;
076: }
077:
078: /**
079: * run method for Thread implementation.
080: */
081: public void run() {
082: while (valid) {
083: BeanFactory bfs = null;
084: synchronized (this ) {
085: if (bfsList.size() == 0) {
086: try {
087: waiting = true;
088: wait(swapTimeout);
089: waiting = false;
090: } catch (InterruptedException e) {
091: TraceEjb.logger.log(BasicLevel.ERROR, getName()
092: + ": swapper interrupted", e);
093: } catch (Exception e) {
094: TraceEjb.logger.log(BasicLevel.ERROR, getName()
095: + ": swapper exception", e);
096: }
097: }
098: try {
099: bfs = (BeanFactory) bfsList.removeFirst();
100: } catch (NoSuchElementException e) {
101: bfs = null;
102: }
103: }
104: // The following code can be done with lock off: avoids deadlocks.
105:
106: if (bfs != null) {
107: // Synchronize all dirty instances for this entity factory (CS only)
108: // This happens usually at the beginning of a transaction
109: bfs.syncDirty(true);
110: }
111: if (System.currentTimeMillis() >= nextSync) {
112: // For each EntityFactory, look for passivationTimeout and inactivityTimeout
113: container.syncAll(false, true);
114: nextSync = System.currentTimeMillis() + swapTimeout;
115: }
116: }
117: }
118:
119: /**
120: * stop the swapper.
121: */
122: public synchronized void stopIt() {
123: valid = false;
124: notify();
125: }
126:
127: /**
128: * synchronizes all instances accessed outside transaction.
129: * This is "CS policy" specific
130: * @param bf the Bean Factory
131: */
132: public synchronized void addBeanFactorySync(BeanFactory bf) {
133: if (!bfsList.contains(bf)) {
134: if (TraceEjb.isDebugSwapper()) {
135: TraceEjb.swapper.log(BasicLevel.DEBUG, ""
136: + bfsList.size());
137: }
138: bfsList.addLast(bf);
139: notify();
140: }
141: }
142:
143: /**
144: * add a BeanFactory to the list
145: * @param bf the Bean Factory
146: */
147: public synchronized void addBeanFactory(BeanFactory bf) {
148: TraceEjb.swapper.log(BasicLevel.DEBUG, "");
149: long curtime = System.currentTimeMillis();
150: if (curtime >= nextSync) {
151: // It's time to check memory
152: if (waiting) {
153: notify();
154: }
155: } else if (nextSync - curtime > SYNC_TIMEOUT) {
156: // advance next check
157: nextSync = SYNC_TIMEOUT;
158: }
159: }
160:
161: /**
162: * set timeout value
163: * @param t in seconds
164: */
165: public synchronized void setSwapperTimeout(int t) {
166: long ms = t * 1000L;
167: if (ms < swapTimeout && ms >= MIN_SWAP_TIMEOUT) {
168: swapTimeout = ms;
169: TraceEjb.swapper.log(BasicLevel.DEBUG, "" + t);
170: }
171: notify();
172: }
173:
174: }
|