Skip to content

KAFKA-8425: Fix for correctly handling immutable maps (KIP-421 bug)#6795

Merged
rajinisivaram merged 4 commits into
apache:trunkfrom
tadsul:immutableMapFix
Jun 3, 2019
Merged

KAFKA-8425: Fix for correctly handling immutable maps (KIP-421 bug)#6795
rajinisivaram merged 4 commits into
apache:trunkfrom
tadsul:immutableMapFix

Conversation

@tadsul

@tadsul tadsul commented May 23, 2019

Copy link
Copy Markdown
Contributor

The originals map passed to the AbstractConfig class can be immutable. The resolveConfigVariable function was modifying the originals map. If this map is immutable it will result in an exception.

This fix resolves this issue

More detailed description of your change,
if necessary. The PR title and PR message become
the squashed commit message, so use a separate
comment to ping reviewers.

Summary of testing strategy (including rationale)
for the feature or bug fix. Unit and/or integration
tests are expected for any behaviour change and
system tests should be considered for larger changes.

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

…. The resolveConfigVariable function was modifying the originals map. If this map is immutable it will result in an exception.

This fix resolves this issue
private Map<String, ?> resolveConfigVariables(Map<String, ?> configProviderProps, Map<String, Object> originals) {
Map<String, String> providerConfigString;
Map<String, ?> configProperties;
Map<String, Object> originalsMutable = new HashMap<>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit weird to convert an immutable map to mutable and never convert back. Could we refactor the logic to push up the modification logic?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tadsul We could perhaps convert this to a immutable map and store in originalslike we do forvalues`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest naming this variable resolvedOriginals.

@rajinisivaram rajinisivaram left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tadsul Thanks for the PR. Left a couple of comments. Can we make sure that we have a test that fails without the change?

private Map<String, ?> resolveConfigVariables(Map<String, ?> configProviderProps, Map<String, Object> originals) {
Map<String, String> providerConfigString;
Map<String, ?> configProperties;
Map<String, Object> originalsMutable = new HashMap<>();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tadsul We could perhaps convert this to a immutable map and store in originalslike we do forvalues`.

}

@Test
public void testImmutableOriginalsWithConfigProvidersProps() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test fail without the change?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tadsul, what is the answer to this question? (Unresolving this conversation.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes the test fails without the comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I am not sure it would. You should run the test without the changes to AbstractConfig.java to verify. The test invokes new TestIndirectConfigResolution(props, immutableMap) where neither props nor immutableMap is actually immutable. In order fot the test to fail props needs to be unmodifiable since that is the map used as originals. And immutableMap needs to be renamed since it is confusing as it is neither immutable nor the map being tested for immutability.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yes i had to modify the test to make it work .. my yes meant that i could reproduce the issue.. sorry about that i will post the modified test

@rajinisivaram

Copy link
Copy Markdown
Contributor

@tadsul There are checkstyle failures in the PR build. Could you please fix those as well?

@rajinisivaram

Copy link
Copy Markdown
Contributor

@tadsul Can we create a JIRA and set 2.3.0 as fix version to make sure it gets merged into 2.3.0 before thre release?

private Map<String, ?> resolveConfigVariables(Map<String, ?> configProviderProps, Map<String, Object> originals) {
Map<String, String> providerConfigString;
Map<String, ?> configProperties;
Map<String, Object> originalsMutable = new HashMap<>();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest naming this variable resolvedOriginals.

Comment thread clients/src/main/java/org/apache/kafka/common/config/AbstractConfig.java Outdated
}

@Test
public void testImmutableOriginalsWithConfigProvidersProps() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tadsul, what is the answer to this question? (Unresolving this conversation.)

@rajinisivaram rajinisivaram changed the title KIP_421 bug: Fix for correctly handling immutable maps KAFKA-8425; KIP_421 bug: Fix for correctly handling immutable maps May 29, 2019
@rajinisivaram

Copy link
Copy Markdown
Contributor

@tadsul At the moment in AbstractConfig constructor, we are doing:

this.originals = resolveConfigVariables(configProviderProps, (Map<String, Object>) originals);

This doesn't work as expected for two reasons:

  1. If we resolve configs in originals and then invoke plugins with the originals that are already resolved, we resolve configs again. I think we dont want that behaviour. This was the case even before this PR.
  2. As you already figured out, this PR breaks AbstractConfigTest#testUnused because we are replacing RecordingMap with a new map. We shouldn't do that either.

Can't think of a way to fix this behaviour neatly. The only hacky solution I can think of that fixes 1) and 2) would be to check if originals passed through the constructor is a RecordingMap and only resolve if it is not.

  1. is already tested by AbstractConfigTest#testUnused. We should also add a test for 1).

@tadsul
tadsul force-pushed the immutableMapFix branch 2 times, most recently from 4fc4c50 to f89a914 Compare May 31, 2019 21:39
@tadsul

tadsul commented May 31, 2019

Copy link
Copy Markdown
Contributor Author

The 'originals' map in AbstractConfig can be mutable or immutable instance. In order to resolve and save the variable configs we have added a new ResolvingMap class. The ResolvingMap class extends from HashMap and keeps a track of original map instance and the resolved configs. It stores the original input map as-is in a separate internal immutable Map field, and stores all the entries (including the resolved ones) in the super.

The 'originals' map can also be an instance of RecordingMap. In order to ensure that all the usage are recorded correctly the ResolvingMap overrides get() function to perform the following

  1. always call originals.get(key) to record the access.
  2. always return super.get(key) so it it returns the resolved value to the caller.

@rhauch

rhauch commented May 31, 2019

Copy link
Copy Markdown
Contributor

This change will require #6855 to be merged first, which addresses an issue with this PR's builds in which the Kafka Streams tests changed the originals map after instantiating the StreamsConfig class. Once that is merged, this PR's builds should pass.

@rhauch rhauch left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @tadsul! LGTM, pending a green build after #6855 is merged.

@rhauch

rhauch commented May 31, 2019

Copy link
Copy Markdown
Contributor

This will need to be backported to the 2.3 branch, which is the first branch with the config variable resolution via config providers.

@guozhangwang

Copy link
Copy Markdown
Contributor

#6855 has been merged. Retest this please

@rhauch

rhauch commented Jun 2, 2019

Copy link
Copy Markdown
Contributor

retest this please

@rhauch rhauch changed the title KAFKA-8425; KIP_421 bug: Fix for correctly handling immutable maps KAFKA-8425: Fix for correctly handling immutable maps (KIP-421 bug) Jun 2, 2019

@rajinisivaram rajinisivaram left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tadsul Thanks for the updates, LGTM. Merging to trunk and 2.3.

@rajinisivaram
rajinisivaram merged commit 2c810e4 into apache:trunk Jun 3, 2019
rajinisivaram pushed a commit that referenced this pull request Jun 3, 2019
…6795)

Since the originals map passed to AbstractConfig constructor may be immutable, avoid updating this map while resolving indirect config variables. Instead a new ResolvingMap instance is now used to store resolved configs.

Reviewers: Randall Hauch <rhauch@gmail.com>, Boyang Chen <bchen11@outlook.com>, Rajini Sivaram <rajinisivaram@googlemail.com>
omkreddy added a commit to confluentinc/kafka that referenced this pull request Jun 4, 2019
* AK_REPO/2.3:
  KAFKA-8155: Add 2.2.0 release to system tests (apache#6597)
  KAFKA-8404: Add HttpHeader to RestClient HTTP Request and Connector REST API (apache#6791)
  KAFKA-8473: Adjust Connect system tests for incremental cooperative rebalancing (apache#6872)
  KAFKA-8475: Temporarily restore SslFactory.sslContext() helper
  KAFKA-8449: Restart tasks on reconfiguration under incremental cooperative rebalancing (apache#6850)
  KAFKA-8426; Fix for keeping the ConfigProvider configs consistent with KIP-297 (apache#6750)
  KAFKA-8425: Fix for correctly handling immutable maps (KIP-421 bug) (apache#6795)
  MINOR: Reordering the props modification with configs construction
pengxiaolong pushed a commit to pengxiaolong/kafka that referenced this pull request Jun 14, 2019
…pache#6795)

Since the originals map passed to AbstractConfig constructor may be immutable, avoid updating this map while resolving indirect config variables. Instead a new ResolvingMap instance is now used to store resolved configs.

Reviewers: Randall Hauch <rhauch@gmail.com>, Boyang Chen <bchen11@outlook.com>, Rajini Sivaram <rajinisivaram@googlemail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants