Bug 2529 - Need to remove non-standard ciao_preactive and ciao_postactivate methods
Summary: Need to remove non-standard ciao_preactive and ciao_postactivate methods
Status: RESOLVED FIXED
Alias: None
Product: CIAO
Classification: Unclassified
Component: CIAO Container Implementation (show other bugs)
Version: 0.3.5
Hardware: All All
: P3 normal
Assignee: Will Otte
URL:
Depends on:
Blocks: 3253
  Show dependency tree
 
Reported: 2006-05-08 13:22 CDT by Nanbor Wang
Modified: 2009-02-18 21:36 CST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nanbor Wang 2006-05-08 13:22:06 CDT
On Tue, 21 Feb 2006 05:01:38 -0600, bala@dre.vanderbilt.edu (Balachandran 
Natarajan) said:

> Nanbor- Hopefully, I will send this out by today. Thanks for the
> long email and some thought provoking insights. Please see below.

> On Monday, 20 February, 2006 at 00:14:46 -0600, nanbor@txcorp.com
> via RT wrote:
>> in composing and sending out this email which I hope will
>> illustrate why I don't think adding the non-standard
>> ciao_preactivate and ciao_postactivate methods is the right
>> approach.
>> 
>> I think it's fair to say that the main motivation of adding
>> ciao_preactivate and ciao_postactivate methods is to provide a
>> mechanism for developers to enforce the order of initialization of
>> many components in an assembled application.  Below, I'll try to
>> argue that this is the wrong approach to solve this problem.
>> 
>> 1. These added methods are *non-standard* should require no further
>> saying.  Moreover, they only help address a limited cases of
>> "component initialization order" problem.  In another word, they
>> were added to address a specific problem that seemingly represent a
>> generic problem.  (I.e., it's more of a hack than a general
>> solution.)

>        Okay. Let me accept this premise (as a hack) for now.

I think my last sentence above probably came across in the wrong way.
Please don't take it personally and my sincere apology if I offend you
in anyway.  Don't forget that Ossama used to think that "Nanbor" was a
code name for hackers. ;-)

>> The problem that ORBInitializer pre_init and post_init methods try
>> to address is very specific, i.e., to support a certain new feature
>> in the ORB, something needs to be done before or after ORB
>> initialization.  These methods have a very definite reference time,
>> the ORB::init call.  Unlike the ORBInitializer methods, there is
>> really no fixed reference call for component activation.  There is
>> only a reference time for *a specific application".

>         Here is where I differ. You make it sound as if, a component
> is _an_ application all by itself. In the type of systems that CIAO
> is focusing on, a component is just _a_piece_ of the
> puzzle. 

Tout au contraire!  My argument is built on the fact that a
application consists multiple components.  Component model allows
developers to change the composition of an application easily.
Therefore, it's not appropriate to hard-code the application-specific
initialization logic/semantic inside a component.  My sincere apology
for not getting the point across.

> Components need to to work with other components to do anything
> useful. 

Absolutely.

> If you accept this, then a component instantiation has a very
> definite reference time (in your parlance).

Not quite.  To which component do you make it the "reference time?"
Precisely because there are potentially many components in an
"application", there's not a "main" initialization point like
ORB_init.  

>> Along with ccm_activation, the added ciao_preactivate and
>> ciao_postactivate calls provide developers 3 distinct levels of
>> ordered initialization.  I will argue that 3 is not generic enough.
>> In fact, I will argue that there should not be a preset number of
>> initialization levels.

>         This is not about initialization levels. This is about
> preset callbacks/hooks/control points that can be externalized and
> controlled when pieces of your application go live. The pre call
> allows you to set up resources that can be used as part of the
> regular activate call, and the post is for cleanup activities. You
> can see this paradigms in many use cases. POA's pre_invoke () and
> post_invoke () is the one probably the most easiest to connect (in
> addition to pre_init () and post_init ()). And you will see below
> why 3 is sufficient.

Again, the example you use, method invocation in POA, there is a clear
reference point.  It makes sense to do something before that and after
that.  

>> Take the ARMS use-case for example.  In the 3 levels of
>> initialization, we would do:

> As an aside ARMS would have been much simpler with just a pre*
> call. The post_* is redundant for ARMS. post* is nice from
> symmetricity perspective.

I agree that ARMS use-case is trivial but that's beside the point
here. 

>> (1) Getting the logging service ready to work properly.  I.e, after
>> pre-activate, we can use the logging service to "log" stuff.

> Okay. Just a little digresison here:

> In ARMS the logging service is _actually_ a component. It abstracts
> away some details of the underlying logger. The logger required that
> an init () (or an equivalent) be called before use. This implied
> that the logger component needs to be intialized first. 

Right.  I knew logging service is a component and why the preactivate
call is used to hard code the fact that logging service is used as a
service for other components.  What if someday, you want to initialize
another service that logging service depends on?  You will need a
prepreactivate call to do that.

> CCM doesn't provide a way to order component initializations based
> on dependencies. 

I agree with this. :)

> Hence the pre* was done to provide some guarantee to the application

But my point is that using pre/post-activate calls is not a general
solution.  

> And, oh, BTW this (ordering/dependency between components) is a very
> very common problem. 

I agree with you on this statement completely.

> I saw it in ARMS. I see it in the software I am writing. 

I am sure they have the same order of initialization problem also.

> The Bob program saw it too (the app strings used to have an ordering
> of software artifacts in the string definitions in those
> days). 

Not sure what Bob program you are referring to...

> Everyone seems to have their own way of solving it.

Absolutely, there are many ways to skin a cat, just like all computer
science or architecturing problems.  However, there are always
tradeoffs in making these decisions.

>> (2) Getting most of other component ready to work in ccm-activate.

> And in addition, provide a guarantee that other components (whether
> remote or collocated) has a valid reference (and is ready to serve
> requests).

I'm not sure what you mean here.  A component can certainly check if
they have the references they need to function properly.  

>>  (3) Getting the application ready to work by using the
>> post-activate methods for a "facade" component.

> I am not sure what you mean by a "facade" component.

Sorry, I was trying to justify the need for a post-activate call
useful in your example.  

> You seem to be talking about "one" component, and I am (and will be)
> worried about "componentS" that make up my application. Some
> componentS in the same process space can probably share the same
> component for say logging.

Again, contrary to your assumption, I'm thinking of applicatons with
multiple components.

>> Why would this scenario not enough for CCM?  Remember, CCM is all
>> about flexibility and dynamic composition of components.

> No question on the flexibility aspects of CCM. When trying to throw
> in requirements for DRE system (including the software that we are
> working on), the vanilla definition of component doesn't seem to
> hold. You not only need dynamic composition of components, but also
> need much better control of your environment in which these
> components are executing.

Not argument about the need.  The question is how do one achieve that
goal without sacrificing what CCM brings us.

>> What if we want to replace a different logging service that utilize
>> another foobar event-channel-like component to delivery the logs to
>> anyone interested in monitoring the system?  We would need to make
>> sure the foobar component is ready to work before the logging
>> component.  In this case, how do we make sure the foobar component
>> gets initialized before the logging component in the application?
>> Do we modify CIAO to add the ciao_prepreactivate method?
>> Similarly, one can imagine the need to have a ciao_postpostactivate
>> method can come up someday...

>         IMHO, you are missing the point. pre* calls only provides a
> guarantee that they are called before ccm_activate is called. It
> doesn't provide a global ordering guarantee.

Uh, that's exactly my point.  pre* calls alongs don't provide enough
ordering in component initialization.

> More reason why 3 levels are sufficient. 

But I see that it just shows that 3 levels are not enough.  Since you
can always need the 4th and the 5th level as an application evolves.  

> Many applications that I am aware off needs to ensure that their
> dependencies (or resources or whatever) are up before they use
> them. And here is how your use case will pan out (please see how
> your requirement for prepre calls is a moot):

You mean a component using preactivate will never depend on another
component?  

> (1) ciao_preactivate() will be invoked on all components, i.e., on
> foobar, logging and the application component (ordering doesn't
> matter).

What if they matter for some components?

> (2) during ccm_activate () any of the components say foobar or
> logging can use each other . Why? There is a guarantee that the
> other component is up due to the contract the CIAO's middleware
> system provides.

> (3) during ciao_post* call, some intializations can be deferred if
> needed.

> I don't see a reason why this wouldn't work. And I can probably try
> establishing why this would be the most preferred way to do this
> :-)!

My example of logging service depending on another component (such as
a specialized event delivery service) to
perform the actual logging at a remote location will break since you
can not guarantee that it will be pre-activated before logging
service. 
        
>> SO, we can see, the ciao_preactivate and ciao_postactivate only
>> solved the order of initialization problem for the use-case that's
>> specific to the ARMS use-case.

> Me feels that you got it wrong without understanding the semantics.

I beg to defer.  I thought I had a pretty good understanding on how it
worked and what it tried to address.

>> 2. This one is the real killer.  By introducing the
>> ciao_preactivate and ciao_postactivate methods, we in effect are
>> pushing application specific logic, i.e., the order of
>> initialization in a specific application, into component
>> implications.

> I completely disagree. Me thinks that we provide an added
> flexibility by:

