2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include <NGObjWeb/WOSessionStore.h>
26 The default session store. It stores all the sessions in memory
27 (it's basically a simple hashmap of the session-id to the session object).
29 If the application goes down, all sessions will go down - this store
30 doesn't provide "session-failover".
33 @interface WOServerSessionStore : WOSessionStore
35 NSMapTable *idToSession;
36 NSMapTable *activeSessions;
40 #include <NGObjWeb/WOContext.h>
41 #include <NGObjWeb/WOApplication.h>
42 #include <NGObjWeb/WOSession.h>
45 /* hh: moved in here from application, check whether it's required ... */
46 @interface WOSessionInfo : NSObject
53 + (WOSessionInfo *)infoForSession:(WOSession *)_session;
55 - (NSString *)sessionID;
56 - (NSDate *)timeoutDate;
60 @implementation WOServerSessionStore
62 static BOOL logExpiredSessions = NO;
65 return [super version] + 0;
68 NSAssert2([super version] == 2,
69 @"invalid superclass (%@) version %i !",
70 NSStringFromClass([self superclass]), [super version]);
74 if ((self = [super init])) {
75 self->idToSession = NSCreateMapTable(NSObjectMapKeyCallBacks,
76 NSObjectMapValueCallBacks,
78 self->activeSessions = NSCreateMapTable(NSObjectMapKeyCallBacks,
79 NSObjectMapValueCallBacks,
81 self->checkedOutSessions = [[NSMutableSet allocWithZone:[self zone]]
84 if ([[[NSUserDefaults standardUserDefaults]
85 objectForKey:@"WORunMultithreaded"]
87 self->lock = [[NSRecursiveLock allocWithZone:[self zone]] init];
88 self->checkoutLock = [[NSConditionLock allocWithZone:[self zone]]
96 if (self->activeSessions) {
97 NSFreeMapTable(self->activeSessions);
98 self->activeSessions = NULL;
100 if (self->idToSession) {
101 NSFreeMapTable(self->idToSession);
102 self->idToSession = NULL;
104 [self->checkedOutSessions release];
105 [self->checkoutLock release];
106 [self->lock release];
112 - (int)activeSessionsCount {
116 count = NSCountMapTable(self->idToSession);
124 - (void)saveSessionForContext:(WOContext *)_context {
125 if (![_context hasSession])
130 WOSession *sn = [_context session];
132 if ([sn isTerminating]) {
135 NSMapRemove(self->idToSession, [sn sessionID]);
136 NSMapRemove(self->activeSessions, [sn sessionID]);
138 NSLog(@"session %@ terminated at %@ ..",
139 [sn sessionID], [NSCalendarDate calendarDate]);
141 [sn release]; sn = nil;
146 NSMapInsert(self->idToSession, [sn sessionID], sn);
148 info = [WOSessionInfo infoForSession:sn];
149 NSMapInsert(self->activeSessions, [sn sessionID], info);
155 - (WOSession *)restoreSessionWithID:(NSString *)_sid
156 request:(WORequest *)_request
158 WOSession *session = nil;
160 if ([_sid length] == 0)
163 if (![_sid isKindOfClass:[NSString class]]) {
165 @"WARNING(%s): got invalid session id (expected string !): %@",
166 __PRETTY_FUNCTION__, _sid];
170 if ([_sid isEqualToString:@"expired"])
174 session = NSMapGet(self->idToSession, _sid);
177 if (logExpiredSessions) {
179 [self logWithFormat:@"session with id %@ expired.", _sid];
187 - (void)sessionExpired:(NSString *)_sessionID {
189 NSMapRemove(self->idToSession, _sessionID);
193 - (void)sessionTerminated:(WOSession *)_session {
194 _session = [_session retain];
196 NSMapRemove(self->idToSession, [_session sessionID]);
200 [[WOApplication application]
202 @"WOServerSessionStore: session %@ terminated.",
203 [_session sessionID]];
206 /* expiration check */
208 - (void)performExpirationCheck:(NSTimer *)_timer {
209 NSNotificationCenter *nc;
210 NSMutableArray *timedOut = nil;
213 WOSessionInfo *info = nil;
217 //NSLog(@"%s: perform expiration check ...", __PRETTY_FUNCTION__);
219 if (self->activeSessions == NULL)
222 count = NSCountMapTable(self->activeSessions);
224 if (!(count > 0 && (self->activeSessions != NULL)))
227 e = NSEnumerateMapTable(self->activeSessions);
230 /* search for expired sessions */
231 while (NSNextMapEnumeratorPair(&e, (void **)&sid, (void **)&info)) {
232 NSDate *timeOutDate = [info timeoutDate];
234 if (timeOutDate == nil) continue;
236 if ([now compare:timeOutDate] != NSOrderedAscending) {
237 [self logWithFormat:@"session %@ expired at %@.", sid, now];
240 timedOut = [NSMutableArray arrayWithCapacity:32];
241 [timedOut addObject:info];
245 /* Expire sessions */
249 nc = [NSNotificationCenter defaultCenter];
251 for (cnt = 0, count = [timedOut count]; cnt < count; cnt++) {
254 info = [timedOut objectAtIndex:cnt];
255 sid = [[info sessionID] copy];
257 NSMapRemove(self->activeSessions, sid);
258 NSMapRemove(self->idToSession, sid);
260 [nc postNotificationName:WOSessionDidTimeOutNotification
269 - (NSString *)description {
270 return [NSString stringWithFormat:@"<%@[0x%08X]: active=%i>",
271 NSStringFromClass([self class]), self,
272 [self activeSessionsCount]
276 @end /* WOServerSessionStore */
278 @implementation WOSessionInfo
280 - (id)initWithSession:(WOSession *)_session {
281 self->sessionID = RETAIN([_session sessionID]);
283 if ([_session respondsToSelector:@selector(timeoutDate)]) {
284 self->timeoutDate = [(id)_session timeoutDate];
287 NSTimeInterval timeOut = [_session timeOut];
289 self->timeoutDate = (timeOut > 0.0)
290 ? [NSDate dateWithTimeIntervalSinceNow:(timeOut + 1.0)]
291 : [NSDate distantFuture];
293 self->timeoutDate = RETAIN(self->timeoutDate);
298 + (WOSessionInfo *)infoForSession:(WOSession *)_session {
299 return AUTORELEASE([[self alloc] initWithSession:_session]);
303 [self->sessionID release];
304 [self->timeoutDate release];
308 - (NSString *)sessionID {
309 return self->sessionID;
311 - (NSDate *)timeoutDate {
312 return self->timeoutDate;
315 @end /* WOSessionInfo */