avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Donald <dona...@apache.org>
Subject Re: proposed kernel redesign
Date Tue, 10 Apr 2001 03:51:14 GMT
At 06:15  9/4/01 +0200, Leo Simons wrote:
>Has anyone had a chance to look at my proposal for Phoenix?
>(under /proposal in the jakarta-avalon-phoenix CVS)
>I'd like some help with various items:
>1) threading. While I'm familiar with the theory, I'm not with
>implementations. In my PhoenixEmbeddor draft, I haven't
>created new threads.
>- should the Manager (JMX), Embeddor, Kernel, Deployer, etc
>be different threads? How do I do this (how do I use the
>thread utils for this?
>- more specifically, do you think this works correctly/fast?
>(Embeddor's run() method)
>    /**
>     * This is the main method of the embeddor. It sets up the core
>     * components, and then deploys the <code>Facilities</code>. These
>     * are registered with the Kernel and the Manager. The same
>     * happens for the <code>Applications</code>.
>     * Now, the Kernel is taken through its lifecycle. When it is
>     * finished, as well as all the applications running in it, it
>     * is shut down, after which the PhoenixEmbeddor is as well.
>     */
>    public void run()
>    {
>        // setup core handler components
>        this.setupLogger();
>        try { this.setupDeployer(); }
>        catch( Exception e ) {  logger.fatalError("Unable to setup
>deployer!", e);
>                                System.exit( 1 ); }
>        try { this.setupManager(); }
>        catch( Exception e ) {  logger.fatalError("Unable to setup
>manager!", e);
>                                System.exit( 1 ); }
>        try { this.setupKernel(); }
>        catch( Exception e ) {  logger.fatalError("Unable to setup kernel!",
>                                System.exit( 1 ); }
>        // deploy facilities and applications
>        try { this.runDeployer(); }
>        catch( Exception e ) {  logger.error("Unable to deploy!", e); }
>        try
>        {
>            kernel.start();
>            // loop until <code>Shutdown</code> is created.
>            while( !this.shutdown )
>            {
>                // loop
>                while( !this.restart && !this.suspend )
>                {
>                    // the run() method in the kernel should
>                    // call wait(), or this doesn't work very
>                    // well...
>                    kernel.run();
>                    // wait() for shutdown(), restart() or
>                    // suspend() to take action...
>                    try { synchronized( this ) { wait(); } }
>                    catch (InterruptedException e) {}
>                }
>                if( this.restart )
>                {
>                    handleRestart();
>                }
>                else if( this.suspend )
>                {
>                    handleSuspend();
>                }
>            }
>            // we can stop everything now...
>            handleDispose();
>        }
>        catch ( Exception e )
>        {
>            // whoops!
>            this.logger.fatalError("There was a fatal error while running
>phoenix.", e );
>            System.exit( 1 );
>        }
>    }

>2) Context vs Configuration. The current system uses Configurations
>extensively; context usage is limited. Context can pass anything;
>configuration can pass strings and numbers (or anything through
>XCommander, but this is probably not worth the trouble). Right?
>That said, where do I use which? Could you give me a few pointers?

Context is information retrieved from environment. So in effect it is
information that the components Container will provide. Where Configuration
is user supplied data, ComponentManager holds peer components and Context
holds information that the Component needs to interact with Container.

>Also, any ideas on how to define the minimum information a
>Kernel's/Embeddor's/Manager's Context should contain? (I'm
>thinking of just javadoccing this in the Contextualize
>methods of these objects inside the Atlantis package)

sounds good. I am not sure how to go about this. In theory the context
contents are fixed by the container-component contract. We could document
it either at container or component level. Personally I sub-classed to get
BlockContext and documented it there but in most cases sub-classing is not

>3) Piping. It seems to me that the lifecycle is set in stone. Is
>the pipeline setup really neccessary? It seems to me that, as long
>as apps get run in a separate thread (within their own
>ApplicationManager facility), the pipeline can be removed and
>the lifecycle methods can simply be called directly.

Possibly - the pipeline was initially created to allow extra stages be
added in (ie Management/distribution) but we can do these another way. I am
not sure which way is best.

>4) Suspend / Resume. It seems to me that any object that supports
>suspend() should support resume() as well. This is not reflected
>in the interfaces. Is there a reason for this?

Essentially to follow the pattern of rest (ie stoppable does not extend

>5) have you got suggestions for the naming of different facilities?
>Are any missing or redundant?

Not sure what you mean here.

>6) Entries. These aren't documented anywhere, and I'm wondering
>exactly what they are and how they're used? To me, it seems instance
>info should be contained in a Context, which means removal of
>Entries or making Entries extend Context. Is this correct/sensible?

nope - neither correct/sensible IMNSHO ;)

Entry is a class used by containers and should never be visible to
components. Context is info available to the component and is part of
container-component contract. Entry is an implementation detail only needed
by container.

>7) Facility deployment. Should we put ".far"s in a facilities/
>directory and otherwise just follow the application deployment
>process, or should there be some kind of checking. Also, if we
>do this, should there still be default facilities in the main

