Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Expose a clean Java API for retrieval and modification of the cluster configuration, as well as injection of elements into the cache and region levels of the cluster configuration.
  • Do not require a developer to explicitly define methods to translate a configuration object to or from XML.
  • Separate concerns of XML generation and function execution.

Approach

  • Define a no-op interfaces CacheElement and RegionElement to identify classes that may be saved to the cache and region XML entities, respectively.
  • Leverage JAXB to generate an initial set of configuration objects.  
  • Expose ClusterConfigurationService via the cache, provided a locator is managing that cache.

...

As a minimum viable product, we would require only two methods: a getter and an updater.

No Format
public interface ClusterConfigurationService {

...


 /**

...


 * @param group The group to which the cluster configuration applies.

...


 * For configuration that applies to every member, use the group "cluster".

...


 * @param additionalBindClass These classes will allow the returned CacheConfig to include objects

...


 * if the bound types, rather than defaulting to {@link com.sun.org.apache.xerces.internal.dom.ElementNSImpl}

...


 * to represent the configuration elements XML.

...


 * @return The cluster configuration for the specified group.

...


 */

...


 CacheConfig getCacheConfig(String group, Class... additionalBindClass);

...



 /**

...


 * @param group The group to which the cluster configuration applies.

...


 * For configuration that applies to every member, use the group "cluster".

...


 * @param mutator Specification of how the cluster configuration should be altered.

...


 * @param additionalBindClass These classes will allow the returned CacheConfig to include objects

...


 * if the bound types, rather than defaulting to {@link com.sun.org.apache.xerces.internal.dom.ElementNSImpl}

...


 * to represent the configuration elements XML.

...


 */

...


 void updateCacheConfig(String group, UnaryOperator<CacheConfig> mutator, Class... additionalBindClass);
}

...

 

 

We accept the UnaryOperator to mutate the existing cluster configuration rather than accepting an explicit CacheConfig to overwrite the existing cluster configuration in the interest of safe concurrent access.  

...

The ClusterConfigurationService will be made available from the Cache, provided the Cache is managed by a Locator.  The service is unavailable for other members.

Intended Use:

Given an interface as the above, we would be able to implement, for instance, the CreateIndexCommand instead as

No Format
public class CreateIndexCommand implements GfshCommand {
  private static final CreateIndexFunction createIndexFunction = new CreateIndexFunction();

  @CliCommand(value = CliStrings.CREATE_INDEX, help = CliStrings.CREATE_INDEX__HELP)
  @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
  @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
      operation = ResourcePermission.Operation.MANAGE, target = ResourcePermission.Target.QUERY)
  public Result createIndex(...){
 
  Result result;
  final Set<DistributedMember> targetMembers = findMembers(group, memberNameOrID);

  if (targetMembers.isEmpty()) {
    return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
  }

  // Objective: create this Index object.
  // This class was generated by JAXB
  RegionConfig.Index index = new RegionConfig.Index();
  index.setName(indexName);
  index.setExpression(indexedExpression);
  index.setType(indexType.name());
  index.setFromClause(regionPath);

  // Pass the function to each member, where the index will be instantiated.
  List<CliFunctionResult> functionResults =
      executeAndGetFunctionResult(createIndexFunction, index, targetMembers);
  result = ResultBuilder.buildResult(functionResults);

  ClusterConfigurationService service = getSharedConfiguration();
  if (result.getStatus().equals(Result.Status.OK) && service != null) {
    // If the function executes successfully and the ClusterConfigurationService exists
    // (i.e., the member executing this command is a Locator), then update the cluster config.

    UnaryOperator<CacheConfig> mutator = cc -> {
      RegionConfig regionConfig =
          cc.getRegion().stream().filter(x -> x.getName().equals(regionPath)).findFirst()
              .orElse(null);
      regionConfig.getIndex().add(index);
      return cc;
    };
    service.updateCacheConfig("cluster", mutator);
  }
  return result;
}

 

Here, we declaratively build the RegionConfig.Index object we would like to add to the configuration.
On successfull creation, we search for the RegionConfig object to which the index configuration should belong and add this index to that array.
With the mutator defined, we execute (a concurrency-safe) update to the cluster configuration.

Long-term Goals

  • Reduce duplication of effort by replacing "creation" classes (i.e., CacheCreation, RegionCreation, BindingCreation, et al) with JAXB-generated classes.
  • Remove requirement of JAXB / XML annotations on configuration element classes.