KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > Swapper


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: Swapper.java,v 1.22 2005/04/28 16:52:59 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas_ejb.container;
27
28 import java.util.LinkedList JavaDoc;
29 import java.util.NoSuchElementException JavaDoc;
30
31 import org.objectweb.util.monolog.api.BasicLevel;
32
33 /**
34  * This class is responsible for swapping bean instances to keep memory usage
35  * low enough, according to entity max-cache-size value and to passivate
36  * instances on timeout when used outside transactions. There is 1 swapper per
37  * Container.
38  * @author Philippe Durieux
39  */

40 class Swapper extends Thread JavaDoc {
41
42     /**
43      * My container
44      */

45     private JContainer container;
46
47     /**
48      * true if still valid. Will be set to false when the container is unloaded.
49      */

50     private boolean valid;
51
52     /**
53      * true when we must synchronize entity beans
54      */

55     private boolean syncallbeans;
56
57     /**
58      * Used to decide to free objects in memory.
59      * The goal is to avoid "out of memory exceptions".
60      */

61     private int memorylow;
62
63     /**
64      * list of BeanFactory used to reduce cache size periodically
65      */

66     private LinkedList JavaDoc bfList = new LinkedList JavaDoc();
67
68     /**
69      * list of BeanFactory used to sync dirty instances
70      */

71     private LinkedList JavaDoc bfsList = new LinkedList JavaDoc();
72
73     /**
74      * Value of the timeout to sync bean instances. default timeout value when
75      * no action required = 5 mn.
76      */

77     private int swapTimeout = 5 * 60;
78
79     /**
80      * Period to see if memory must be freed. Default value = every 10 loops.
81      */

82     private int memoryCount = 10;
83
84     /**
85      * constructor
86      * @param cont The Container
87      */

88     public Swapper(JContainer cont) {
89         super("JonasSwapper");
90         valid = true;
91         syncallbeans = false;
92         memorylow = 0;
93         container = cont;
94     }
95
96     /**
97      * run method for Thread implementation.
98      */

99     public void run() {
100
101         while (valid) {
102             BeanFactory bf = null;
103             BeanFactory bfs = null;
104             synchronized (this) {
105                 if (bfsList.size() == 0 && bfList.size() == 0) {
106                     try {
107                         wait(swapTimeout * 1000);
108                     } catch (InterruptedException JavaDoc e) {
109                         TraceEjb.logger.log(BasicLevel.ERROR, getName() + ": swapper interrupted", e);
110                     } catch (Exception JavaDoc e) {
111                         TraceEjb.logger.log(BasicLevel.ERROR, getName() + ": swapper exception", e);
112                     }
113                 }
114                 try {
115                     bf = (BeanFactory) bfList.removeFirst();
116                 } catch (NoSuchElementException JavaDoc e) {
117                     bf = null;
118                 }
119                 try {
120                     bfs = (BeanFactory) bfsList.removeFirst();
121                 } catch (NoSuchElementException JavaDoc e) {
122                     bfs = null;
123                 }
124             }
125             // This can be done with lock off.
126
if (bf != null) {
127                 if (TraceEjb.isDebugSwapper()) {
128                     TraceEjb.swapper.log(BasicLevel.DEBUG, "swapper will try to reduce the cache");
129                 }
130                 bf.reduceCache();
131                 continue;
132             }
133             if (bfs != null) {
134                 if (TraceEjb.isDebugSwapper()) {
135                     TraceEjb.swapper.log(BasicLevel.DEBUG, "swapper will sync dirty instances");
136                 }
137                 bfs.sync();
138                 continue;
139             }
140             // We were notified on timeout, probably to sync all beans.
141
if (memorylow >= 10) {
142                 if (TraceEjb.isDebugSwapper()) {
143                     TraceEjb.swapper.log(BasicLevel.DEBUG, "swapper will passivate all entity factories");
144                 }
145                 container.syncAll(true);
146                 memorylow = 0;
147             } else if (syncallbeans) {
148                 if (TraceEjb.isDebugSwapper()) {
149                     TraceEjb.swapper.log(BasicLevel.DEBUG, "swapper will sync all entity factories - " + memorylow);
150                 }
151                 container.syncAll(false);
152                 memorylow++;
153             }
154         }
155     }
156
157     /**
158      * stop the swapper.
159      */

160     public synchronized void stopIt() {
161         valid = false;
162         notify();
163     }
164
165     /**
166      * synchronizes all instances accessed outside transaction.
167      * @param bf the Bean Factory
168      */

169     public synchronized void addBeanFactorySync(BeanFactory bf) {
170         if (!bfsList.contains(bf)) {
171             if (TraceEjb.isDebugSwapper()) {
172                 TraceEjb.swapper.log(BasicLevel.DEBUG, "" + bfsList.size());
173             }
174             bfsList.addLast(bf);
175             notify();
176         }
177     }
178
179     /**
180      * add a BeanFactory to the list
181      * @param bf the Bean Factory
182      */

183     public synchronized void addBeanFactory(BeanFactory bf) {
184         if (!bfList.contains(bf)) {
185             if (TraceEjb.isDebugSwapper()) {
186                 TraceEjb.swapper.log(BasicLevel.DEBUG, "" + bfList.size());
187             }
188             bfList.addLast(bf);
189             // don't notify because it's better to wait that instances are released
190
// before reducing the pool.
191
// This is called typically when the pool is empty!
192
}
193     }
194
195     /**
196      * set timeout value
197      * @param t in seconds
198      */

199     public synchronized void setSwapperTimeout(int t) {
200         if (TraceEjb.isDebugSwapper()) {
201             TraceEjb.swapper.log(BasicLevel.DEBUG, "" + t);
202         }
203         syncallbeans = true;
204         if (t < swapTimeout) {
205             swapTimeout = t;
206         }
207         notify();
208     }
209
210     /**
211      * return the timeout for this container, in milliseconds. 0 means "no
212      * timeout".
213      * @return timeout value in seconds.
214      */

215     public int getSwapperTimeout() {
216         if (syncallbeans) {
217             return swapTimeout;
218         } else {
219             return 0;
220         }
221     }
222 }
223
Popular Tags