Nicolas Lehuen wrote:
In the Java (i.e. servlets) world, when you want a session, you just
ask for it on the HttpRequest object. If a session exist, you get it,
if not, it is created. If you never ask for a session, then it is not
created, this way a session is not mandatory for pages which do not
require it.
I really think the current way of building Session instances in
mod_python is weird. First, because it opens a whole bunch of bugs due
to multiple Session instantiation (i.e. deadlocks). Second, because
the Session hosting infrastructure is up to the developer (which can
choose between MemorySession, DBMSession or FileSession) whereas I
think it should be up to the hoster.
The session infrastructure should be defined in httpd.conf or a
.htaccess file, with something like :
PythonOption SessionInstantiation "FileSession(directory='/tmp/sessions')"
Then, there would be a get_session() method on the request object,
that would check if a session is already present and if not would
execute the code defined in SessionInstantiation.
Here is my first attempt at get_session(). I've attached a patch if
anyone wants to give it a try.
Currently the dict from req.get_options() is passed to new_session(),
but I'm thinking this could be a dict passed to req.get_session() to
allow the user to over-ride some directives in httpd.conf.
src/requestobject.c
-------------------
static PyObject *req_get_session(requestobject *self)
{
PyObject *m;
PyObject *options;
if (!self->session) {
options = req_get_options(self, NULL);
m = PyImport_ImportModule("mod_python.SessionTest");
// Does PyObject_CallMethod do the Py_INCREF? That's my
understanding.
self->session = PyObject_CallMethod(m, "new_session", "(OO)",
self, options);
if (self->session == NULL)
return NULL;
}
Py_INCREF(self->session);
return self->session;
}
At this point mod_python.SessionTest.new_session is just a test harness
and always returns a FileSession instance.
lib/python/mod_python/SessionTest.py
------------------------------------
import Session
def new_session(req,options):
sess = Session.FileSession(req)
return sess
Comments are welcome. Just don't blame me if it eats your server. :)
Regards,
Jim
Index: src/include/requestobject.h
===================================================================
--- src/include/requestobject.h (revision 178884)
+++ src/include/requestobject.h (working copy)
@@ -50,6 +50,7 @@
char * rbuff; /* read bufer */
int rbuff_len; /* read buffer size */
int rbuff_pos; /* position into the buffer */
+ PyObject * session;
} requestobject;
extern DL_IMPORT(PyTypeObject) MpRequest_Type;
Index: src/requestobject.c
===================================================================
--- src/requestobject.c (revision 178884)
+++ src/requestobject.c (working copy)
@@ -1,4 +1,6 @@
/*
+ vim:ts=4:sw=4:sta:et:sts=4:syntax=c:
+
* Copyright 2004 Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
@@ -62,6 +64,7 @@
result->rbuff = NULL;
result->rbuff_pos = 0;
result->rbuff_len = 0;
+ result->session = NULL;
// we make sure that the object dictionary is there
// before registering the object with the GC
@@ -372,7 +375,32 @@
return MpTable_FromTable(table);
}
+
/**
+ ***** WARNING: Experimental code. *****
+ ** Jim's session handling stuff.
+ ** JJJJ
+ */
+
+static PyObject *req_get_session(requestobject *self)
+{
+ PyObject *m;
+ PyObject *options;
+
+ if (!self->session) {
+ options = req_get_options(self, NULL);
+ m = PyImport_ImportModule("mod_python.SessionTest");
+ // Does PyObject_CallMethod do the Py_INCREF? That's my understanding.
+ self->session = PyObject_CallMethod(m, "new_session", "(OO)", self,
options);
+ if (self->session == NULL)
+ return NULL;
+ }
+
+ Py_INCREF(self->session);
+ return self->session;
+}
+
+/**
** request.internal_redirect(request self, string newuri)
**
*/
@@ -725,7 +753,6 @@
* registers a cleanup at request pool destruction time.
* optional data argument will be passed to the cleanup function.
*/
-
static PyObject *req_register_cleanup(requestobject *self, PyObject *args)
{
cleanup_info *ci;
@@ -972,6 +999,7 @@
{"sendfile", (PyCFunction) req_sendfile,
METH_VARARGS},
{"set_content_length", (PyCFunction) req_set_content_length,
METH_VARARGS},
{"write", (PyCFunction) req_write,
METH_VARARGS},
+ {"get_session", (PyCFunction) req_get_session,
METH_NOARGS},
{ NULL, NULL } /* sentinel */
};
@@ -1371,6 +1399,7 @@
Py_XDECREF(self->notes);
Py_XDECREF(self->phase);
Py_XDECREF(self->hlo);
+ Py_XDECREF(self->session);
PyObject_GC_Del(self);
}
@@ -1466,6 +1495,3 @@
-
-
-
Index: lib/python/mod_python/SessionTest.py
===================================================================
--- lib/python/mod_python/SessionTest.py (revision 0)
+++ lib/python/mod_python/SessionTest.py (revision 0)
@@ -0,0 +1,5 @@
+import Session
+
+def new_session(req,options):
+ sess = Session.FileSession(req)
+ return sess