Re: Module isolation

2007-06-18 Thread Bryan Atsatt

Stanley M. Ho wrote:

Hello Bryan,

Bryan Atsatt wrote:

...
But this approach doesn't really work very well. What happens when,
moments after releasing a module, another application is deployed that
needs the same module? It gets a different instance. And that could
easily lead to ClassCastExceptions and/or LinkageErrors.

How is it possible to know when it is safe to free up resources?


The use case I have is that sometimes we might want to make a module
temporary unavailable (e.g. turning off a plugin in the IDE), without
shutting down the repository (possibly with hundreds/thousands of other
modules) or uninstall the module. In this case, the container will
trigger not only the release of the existing module instance (so it will
have a chance to be GCed eventually), but it will also make the module
definition invisible (through visibility policy) from other modules.
Without the second part, it has the potential problem you described.


This use case seems to presume that the IDE can/will ensure that there
is only *one* consumer of the module: itself. What if a different plugin
has a dependency on it, and has already been resolved? Is the intention
that the IDE will be wired into the module system deeply enough to
manage this correctly?

Again, this is why we need either a real, general, isolation model, or
an access control model:

Containers, of any kind, must be able to explicitly control access to
private modules.


An application server, for example, will need to keep one application
from accessing the modules of another. And it must *know* that there is
no sharing, so that the application lifecycles can remain independent.

So we need some notion of a context. A purely private repository
instance is one (probably good) possibility. Another is the wrapper
Repository approach, but this requires definition copies (and management
of sharing content, lifecycle, etc).

I started this thread with another, explicit type (ModuleContext), but
it isn't obvious how to use such beast correctly.

An access control model would also work, where all parties can share
Repository instances, but we somehow discriminate between *callers* to
return different results.

We may even want to support some mixture of private + access control.

Regardless of what approach we take, the releaseModule() idea is too
simplistic. Having originally created the detach() method, thinking
along similar lines as you are with the plugin case, I do understand the
idea; I just no longer think it is sufficient :^).

The only safe time to release a module is when there are *zero*
importers, and, even then, you must hide/release atomically, ensuring
that no new imports spring up during the operation.



Note that I don't think this is a common thing many developers want to
do. In fact, I think we should discourage most developers from calling
releaseModule() because of the potential consequences. On the other
hand, we shouldn't preclude this use case either. If you have better
suggestion to address this use case, I would like to hear it.


Well, I agree in theory. But... I am struggling to understand how we
provide an isolation model. If:

- There is a 1:1 relation for ModuleDefinition-Module instance, and
- Isolation requires separate Module instances, then
- Isolation requires separate ModuleDefinition instances

If this is our isolation model, then how does a ModuleSystem instance
support this? Clearly, it would need to keep a mapping from each
ModuleDefinition to its Module instance. How is this simpler, or better?

In your current model (just as in my detach() model), there is still a
1:1 from *at any given moment*, at least from the perspective of the
definition.

Are you thinking that the ModuleSystem would have to keep track of
released modules?


The ModuleSystem instance would have a ModuleDefinition, Module
mapping, and this should be a very simple thing to support and maintain.
Also, the ModuleSystem needs to maintain this information anyway to
avoid multiple Module instances to be instantiated for a given
ModuleDefinition, or to avoid a Module instance to be instantiated if a
ModuleDefinition has been uninstalled or belongs to a repository which
has been shutdown. And yes, the ModuleSystem would have another map to
keep track of all the ModuleDefinitions that are no longer
usable/instantiated. Having the information centralized in one place has
other benefits too, e.g. if we want to find out what the outstanding
module instances from module definitions in all repositories, the
ModuleSystem can provide the answer easily.


Sure. (And the ModuleSystem could not use strong references to hold
released Module instances, else it would prevent GC.)


My view is that ModuleSystem needs to keep track of various runtime
information related to ModuleDefinition and Module anyway, so I don't
see clear benefit in moving part of that information into other classes.


Other than Module instances, what other runtime information is there
to 

Re: Module isolation

2007-06-13 Thread Stanley M. Ho

Resend.

Bryan Atsatt wrote:

...
Stanley's idea was that a Repository implementation could return a
*copy* of a ModuleDefinition created by a different Repository. Such a
Repository would in fact form an isolation context. And caching Module
instances becomes trivial: each definition can just have one as a field.

While there are definite lifecycle issues here between such repository
instances, they are probably solvable.

And then we really *do* have an exact analogue of the loader delegation
model, in which:

   Repository   ~= ClassLoader
   ModuleDefinition ~= Class
   Module   ~= Object

Isolation of classes requires different Class instances. So isolation of
 modules requires different ModuleDefinition instances.


Yes, that's the basic idea for isolation. In addition, the ModuleSystem
object is the one actually handling the module instances' instantiation,
initialization, and release, so the repository implementors do not have
to be aware of most of the module runtime's complexities.

- Stanley