📄 session.py
字号:
def do_delete(self): _apache._global_lock(self._req.server, None, 0) dbm = self._get_dbm() try: try: del dbm[self._sid] except KeyError: pass finally: dbm.close() _apache._global_unlock(self._req.server, None, 0)############################################################################# FileSessionDFT_FAST_CLEANUP = True DFT_VERIFY_CLEANUP = True DFT_GRACE_PERIOD = 240DFT_CLEANUP_TIME_LIMIT = 2# Credits : this was initially contributed by dharana <dharana@dharana.net>class FileSession(BaseSession): def __init__(self, req, sid=0, secret=None, timeout=0, lock=1, fast_cleanup=-1, verify_cleanup=-1): opts = req.get_options() if fast_cleanup == -1: if opts.has_key('mod_python.file_session.enable_fast_cleanup'): self._fast_cleanup = true_or_false(opts.get('mod_python.file_session.enable_fast_cleanup', DFT_FAST_CLEANUP)) else: # For backwards compatability with versions # of mod_python prior to 3.3. self._fast_cleanup = true_or_false(opts.get('session_fast_cleanup', DFT_FAST_CLEANUP)) else: self._fast_cleanup = fast_cleanup if verify_cleanup == -1: if opts.has_key('mod_python.file_session.verify_session_timeout'): self._verify_cleanup = true_or_false(opts.get('mod_python.file_session.verify_session_timeout', DFT_VERIFY_CLEANUP)) else: # For backwards compatability with versions # of mod_python prior to 3.3. self._verify_cleanup = true_or_false(opts.get('session_verify_cleanup', DFT_VERIFY_CLEANUP)) else: self._verify_cleanup = verify_cleanup if opts.has_key('mod_python.file_session.cleanup_grace_period'): self._grace_period = int(opts.get('mod_python.file_session.cleanup_grace_period', DFT_GRACE_PERIOD)) else: # For backwards compatability with versions # of mod_python prior to 3.3. self._grace_period = int(opts.get('session_grace_period', DFT_GRACE_PERIOD)) if opts.has_key('mod_python.file_session.cleanup_time_limit'): self._cleanup_time_limit = int(opts.get('mod_python.file_session.cleanup_time_limit',DFT_CLEANUP_TIME_LIMIT)) else: # For backwards compatability with versions # of mod_python prior to 3.3. self._cleanup_time_limit = int(opts.get('session_cleanup_time_limit',DFT_CLEANUP_TIME_LIMIT)) if opts.has_key('mod_python.file_session.database_directory'): self._sessdir = os.path.join(opts.get('mod_python.file_session.database_directory', tempdir), 'mp_sess') elif opts.has_key('mod_python.session.database_directory'): self._sessdir = os.path.join(opts.get('mod_python.session.database_directory', tempdir), 'mp_sess') else: # For backwards compatability with versions # of mod_python prior to 3.3. self._sessdir = os.path.join(opts.get('session_directory', tempdir), 'mp_sess') # FIXME if timeout: self._cleanup_timeout = timeout else: self._cleanup_timeout = DFT_TIMEOUT BaseSession.__init__(self, req, sid=sid, secret=secret, timeout=timeout, lock=lock) def do_cleanup(self): data = {'req':self._req, 'sessdir':self._sessdir, 'fast_cleanup':self._fast_cleanup, 'verify_cleanup':self._verify_cleanup, 'timeout':self._cleanup_timeout, 'grace_period':self._grace_period, 'cleanup_time_limit': self._cleanup_time_limit, } self._req.register_cleanup(filesession_cleanup, data) self._req.log_error("FileSession: registered filesession cleanup.", apache.APLOG_NOTICE) def do_load(self): self.lock_file() try: try: path = os.path.join(self._sessdir, self._sid[0:2]) filename = os.path.join(path, self._sid) fp = file(filename,'rb') try: data = cPickle.load(fp) if (time.time() - data["_accessed"]) <= data["_timeout"]: # Change the file access time to the current time so the # cleanup does not delete this file before the request # can save it's session data os.utime(filename,None) return data finally: fp.close() except: s = cStringIO.StringIO() traceback.print_exc(file=s) s = s.getvalue() self._req.log_error('Error while loading a session : %s'%s) return None finally: self.unlock_file() def do_save(self, dict): self.lock_file() try: try: path = os.path.join(self._sessdir, self._sid[0:2]) if not os.path.exists(path): make_filesession_dirs(self._sessdir) filename = os.path.join(path, self._sid) fp = file(filename, 'wb') try: cPickle.dump(dict, fp, 2) finally: fp.close() except: s = cStringIO.StringIO() traceback.print_exc(file=s) s = s.getvalue() self._req.log_error('Error while saving a session : %s'%s) finally: self.unlock_file() def do_delete(self): self.lock_file() try: try: path = os.path.join(self._sessdir, self._sid[0:2]) filename = os.path.join(path, self._sid) os.unlink(filename) except Exception: pass finally: self.unlock_file() def lock_file(self): # self._lock = 1 indicates that session locking is turned on, # so let BaseSession handle it. # Otherwise, explicitly acquire a lock for the file manipulation. if not self._locked: _apache._global_lock(self._req.server, self._sid) self._locked = 1 def unlock_file(self): if self._locked and not self._lock: _apache._global_unlock(self._req.server, self._sid) self._locked = 0FS_STAT_VERSION = 'MPFS_3.2'def filesession_cleanup(data): # There is a small chance that a the cleanup for a given session file # may occur at the exact time that the session is being accessed by # another request. It is possible under certain circumstances for that # session file to be saved in another request only to immediately deleted # by the cleanup. To avoid this race condition, a session is allowed a # grace_period before it is considered for deletion by the cleanup. # As long as the grace_period is longer that the time it takes to complete # the request (which should normally be less than 1 second), the session will # not be mistakenly deleted by the cleanup. By doing this we also avoid the # need to lock individual sessions and bypass any potential deadlock # situations. req = data['req'] sessdir = data['sessdir'] fast_cleanup = data['fast_cleanup'] verify_cleanup = data['verify_cleanup'] timeout = data['timeout'] grace_period = data['grace_period'] cleanup_time_limit = data['cleanup_time_limit'] req.log_error('FileSession cleanup: (fast=%s, verify=%s) ...' % (fast_cleanup,verify_cleanup), apache.APLOG_NOTICE) lockfile = os.path.join(sessdir,'.mp_sess.lck') try: lockfp = os.open(lockfile, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0660) except: # check if it's a stale lockfile mtime = os.stat(lockfile).st_mtime if mtime < (time.time() - 3600): # lockfile is over an hour old so it's likely stale. # Even though there may not be another cleanup process running, # we are going to defer running the cleanup at this time. # Short circuiting this cleanup just makes the code a little cleaner. req.log_error('FileSession cleanup: stale lockfile found - deleting it', apache.APLOG_NOTICE) # Remove the stale lockfile so the next call to filesession_cleanup # can proceed. os.remove(lockfile) else: req.log_error('FileSession cleanup: another process is already running', apache.APLOG_NOTICE) return try: status_file = file(os.path.join(sessdir, 'fs_status.txt'), 'r') d = status_file.readline() status_file.close() if not d.startswith(FS_STAT_VERSION): raise Exception, 'wrong status file version' parts = d.split() stat_version = parts[0] next_i = int(parts[1]) expired_file_count = int(parts[2]) total_file_count = int(parts[3]) total_time = float(parts[4]) except: stat_version = FS_STAT_VERSION next_i = 0 expired_file_count = 0 total_file_count = 0 total_time = 0.0 try: start_time = time.time() filelist = os.listdir(sessdir) dir_index = range(0,256)[next_i:] for i in dir_index: path = '%s/%s' % (sessdir,'%02x' % i) if not os.path.exists(path): continue filelist = os.listdir(path) total_file_count += len(filelist) for f in filelist: try: filename = os.path.join(path,f) if fast_cleanup: accessed = os.stat(filename).st_mtime if time.time() - accessed < (timeout + grace_period): continue if fast_cleanup and not verify_cleanup: delete_session = True else: try: fp = file(filename) dict = cPickle.load(fp) if (time.time() - dict['_accessed']) > (dict['_timeout'] + grace_period): delete_session = True else: delete_session = False finally: fp.close() if delete_session: os.unlink(filename) expired_file_count += 1 except: s = cStringIO.StringIO() traceback.print_exc(file=s) s = s.getvalue() req.log_error('FileSession cleanup error: %s' % (s), apache.APLOG_NOTICE) next_i = (i + 1) % 256 time_used = time.time() - start_time if (cleanup_time_limit > 0) and (time_used > cleanup_time_limit): break total_time += time.time() - start_time if next_i == 0: # next_i can only be 0 when the full cleanup has run to completion req.log_error("FileSession cleanup: deleted %d of %d in %.4f seconds" % (expired_file_count, total_file_count, total_time), apache.APLOG_NOTICE) expired_file_count = 0 total_file_count = 0 total_time = 0.0 else: req.log_error("FileSession cleanup incomplete: next cleanup will start at index %d (%02x)" % (next_i,), apache.APLOG_NOTICE) status_file = file(os.path.join(sessdir, 'fs_status.txt'), 'w') status_file.write('%s %d %d %d %f\n' % (stat_version, next_i, expired_file_count, total_file_count, total_time)) status_file.close() try: os.unlink(lockfile) except: pass finally: os.close(lockfp)def make_filesession_dirs(sess_dir): """Creates the directory structure used for storing session files""" for i in range(0,256): path = os.path.join(sess_dir, '%02x' % i) if not os.path.exists(path): os.makedirs(path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP)############################################################################# MemorySessiondef mem_cleanup(sdict): for sid in sdict.keys(): try: session = sdict[sid] if (time.time() - session["_accessed"]) > session["_timeout"]: del sdict[sid] except: passclass MemorySession(BaseSession): sdict = {} def __init__(self, req, sid=0, secret=None, timeout=0, lock=1): BaseSession.__init__(self, req, sid=sid, secret=secret, timeout=timeout, lock=lock) def do_cleanup(self): self._req.register_cleanup(mem_cleanup, MemorySession.sdict) self._req.log_error("MemorySession: registered session cleanup.", apache.APLOG_NOTICE) def do_load(self): if MemorySession.sdict.has_key(self._sid): return MemorySession.sdict[self._sid] return None def do_save(self, dict): MemorySession.sdict[self._sid] = dict def do_delete(self): try: del MemorySession.sdict[self._sid] except KeyError: pass############################################################################# Sessiondef Session(req, sid=0, secret=None, timeout=0, lock=1): opts = req.get_options() # Check the apache config for the type of session if opts.has_key('mod_python.session.session_type'): sess_type = opts['mod_python.session.session_type'] elif opts.has_key('session'): # For backwards compatability with versions # of mod_python prior to 3.3. sess_type = opts['session'] else: # no session class in config so get the default for the platform threaded = _apache.mpm_query(apache.AP_MPMQ_IS_THREADED) forked = _apache.mpm_query(apache.AP_MPMQ_IS_FORKED) daemons = _apache.mpm_query(apache.AP_MPMQ_MAX_DAEMONS) if (threaded and ((not forked) or (daemons == 1))): sess_type = 'MemorySession' else: sess_type = 'DbmSession' if sess_type == 'FileSession': sess = FileSession elif sess_type == 'DbmSession': sess = DbmSession elif sess_type == 'MemorySession': sess = MemorySession else: # TODO Add capability to load a user defined class # For now, just raise an exception. raise Exception, 'Unknown session type %s' % sess_type return sess(req, sid=sid, secret=secret, timeout=timeout, lock=lock)## helper functionsdef true_or_false(item): """This function is used to assist in getting appropriate values set with the PythonOption directive """ try: item = item.lower() except: pass if item in ['yes','true', '1', 1, True]: return True elif item in ['no', 'false', '0', 0, None, False]: return False else: raise Exception
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -