Mercurial > hg > env-test-daniele
view DirectorySession.py @ 0:032bc65ebafc
added core components
author | George Fazekas <gyorgy.fazekas@eecs.qmul.ac.uk> |
---|---|
date | Wed, 06 Mar 2013 15:45:48 +0000 |
parents | |
children | 89978106f0bb |
line wrap: on
line source
""" DiractorySession.py Created by George Fazekas, QMUL on 2009-06-03. Copyright (c) 2009 QMUL. All rights reserved. This Cherrypy extension implements a hybrid session type, where data is held in memory, while files are written to a directory created for each session. To use it as a builtin session type, we use: cherrypy.lib.sessions.DirectorySession = DirectorySession """ from __future__ import with_statement import os,sys,time,shutil,datetime,logging,threading,cherrypy from cherrypy.lib.sessions import Session from cherrypy.lib import static from sawautil import convertFilename class DirectorySession(Session): cache = {} locks = {} instanceList = [] def __init__(self, id=None, **kwargs): # for i in self.instanceList : # print 'previous-sessions: ', i.id # if (i.id == id) : # print 'got instance already!' # self.instanceList.append(self) # print 'instance initialised:' + str(len(self.instanceList)) # kwargs['SESSIONS_PATH'] = os.path.abspath(kwargs['SESSIONS_PATH']) if not id in self.cache: new_session_signal = True else : new_session_signal = False Session.__init__(self, id=id, **kwargs) if new_session_signal or not self.has_key('name'): active_sessions = str(self.__len__()) self.name = "Session %s.%s: " %(active_sessions, str(self.id)[-2:]) self['name'] = self.name self['log_count'] = 0 try : # try to write initial session data into the log file log_msg = "%sCherrypy::DirectorySession:New Session Created: ID = %s active sessions: %s \n" %(self.name,str(self.id),active_sessions) log_msg += '\n'.join(map ( lambda x: " %s: %s " %x , cherrypy.request.headers.items() )) cherrypy.log(log_msg) except : print "An error has occured while writing initial session data to the log file." def setup(cls,**kwargs): print 'Setting up storage class... Nothing to do here yet.' for k, v in kwargs.iteritems(): setattr(cls, k, v) print k,v # cls.SESSIONS_PATH = kwargs['SESSIONS_PATH'] we could setup a cleanup thread here for the dirs too. kwargs['sessions_path'] = os.path.abspath(kwargs['sessions_path']) # NOTE: This is now passed in via tools.config: # tools.sessions.SESSIONS_PATH # DELETION COMMENTED OUT #if (os.path.exists(cls.SESSIONS_PATH)) : # shutil.rmtree (cls.SESSIONS_PATH, ignore_errors=True, onerror=None) # cherrypy.log('Cherrypy::DirectorySession:setup (classmethod) Existing session directory removed.') if not (os.path.exists(cls.SESSIONS_PATH)) : os.mkdir(cls.SESSIONS_PATH) cherrypy.log('Cherrypy::DirectorySession:setup (classmethod) New sessions path created: %s' %str(cls.SESSIONS_PATH)) setup = classmethod(setup) def get_session_name(self): """ Return the human readable name of the session. """ if self.has_key('name') : return self['name'] else : return 'Session None: ' def log(self,msg,context='',severity=logging.DEBUG,traceback=True): """ Write into cherrypy.log using the session prefix.""" if not self.has_key('log_count') : self['log_count'] = 0 log_msg = self.get_session_name() + "m%03i. %s" %(self['log_count'],msg) self['log_count'] += 1 cherrypy.log(log_msg,context,severity,traceback) def get_session_path(self): """ Return a valid path for this session """ if self.has_key('session_path') : return self.get('session_path',None) else : if not self.id : raise AssertionError("Can not create directory for uninitialised session.") return None sessionPath = os.path.join(self.SESSIONS_PATH,str(self.id)) if os.path.exists(sessionPath) : # clash of session IDs (unprobable), flush data shutil.rmtree (sessionPath, ignore_errors=True, onerror=None) print "flushed data in %s" % sessionPath try : os.makedirs(sessionPath) except: raise IOError("Session directory for id %r not created." % self.id) return None if os.path.exists(sessionPath) : # create an entry in self so that the clean_up thread knows about this session # setattr(self._data,'session_path',sessionPath) self['session_path'] = sessionPath return sessionPath # TODO: the other use case: write the output of a pipe def write_file(self,fileObj,fileName,filetype = None): pass def write_data(self,data,filename,filetype = None): data = str(data) sessionPath = self.get_session_path() filePath = os.path.join(sessionPath,filename) # print 'writing file to: ',filePath with open(filePath,'wb') as f: f.writelines(data) # check file and save filetype key if given if not os.path.exists(filePath) \ or not os.stat(filePath).st_size > 0 : cherrypy.log("Session x.xx: mxxx. Cherrypy::DirectorySession:write_data: Warning: Could not verify file: %s " %filePath) return False elif not filetype : return True elif self.has_key(filetype) : ol = self.get(filetype,None) ol.append(os.path.basename(filePath)) self[filetype] = list(ol) else : self[filetype]= list([os.path.basename(filePath)]) self.save() return True def write_fsfile(self,fsFile,filetype = None): '''Write file to session given as CGI field-storage object.''' #fsFile is a cgi.FieldStorage object : cherrypy._cpcgifs.FieldStorage() if hasattr (fsFile,'filename') and hasattr(fsFile,'file'): return self._write_file(fsFile.file,fsFile.filename,filetype) def write_fsfile_as(self,fsFile,filename,filetype = None): '''Write file to session given as CGI field-storage object.''' #fsFile is a cgi.FieldStorage object : cherrypy._cpcgifs.FieldStorage() if hasattr (fsFile,'filename') and hasattr(fsFile,'file'): return self._write_file(fsFile.file,filename,filetype) def _write_file(self,file,filename,filetype): '''Write file to session given as python file object.''' filename = convertFilename(filename) sessionPath = self.get_session_path() filePath = os.path.join(sessionPath,filename) # print 'writing file to: ',filePath file.seek(0) newFile = open(filePath,'wb') try : shutil.copyfileobj(file,newFile) except : try : while True: data = file.read(8192) if not data: break newFile.write(data) except: # newFile.close() cherrypy.log("Session x.xx: mxxx. Cherrypy::DirectorySession: Could not write file to session: %i " %self.id) raise IOError("Cherrypy::DirectorySession: Could not write file to session %r " %self.id) finally: newFile.close() if not os.path.exists(filePath) \ or not os.stat(filePath).st_size > 0 : cherrypy.log("Session x.xx: mxxx. Cherrypy::DirectorySession:_write_file: Warning: Failed to verify file at: %s " %filePath) return False elif not filetype : return True elif self.has_key(filetype) : ol = self.get(filetype,None) ol.append(os.path.basename(filePath)) self[filetype] = list(ol) else : self[filetype]= list([os.path.basename(filePath)]) self.save() return True def getFiles(self,filelist): pass def clean_up(self): """Clean up expired sessions.""" now = datetime.datetime.now() log_msg = "Session x.xx: mxxx. Cherrypy::DirectorySession: Cleaning up session data at: %s Length of cache = %i " %(str(now), len(self.cache)) print '\nCeaning up session data at %s: \n===========================' % now print 'Length of cache = ', len(self.cache) print 'cache members: ', self.cache.keys() cherrypy.log(log_msg) #clean up temp if server not in use temp_path='/Users/Shared/george/sawa/sonic-annotator-webapp/static/temp/' if len(self.cache.keys()) == 0 and os.path.exists(temp_path): try : for fname in os.listdir(temp_path): os.remove(os.path.join(temp_path,fname)) print "Note: Cleaned temp directory." except: print "Warning: could not clear temp directory." pass for id, (data, expiration_time) in self.cache.items(): print 'Id: ', id print 'expiration time: ', expiration_time print 'Length of data: ', len(data) print 'data members: ', data.keys() print 'SESSIONS_PATH: ', self.SESSIONS_PATH if expiration_time < now: path = os.path.join(self.SESSIONS_PATH,str(id)) if os.path.exists(path) : for fname in os.listdir(path): os.remove(os.path.join(path,fname)) # os.removedirs(path) -> removes sessions too os.rmdir(path) try: del self.cache[id] except KeyError: pass try: del self.locks[id] except KeyError: pass def _exists(self): return self.id in self.cache def _load(self): return self.cache.get(self.id) #this is always called on an on_end_request hook (by cherrypy.session.save) def _save(self, expiration_time): print 'Saving Session ', self.id self.cache[self.id] = (self._data, expiration_time) def _delete(self): del self.cache[self.id] def acquire_lock(self): """Acquire an exclusive lock on the currently-loaded session data.""" self.locked = True self.locks.setdefault(self.id, threading.RLock()).acquire() def release_lock(self): """Release the lock on the currently-loaded session data.""" self.locks[self.id].release() self.locked = False def __len__(self): """Return the number of active sessions.""" return len(self.cache) cherrypy.lib.sessions.DirectorySession = DirectorySession