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