[ 
https://issues.apache.org/jira/browse/FELIX-6862?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Kevan Jahanshahi updated FELIX-6862:
------------------------------------
    Issue Type: Bug  (was: Task)

> ConfigInstaller adopts and deletes configuration files that another 
> ArtifactInstaller handles
> ---------------------------------------------------------------------------------------------
>
>                 Key: FELIX-6862
>                 URL: https://issues.apache.org/jira/browse/FELIX-6862
>             Project: Felix
>          Issue Type: Bug
>          Components: File Install
>    Affects Versions: fileinstall-3.7.4
>            Reporter: Kevan Jahanshahi
>            Priority: Major
>
> h2. Summary
> {{ConfigInstaller}} adopts every configuration that records 
> {{felix.fileinstall.filename}}, whatever the format of the file. The 
> {{CM_DELETED}} path then deletes the file that the resulting {{pidToFile}} 
> entry names. An installer therefore deletes a configuration file that another 
> {{ArtifactInstaller}} handles.
> h2. Where this comes from
> FELIX-5832 added a {{canHandle}} filter to the {{CM_UPDATED}} path in 2018, 
> and the subject of that commit states the rule:
> bq. Only handle ConfigurationEvents for config objects managed by us
> Three sites read or write {{pidToFile}}, and FELIX-5832 covered one of them. 
> The other two sites are still unfiltered on {{master}} today.
> * {{init()}} puts every configuration that records a file name into 
> {{pidToFile}}, with no filter.
> * The {{CM_DELETED}} path removes the pid from {{pidToFile}} and deletes the 
> file, with no filter.
> h2. Failure scenario
> A container runs a second {{ArtifactInstaller}} for another configuration 
> format. Jahia ships one for {{.yml}} and {{.yaml}}, and that installer 
> records {{felix.fileinstall.filename}} the same way any installer does.
> # The second installer creates a configuration from {{example.yml}} and 
> records that file name.
> # The container restarts, and {{ConfigInstaller.init()}} adopts the pid, 
> because no filter rejects the format.
> # Something deletes that configuration through Configuration Admin.
> # {{ConfigInstaller}} deletes {{example.yml}}, although it never handled that 
> file.
> The defect needs a restart, because {{init()}} is the only unfiltered writer 
> of {{pidToFile}}. The guarded {{CM_UPDATED}} path rejects the foreign format, 
> so a configuration created while the container runs never enters the map.
> A guard in the second installer cannot prevent the deletion. That installer 
> can decline to delete the file itself, and {{ConfigInstaller}} deletes the 
> file anyway on the same event.
> h2. Proposed fix
> Apply the filter FELIX-5832 already wrote, at both remaining sites.
> {code:java}
> // in init()
> if (fileName != null && canHandle(new File(fileName))) {
>     pidToFile.put(config.getPid(), fileName);
> }
> // in the CM_DELETED path
> if (file != null && file.isFile() && canHandle(file)) {
> {code}
> The filter at the deletion site matters on its own. Deleting the file is the 
> act that loses data, and a filter at each writer makes the invariant depend 
> on every future writer repeating it.
> {{init()}} passes {{new File(fileName)}} rather than 
> {{fromConfigKey(fileName)}}. {{canHandle}} reads the file name only, and 
> {{fromConfigKey}} calls {{URI.create}}, which throws on a value that is not a 
> URI. The catch around that loop would then leave {{pidToFile}} half-built.
> Behaviour for {{.cfg}} and {{.config}} files is unchanged.
> h2. Patch
> A pull request follows. It carries two tests, and the first fails when both 
> filters are removed.
> * {{testCmDeletedKeepsAFileOfAnotherInstallersFormat}} asserts that a 
> {{.yml}} file survives {{CM_DELETED}}.
> * {{testCmDeletedStillRemovesAFileOfItsOwnFormat}} asserts that a {{.cfg}} 
> file is still deleted.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to