On Mon, May 21, 2012 at 1:12 AM, Alex Karasulu <akarasulu@apache.org> wrote:
On Wed, May 16, 2012 at 6:58 AM, Göktürk Gezer <gokturk.gezer@gmail.com> wrote:
> Hi Everyone,
>
> As i told you in OSGI branch update, JDBM is so immutable in runtime. Almost
> every setter calls checkInitialized() method first which throws an exception
> when its already initialized.

This may be unavoidable but I am not qualified to make this call. At
the present moment I am not familiar enough with the internals to
understand how each setting would impact a reconfiguration. It may be
trivial with some settings like for example cache settings by changing
just a few things in JDBM.
Most of checkInitialized() calls are necessary for current design of Jdbm/AbstractBTree Partition. 

In the worst case, if reinitialization with re-configuration must take
place then the proper management can be handled. For example changing
the files/directory path for the record manager for example can occur
with a move of the actual files after the shutdown before the
re-configuration, and before restarting the record manager service
with the new setting for the the db file. Just giving this as one
example. The other settings might require less management overheads.
Moving system files of partition is only necessary when we change its partitionId as i see?
And i believe moving partition files around directories is conflicting with partitionId property's purpose.
Using partitionId property as a pointer to where partition system files are is more consistent IMO. So when
somebody changes some partition's partitionId, then this partition instance must be reinitialized to use the partition files
under specified directory. If new specified directory has incompatible content then we switch back to previous partitionId.
( ComponentHub system supports what i described: when some active component is reconfigured in a state which is not valid,
 then reconfiguration is reverted. further explained below.)

> We have to change that behavior in as much aspects of it as we can.
> Otherwise there is no point in going into OSGI. However i can't always be
> sure what my changes might lead on runtime. I need some serious help here,
> especially from those are actively working on JDBM, otherwise i'll jump into
> trial and error cycle which will probably last long.
>
> Here is the current configuration points for JdbmPartition:

OK Jdbm partition unlike jdbm internals proper I have some suggestions
on. Some settings are not that difficult to deal with on
re-configuration events.

These should be easier to handle:

> cacheSize(int)
> optimizerEnabled(boolean)
> syncOnWrite(boolean)
First 2 don't have checkInitialized() checks already. syncOnWrite() has that check, but i guess we can remove it. 
We only have to insert sync() call before setting this property to ensure none remains in buffers. Right? 

These below I suspect will impose many more management issues to
properly reconfigure on the fly due to file movements and the creation
of new indices (deletion of old indices).
Yes, they're currently not reconfigurable and it seems hard to make them. All three is designed to be read at beginning and no altering mechanism is supplied.
 

> indexedAttributes(List<Index>)
> partitionPath(File)
> suffixDn(Dn)
>
> Currently none of them is reconfigurable, once the partition is initialized.

Right.

> However i need to know which are actually reconfigurable among these ones.
> And which are not really reconfigurable and why?
>
> Every reconfiguration will invoke some setter method at desired
> configuration point. So i guess we can make this reconfigurations work
> actually based on it's initialized or not, rather than throwing an exception
> blindly.

Of course we want re-configuration to be hot because that's really
cool. Sometimes you just don't have the option of shutting down the
server. Then there are software updates to the actual component and
that adds yet another dimension of problems to hot reconfiguration. In
the case of the JDBM partition some changes that change the structure
will make it so the jdbm db files are no longer compatible. So hot
deploys of new versions are not easy or may require long running
changes.
This dynamism can be handled, but i'll cause pain of course, but not much. .db files being incompatible with new version is
something JdbmPartition implementation must handle by itself IMO. It must have mechanisms to migrate old .db files to its own format at initialization time.

And i remember now that i forgot to implement hot bundle replacements(cold replacements are supported which is simply replacing bundle when none of its components are instantiated). But no worries, with cold replacement implemented, it is easy to implement hot reconfiguration in minutes.

Another option or approach can be to handle some of these long running
reconfiguration or software component (bundle) update events not hot
(live) while the server is up and running but after a restart. However
I do not recommend this. There are easy ways to mitigate all these
problems.
No, it would not be good. Conflicting with OSGI anyway. 

