[Mapserver-dev] Re: mappool.c thoughts
Sean Gillies
sgillies at frii.com
Tue Oct 5 11:54:04 EDT 2004
Thanks for forwarding, more below ...
On Oct 5, 2004, at 9:14 AM, Frank Warmerdam wrote:
> Sean Gillies wrote:
>> Hi Frank,
>> I've finally made the time to read through mappool.c. It's
>> clearly a huge improvement over the old "same connection as"
>> sharing, thanks! I'd like to use it in my mod_python applications
>> (which have a lot in common with fastcgi) and also for my
>> mapserver/Zope project (if possible).
> > What would you think about making it more object oriented? I
> > think that having a module-level pool will be problematic for
> > Python threads, and that it could be better to make the pool
> > a class and let user/programmers deal with how to make access thread
> > safe.
> >
> > Right now the pool is implemented as 3 module-level variables,
> > could we instead have a ConnectionPool like
> >
> > typedef struct {
> > int count;
> > int maxcount;
> > connectionObj *connections;
> > } ConnectionPool;
> >
>> ? I imagine that the mapserv app object (a mapservObj) would
>> contain an instance of this. Likewise, mapscript applications
>> could create an instance and use it like
>> pool = mapscript.ConnectionPool()
>> for layer in postgis_layers:
>> pool.register(layer, ...)
>> The connection pool would be thread local by default. If someone
>> wanted to program a multi-threaded app, they could deal with
>> threading and locking themselves.
> >
>> This complicates the implementation. Would require adding a
>> connectionObj * argument to every one of the msConnPool functions,
>> and we'd also have to pass a pointer into msLoadMap so that layer
>> connnections are registered when loaded. Do you see any other
>> complications?
>
> Sean,
>
> I think what I am least clear on is how we know what connection
> pool to use down at the layer level. A function like
> msPOSTGISLayerOpen()
> takes in *only* a layerObj. It doesn't know what map that layer is
> associated with. It doesn't know what mapservObj (if any) is being
> used
> to process it.
>
> I don't mind adding a ConnectionPool * to the functions. What I think
> is
> much less paletable is having to pass connection pools up and down the
> how tree of functions. (msDrawMap() / msLoadMap() / msOpenLayer() /
> msPOSTGISOpenLayer()) and so on.
>
> In fact, this is the same sort of problem we face with generalizing he
> IO redirection. Low level MapServer functions generally get a very
> limited
> amount of context information to execute their operations. For
> instance,
> msSetError() doesn't have any idea of it's external context though it
> assumes
> it can safely managed its own internal per-thread stack of error
> objects.
>
> If our objective with connection pools is to make them thread-local or
> to
> allow that degree of control, why not just implement that in the
> mappool API
> possibly along with some "policy" control functions?
>
> It seems to me that unless we are going to substantially most
> functions in
> MapServer, we are going to need an easy way of managing thread local
> "globals"
> that doesn't involve passing thread context around everywhere. Pools
> are one
> example.
>
> --
>
> Setting aside that broader issue, I would be willing to implement the
> suggested ConnectionPool structure. The various connection pool
> functions
> would have a ConnectionPool object added as their first argument.
>
> My caveats are this:
>
> o It would always be legal to pass NULL as the ConnectionPool which
> would cause
> mappool.c to select an appropriate pool.
>
> o By default a global pool would be used (managed internally as a
> static).
>
> o If the layerObj has a "CONNECTION_POOL=%p" directive, the pointer
> value from
> that would be used instead. This is how python mapScript would
> have to
> force a particular layer to use a particular pool.
>
> o msConnPoolRegister() would have an extra argument indicating if a
> given
> connection is "this thread only", "one thread at a time" or
> "multithread safe".
> The connection pool would track that status, and also (when the
> ref_count
> is non-zero) what thread is using it if it is not "multithread
> safe".
>
> o I would also ensure that any use of globals in mappool is protected
> by a
> mutex.
>
> Note, the above changes do not require any api changes higher than the
> msConnPool API. Furthermore, I think it provides good default
> multi-thread
> safety and some ability to tinker for those who want more control over
> the
> locking themselves.
>
> BTW, when registering connections (in advance) from MapScript I am
> assuming
> a NULL close function would be provided and the mapscript app would
> take care
> of connection cleanup. Of course, a wrapper close() callback could
> also be
> provided.
>
> Finally, I took the liberty of cc:ing this back to the -dev list
> because I
> think some of the issues are of broader interest and I want to get a
> feel for
> where the rest of the developers stand with regard to general thread
> safety
> issues.
>
Frank,
I think it's a good thing that our functions require just the bare
minimum
context. Passing a connection pool everywhere would suck. I'm happy
with
your proposed solution, with one additional suggestion.
Let's consider adding a
ConnectionPool *connectionpool
member to layerObj. If NULL, we use the default module-level pool. In
the
mapscript case, it would reference an application-level pool. Calls to
the msConnPool functions could be passed self->connectionpool.
Sean
--
Sean Gillies
sgillies at frii dot com
http://users.frii.com/sgillies
More information about the mapserver-dev
mailing list