001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.terracotta.session;
006:
007: import com.tc.object.bytecode.Manageable;
008: import com.tc.object.bytecode.ManagerUtil;
009: import com.terracotta.session.util.Assert;
010: import com.terracotta.session.util.ContextMgr;
011: import com.terracotta.session.util.LifecycleEventMgr;
012: import com.terracotta.session.util.Lock;
013: import com.terracotta.session.util.Timestamp;
014:
015: import java.util.Hashtable;
016: import java.util.Map;
017: import java.util.Set;
018:
019: public class SessionDataStore {
020:
021: private final Map store; // <SessionData>
022: private final Map dtmStore; // <Timestamp>
023: private final int maxIdleTimeoutSeconds;
024: private final ContextMgr ctxMgr;
025: private final LifecycleEventMgr lifecycleEventMgr;
026: private final SessionManager sessionManager;
027:
028: public SessionDataStore(String appName, int maxIdleTimeoutSeconds,
029: LifecycleEventMgr lifecycleEventMgr, ContextMgr ctxMgr,
030: SessionManager sessionManager) {
031: this .sessionManager = sessionManager;
032: Assert.pre(appName != null && appName.length() > 0);
033:
034: this .maxIdleTimeoutSeconds = maxIdleTimeoutSeconds;
035: this .lifecycleEventMgr = lifecycleEventMgr;
036: this .ctxMgr = ctxMgr;
037:
038: final String sessionRootName = "tc:session_" + appName;
039: final String dtmRootName = "@tc:session_timestamp_" + appName;
040: final Lock lock = new Lock(sessionRootName);
041: lock.getWriteLock();
042: try {
043: this .store = (Hashtable) ManagerUtil
044: .lookupOrCreateRootNoDepth(sessionRootName,
045: new Hashtable());
046: ((Manageable) store).__tc_managed().disableAutoLocking();
047: this .dtmStore = (Hashtable) ManagerUtil
048: .lookupOrCreateRootNoDepth(dtmRootName,
049: new Hashtable());
050: ((Manageable) dtmStore).__tc_managed().disableAutoLocking();
051: } finally {
052: lock.commitLock();
053: }
054: Assert.post(store != null);
055: }
056:
057: /**
058: * <ol>
059: * <li>get WRITE_LOCK for sessId
060: * <li>creates session data
061: * <li>put newly-created SessionData into the global Map
062: * <li>returns newly-created SessionData
063: * </ol>
064: */
065: public SessionData createSessionData(final SessionId sessId) {
066: Assert.pre(sessId != null);
067: SessionData rv = null;
068: sessId.getWriteLock();
069: rv = new SessionData(maxIdleTimeoutSeconds);
070: rv.associate(sessId, lifecycleEventMgr, ctxMgr, sessionManager);
071: store.put(sessId.getKey(), rv);
072: dtmStore.put(sessId.getKey(), rv.getTimestamp());
073: rv.startRequest();
074: return rv;
075: }
076:
077: /**
078: * <ol>
079: * <li>get WRITE_LOCK for sessId
080: * <li>look up SessionData for sessId.getKey() in the global Map
081: * <li>if SessionData is invalid, unlock sessId and return null (invalidator will take care of killing this session)
082: * <li>return valid SessionData
083: */
084: public SessionData find(final SessionId sessId) {
085: Assert.pre(sessId != null);
086:
087: SessionData rv = null;
088: sessId.getWriteLock();
089: try {
090: rv = (SessionData) store.get(sessId.getKey());
091: if (rv != null) {
092: rv.associate(sessId, lifecycleEventMgr, ctxMgr,
093: sessionManager);
094: rv.startRequest();
095: if (!rv.isValid())
096: rv = null;
097: else {
098: updateTimestampIfNeeded(rv);
099: }
100: }
101: } finally {
102: if (rv == null)
103: sessId.commitLock();
104: }
105: return rv;
106: }
107:
108: void updateTimestampIfNeeded(SessionData sd) {
109: Assert.pre(sd != null);
110:
111: if (sd.neverExpires()) {
112: return;
113: }
114:
115: final long now = System.currentTimeMillis();
116: final Timestamp t = sd.getTimestamp();
117: final long diff = t.getMillis() - now;
118:
119: if (diff < (sd.getMaxInactiveMillis() / 2)
120: || diff > (sd.getMaxInactiveMillis())) {
121: t.setMillis(now + sd.getMaxInactiveMillis());
122: }
123: }
124:
125: public void remove(final SessionId id) {
126: Assert.pre(id != null);
127: id.getWriteLock();
128: try {
129: store.remove(id.getKey());
130: dtmStore.remove(id.getKey());
131: } finally {
132: id.commitLock();
133: }
134: }
135:
136: public String[] getAllKeys() {
137: String[] rv;
138: synchronized (store) {
139: Set keys = store.keySet();
140: rv = (String[]) keys.toArray(new String[keys.size()]);
141: }
142: Assert.post(rv != null);
143: return rv;
144: }
145:
146: Timestamp findTimestampUnlocked(final SessionId sessId) {
147: return (Timestamp) dtmStore.get(sessId.getKey());
148: }
149:
150: SessionData findSessionDataUnlocked(final SessionId sessId) {
151: final SessionData rv = (SessionData) store.get(sessId.getKey());
152: if (rv != null) {
153: rv.associate(sessId, lifecycleEventMgr, ctxMgr,
154: sessionManager);
155: }
156: return rv;
157: }
158:
159: }
|