/** GSWSessionStore.m - GSWeb: Class GSWSessionStore Copyright (C) 1999-2003 Free Software Foundation, Inc. Written by: Manuel Guesdon Date: Jan 1999 $Revision$ $Date$ $Id$ This file is part of the GNUstep Web Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **/ #include "config.h" RCS_ID("$Id$") #include "GSWeb.h" #include #include //==================================================================== @implementation GSWSessionStore //-------------------------------------------------------------------- -(id)init { LOGObjectFnStart(); if ((self=[super init])) { _lock=[NSRecursiveLock new]; _timeOutManager=[GSWSessionTimeOutManager new]; NSDebugMLLog(@"sessions",@"GSWSessionStore self=%p class=%@",self,[self class]); [_timeOutManager setCallBack:@selector(removeSessionWithID:) target:self]; [_timeOutManager startHandleTimerRefusingSessions]; [self _validateAPI]; }; LOGObjectFnStop(); return self; }; //-------------------------------------------------------------------- -(void)dealloc { GSWLogC("Dealloc GSWSessionStore"); GSWLogC("Dealloc GSWSessionStore: lock"); DESTROY(_lock); GSWLogC("Dealloc GSWSessionStore: timeOutManager"); DESTROY(_timeOutManager); GSWLogC("Dealloc GSWSessionStore Super"); [super dealloc]; GSWLogC("End Dealloc GSWSessionStore"); }; //-------------------------------------------------------------------- /** Abstract **/ -(GSWSession*)removeSessionWithID:(NSString*)aSessionID { NSDebugMLLog(@"sessions",@"self=%p class=%@",self,[self class]); [self subclassResponsibility: _cmd]; return nil; }; //-------------------------------------------------------------------- /** Abstract **/ -(GSWSession*)restoreSessionWithID:(NSString*)aSessionID request:(GSWRequest*)aRequest { [self subclassResponsibility: _cmd]; return nil; }; //-------------------------------------------------------------------- /** Abstract **/ -(void)saveSessionForContext:(GSWContext*)aContext { [self subclassResponsibility: _cmd]; }; //-------------------------------------------------------------------- -(GSWSession*)checkOutSessionWithID:(NSString*)aSessionID request:(GSWRequest*)aRequest { GSWSession* session=nil; BOOL isCheckedOut=YES; int tryCount=0; int startTime=(int)time(NULL); int currentTime=startTime; int expirationTime=60; // default exp time is 60s //OK LOGObjectFnStart(); NSDebugMLLog(@"sessions",@"aSessionID=%@",aSessionID); NSDebugMLLog(@"sessions",@"self=%@",self); do { tryCount++; if ([self tryLock]) { GSWSessionTimeOut* entry=[_timeOutManager sessionTimeOutForSessionID:aSessionID]; NS_DURING { expirationTime=(int)[entry sessionTimeOut];//seconds //NSLog(@"expirationTime=%d",(int)expirationTime); isCheckedOut=[entry isCheckedOut]; // See if session is used //NSLog(@"aSessionID=%@ isCheckedOut=%d",aSessionID,(int)isCheckedOut); //NSLog(@"entry=%@",(int)entry); // if it is not used, restore it and so on.... if (!isCheckedOut) { session=[self restoreSessionWithID:aSessionID request:aRequest]; if (session) { //NSLog(@"CheckOut: %@. SessionID:%@",aSessionID,[session sessionID]); // If sessionID has Changed, re-find entry if (![[session sessionID] isEqualToString:aSessionID]) { aSessionID=[session sessionID]; entry=[_timeOutManager sessionTimeOutForSessionID:aSessionID]; }; isCheckedOut=[entry isCheckedOut]; if (!isCheckedOut) { [session _createAutoreleasePool]; [entry setIsCheckedOut:YES]; }; }; }; } NS_HANDLER { NSDebugMLLog(@"sessions",@"Can't checkOutSessionID=%@",aSessionID); localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException, @"In checkOutSessionWithID:request:"); LOGException(@"%@ (%@)",localException,[localException reason]); // Put the previous check in/out state [entry setIsCheckedOut:isCheckedOut]; [self unlock]; [localException raise]; } NS_ENDHANDLER; [self unlock]; currentTime=(int)time(NULL); if (isCheckedOut) // Session already check out. Wait... { NSTimeIntervalSleep(0.010); // sleep for 10 ms if (tryCount%100==0) NSLog(@"Try check out %@ for %d seconds (tryCount=%d)",aSessionID,(currentTime-startTime),tryCount); }; } else { NSLog(@"Try lock failed"); currentTime=(int)time(NULL); }; } while(isCheckedOut && (currentTime-startTime)