KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > tomcat > tc6 > session > AttributeBasedClusteredSession


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.web.tomcat.tc6.session;
23
24 import java.util.Collections JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.Map.Entry;
30
31 /**
32  * Implementation of a clustered session for the JBossCacheManager. The replication granularity
33  * level is attribute based; that is, we replicate only the dirty attributes.
34  * We use JBossCache for our internal, deplicated data store.
35  * The internal structure is like in JBossCache:
36  * <pre>
37  * /JSESSION
38  * /hostname
39  * /web_app_path (path + session id is unique)
40  * /id Map(id, session)
41  * (VERSION_KEY, version) // Used for version tracking. version is an Integer.
42  * /ATTRIBUTE Map(attr_key, value)
43  * </pre>
44  * <p/>
45  * Note that the isolation level of the cache dictates the
46  * concurrency behavior. Also note that session and its associated attribtues are stored in different nodes.
47  * This will be ok since cache will take care of concurrency. When replicating, we will need to replicate both
48  * session and its attributes.</p>
49  *
50  * @author Ben Wang
51  * @author Brian Stansberry
52  *
53  * @version $Revision: 56542 $
54  */

55 class AttributeBasedClusteredSession
56    extends JBossCacheClusteredSession
57 {
58    static final long serialVersionUID = -5625209785550936713L;
59    /**
60     * Descriptive information describing this Session implementation.
61     */

62    protected static final String JavaDoc info = "AttributeBasedClusteredSession/1.0";
63
64    // Transient map to store attr changes for replication.
65
private transient Map JavaDoc attrModifiedMap_ = new HashMap JavaDoc();
66    // Note that the removed attr is intentionally stored in a map
67
// instead of a Set so it is faster to lookup and remove.
68
private transient Map JavaDoc attrRemovedMap_ = new HashMap JavaDoc();
69    private static final int REMOVE = 0; // Used to track attribute changes
70
private static final int MODIFY = 1;
71    // TODO why isn't the superclass field sufficient?
72
private transient Map JavaDoc attributes_ = Collections.synchronizedMap(new HashMap JavaDoc());
73
74    public AttributeBasedClusteredSession(JBossCacheManager manager)
75    {
76       super(manager);
77    }
78
79    // ----------------------------------------------- Overridden Public Methods
80

81
82    /**
83     * Override the superclass to additionally reset this class' fields.
84     * <p>
85     * <strong>NOTE:</strong> It is not anticipated that this method will be
86     * called on a ClusteredSession, but we are overriding the method to be
87     * thorough.
88     * </p>
89     */

90    public void recycle()
91    {
92       super.recycle();
93
94       attributes_.clear();
95       clearAttrChangedMaps();
96    }
97
98    /**
99     * Return a string representation of this object.
100     */

101    public String JavaDoc toString()
102    {
103
104       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
105       sb.append("AttributeBasedClusteredSession[");
106       sb.append(super.toString());
107       sb.append("]");
108       return (sb.toString());
109
110    }
111
112    /**
113     * Overrides the superclass version to read in the attributes.
114     */

115    public synchronized void processSessionRepl()
116    {
117       // Replicate the metadata first. Note this will be lightweight since many
118
// of the fields are transient and the attribute map isn't included.
119
if (log.isTraceEnabled())
120       {
121          log.trace("processSessionRepl(): session is dirty. Will increment " +
122                 "version from: " + getVersion() + " and replicate.");
123       }
124       this.incrementVersion();
125       proxy_.putSession(realId, this);
126
127       // Go thru the attribute change list
128

129       if (getSessionAttributesDirty())
130       {
131          // Go thru the modified attr list first
132
int modCount = attrModifiedMap_.size();
133          if (modCount == 1)
134          {
135             for (Iterator JavaDoc it = attrModifiedMap_.entrySet().iterator(); it.hasNext(); )
136             {
137                Map.Entry JavaDoc entry = (Entry) it.next();
138                proxy_.putAttribute(realId, (String JavaDoc) entry.getKey(), entry.getValue());
139             }
140          }
141          else if (modCount > 0)
142          {
143             // It's more efficient to write a map than 2 method calls,
144
// plus it reduces the number of CacheListener notifications
145
proxy_.putAttribute(realId, attrModifiedMap_);
146          }
147          
148          // Go thru the remove attr list
149
if (attrRemovedMap_.size() > 0)
150          {
151             for (Iterator JavaDoc it = attrRemovedMap_.keySet().iterator(); it.hasNext(); )
152             {
153                proxy_.removeAttribute(realId, (String JavaDoc) it.next());
154             }
155          }
156          
157          clearAttrChangedMaps();
158       }
159       
160       sessionAttributesDirty = false;
161       sessionMetadataDirty = false;
162       
163       updateLastReplicated();
164    }
165
166    public void removeMyself()
167    {
168       // This is a shortcut to remove session and it's child attributes.
169
proxy_.removeSession(realId);
170    }
171
172    public void removeMyselfLocal()
173    {
174       // Need to evict attribute first before session to clean up everything.
175
// BRIAN -- the attributes *are* already evicted, but we leave the
176
// removeAttributesLocal call here in order to evict the ATTRIBUTE node.
177
// Otherwise empty nodes for the session root and child ATTRIBUTE will
178
// remain in the tree and screw up our list of session names.
179
proxy_.removeAttributesLocal(realId);
180       proxy_.removeSessionLocal(realId);
181    }
182
183    // ------------------------------------------------ JBoss internal abstract method
184

185    /**
186     * Populate the attributes stored in the distributed store to local transient ones.
187     */

188    protected void populateAttributes()
189    {
190       Map JavaDoc map = proxy_.getAttributes(realId);
191       
192       // Preserve any local attributes that were excluded from replication
193
Map JavaDoc excluded = removeExcludedAttributes(attributes_);
194       if (excluded != null)
195          map.putAll(excluded);
196       
197       attributes_ = Collections.synchronizedMap(map);
198       attrModifiedMap_.clear();
199       attrRemovedMap_.clear();
200    }
201
202    protected Object JavaDoc getJBossInternalAttribute(String JavaDoc name)
203    {
204       Object JavaDoc result = attributes_.get(name);
205
206       // Do dirty check even if result is null, as w/ SET_AND_GET null
207
// still makes us dirty (ensures timely replication w/o using ACCESS)
208
if (isGetDirty(result) && !replicationExcludes.contains(name))
209       {
210          attributeChanged(name, result, MODIFY);
211       }
212
213       return result;
214    }
215
216    protected Object JavaDoc removeJBossInternalAttribute(String JavaDoc name,
217                                                  boolean localCall,
218                                                  boolean localOnly)
219    {
220       Object JavaDoc result = attributes_.remove(name);
221       if (localCall && !replicationExcludes.contains(name))
222          attributeChanged(name, result, REMOVE);
223       return result;
224    }
225
226    protected Map JavaDoc getJBossInternalAttributes()
227    {
228       return attributes_;
229    }
230
231    protected Set JavaDoc getJBossInternalKeys()
232    {
233       return attributes_.keySet();
234    }
235
236    /**
237     * Method inherited from Tomcat. Return zero-length based string if not found.
238     */

239    protected String JavaDoc[] keys()
240    {
241       return ((String JavaDoc[]) getJBossInternalKeys().toArray(EMPTY_ARRAY));
242    }
243
244    protected Object JavaDoc setJBossInternalAttribute(String JavaDoc key, Object JavaDoc value)
245    {
246       Object JavaDoc old = attributes_.put(key, value);
247       if (!replicationExcludes.contains(key))
248          attributeChanged(key, value, MODIFY);
249       return old;
250    }
251
252    protected synchronized void attributeChanged(Object JavaDoc key, Object JavaDoc value, int op)
253    {
254       if (op == MODIFY)
255       {
256          if (attrRemovedMap_.containsKey(key))
257          {
258             attrRemovedMap_.remove(key);
259          }
260          attrModifiedMap_.put(key, value);
261       }
262       else if (op == REMOVE)
263       {
264          if (attrModifiedMap_.containsKey(key))
265          {
266             attrModifiedMap_.remove(key);
267          }
268          attrRemovedMap_.put(key, value);
269       }
270       sessionAttributesDirty();
271    }
272
273    protected synchronized void clearAttrChangedMaps()
274    {
275       attrRemovedMap_.clear();
276       attrModifiedMap_.clear();
277    }
278 }
279
Popular Tags