Skip to content

Allow blocking or explicitly selecting PV sources #2939

@smarsching

Description

@smarsching

At the moment, the choice of data source implementations for certain protocols is hard-coded. For example, the org.phoebus.pv.ca.JCA_PVFactory will always be registered for PVs with the type ca.

I am in the process of preparing a custom product of Phoebus, and due to having experienced issues with JCA in the past, we want to use EPICS Jackie instead of JCA. Some time ago, we did the same for a custom product of CSS. There, this was easy because the relevant bundle could simply be excluded from the built and be replaced with a different bundle.

In Phoebus, however, the CA support that is based on JCA is part of the core-pv module. So, in order to replace JCA_PVFactory with a different implementation we would have to maintain a fork of core-pv, which is bothersome in the long run.

I see three ways how this could be avoided:

  1. The contents of the org.phoebus.pv.ca package could be moved from the core-pv to a separate module (e.g. core-pv-ca).
  2. A block_pv_sources preference could be added to the org.phoebus.pv.PVPool class. This preference would specify a comma-separated list of classes that should be ignored when discovering PVFactory implementations.
  3. A pv_sources_map preference could be added to the org.phoebus.pv.PVPool class. This prerence would specify a comma-separated list of type to class mappings (e.g. ca:com.example.MySource,pva:com.example.OtherSource) which would override the discovery mechanism for the specified types.

Option 1 upsides:

  • Clear separation of interface and implementation.
  • Code which is not used does not have to be distributed with a product. Neither do their dependencies.

Option 1 downsides:

  • In order to make this truly modular and to allow the distributor to choose which data sources shall be provided, this would also have to be done for all the other data sources that are part of the core-pv module. So, several new modules would have to be added.
  • The build logic of existing products would have to be modified to explicitly depend on the desired modules because unlike the core-pv module, this modules would not be pulled in as transitive dependencies. However, I think that this problem could be alleviated by adding another module that depends on all these new modules and adding this new module as a dependency of all modules that currently only depend on core-pv. Distributors wanting to exclude certain PV sources could exclude this dependency in their build configuration and add explicit dependencies to the desired modules instead.

Option 2 upsides:

  • Very simple, localized change. Only touches a few lines of code in PVPool.
  • Blocked data-source classes will not have to be loaded at all, so dependencies of these classes do not have to be included in the product.

Option 2 downsides:

  • Every data source that shall not be used has to be listed explicitly. This configuration has to be adjusted when the class name of the blocked data source changes for some reason.

Option 3 upsides:

  • Data sources can be overriden by type instead of the class name. This means that renaming the class providing the default implementation for a certain type will not effect existing product configurations and one does not have to no the class name providing the data source for a type that one would like to override.

Option 3 downsides:

  • Data-source classes have to be loaded in order to determine their type. This means that dependencies for these classes must be present as well, even if the class is not used in the end. This could be resolved by combining the mechanism with the one from option 2.

I am happy to provide a PR that makes the necessary changes. However, I want to discuss which of the suggested solutions is preferred first (or maybe there even is a solution that I have not considered yet).

I have a preference for option 1, because from a software design perspective it is the cleanest one. However, I am aware that it also is the most invasive one. If such an invasive change shall be avoided, option 2 is probably the best one (possibly with option 3 added as an additional feature).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions