/jboss-as-7.1.1.Final/web/src/main/java/org/jboss/as/web/session/AttributeBasedClusteredSession.java
Java | 180 lines | 102 code | 27 blank | 51 comment | 18 complexity | c0bd8351b839078735c476e8ca8772b8 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
1/*
2 * JBoss, Home of Professional Open Source.
3 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
4 * as indicated by the @author tags. See the copyright.txt file in the
5 * distribution for a 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 */
22package org.jboss.as.web.session;
23
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.Map;
27import java.util.Set;
28
29import org.jboss.as.clustering.web.DistributableSessionMetadata;
30import org.jboss.as.clustering.web.OutgoingAttributeGranularitySessionData;
31
32/**
33 * Implementation of a clustered session where the replication granularity level is attribute based; that is, we replicate only
34 * the dirty attributes.
35 * <p/>
36 * Note that the isolation level of the cache dictates the concurrency behavior. Also note that session and its associated
37 * attributes are stored in different nodes. This will be ok since cache will take care of concurrency. When replicating, we
38 * will need to replicate both session and its attributes.
39 * </p>
40 * @author Ben Wang
41 * @author Brian Stansberry
42 */
43class AttributeBasedClusteredSession extends ClusteredSession<OutgoingAttributeGranularitySessionData> {
44 static final long serialVersionUID = -5625209785550936713L;
45 /**
46 * Descriptive information describing this Session implementation.
47 */
48 protected static final String info = "AttributeBasedClusteredSession/1.0";
49
50 // Transient map to store attr changes for replication.
51 private transient Map<String, Object> attrModifiedMap_ = new HashMap<String, Object>();
52 // Transient set to store attr removals for replication
53 private transient Set<String> attrRemovedSet_ = new HashSet<String>();
54
55 // ------------------------------------------------------------ Constructors
56
57 public AttributeBasedClusteredSession(ClusteredSessionManager<OutgoingAttributeGranularitySessionData> manager) {
58 super(manager);
59 }
60
61 // ----------------------------------------------- Overridden Public Methods
62
63 @Override
64 public String getInfo() {
65 return (info);
66 }
67
68 /**
69 * Override the superclass to additionally reset this class' fields.
70 * <p>
71 * <strong>NOTE:</strong> It is not anticipated that this method will be called on a ClusteredSession, but we are overriding
72 * the method to be thorough.
73 * </p>
74 */
75 @Override
76 public void recycle() {
77 super.recycle();
78
79 clearAttrChangedMaps();
80 }
81
82 // -------------------------------------------- Overridden Protected Methods
83
84 @Override
85 protected OutgoingAttributeGranularitySessionData getOutgoingSessionData() {
86 Map<String, Object> modAttrs = null;
87 Set<String> removeAttrs = null;
88 if (isSessionAttributeMapDirty()) {
89 if (attrModifiedMap_.size() > 0) {
90 modAttrs = new HashMap<String, Object>(attrModifiedMap_);
91 }
92
93 if (attrRemovedSet_.size() > 0) {
94 removeAttrs = new HashSet<String>(attrRemovedSet_);
95 }
96
97 clearAttrChangedMaps();
98 }
99 DistributableSessionMetadata metadata = isSessionMetadataDirty() ? getSessionMetadata() : null;
100 Long timestamp = modAttrs != null || removeAttrs != null || metadata != null || getMustReplicateTimestamp() ? Long
101 .valueOf(getSessionTimestamp()) : null;
102 return new OutgoingData(getRealId(), getVersion(), timestamp, metadata, modAttrs, removeAttrs);
103 }
104
105 @Override
106 protected Object getAttributeInternal(String name) {
107 Object result = getAttributesInternal().get(name);
108
109 // Do dirty check even if result is null, as w/ SET_AND_GET null
110 // still makes us dirty (ensures timely replication w/o using ACCESS)
111 if (isGetDirty(result) && !replicationExcludes.contains(name)) {
112 attributeChanged(name, result, false);
113 }
114
115 return result;
116 }
117
118 @Override
119 protected Object removeAttributeInternal(String name, boolean localCall, boolean localOnly) {
120 Object result = getAttributesInternal().remove(name);
121 if (localCall && !replicationExcludes.contains(name))
122 attributeChanged(name, result, true);
123 return result;
124 }
125
126 @Override
127 protected Object setAttributeInternal(String key, Object value) {
128 Object old = getAttributesInternal().put(key, value);
129 if (!replicationExcludes.contains(key))
130 attributeChanged(key, value, false);
131 return old;
132 }
133
134 // ------------------------------------------------------- Private Methods
135
136 private synchronized void attributeChanged(String key, Object value, boolean removal) {
137 if (removal) {
138 if (attrModifiedMap_.containsKey(key)) {
139 attrModifiedMap_.remove(key);
140 }
141 attrRemovedSet_.add(key);
142 } else {
143 if (attrRemovedSet_.contains(key)) {
144 attrRemovedSet_.remove(key);
145 }
146 attrModifiedMap_.put(key, value);
147 }
148 sessionAttributesDirty();
149 }
150
151 private synchronized void clearAttrChangedMaps() {
152 attrRemovedSet_.clear();
153 attrModifiedMap_.clear();
154 }
155
156 // ----------------------------------------------------------------- Classes
157
158 private static class OutgoingData extends OutgoingDistributableSessionDataImpl implements
159 OutgoingAttributeGranularitySessionData {
160 private final Map<String, Object> modifiedAttributes;
161 private final Set<String> removedAttributes;
162
163 public OutgoingData(String realId, int version, Long timestamp, DistributableSessionMetadata metadata,
164 Map<String, Object> modifiedAttributes, Set<String> removedAttributes) {
165 super(realId, version, timestamp, metadata);
166 this.modifiedAttributes = modifiedAttributes;
167 this.removedAttributes = removedAttributes;
168 }
169
170 @Override
171 public Map<String, Object> getModifiedSessionAttributes() {
172 return modifiedAttributes;
173 }
174
175 @Override
176 public Set<String> getRemovedSessionAttributes() {
177 return removedAttributes;
178 }
179 }
180}