Apache Mod-Python - [importing] Disabling of AutoReload

This is Interesting: Free IT Magazines  
Home > Archive > Apache Mod-Python > July 2005 > [importing] Disabling of AutoReload





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author [importing] Disabling of AutoReload
Gregory (Grisha) Trubetskoy

2005-07-08, 5:47 pm


I think that the issue of import_module not honoring the AutoReload and
Debug directives (because it was originally only used internally and was
used a level "below" the directives) is a fairly serious one and something
should be done before 3.2.

So perhaps we rename import_module() to something else, and create a
separate import_module which checks the directives, then calls the low
level one?

Grisha

Graham Dumpleton

2005-07-08, 5:47 pm

One issue at a time sounds good. :-)

On 08/07/2005, at 11:38 PM, Gregory (Grisha) Trubetskoy wrote:

>
> I think that the issue of import_module not honoring the AutoReload
> and Debug directives (because it was originally only used internally
> and was used a level "below" the directives) is a fairly serious one
> and something should be done before 3.2.
>
> So perhaps we rename import_module() to something else, and create a
> separate import_module which checks the directives, then calls the low
> level one?


Because a caller will not always have access to the req object and thus
can't
be made to pass it in as an explicit argument, there needs to be a way
of
caching the request at a high level. The internals of the
import_module()
method can then access it directly to determine the log and autoreload
options.
The current arguments thus become redundant.

The code I have been playing with for this is included at the end of
the email.

Some of the issues in the implementation that came up were:

1. Must be thread safe because of multithreaded MPMs.

2. Needed to cope with same req object being pushed into cache more
than once
for the thread handling the specific request. In case it was being
called at
start of every handler phase for a request.

3. The req object obviously has to be discarded from cache at end of
request
by way of cleanup handler.

4. The PythonCleanupHandler is called after registered cleanup handlers
and
so if you cache req at beginning of every handler, you cache it again
here
after you already discarded it once. It is interesting that a
PythonCleanupHandler
can have its own distinct registered cleanup handler which is called
after
that phase is called.

5. A stack for each thread was effectively required because of internal
redirects. Ie., same thread could be use to serve redirect request but
different req object instance is created for it.

Anyway, think that is all. I was simply calling cacheRequest() as the
first
thing where top level handlers were being called. This caching may
however
be better off in mod_python.c as it is probably holding it anyway and so
access to it simply needs to be provided based on looking at the thread
which is executing.

from mod_python import apache

try:
from threading import currentThread
except:
def currentThread():
return None

_requestCache = {}

def _discardRequest(thread):
try:
_requestCache[thread].pop()
if len(_requestCache[thread]) == 0:
del _requestCache[thread]
except:
pass

def cacheRequest(req):
thread = currentThread()
if _requestCache.has_key(thread):
if _requestCache[thread][-1] == req:
return
_requestCache[thread].append(req)
else:
_requestCache[thread] = [req]

req. register_cleanup(_discardRequest,(thread
,))

def currentRequest():
try:
thread = currentThread()
return _requestCache[thread][-1]
except:
pass

Hope I didn't delete any important bits when I took out by debug. :-)

Graham


Nicolas Lehuen

2005-07-08, 5:47 pm

Local thread variables would be perfect to store the request object.
Unfortunately they are specific for Python 2.4 :

*class local* A class that represents thread-local data. Thread-local data
are data whose values are thread specific. To manage thread-local data, just
create an instance of local (or a subclass) and store attributes on it:

mydata = threading.local()
mydata.x = 1

The instance's values will be different for separate threads.

For more details and extensive examples, see the documentation string of the
_threading_local module.

New in version 2.4.


2005/7/8, Graham Dumpleton <grahamd@dscpl.com.au>:
>
> One issue at a time sounds good. :-)
>
> On 08/07/2005, at 11:38 PM, Gregory (Grisha) Trubetskoy wrote:
>
>
> Because a caller will not always have access to the req object and thus
> can't
> be made to pass it in as an explicit argument, there needs to be a way
> of
> caching the request at a high level. The internals of the
> import_module()
> method can then access it directly to determine the log and autoreload
> options.
> The current arguments thus become redundant.
>
> The code I have been playing with for this is included at the end of
> the email.
>
> Some of the issues in the implementation that came up were:
>
> 1. Must be thread safe because of multithreaded MPMs.
>
> 2. Needed to cope with same req object being pushed into cache more
> than once
> for the thread handling the specific request. In case it was being
> called at
> start of every handler phase for a request.
>
> 3. The req object obviously has to be discarded from cache at end of
> request
> by way of cleanup handler.
>
> 4. The PythonCleanupHandler is called after registered cleanup handlers
> and
> so if you cache req at beginning of every handler, you cache it again
> here
> after you already discarded it once. It is interesting that a
> PythonCleanupHandler
> can have its own distinct registered cleanup handler which is called
> after
> that phase is called.
>
> 5. A stack for each thread was effectively required because of internal
> redirects. Ie., same thread could be use to serve redirect request but
> different req object instance is created for it.
>
> Anyway, think that is all. I was simply calling cacheRequest() as the
> first
> thing where top level handlers were being called. This caching may
> however
> be better off in mod_python.c as it is probably holding it anyway and so
> access to it simply needs to be provided based on looking at the thread
> which is executing.
>
> from mod_python import apache
>
> try:
> from threading import currentThread
> except:
> def currentThread():
> return None
>
> _requestCache = {}
>
> def _discardRequest(thread):
> try:
> _requestCache[thread].pop()
> if len(_requestCache[thread]) == 0:
> del _requestCache[thread]
> except:
> pass
>
> def cacheRequest(req):
> thread = currentThread()
> if _requestCache.has_key(thread):
> if _requestCache[thread][-1] == req:
> return
> _requestCache[thread].append(req)
> else:
> _requestCache[thread] = [req]
>
> req. register_cleanup(_discardRequest,(thread
,))
>
> def currentRequest():
> try:
> thread = currentThread()
> return _requestCache[thread][-1]
> except:
> pass
>
> Hope I didn't delete any important bits when I took out by debug. :-)
>
> Graham
>
>


