Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 940

Show
Ignore:
Timestamp:
01/26/06 05:59:08
Author:
rdelon
Message:

Improvements to sessionfilter: using lazy loading of session data (so data is never loaded/saved if user doesn't access it). Make acquire_lock work as expected.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/filters/sessionfilter.py

    r938 r940  
    66 
    77Variables used to store config options: 
    8     - sess.sessionTimeout: timeout delay for the session 
    9     - sess.sessionLocking: mechanism used to lock the session ('implicit' or 'explicit') 
     8    - sess.session_timeout: timeout delay for the session 
     9    - sess.session_locking: mechanism used to lock the session ('implicit' or 'explicit') 
    1010 
    1111Variables used to store temporary variables: 
     
    1515Variables used to store the session for the current request: 
    1616    - sess.session_data: dictionary containing the actual session data 
    17     - sess.sessionID: current session ID 
     17    - sess.session_id: current session ID 
    1818    - sess.expiration_time: date/time when the current session will expire 
    1919 
    2020Global variables (RAM backend only): 
    21     - cherrypy._session_lock_dict: dictionary containing the locks for all sessionIDs 
    22     - cherrypy._sessionHolder: dictionary containing the data for all sessions 
     21    - cherrypy._session_lock_dict: dictionary containing the locks for all session_id 
     22    - cherrypy._session_data_holder: dictionary containing the data for all sessions 
    2323 
    2424""" 
     
    6464         
    6565        sess = cherrypy.request._session 
    66         now = datetime.datetime.now() 
    6766        # Dont enable session if session_filter is off or if this is a 
    6867        #   request for static data 
     
    7170            sess.session_storage = None 
    7271            return 
    73          
     72 
    7473        sess.locked = False # Not locked by default 
     74        sess.to_be_loaded = True 
    7575         
    7676        # Read config options 
    77         sess.sessionTimeout = conf('session_filter.timeout', 60) 
    78         sess.sessionLocking = conf('session_filter.locking', 'explicit') 
    79         sess.onCreateSession = conf('session_filter.on_create_session', 
     77        sess.session_timeout = conf('session_filter.timeout', 60) 
     78        sess.session_locking = conf('session_filter.locking', 'explicit') 
     79        sess.on_create_session = conf('session_filter.on_create_session', 
    8080                lambda data: None) 
    81         sess.onDeleteSession = conf('session_filter.on_delete_session', 
     81        sess.on_delete_session = conf('session_filter.on_delete_session', 
    8282                lambda data: None) 
    8383        sess.generate_session_id = conf('session_filter.on_delete_session', 
    8484                generate_session_id) 
    8585         
    86         cleanUpDelay = conf('session_filter.clean_up_delay', 5) 
    87         cleanUpDelay = datetime.timedelta(seconds = cleanUpDelay * 60) 
    88          
    89         cookieName = conf('session_filter.cookie_name', 'sessionID') 
    90         cookieDomain = conf('session_filter.cookie_domain', None) 
    91         cookieSecure = conf('session_filter.cookie_secure', False) 
    92         cookiePath = conf('session_filter.cookie_path', None) 
    93  
    94         if cookiePath is None: 
    95             cookiePathHeader = conf('session_filter.cookie_path_from_header', None) 
    96             if cookiePathHeader is not None: 
    97                 cookiePath = cherrypy.request.headerMap.get(cookiePathHeader, None) 
    98             if cookiePath is None: 
    99                 cookiePath = '/' 
    100  
    101         sess.deadlockTimeout = conf('session_filter.deadlock_timeout', 30) 
     86        clean_up_delay = conf('session_filter.clean_up_delay', 5) 
     87        clean_up_delay = datetime.timedelta(seconds = clean_up_delay * 60) 
     88         
     89        cookie_name = conf('session_filter.cookie_name', 'session_id') 
     90        cookie_domain = conf('session_filter.cookie_domain', None) 
     91        cookie_secure = conf('session_filter.cookie_secure', False) 
     92        cookie_path = conf('session_filter.cookie_path', None) 
     93 
     94        if cookie_path is None: 
     95            cookie_path_header = conf('session_filter.cookie_path_from_header', None) 
     96            if cookie_path_header is not None: 
     97                cookie_path = cherrypy.request.headerMap.get(cookie_path_header, None) 
     98            if cookie_path is None: 
     99                cookie_path = '/' 
     100 
     101        sess.deadlock_timeout = conf('session_filter.deadlock_timeout', 30) 
    102102         
    103103        storage = conf('session_filter.storage_type', 'Ram') 
     
    113113         
    114114        # Check if we need to clean up old sessions 
    115         if cherrypy._session_last_clean_up_time + cleanUpDelay < now: 
     115        if cherrypy._session_last_clean_up_time + clean_up_delay < \ 
     116                datetime.datetime.now(): 
    116117            sess.session_storage.clean_up() 
    117118         
    118119        # Check if request came with a session ID 
    119         if cookieName in cherrypy.request.simpleCookie: 
    120             # It did: we try to load the session data 
    121             sess.sessionID = cherrypy.request.simpleCookie[cookieName].value 
     120        if cookie_name in cherrypy.request.simpleCookie: 
     121            # It did: we mark the data as needing to be loaded 
     122            sess.session_id = cherrypy.request.simpleCookie[cookie_name].value 
    122123             
    123124            # If using implicit locking, acquire lock 
    124             if sess.sessionLocking == 'implicit': 
    125                 sess.session_data = {'_id': sess.sessionID
     125            if sess.session_locking == 'implicit': 
     126                sess.session_data = {'_id': sess.session_id
    126127                sess.session_storage.acquire_lock() 
    127128             
    128             data = sess.session_storage.load(sess.sessionID) 
    129             # data is either None or a tuple (session_data, expiration_time) 
    130             if data is None or data[1] < now: 
    131                 # Expired session: 
    132                 # flush session data (but keep the same sessionID) 
    133                 sess.session_data = {'_id': sess.sessionID} 
    134             else: 
    135                 sess.session_data = data[0] 
     129            sess.to_be_loaded = True 
     130 
    136131        else: 
    137             # No sessionID yet 
    138             sess.sessionID = sess.generate_session_id() 
    139             sess.session_data = {'_id': sess.sessionID
    140             sess.onCreateSession(sess.session_data) 
     132            # No session_id yet 
     133            sess.session_id = sess.generate_session_id() 
     134            sess.session_data = {'_id': sess.session_id
     135            sess.on_create_session(sess.session_data) 
    141136        # Set response cookie 
    142137        cookie = cherrypy.response.simpleCookie 
    143         cookie[cookieName] = sess.sessionID 
    144         cookie[cookieName]['path'] = cookiePath 
    145         cookie[cookieName]['max-age'] = sess.sessionTimeout * 60 
    146         cookie[cookieName]['version'] = 1 
    147         if cookieDomain is not None: 
    148             cookie[cookieName]['domain'] = cookieDomain 
    149         if cookieSecure is True: 
    150             cookie[cookieName]['secure'] = 1 
     138        cookie[cookie_name] = sess.session_id 
     139        cookie[cookie_name]['path'] = cookie_path 
     140        cookie[cookie_name]['max-age'] = sess.session_timeout * 60 
     141        cookie[cookie_name]['version'] = 1 
     142        if cookie_domain is not None: 
     143            cookie[cookie_name]['domain'] = cookie_domain 
     144        if cookie_secure is True: 
     145            cookie[cookie_name]['secure'] = 1 
    151146     
    152147    def before_finalize(self): 
     
    159154             
    160155            # Save session data 
    161             t = datetime.timedelta(seconds = sess.sessionTimeout * 60) 
    162             expiration_time = datetime.datetime.now() + t 
    163             sess.session_storage.save(sess.sessionID, sess.session_data, 
    164                                      expiration_time) 
     156            if sess.to_be_loaded is False: 
     157                t = datetime.timedelta(seconds = sess.session_timeout * 60) 
     158                expiration_time = datetime.datetime.now() + t 
     159                sess.session_storage.save(sess.session_id, 
     160                        sess.session_data, expiration_time) 
     161            else: 
     162                # If session data has never been loaded then it's never been 
     163                #   accesses: not need to delete it 
     164                pass 
    165165            if sess.locked: 
    166166                # Always release the lock if the user didn't release it 
     
    205205    def acquire_lock(self): 
    206206        sess = cherrypy.request._session 
    207         id = cherrypy.session['_id'] 
     207        id = cherrypy.session.id 
    208208        lock = cherrypy._session_lock_dict.get(id) 
    209209        if lock is None: 
     
    214214            if lock.acquire(False): 
    215215                break 
    216             if time.time() - startTime > sess.deadlockTimeout: 
     216            if time.time() - startTime > sess.deadlock_timeout: 
    217217                raise SessionDeadlockError() 
    218218            time.sleep(0.5) 
     
    236236                deleted_session = cherrypy._session_data_holder[id] 
    237237                del cherrypy._session_data_holder[id] 
    238                 sess.onDeleteSession(deleted_session) 
     238                sess.on_delete_session(deleted_session) 
    239239            except KeyError: 
    240240                # The session probably got deleted by a concurrent thread 
     
    267267    def acquire_lock(self): 
    268268        sess = cherrypy.request._session 
    269         filePath = self._getFilePath(cherrypy.session['_id']
     269        filePath = self._getFilePath(cherrypy.session.id
    270270        lockFilePath = filePath + self.LOCK_SUFFIX 
    271271        self._lockFile(lockFilePath) 
     
    274274    def release_lock(self): 
    275275        sess = cherrypy.request._session 
    276         filePath = self._getFilePath(cherrypy.session['_id']
     276        filePath = self._getFilePath(cherrypy.session.id
    277277        lockFilePath = filePath + self.LOCK_SUFFIX 
    278278        self._unlockFile(lockFilePath) 
     
    298298                        # Session expired: deleting it 
    299299                        id = fname[len(self.SESSION_PREFIX):] 
    300                         sess.onDeleteSession(data) 
     300                        sess.on_delete_session(data) 
    301301                        os.unlink(filePath) 
    302302                except: 
     
    317317                lockfd = os.open(path, os.O_CREAT|os.O_WRONLY|os.O_EXCL) 
    318318            except OSError: 
    319                 if time.time() - startTime > sess.deadlockTimeout: 
     319                if time.time() - startTime > sess.deadlock_timeout: 
    320320                    raise SessionDeadlockError() 
    321321                time.sleep(0.5) 
     
    377377        self.cursor.execute( 
    378378            'select id from session where id=%s for update', 
    379             (cherrypy.session['_id'],)) 
     379            (cherrypy.session.id,)) 
    380380     
    381381    def release_lock(self): 
     
    393393        rows = self.cursor.fetchall() 
    394394        for row in rows: 
    395             sess.onDeleteSession(row[0]) 
     395            sess.on_delete_session(row[0]) 
    396396        self.cursor.execute( 
    397397            'delete from session where expiration_time < %s', 
     
    400400 
    401401def generate_session_id(): 
    402     """ Return a new sessionID """ 
     402    """ Return a new session_id """ 
    403403    return sha.new('%s' % random.random()).hexdigest() 
    404404 
     
    415415            raise SessionNotEnabledError() 
    416416        # Create thread-specific dictionary if needed 
    417         sess.session_data = getattr(sess, 'session_data', {}) 
     417        session_data = getattr(sess, 'session_data', None) 
     418        if session_data is None: 
     419            sess.session_data = {} 
    418420        if name == 'acquire_lock': 
    419421            return sess.session_storage.acquire_lock 
    420422        elif name == 'release_lock': 
    421423            return sess.session_storage.release_lock 
     424        elif name == 'id': 
     425            return sess.session_id 
     426 
     427        if sess.to_be_loaded: 
     428            data = sess.session_storage.load(sess.session_id) 
     429            # data is either None or a tuple (session_data, expiration_time) 
     430            if data is None or data[1] < datetime.datetime.now(): 
     431                # Expired session: 
     432                # flush session data (but keep the same session_id) 
     433                sess.session_data = {'_id': sess.session_id} 
     434            else: 
     435                sess.session_data = data[0] 
     436            sess.to_be_loaded = False 
     437 
    422438        return getattr(sess.session_data, name) 
    423439 

Hosted by WebFaction

Log in as guest/cpguest to create tickets