KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > framework > transport > http > SyncHolderCache


1 /**
2  * Copyright (C) 2003-2005 Funambol
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package sync4j.framework.transport.http;
20
21 import java.util.*;
22 import java.util.logging.*;
23
24 /**
25  * This class implements a <i>SyncHolder</i> cache. <br>
26  * It holds an HashMap in its instance parameter <i>cache</i>.
27  * <p>
28  * An optimization performed in this object is about avoiding memory eating
29  * due to missing SyncHolders removing. This problem is solved with the
30  * following actions:
31  * <ul>
32  * <li> each SyncHolder stores a creation timestamp that is set in the
33  * constructor to the current system time millis;
34  * <li> HolderCache stores in the lastCleaningTimestamp static field the last
35  * time the cache was cleared;
36  * <li> If the the difference between the current time millis and the
37  * lastCleaningTimestamp is greater then the configured sessionTimeToLive,
38  * the cleaner process is executed;
39  * <li> the cleaner process iterates the sync holders in the cache and closes and removes the expired ones;
40  * </ul>
41  * <p>
42  * NOTES:
43  * <p>
44  * 1. The cleaning process could be moved to a separate thread and executed
45  * asynchronously respect to the execution of servlet execution.
46  *
47  * @author Stefano Fornari
48  * @version $Id: SyncHolderCache.java,v 1.6 2005/03/02 20:57:38 harrie Exp $
49  */

50 public class SyncHolderCache {
51
52     // --------------------------------------------------------------- Constants
53

54     public static final long CLEANING_PERIOD = 300000; // 5 mins
55
public static final long DEFAULT_TTL = 300000; // 5 mins
56
public static final String JavaDoc LOG_NAME = "sync4j.transport.http";
57
58     private static final Logger log = Logger.getLogger(LOG_NAME);
59
60     // ------------------------------------------------------------ Private data
61

62     private long holderTimeToLive = DEFAULT_TTL;
63
64     private long lastCleaningTimestamp = 0;
65
66     private Map cache;
67
68     // ------------------------------------------------------------ Constructors
69

70
71     public SyncHolderCache(long timeToLive) {
72         cache = new HashMap(97);
73
74         lastCleaningTimestamp = System.currentTimeMillis();
75
76         holderTimeToLive = timeToLive;
77     }
78
79     // ------------------------------------------- Implementation of HolderCache
80

81     public void put(SyncHolder holder) {
82         clean();
83
84         if (log.isLoggable(Level.FINEST)) {
85             log.finest("Caching " + holder.getSessionId() + '(' + holder + ')');
86         }
87
88         synchronized (cache) {
89             cache.put(holder.getSessionId(), holder);
90         }
91     }
92
93     public SyncHolder get(String JavaDoc sessionId) {
94         return (SyncHolder)cache.get(sessionId);
95     }
96
97     public void remove(String JavaDoc sessionId) {
98         if (log.isLoggable(Level.FINEST)) {
99             log.finest("Removing holder for " + sessionId);
100         }
101         synchronized (cache) {
102             cache.remove(sessionId);
103         }
104     }
105
106     // ---------------------------------------------------- Other public methods
107

108     public String JavaDoc toString() {
109         String JavaDoc s = null;
110         synchronized (cache) {
111             s = String.valueOf(cache);
112         }
113         return s;
114     }
115
116     // --------------------------------------------------------- Private methods
117

118     /**
119      * If System.currentTimeMillis() - lastCleaningTimestamp is greater than
120      * holderTimeToLive, purge old holders.
121      *
122      * @returns true if cleaning was performed, false otherwise
123      */

124     private boolean clean() {
125         long now = System.currentTimeMillis();
126
127         if (log.isLoggable(Level.FINEST)) {
128             log.finest("Cleaning procedure..." );
129             log.finest("now: " + now );
130             log.finest("CLEANING_PERIOD: " + CLEANING_PERIOD );
131             log.finest("lastCleaningTimestamp: " + lastCleaningTimestamp);
132             log.finest("holderTimeToLive: " + holderTimeToLive );
133         }
134
135         ArrayList toBeRemoved = null;
136         SyncHolder h;
137         Object JavaDoc key, value;
138         Iterator i = null;
139
140         synchronized (cache) {
141
142             if ((now - lastCleaningTimestamp) <= CLEANING_PERIOD) {
143                 if (log.isLoggable(Level.FINEST)) {
144                     log.finest("No purging required");
145                 }
146                 return false;
147             }
148
149             if (log.isLoggable(Level.FINEST)) {
150                 log.finest("Performing purging...");
151             }
152
153             toBeRemoved = new ArrayList();
154
155             i = cache.keySet().iterator();
156             while (i.hasNext()) {
157                 key = i.next();
158                 value = cache.get(key);
159
160                 if (!(value instanceof SyncHolder)) {
161                     // You shouldn't be here matey!!!
162
if (log.isLoggable(Level.FINEST)) {
163                         log.finest("Found unexpected object: " + key + " will be removed!");
164                     }
165                     toBeRemoved.add(key);
166                     continue;
167                 }
168                 h = (SyncHolder)value;
169                 if ((now - h.getCreationTimestamp()) > holderTimeToLive) {
170
171                     if (log.isLoggable(Level.FINEST)) {
172                         log.finest("Purging holder for session " + key);
173                     }
174
175                     try {
176                         h.close();
177                     } catch (Exception JavaDoc e) {
178                         log.severe(e.getMessage());
179                         log.throwing(getClass().getName(), "clean", e);
180                     }
181                     toBeRemoved.add(key);
182                 }
183             }
184
185             //
186
// Now remove the purged objects
187
//
188
i = toBeRemoved.iterator();
189             while(i.hasNext()) {
190                 cache.remove(i.next());
191             }
192         }
193
194         lastCleaningTimestamp = System.currentTimeMillis();
195
196         return true;
197     }
198 }
199
Popular Tags