Hi all,
A few months ago, started a conversation about what I'll call multi-tenant
applications: that is, a single pike process running multiple applications
(perhaps including copies of a given application) with isolated program
and module spaces. The idea is to provide a similar capability to that
provided by Java's ClassLoader API.
That is, I'd like to be able to do the following:
pike
+-----------------|-----------------+
| |
thread a1...an thread b1 ... bn
compilation handler a compilation handler b
loads classes for app1 instance 1 loads classes for app1 instance
from location a,b from location a,c (perhaps)
uses module foo.bar uses module foo.bar
foo.bar != foo.bar
though it would perhaps be acceptable if
object_program(foo.bar) == object_program(foo.bar)
applications would not be aware of each other (a condition
of the multi-tenant contract) and thus object identity
would not need to be maintained.
I've been dabbling with the approach suggested at the Pike conference,
which was to use a compilation handler to provide this functionality. I've
come tantalizingly close, being able to use an overriden master to provide
versions of compile_string() and friends that automatically select the
desired compilation handler based on various criteria (such as threads in
an application). While a bit clunky, it seems to allow me to control
visibility of identifiers in a given application or thread, but there does
seem to be a limitation that for me is fatal: the programs and module
objects are cached by the master, and therefore any two applications are
not truely isolated: they share a common set of modules (and
join/dirnodes) and (though less problematic) precompiled programs.Because
programs and modules seem to be indexed by filename, I've played around
with adding a unique identifier in order to split the cache on a
per-handler basis, but this hasn't worked either (programs seem to be
loaded as desired, but modules are still problematic.)
I've attempted to add storage of these caches in the compilation handler,
but it results in extremely odd failures (for example, a given class will
be cached as a zero value in the programs mapping, which means the program
won't be found, even if it's on disk.
As a brute force attempt to prove that the idea can work, I'm thinking
about short circuiting the auto-reload functionality so that it always
reloads a given class from disk. I'm not sure that this will actually
prove beneficial, as modules would still be persistent.
As always, any thoughts or suggestions would be welcome.
Bill