> For your information, as we have the lifecycle control capability of
> components created from within ApacheDS, we can implement some fancy stuff.
> Like re-instantiating a component when one of its immutable property is
> changed, or stop it and remove from DirectoryService when one of its
> immutable property is changed to prevent accepting operations while
> reconfiguring. These migtht be implemented in case there is " no
> possibility! " to handle reconfigurations in live and initialized
> JdbmPartition reference.

This is the difference between two different modes of reconfiguration:

(1) An "in-place" re-configuration event recovery by a reconfigured
component while it continues to operate.
(2) A component instance swap out where the reconfiguration causes a
new instance of the component to be constructed and configured with
the new settings while on standby. Until the standby is started and
operational the old component continues to operate. Then the old is
shutdown after a swap out.

Overall the #2 approach is much better in my opinion. Why? Because you
can never predict the outcome of in place modifications to settings.
Changing the component directly may not be something the bundle
developer accounted for right?
Here is how i handled it, (could be changed of course):
 When configuration of some component is changed(via config partition or webconsole plugin which i'll implement later...),
new configuration's validity is checked. Valid means all property values are compatible with the property types defined in component's metadata.
 * for primitives no check is performed, because they are ensured by Ldap schema which is being created for that component specifically.
 * for reference types, it's checked that referenced component's type is compatible with property's type.
 * for collection types, same with reference types + check if all collection items are compatible with specified collection item type.
 * some more consistency checks.
So after these checks, new configuration is considered valid and it's sent to underlying component framework which is used to create the component in first hand to reconfigure that component. So at that point, it is guaranteed that underlying component framework will not complain about any type clashes.

However, component implementation can reject some configuration options even if it is valid schematically. At that point component implementation can choose to set some default value for this property or simply raise an exception. If exception is thrown, then reconfigured component is deactivated completely and it is set as dirty, meaning any further reconfiguration will cause it to be instantiated again.

So this is how it works now. It is some kind a mixture of 1. and 2. way you proposed. And it does real reconfiguration on components rather than what 2. option suggest. 

However using 2. option would be in my favor too, Though it is not really a reconfiguration, it is much easier to manage and it covers much more error scenario which my be thrown while reconfiguration. And by employing such mechanism we don't have to worry about Jdbm begin immutable. Because we'll create new instance anyway, if there are no some lock-file mechanism inside partition directory, we're golden.

Also there is a facility which makes it closer to 2. option, "immutable properties". When you reconfigure an immutable property of some component it is deleted first from system and component listeners, and then it's created with new configuration and introduces into system again. By deactivating-and-activating in order rather than swapping the active instance on the fly, we ensure that hub can detect structural inconsistencies which may come along with that reconfiguration, for example if SystemPartition's partitionId is changed from "system" to "dummy", hub will abort that reconfiguration because ApacheDS can't work without system partition. If we were handled it by swapping instances on the fly, server would continue working but then on the next run it wouldn't start because it's lacking partition with "system" id.

If we'll change the reconfiguration schema to 2. option, then we should put 'immutable properties' into consideration here too. Because we just can not modify some properties which are hardwired to DirectoryService without checking if modification is valid to defined constraints on that property. Otherwise next run of server may not take place properly.

Of course there's the events that are propagated by the OSGi container
when such an event does occur. I imagine these events have fired and
then the actual getter/setter configuration method is invoked in the
framework. Is this correct to presume?
Yes, All frameworks have different invoking policies but in ComponentHub we only care about configuration change. We have activated configuration in one hand and altered configuration in other hand. We validate the altered configuration and send it to underlying component framework.

I think with option #2 we can be more certain that reconfigurations
are better accounted for by bundle developers.
While it destroys hot reconfiguration, yes it is much more accountable. Not so performance wise, but reconfigurations are seldom to appear, so it won't be a problem.

So its your call, i'm good with every option. We can go with option 1 to make real hot reconfigurations, or we can go with option 2 to create an illusion of hot reconfigurations while keeping existing code. 
FYI Switching from 1. to 2. reconfiguration policy in ComponentHub is trivial as i see it.

Thanks,
Gokturk

--
Best Regards,
-- Alex