[mod_python] MySQLSession available!!

Martijn Moeling martijn at xs4us.nu
Mon Nov 27 10:09:21 EST 2006


Well after investigating "sessions.py" a bit more I have come up with a
working MySQLSession object added to "sessions.py"

See code (only the changed parts) below....

The nasty thing is that it will be overwritten by any mod_python
updates, or if it is interesting enough (hopefully) it gets into the
next major mod_python release.

By checking for the req.cursor, there is no need for importing MySQLdb
into session.py

See code (only the changed parts) below....

8<---------------------------------------------------------------------
########################################################################
###
## MySQLSession
## M. Moeling, martijn at xs4us.nu
##
## In order to use MySQLSession:
## in your handler.py:        
## import MySQLdb
##
##  Somewhere before the session stuff use:
##
##  req.db =
MySQLdb.connect(host=Chost,user=Cuser,passwd=Cpasswd,db=Cdb)
##  req.cursor = req.db.cursor()
## 
##  When req.cursor is existing, Session.py will default to MySQLSession
##  Can be overruled with pythonoptions in apache config
##
## To create table in MySQL use the following:
## CREATE TABLE `Session` (
##  `sid` varchar(50) NOT NULL,
##  `store` text NOT NULL,
##  PRIMARY KEY  (`sid`)
## ) TYPE=MyISAM;
        
def mysql_cleanup(req):
    req.cursor.execute("Select * from Session")
    AllSessions = req.cursor.fetchall()
    for records in AllSessions:
        session = cPicle.loads(record[1])
        if (time.time() - session["_accessed"]) > session["_timeout"]:
            req.cursor.execute("DELETE FROM Session where
sid='"+session[0]+"'")        

        
class MySQLSession(BaseSession):

    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(MySQL_cleanup, self._req)
        self._req.log_error("MySQLSession: registered session cleanup.",
                            apache.APLOG_NOTICE)

    def do_load(self):
        self._req.cursor.execute("Select store from Session where
sid='"+self._sid+"'")
        store=self._req.cursor.fetchone()
        if self._req.cursor.rowcount==1:
            return cPickle.loads(store[0])
        return None

    def do_save(self, dict):
        self._req.cursor.execute("Select store from Session where
sid='"+self._sid+"'")
        store=self._req.cursor.fetchone()
        if self._req.cursor.rowcount==1:
            Query="Update Session set store=\""+cPickle.dumps(dict)+"\"
where sid='"+self._sid+"'"
        else:
            Query="Insert into Session (sid,store) values
(\""+self._sid+"\",\""+cPickle.dumps(dict)+"\")"           
         self._req.cursor.execute(Query)
        
    def do_delete(self):
        try:
            self._req.cursor.execute("DELETE FROM Session where
sid='"+self._sid+"'")
        except:
            pass


########################################################################
###
## Session

## Changes made for MySQLSession
## the application should set req.cursor as an MySQLdb cursor object


def Session(req, sid=0, secret=None, timeout=0, lock=1):

    opts = req.get_options()
    if opts.has_key('session'):
        # Check the apache config for the type of session
        sess_type = opts['session']
    else:
        ## MySQLSession is default when req.cursor exists
        if req.cursor:
            sess_type = 'MySQLSession'
        else:
        ## END of MySQLSession modification
            # 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
    ## Added for MySQLSession
    elif sess_type == 'MySQLSession':
        sess = MySQLSession
    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)
8<---------------------------------------------------------------------

-----Oorspronkelijk bericht-----
Van: mod_python-bounces at modpython.org
[mailto:mod_python-bounces at modpython.org] Namens Martijn Moeling
Verzonden: Monday, November 27, 2006 12:08 PM
Aan: mod_python at modpython.org
Onderwerp: [mod_python] Session Storage : memory, file, dbm....Mysql?

Hi,

I am building an application framework (yes!) with very specific needs.
One of the main problems I run into is session management, I'll explain:

My application (Running on Fedora) Is prepared for multiple front-end
servers communicating on an Internal backbone to a database server.
Think of it as some sort of web based Citrix able to run on all browsers
without the need of client-side software installation. Fully
programmable in python (even the front-end) and if the time gets there
even Visual. So build a browser based application within an application
with central storage and management. Mod Python is used to implement a
part of an OS if you wish to call it that way.

The front ends will be Apache servers with mod_python connected to the
Internet using round-robin DNS (Multiple ip addresses for one Host), In
theory a PC will do a DNS lookup and get the address of one of the
front-end, this PC will keep this address until the TTL makes it expire
in the DNS caches along the way, there is no problem since each session
will be served by the same front end.

But I need to find a way to get the session information into the MySQL
database in the backend server to enable central monitoring and inter
user communications etc. (think of a Messenger online userlist as an
example)

I can of course write stuff to maintain this sort of data in the MySQL
database but what if the session ends other than a user logging out
nicely (broken connection, browser close etc.)

It would be nice to have a MySQLsession object, an extra parameter could
be added like a MySQLdb cursor object, or am I wrong and are sessions
maintained by Apache (since modpython does not seem to keep track of
Session closing), or is there any way to "list" active sessions from
within modpython, so I can let the backend server send an http request
to the front-end and doing something like:
http://frontend1/getsessionlist which returns a comma separated list of
active session id's, so the stale session records in the database can be
removed.

I have been researching Session.py
Where I interestingly found:
(from def dbm_cleanup(data):)

If (time.time() - dict[_accessed]) > dict["_timeout]:
	old.append(key)
..
..
..
For key in old:
	Del db[key]

If I understand this right, this means that this is done to see if the
session is ended right? So It I alter Session.py I could make my own
MySQL Session right?

Would there be anyone else Interested in a MySQLSession object and what
do I need to take into account when modifying it?


Please feel free to comment on any of this,

Martijn Moeling

_______________________________________________
Mod_python mailing list
Mod_python at modpython.org
http://mailman.modpython.org/mailman/listinfo/mod_python



More information about the Mod_python mailing list