> (1) allowing developers to abstract out environment or deployment
> details to a specific component and

Abstract and hard-code the environment and deployment details _inside_
the component implementation.

> (2) providing a guarantee that the environment controller is up and
> running before the actual application that needs to be running in
> that environment is live.

Which also scatter among multiple components.  This is equivalent to
tying these components together and prevent them to be reused with other
components, under different environment.

> It all depends on how one wants to leverage such features in large
> scale embedded systems.

Or hard-code your components for one context.

>> This, in turn, reduce the reusability of a component
>> implementation.  For example, the logging service component
>> mentioned earlier can only be used in applications that use it as a
>> pre-initialized service.

> I think you have a uni-dimensional definition of a component, and
> you also assume that a component by virtue should be resuable.

I'm not sure which dimension you are referring to but yes, I do think
that a component should be reusable.  Do I miss something?

> I say not necessary. You write reusable classes and you also write
> helper classes. Your helper classes (that kitchen sink of a class)
> would be making reusable classes more effective. Similarly you write
> reusable components which embeds pieces of application logic and you
> abstract out the details not expressible in descriptors, into a
> software entity which can be hosted using the same infrastructure
> (and one that would make the reusable component very
> effective). Think of these as helper components that are deployment
> specific.

Components should be reusable.  Even for helper components that are
seemingly hard to reuse, one would eventually figure out some usage
patterns and try to generalize it so they can be used in a broader
categories of applications.  

>> As we can see, components utilizing these methods are in effect
>> restricting how they can be used in an application assembly that
>> requires the specific initialization order.

> Please see above.

>> The ccm_activate and ccm_passivate are really just methods the CCM
>> runtime system calls back to component implementations to get them
>> ready to begin or finish "normal functioning" by, for example,
>> acquiring and releasing resources or verifying a component
>> implementation are in a state for "normal functioning" (such as
>> having all the receptacle connected.)

> Sorry, it is not "just". I am very sorry for not getting this very
> (the intent) clearly across earlier.

>> The key here is that the component need to verify this by itself
>> without depending on other component.  This helps ensure the
>> reusability of a component implementation.  In our previous
>> example, component utilizing the loggging service can only be used
>> with the logging service with that specific initialization order.

> Please see above.

>> What might be a solution to address this "order of initialization"
>> problem?  I think we should explore how to apply the DnC spec to
>> achieve this goal and to avoid modifying the underlying CCM runtime
>> infrastructure.  One thing I'm sure is that the
>> order-of-initialization if an application-specific problem.
>> Therefore, it should be dealt with at the application-level, rather
>> than in the component-implementation-level.

> Couldn't have been better. Yes, order-of-initialization is
> application specific problem. Will your middleware make my task
> easier when I am dealing with 'n' number of dependencies?

Most definitely.  

>> One naive and straightforward way of handling this is to treat
>> components at different init-order as separate applications.  Using
>> this approach, an application assembly under the old approach will
>> then be split into multiple sub-applications that will be deployed
>> in certain order.  This will ensure the earlier deployed
>> sub-applications (e.g, the logging service sub-application) are
>> fully functional before other sub-applications are started.  A
>> simple script that invokes plan-launcher multiple times using
>> different "sub-application assemblies" is a simple way of achieving
>> this goal.

> Oh my! Have you been spending too much time with component folks?
> :-) 

Is that a surprise to you? :-p

> How can I handle components that need to be collocated in the same
> process space as the "application" component?

I think you can easily call out the same NodeApplication when you
install the second batch of the application.  I never said that CIAO
already support this, mind you. :)

>> Another, more elegant approach, is to enhance DnC spec to
>> explicitly define the order of initialization in a hierarchical
>> (nested) assembly.  Since DnC allows assemblies to be viewed as
>> components, if the deployment mechanism can ensure that the
>> sub-application assemblies will always be fully deployed before
>> upper level assemblies, the problem is easy to solve.  For the ARMS
>> use-case, the logging component can then be defined as a single
>> component assembly which will implicitly instruct the enhanced DnC
>> mechanism to finalize the component before deploying the others.
>> This approach is more involved and will likely need to modify the
>> DnC spec.

> Yup! Too complex and hard to get it right.

We haven't even tried or put too much thought into it yet.  :)  

>> application-level.  Anyhow, I hope the above analysis makes sense
>> to you folk.

> Not for me, since your analysis assumes some stereotyped definitions
> and usage rules. I don't think (and believe) CIAO will make a cut in
> those areas. 

I'm not sure what you mean by stereotyped definitions and usage
rules.  