No idea - when we get closer to having a real-life example we can
re-examine it then. I would prefer just placing it in <dist>/lib and
changing config setting though I am not sure.

>8) JMX. Does it need to be optional, or can we make it the core of
>the process in the future? 

It can be core now but in the future it has to be optional. JMX is heavy
weight and definetly not needed by some deployment situations.

>What I'm doing now is putting an
>instance of the Manager created by the Embeddor in the Kernel's
>Context, and I could do so for the Deployer as well. We could
>use RTTI to create an MBean for each application/facility and
>have the Kernel talk to that.
>This means less duplicity as the kernel/deployer can simply
>leave some of the handling of server apps to the Manager. It
>also means JMX cannot be removed from the kernel anymore.

I am not sure what you are meaning here. It is my opinion that the kernel
is the one that should be doing 90% of the work. The kernel can expose
interfaces to the deployer/manager who will do work. In the case of
deployer it gets/unpacks/processes sars and creates the applicable
BlockEntrys. The manager acts as the exporting mechanism for management etc.

>9) Should we have an interface Manageable that blocks that
>wish to expose their public attributes/methods through JMX
>have to implement, or simply make all blocks manageable?
>(alternative: a NotManageable to disable JMX Management,

Last time we discussed it we talked about something like

interface Manageable extends Service {}

interface MyManageableService
  extends Manageable
  void doSomething();
  void addSomeListener( SomeListener listener );
  void removeSomeListener( SomeListener listener );
  void doSomethingElse( int param1, int param2, int param3 );

This way we could look at exported services and use those etc.
Alternatively instead of extending Manageable we could add a
manageable="true" attribute in service definition in blockinfo file. 

>10) General Kernel operation. There's a complete lack of
>documentation, which makes it very difficult for me to
>grasp how it operates, and especially why.

yup ;)

>- can I call compose() on the Deployer, passing it the
>  Kernel, before I call Contextualize() etc. on the kernel?

You shouldn't - everything should be up to init() stage in pipeline before
being passed to anything else.

>- what do you think of the following revised process?
>1) Start.java creates an Embeddor based on cl options

Sounds like Main.java to me ;)

>2) the Embeddor creates a Logger, a Deployer, a Manager,
>and a Kernel, based on a Configuration (which it may
>build itself from a configuration file specified by


>3) the Embeddor runs the lifecycle methods up to
>init() for Logger, Deployer, Manager and finally
>	- the deployer gets a (currently empty) context
>	- the deployer gets a componentManager referencing
>	the kernel
>	- the manager gets an MBeanServer and a reference
>	to the deployer and to the Embeddor (to create
>	MBeans for 'em)

sounds good.

>	- the Kernel is given the location of its
>	configuration file.

-1 it should be Embeddor that loads Configuration data and passes it to

>4) the .sar and .far (Facility Archives, which should
>contain kernel functionality) files are all installed
>by the deployer.

Not sure about .fars yet ...

>5) the Kernel is start()ed. It gets the facilities,
>creates instances of them, configures them, and
>intializes them.


>6) the Kernel is run(). It must now create and install
>all Applications it got from the deployer. It also
>sends the Applications to the Manager which creates
>MBeans for them and registers those with the

kewl - maybe we could instead run() the Kernel but send a message to the
manager. The manager then activates the deployed applications. This would
allow some applications to be deployed but not activated.

>7) if supported, suspend() and resume() can be called
>on the Embeddor which in turn suspend()s the kernel
>(or destroys it if the kernel does not support suspend,
>and re-initializes and runs the kernel on resume()).
>	- the kernel should suspend() all applications
>	that support it, and dispose of all that don't.
>	- on resume(), all apps should be resumed and
>	non-suspendable apps should be recreated and
>	started.

Why do we ever need to suspend a kernel?

>8) when Shutdown is run, we dispose() the embeddor which
>calls the same method on all its helper components.
>The system exits.


>We should hammer out the above and then vote on it,
>and then
>- we need to create a manager that can create DynamicMBeans
>for Facilities and Applications and register those with
>an MBeanServer (org.apache.phoenix.engine.facilities.Manager).
>- we need to create the different Facilities in that
>same package, after having defined the interfaces in
>- we need to rewrite the kernel (or write one
>from scratch) to support facilities (using .fars)
>and the new Manager.

sounds good.

>PS: on timetables - I have no idea how much
>time it takes to do all this refactoring and
>then test everything. I'm guessing the
>completion of it all will not make it into
>the v4 beta, but some elements (like the
>an adaption of the Start.java, Shutdown.java
>and Restart.java files I wrote to work with
>the current Kernel) might.

The phoenix part is not going beta for a while yet IMHO. Only the framework
part and some of the components. The rest will remain alpha until it is
feature complete ;)



| "Faced with the choice between changing one's mind, |
| and proving that there is no need to do so - almost |
| everyone gets busy on the proof."                   |
|              - John Kenneth Galbraith               |

To unsubscribe, e-mail: avalon-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: avalon-dev-help@jakarta.apache.org

View raw message