cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Leo Sutic" <leo.su...@inspireinfrastructure.com>
Subject RE: [Kernel2.2] Comments
Date Wed, 31 Mar 2004 13:33:19 GMT
OK, I've gotten my head round the kernel in a sort-of kind-of 
way.

My basic problem with it is the management of block instances.
(I absolutely love it in every other respect.)

1. Singletons

I have repeatedly (both in my own development and based on 
questions from users) seen the need for a singleton design
pattern. I.e. when a block instance corresponds to some
physical resource that can't be virtualized. For example,
a database connection (if you're only allowed one), can
be shared among several clients, but you must still have
a singleton that manages that single connection.

For Cocoon, one could argue that such blocks should be
outside of Cocoon, but this is not always possible.


2. Reloading

When I first read about this framework the plan was to 
simply drop the block when it was being reloaded, no matter
if it was currently executing a method call, or whatever.

Then after some discussion the idea was to keep the new block
and the old block side by side and gradually phase out the 
old block as it was released by clients.

However, I think this will lead to unpredictable behavior.
This type of lazy reloading will cause problems, even more
problems than the usual ones you get when reloading classes.

2a. Stale classes

One problem is when you retain a reference to a class that
is about to become reloaded. For example:

    interface Templates {
        public TransformerHandler getTransformerHandler ();
    }

    interface MyBlock {
        public Templates getTemplates ();
    }

and the impls: TemplatesImpl, MyBlockImpl.

Suppose you get a handle to MyBlock. Then you get the Templates 
from it. Then the MyBlockImpl block is reloaded. When you call
getTransformerHandler on the Templates you just retrieved, will 
you execute the old code or the new code? Obviously, the old 
code.

Will this old code work with the new classes that has been reloaded
in the rest of the system?

Maybe.

Suppose a you have a SSL block. Further suppose that a bug has
been discovered in it and you have to get it patched.

With the side-by-side running, I have *no guarantee* that the new
block is active.


2b. Multiple blocks stepping on each other's toes

Suppose a block accesses some kind of resource that only accepts
one client, meaning that the block must serialize access to
that resource. This can be done via synchronized wrapper 
methods, mutexes or whatever.

But if you suddenly have two instances of the block... Well, you've
pretty much had it then.

You risk not only a crash, but that ***wrong stuff*** is being done
***without a crash***. The resource may be stateful:

    interface AccountCursor {
        public void moveToAccount (String account);
        public void withdraw (int amountOfEuro);
        public void put (int amountOfEuro);
    }

What would happen if two block instances accessed this resource
in parallell? No errors, but a messed up account DB.


3. Over-reliance on Administrator Omniscience

Linked to the "maybe" in 2a.

    http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=108032323410266&w=2
    Thing, that (by the way) will _NEVER_ happen automagically, but only

    when the administrator decides that it's time to reload a block 
    instance?

So, why should we bother with these problems? The administrator
knows when a block can be reloaded, right?

Wrong.

What sane admin will hit the reload button, unless he knows
with some certainty what will happen, or that the system will
crash instead of trashing important databases if something goes 
wrong?

Frankly, I'll be too scared to use this reloading functionality.

And then what's the point?

I can also answer the question immediately before the quote above:

    http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=108032323410266&w=2
    What's the difference between that, and loosing the connection 
    for a second with a component?

When a connection is lost it is *lost*. It has well defined behavior. It

has easily understood effects on the code. It has *visible* effects on 
the code (Exceptions being thrown everywhere).

With this lazy reloading scheme, or any reloading scheme that doesn't
involve locking, you won't get any exceptions, but you'll get a whole
lot of nasty errors that will not leave any other trace except a trashed
server after a few hours of running bad code.

/LS


Mime
View raw message