> TAO is successful (and so will CIAO be) since it stepped away from
> canonical usage models and exposed what is important for
> applications in a proprietary manner.

I have no doubt that TAO addresses tough problems in ORB design and
thus is very successful.  I don't think that I'm suggesting that CIAO
should try to stay mediocre by avoiding hard problems.  I'm just
suggesting that there should be a way to address these hard problems
while staying true to the component programming model. 

>> If not, please let me know.

> Please see above.

Again, I'm sorry that I didn't get my point across the first time.  I
believe you're reply further validate my claim.  Hopefully, I am
making my point clearer now.  

Thanks,

nanbor
Comment 1 Nanbor Wang 2006-05-08 13:23:45 CDT
This looks fine with me.  However, I wonder if we should reword it to
emphasize the following points:

  1. They are non-standard
  2. Users should avoid using them
  3. They will be deprecated (well, we haven't decided on this yet,
     but IMO it will be a good thing to do.
  4. Elaborate more on how we will fix it in the future.

I'll be happy to take a stab at this if we can agree on this approach.

Thanks,

nanbor

On Tue, 07 Mar 2006 08:38:32 -0600, Gan Deng <gan.deng@vanderbilt.edu> said:

> Hi Nanbor, Could you please make a pass on the Q/A entry I put up
> with below?

> Thanks, Gan

> Q: What is the purpose of the ciao_preactivate() and
> ciao_postactivate() operations and how do I use them?

> A: The purpose of ciao_preactivate and ciao_postactivate methods is
> to provide a mechanism for developers to enforce the order of
> initialization of many components in an assembled application.

> For example, the ciao_preactivate method can be used to initialize
> certain services (such as application specific logging mechanism)
> before all the compnoents in the assembly are activated through
> ccm_activate. Similarly, the ciao_postactivate can be used to
> finalize some services after components are activated (such as
> sending diagnostic messages to the logging server if necessary).

> In the future, CIAO component middleware will use the
> "ImplementationDependency" tag under the
> "ComponentImplementationDescription" tag, as defined by the OMG
> Deployment and Configuration Sepcification, to specify the
> dependencies a particular component could have on the external
> environment, including dependencies to other components.
Comment 2 Nanbor Wang 2006-05-08 13:24:26 CDT
> This looks fine with me.  However, I wonder if we should reword it to
> emphasize the following points:
> 
>   1. They are non-standard
>   2. Users should avoid using them
>   3. They will be deprecated (well, we haven't decided on this yet,
>      but IMO it will be a good thing to do.
>   4. Elaborate more on how we will fix it in the future.
> 
> I'll be happy to take a stab at this if we can agree on this approach.

That sounds fine to me.  I think it's particularly important to address
point #4, i.e., we need to figure out how to alleviate the need for this
stuff, particularly in ARMS!

Thanks,

Doug
Comment 3 Nanbor Wang 2006-05-08 13:24:52 CDT
We could use the "ImplementationDependency" tag under the 
ComponentImplementationDescription, to specify the dependencies a 
particular component could have on the external environment.

Please note, that i am making the following assumptions:

1. The external environment is also another component, as the logging 
service in the ARMS example, that Bala pointed out.

2. We cannot handle post_activate case with this, because the D&C spec 
does not believe on an intermediate stage between ccm_activate and 
ccm_passivate (and hence ccm_remove).

We would need to define the semantics of post_activate more, to see if 
it is an implementation issue, in which case we can handle them as 
part of the component implementation logic.

Current DAnCE makes all pre_activate calls, then makes all 
ccm_activate calls and then makes all post_activate calls.

The new DAnCE will first activate all the components referred as 
"ImplementationDependency" (there must be some intelligence to derive 
which is the order of initialization), and then activate all other 
components. There would not be any post_activate calls.

There could be some speed decrease in deployment time, because of the 
operation of the dependency-resolver algorithm, but its a one time 
occurrence.

But now, we have the flexibility of reusable components at both the 
application level (composition of assemblies) as well as at a 
monolithic level (because the dependencies need not be specified as 
part of the implementation logic, but rather as XML descriptions).

I have been wanting to explore this for sometime now, and would love 
to give it a try sometime soon.

Thanks,
	Jai
Comment 4 Nanbor Wang 2006-05-08 13:27:32 CDT
I think we should examine if we can use of ImplementationDependency to solve 
this problem, as Jai pointed out.  Redeploying a component instance could be 
hairly tho.
Comment 5 Will Otte 2008-03-15 10:49:30 CDT
This stuff is coming out in the refactoring branch, activation ordering will be implemented later as a part of my research.  
Comment 6 Will Otte 2009-02-18 21:36:16 CST
ciao_{pre,post}activate are gone.