Gregory (Grisha) Trubetskoy

2005-07-12, 5:46 pm


It's interesting how quickly the knowledge about the code you yourself
write evaporates without a trace... Somehow the point that import_module
cannot require a request object because you usually don't have access to
it at the beginning of your code where imports are usually done escaped
me..

After this realization, I'm now more inclined to push this until after
3.2, and for how just make sure it is well noted in the documentation that
import_module does not require a request object, but as a consequence it
is not affected by the configuration directives. This currently isn't
documented (in 3.1 at least).

Does this sound agreable?

P.S. On magic request caching - I think that if this works, then why not,
though I think it needs to be bounced around a little more. BTW - from the
code below:

> _requestCache[thread].pop()


was this meant to be

del _requestCache[thread]

Grisha


On Sat, 9 Jul 2005, Graham Dumpleton wrote:

> One issue at a time sounds good. :-)
>
> On 08/07/2005, at 11:38 PM, Gregory (Grisha) Trubetskoy wrote:
>
>
> Because a caller will not always have access to the req object and thus can't
> be made to pass it in as an explicit argument, there needs to be a way of
> caching the request at a high level. The internals of the import_module()
> method can then access it directly to determine the log and autoreload
> options.
> The current arguments thus become redundant.
>
> The code I have been playing with for this is included at the end of the
> email.
>
> Some of the issues in the implementation that came up were:
>
> 1. Must be thread safe because of multithreaded MPMs.
>
> 2. Needed to cope with same req object being pushed into cache more than once
> for the thread handling the specific request. In case it was being called at
> start of every handler phase for a request.
>
> 3. The req object obviously has to be discarded from cache at end of request
> by way of cleanup handler.
>
> 4. The PythonCleanupHandler is called after registered cleanup handlers and
> so if you cache req at beginning of every handler, you cache it again here
> after you already discarded it once. It is interesting that a
> PythonCleanupHandler
> can have its own distinct registered cleanup handler which is called after
> that phase is called.
>
> 5. A stack for each thread was effectively required because of internal
> redirects. Ie., same thread could be use to serve redirect request but
> different req object instance is created for it.
>
> Anyway, think that is all. I was simply calling cacheRequest() as the first
> thing where top level handlers were being called. This caching may however
> be better off in mod_python.c as it is probably holding it anyway and so
> access to it simply needs to be provided based on looking at the thread
> which is executing.
>
> from mod_python import apache
>
> try:
> from threading import currentThread
> except:
> def currentThread():
> return None
>
> _requestCache = {}
>
> def _discardRequest(thread):
> try:
> _requestCache[thread].pop()
> if len(_requestCache[thread]) == 0:
> del _requestCache[thread]
> except:
> pass
>
> def cacheRequest(req):
> thread = currentThread()
> if _requestCache.has_key(thread):
> if _requestCache[thread][-1] == req:
> return
> _requestCache[thread].append(req)
> else:
> _requestCache[thread] = [req]
>
> req. register_cleanup(_discardRequest,(thread
,))
>
> def currentRequest():
> try:
> thread = currentThread()
> return _requestCache[thread][-1]
> except:
> pass
>
> Hope I didn't delete any important bits when I took out by debug. :-)
>
> Graham
>


Graham Dumpleton

2005-07-12, 5:46 pm


On 13/07/2005, at 3:32 AM, Gregory (Grisha) Trubetskoy wrote:

> P.S. On magic request caching - I think that if this works, then why
> not, though I think it needs to be bounced around a little more. BTW -
> from the code below:
>
>
> was this meant to be
>
> del _requestCache[thread]


I admit I didn't check, but I effectively have a stack of request
objects for the thread and only pop the top one, because if one
does an internal redirect it reenters within same thread but with
a different request object. You thus need to keep the outer request
object around still. When the cleanup handler runs from the
inner internal redirect handler, it should only pop off its own
request object as the outer still needs to be accessible when the
internal redirect returns to the outer handler. This is assuming
the inner internal redirect handlers cleanup handler is run before
it returns back to the outer handler.

Graham


Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com