On 2 Apr 2015, at 17:17, Brian Stansberry
<brian.stansberry(a)redhat.com> wrote:
On 4/2/15 6:11 AM, Kabir Khan wrote:
>
>> On 2 Apr 2015, at 11:01, Kabir Khan <kabir.khan(a)jboss.com> wrote:
>>
>>
>>> On 1 Apr 2015, at 19:48, Brian Stansberry <brian.stansberry(a)redhat.com>
wrote:
>>>
>>> Are the classes in your 2) and 3) new base classes, or examples of what
>>> users would need to do?
>>>
>>> Given your question, I figure it's the latter.
>> Yes they are examples cut and paste from a test case I am working on.
>>>
>>> It seems like it would be fairly straightforward to add the 3) stuff to
>>> AbstractAddStepHandler via a simple constructor param. The 1) stuff is
>>> pretty simple too, but doing both it and 3) starts to get messy in terms
>>> of too many constructor variants.
>> Rather than polluting the existing class too much, since this should really be an
uncommon case (?) perhaps we need an AbstractOrderedAddStepHandler. But it is a bit weird
since the parent and the child both need to override this differently. It shouldn’t be too
hard to come up with something nicer though, I’ll let you know once I have had a play.
> It is doable, but all the constructors are getting a bit messy anyway. I’ll add a
builder to AbstractAddStepHandler instead.
This (meaning the general problem, not a builder approach per se) can get complicated,
due to the different varieties:
AbstractBoottimeAddStepHandler
RestartParentResourceAddHandler
The latter sounds particularly relevant for the child resources, as the need for ordering
implies that it's the parent that's using the child's config data to manage
some service.
I have scrapped the builder approach for now since these classes are
built for overriding. I have:
public abstract class AbstractOrderedResourceAddStepHandler extends AbstractAddStepHandler
{
//Constructors
….
/**
* If this ia a parent resource with ordered child resources, return a set of the
names of the ordered child types.
* If there are no ordered child types, return an empty set.
*
* @return the ordered child types
*/
protected Set<String> getOrderedChildTypes() {
return Collections.emptySet();
}
/**
* Return {@code true} if this is a child resource of a type whose parent supports
ordered inserts
*
* @return whether ordered inserts are supportered
*/
protected boolean supportIndexedAdd() {
return false;
}
@Override
protected Resource createResource(OperationContext context, ModelNode operation) {
Set<String> orderedChildTypes = getOrderedChildTypes();
//Creates a parent with ordered children (if set is not empty)
Resource resource = Resource.Factory.create(false, orderedChildTypes);
//Attempts to do the insert
int index = -1;
if (supportIndexedAdd() && operation.hasDefined(ADD_INDEX)) {
index = operation.get(ADD_INDEX).asInt();
}
if (index >= 0) {
context.addResource(PathAddress.EMPTY_ADDRESS,
operation.get(ADD_INDEX).asInt(), resource);
} else {
context.addResource(PathAddress.EMPTY_ADDRESS, resource);
}
return resource;
}
}
but that does not take the restart part into account at all. Perhaps I should push this
all up into AbstractAddHandler anyway. Do you mind having something like a
public class AbstractAddHandler implements OperationStepHandler {
….
protected ResourceCreator getResourceCreator() {
return DEFAULT; // does what AbstractAddHandler does presently
}
protected Resource createResource(OperationContext context, ModelNode operation) {
return getResourceCreator().createResource(context, operation);
}
}
I could then have an implementation along the lines of
public class OrderedResourceCreator implements ResourceCreator {
private final Set<String> orderedChildTypes;
private final boolean indexedAdd;
public OrderedResourceCreator(Set<String> orderedChildTypes, boolean indexedAdd) {
this.orderedChildTypes = orderedChildTypes;
this.indexedAdd = indexedAdd;
}
protected Resource createResource(OperationContext context, ModelNode operation) {
//same as AbstractOrderedResourceAddStepHandler.createResource() above
}
}
and have sub-classes override getResourceCreator() to return that. Or do you really,
really want this in the constructor rather than in an overridden getter?
>>>
>>> What about re-ordering? Done via add/remove?
>> Yes that would need to be done via remove and add (with add-index). Moving stuff
around would still need to trigger awareness that something changed, but perhaps that
could be done with a handler registered for these parent resources. e.g. something along
the lines of /some=where:reorder-children(child-type=orderedA, order=[tree, bush, hedge]).
For now I see this as a nice to have enhancement which can happen in the future :-)
>>>
I think remove+add is fine.
>>> On 4/1/15 7:54 AM, Kabir Khan wrote:
>>>> I am working on being able to order child resources, this is important
for things like jgroups where the protocol order matters. On top of the domain operations
work I inherited from Emanuel the order will get propagated through the domain. Currently
for jgroups the only way to adjust the protocol order is to remove all protocols and add
them again, and on the domain ops branch (before what I am outlining here) upon reconnect
any new protocols end up at the end of the slave’s list.
>>>>
>>>> The steps to make a child resource ordered are currently:
>>>> 1) Make the ‘parent’ resource’s add handler call a different factory
method:
>>>> @Override
>>>> protected Resource createResource(OperationContext context) {
>>>> Resource resource = Resource.Factory.create(false, “orderedA”,
“orderedB"); //Names of the child types where ordering matters
>>>> context.addResource(PathAddress.EMPTY_ADDRESS, resource);
>>>> return resource;
>>>> }
>>>>
>>>> 2) In the ordered child resource definitions, override the new
getOrderedChildResource() operation to
>>>> class OrderedChildResourceDefinition extends SimpleResourceDefinition {
>>>> public OrderedChildResourceDefinition(PathElement element) {
>>>> super(PathElement.pathElement(“orderedA", new
NonResolvingResourceDescriptionResolver(),
>>>> new OrderedChildAddHandler(REQUEST_ATTRIBUTES), new
ModelOnlyRemoveStepHandler());
>>>> }
>>>>
>>>> @Override
>>>> protected boolean getOrderedChildResource() {
>>>> return true;
>>>> }
>>>> ….
>>>> }
>>>> This has the effect of adding a parameter called ‘add-index’ to the ‘add’
operation’s description. So if you have
>>>> /some=where/orderedA=tree
>>>> /some=where/orderedA=bush
>>>> You can do e.g. /some=where/orderedA=hedge:add(add-index=1) and end up
with:
>>>> /some=where/orderedA=tree
>>>> /some=where/orderedA=hedge
>>>> /some=where/orderedA=bush
>>>>
>>>> 3) The final part is to adjust the ordered child resource’s add handler
to honour the add-index parameter:
>>>>
>>>> class OrderedChildAddHandler extends AbstractAddStepHandler {
>>>> public OrderedChildAddHandler(AttributeDefinition... attributes) {
>>>> super(attributes);
>>>> }
>>>>
>>>> @Override
>>>> protected Resource createResource(OperationContext context, ModelNode
operation) {
>>>> if (!operation.hasDefined(ADD_INDEX) ||
operation.get(ADD_INDEX).asInt() < 0) {
>>>> return super.createResource(context);
>>>> }
>>>> return context.createResource(PathAddress.EMPTY_ADDRESS,
operation.get(ADD_INDEX).asInt());
>>>> }
>>>>
>>>> 4) Not really related to what a user needs to do to create an ordered
resource, but 1-3 are made possible by that on the resource interface I have two new
methods:
>>>> /**
>>>> * Return the child types for which the order matters.
>>>> *
>>>> * @return {@code true} if the order of the children matters. If there
are no ordered
>>>> * children and empty set is returned. This method should never return
{@code null}
>>>> */
>>>> Set<String> getOrderedChildTypes();
>>>>
>>>> /**
>>>> * Register a child resource
>>>> *
>>>> * @param address the address
>>>> * @param index the index at which to add the resource. Existing
children with this index and higher will be shifted one uo
>>>> * @param resource the resource
>>>> * @throws IllegalStateException for a duplicate entry or if the
resource does not support ordered children
>>>> */
>>>> void registerChild(PathElement address, int index, Resource resource);
>>>>
>>>>
>>>> The main question I have is whether 1-3 are too ‘fragile’ and if we need
something to enforce/glue this together a bit more? At the same time ordered child
resources should be the exception rather than the rule.
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> wildfly-dev mailing list
>>>> wildfly-dev(a)lists.jboss.org
>>>>
https://lists.jboss.org/mailman/listinfo/wildfly-dev
>>>>
>>>
>>>
>>> --
>>> Brian Stansberry
>>> Senior Principal Software Engineer
>>> JBoss by Red Hat
>>> _______________________________________________
>>> wildfly-dev mailing list
>>> wildfly-dev(a)lists.jboss.org
>>>
https://lists.jboss.org/mailman/listinfo/wildfly-dev
>>
>>
>> _______________________________________________
>> wildfly-dev mailing list
>> wildfly-dev(a)lists.jboss.org
>>
https://lists.jboss.org/mailman/listinfo/wildfly-dev
>
--
Brian Stansberry
Senior Principal Software Engineer
JBoss by Red Hat