Skip to content

Conversation

@elek
Copy link
Member

@elek elek commented Apr 25, 2019

See the design doc in the parent jira for more details.

In this jira I introduce a new annotation processor which can generate ozone-default.xml fragments based on the annotations which are introduced by HDDS-1468.

The ozone-default-generated.xml fragments can be used directly by the OzoneConfiguration as I added a small code to the constructor to check ALL the available ozone-default-generated.xml files and add them to the available resources.

With this approach we don't need to edit ozone-default.xml as all the configuration can be defined in java code.

As a side effect each service will see only the available configuration keys and values based on the classpath. (If the ozone-default-generated.xml file of OzoneManager is not on the classpath of the SCM, SCM doesn't see the available configs.)

See: https://issues.apache.org/jira/browse/HDDS-1469

@elek elek added the ozone label Apr 25, 2019
@elek
Copy link
Member Author

elek commented Apr 25, 2019

/cc @anuengineer This is the annotation processor. With a small modification in the OzoneConfiguration (to load all the generated fragments) we don't need to merge all the generated config files to one big ozone-default.xml

@hadoop-yetus
Copy link

💔 -1 overall

Vote Subsystem Runtime Comment
0 reexec 0 Docker mode activated.
-1 patch 8 #773 does not apply to trunk. Rebase required? Wrong Branch? See https://wiki.apache.org/hadoop/HowToContribute for help.
Subsystem Report/Notes
GITHUB PR #773
Console output https://builds.apache.org/job/hadoop-multibranch/job/PR-773/1/console
Powered by Apache Yetus 0.9.0 http://yetus.apache.org

This message was automatically generated.

Copy link
Contributor

@anuengineer anuengineer left a comment

Choose a reason for hiding this comment

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

The code changes look excellent. I have some questions and Jenkins was not very happy, but in spirit, I am +1.

Configuration.addDefaultResource("hdfs-default.xml");
Configuration.addDefaultResource("hdfs-site.xml");
Configuration.addDefaultResource("ozone-default.xml");
Configuration.addDefaultResource("ozone-site.xml");
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we still allow this over-ride?

Copy link
Member Author

@elek elek Apr 26, 2019

Choose a reason for hiding this comment

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

We should. But in fact I didn't remove the possibility to use ozone-site.xml I just moved it.

The problem here is that the hadoop Configuration is not designed to be reused. We can use multiple Configuration.addDefaultResource(String) but there is no Configuration.addDefaultResource(URL) (and we can't create one as all the required methods are private :-( ).

With using configuration fragments we have multiple files with the same name (String) but with different URL (eg. jar://hadoop-ozone-ozone-manager.jar!/ozone-default-generated.xml).

To support this, but keep the same precedence I modified the configuration loading:

Configuration.addDefaultResource("hdfs-default.xml");
Configuration.addDefaultResource("hdfs-site.xml");
Configuration.addDefaultResource("ozone-default.xml");

conf.addResource("jar://ozone-manager.jar!/ozone-site-generated.xml");
conf.addResource("jar://storage-container-manager.jar!/ozone-site-generated.xml");

conf.addResource("ozone-site.xml");

The last three lines are in the constructor of OzoneConfiguration and as I would like to load ozone-site.xml at the end I moved it to there.

loadDefaults();
}

private void loadDefaults() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can I be a greedy pig and request that we also sort these keys (in another JIRA of course) before we write out the XML?


@Config(key = "enabled", defaultValue = "true")
public void setEnabled(boolean enabled) {
this.enabled = enabled;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: what does client. enabled mean?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is just an example configuration (for unit tests) I invented a random boolean configuration. Name doesn't matter but I can use a more meaningful one. For example client.compression.enabled.


@Config(key = "wait", type = ConfigType.TIME, timeUnit =
TimeUnit.SECONDS, defaultValue = "10m")
public void setWaitTime(long waitTime) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice 👏

*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;

ConfigTag[] tags() default {ConfigTag.OZONE};
Copy link
Contributor

Choose a reason for hiding this comment

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

We should enforce this and description, so the code will error out during compile.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point. I removed the 'default's for tags and description.

<parent>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdds</artifactId>
<version>0.5.0-SNAPSHOT</version>
Copy link
Contributor

Choose a reason for hiding this comment

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

is it possible to inherit this value from the parent POM ? more a question for my understanding..

Copy link
Member Author

Choose a reason for hiding this comment

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

This is some kind of chicken egg problem. You should have an exact version for your parent pom as you don't know which parent should be downloaded to check the current version.

What you can remove is the normal <version> (not the <version> of the parent) which is by default the same as the parent.version (AFAIK).

But as a solution the maven version plugin is introduced to search and replace both version and parent version in a consistent way so it's not a problem.


/**
* Annotation processor to generate ozone-site-generated fragments from
* ozone-site.xml.
Copy link
Contributor

Choose a reason for hiding this comment

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

wrong comment? from config classes?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep. Thanks.

}

Filer filer = processingEnv.getFiler();
System.out.println("round");
Copy link
Contributor

Choose a reason for hiding this comment

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

Debug?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ups.

if (element.getKind() == ElementKind.METHOD) {
processingEnv.getMessager()
.printMessage(Kind.WARNING, element.getSimpleName().toString());
if (element.getSimpleName().toString().startsWith("set")
Copy link
Contributor

Choose a reason for hiding this comment

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

In future, we might want to emit a warning if you have "Set" for example, assuming that was a mistake that user is making, and letting them know we are ignoring it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we can implement a lot of validation. For example if you have a class with @ConfigGroup annotation but without annotated setters.

defaultValue = "3s",
tags = {SCM, OZONE},
description = "When a heartbeat from the data node arrives on SCM, "
+ "It is queued for processing with the time stamp of when the "
Copy link
Contributor

Choose a reason for hiding this comment

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

@nandakumar131 Do we still use this Key ? or is this some code changed but we forgot to remove the config value case?

Copy link
Member Author

Choose a reason for hiding this comment

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

We use it (conf.getInterval())

 /**
   * ReplicationMonitor thread runnable. This wakes up at configured
   * interval and processes all the containers in the system.
   */
  private synchronized void run() {
    try {
      while (running) {
        final long start = Time.monotonicNow();
        final Set<ContainerID> containerIds =
            containerManager.getContainerIDs();
        containerIds.forEach(this::processContainer);

        LOG.info("Replication Monitor Thread took {} milliseconds for" +
                " processing {} containers.", Time.monotonicNow() - start,
            containerIds.size());

        wait(conf.getInterval());
      }
    } catch (Throwable t) {
      // When we get runtime exception, we should terminate SCM.
      LOG.error("Exception in Replication Monitor Thread.", t);
      ExitUtil.terminate(1, t);
    }
  }

@anuengineer
Copy link
Contributor

/cc @anuengineer This is the annotation processor. With a small modification in the OzoneConfiguration (to load all the generated fragments) we don't need to merge all the generated config files to one big ozone-default.xml

I am ok with that, but some of the old school people might like a single file, and in the deployment, phase don't we need a single file ? or should we move away since the code already has the default?

@elek
Copy link
Member Author

elek commented Apr 26, 2019

I am ok with that, but some of the old school people might like a single file, and in the deployment, phase don't we need a single file ? or should we move away since the code already has the default?

It's a very good question and I don't know the final answer. In fact we use standard hadoop Configuration features to load all the fragments, so it should be fine. I would prefer to try out this approach (with independent config fragments), but based on the feedback, experiences, we can improve/refactor it.

My arguments:

  1. First of all, it's easier to implement. We don't need a final merge.
  2. It's way easier to test. To generate the final ozone-default.xml we need a project which depends on all the others with config fragments. But in the mean time we need merged ozone-default.xml to test the different components. With fragments it just works based on classpath.
  3. The biggest argument to use one ozone-default.xml (IMHO) is that it can be used as a documentation. But I think we can provide better documentation page (with better structures). But it can be true: we may need to generate a static doc page about all the configuration settings.
  4. It's very interesting that the source of a key is recorded in the Configuration class. With using fragments we will have a source information out of the box:
<property>
   <name>hdds.scm.replication.event.timeout</name>
   <value>10m</value>
   <final>false</final>
   <source>jar:file:/opt/hadoop/share/ozone/lib/hadoop-hdds-server-scm-0.5.0-SNAPSHOT.jar!/ozone-default-generated.xml</source>
</property>

It also means that we don't need to use SCM, HDDS, OZONE tags any more as they can be added based on the source. And with this approach we can print out the configuration based on the components (eg. SCM configs, common configs, etc.). Would be great to add an other information, too: which class defined the specific configuration key.

@hadoop-yetus
Copy link

💔 -1 overall

Vote Subsystem Runtime Comment
0 reexec 0 Docker mode activated.
-1 patch 7 #773 does not apply to trunk. Rebase required? Wrong Branch? See https://wiki.apache.org/hadoop/HowToContribute for help.
Subsystem Report/Notes
GITHUB PR #773
Console output https://builds.apache.org/job/hadoop-multibranch/job/PR-773/2/console
Powered by Apache Yetus 0.9.0 http://yetus.apache.org

This message was automatically generated.

@anuengineer
Copy link
Contributor

Thank you for your comments and explanations. +1. Please feel free to commit this. Thanks for getting this done. We can now add more features into the processor, hopefully generating code for get/set and validation methods. At some point, it would be nice to have a validation method too.

@elek
Copy link
Member Author

elek commented Apr 28, 2019

Thank you very much the review @anuengineer

I will merge it and create follow-up jiras about validation, start to use the API at more places, generate docs, etc.

This patch includes the commit of HDDS-1468 as it's based on that previous work. You already commented on that one and I addressed the comments but for the sake of the formality could you please also give me a +1 there (to make it clear that it's reviewed).

@anuengineer
Copy link
Contributor

👍 +1 , thanks LGTM.

@elek
Copy link
Member Author

elek commented May 2, 2019

Thanks the review @anuengineer I am merging it right now.

@elek elek closed this in e2f0f72 May 2, 2019
@hadoop-yetus
Copy link

💔 -1 overall

Vote Subsystem Runtime Comment
0 reexec 45 Docker mode activated.
_ Prechecks _
+1 @author 0 The patch does not contain any @author tags.
+1 test4tests 0 The patch appears to include 8 new or modified test files.
_ trunk Compile Tests _
0 mvndep 76 Maven dependency ordering for branch
+1 mvninstall 1200 trunk passed
+1 compile 1002 trunk passed
+1 checkstyle 143 trunk passed
-1 mvnsite 43 server-scm in trunk failed.
+1 shadedclient 1166 branch has no errors when building and testing our client artifacts.
0 findbugs 0 Skipped patched modules with no Java source: hadoop-hdds hadoop-ozone/integration-test
-1 findbugs 30 server-scm in trunk failed.
+1 javadoc 172 trunk passed
_ Patch Compile Tests _
0 mvndep 22 Maven dependency ordering for patch
+1 mvninstall 240 the patch passed
+1 compile 941 the patch passed
+1 javac 941 the patch passed
+1 checkstyle 143 the patch passed
+1 mvnsite 251 the patch passed
+1 whitespace 0 The patch has no whitespace issues.
+1 xml 8 The patch has no ill-formed XML file.
+1 shadedclient 739 patch has no errors when building and testing our client artifacts.
0 findbugs 0 Skipped patched modules with no Java source: hadoop-hdds hadoop-ozone/integration-test
+1 findbugs 179 the patch passed
+1 javadoc 70 hadoop-hdds generated 0 new + 14 unchanged - 6 fixed = 14 total (was 20)
+1 javadoc 47 common in the patch passed.
+1 javadoc 28 config in the patch passed.
+1 javadoc 30 hadoop-hdds_server-scm generated 0 new + 5 unchanged - 6 fixed = 5 total (was 11)
+1 javadoc 26 integration-test in the patch passed.
_ Other Tests _
-1 unit 161 hadoop-hdds in the patch failed.
+1 unit 84 common in the patch passed.
+1 unit 31 config in the patch passed.
+1 unit 128 server-scm in the patch passed.
-1 unit 828 integration-test in the patch failed.
+1 asflicense 49 The patch does not generate ASF License warnings.
8045
Reason Tests
Failed junit tests hadoop.ozone.client.rpc.TestOzoneClientRetriesOnException
hadoop.hdds.scm.safemode.TestSCMSafeModeWithPipelineRules
hadoop.ozone.scm.TestXceiverClientMetrics
hadoop.ozone.web.TestOzoneVolumes
hadoop.ozone.om.TestOmInit
hadoop.ozone.web.client.TestKeys
hadoop.ozone.scm.pipeline.TestSCMPipelineMetrics
hadoop.ozone.web.client.TestOzoneClient
hadoop.ozone.om.TestOmAcls
hadoop.hdds.scm.container.TestContainerStateManagerIntegration
hadoop.ozone.ozShell.TestOzoneDatanodeShell
hadoop.ozone.TestStorageContainerManager
hadoop.ozone.scm.pipeline.TestPipelineManagerMXBean
hadoop.ozone.om.TestOzoneManagerHA
hadoop.ozone.container.TestContainerReplication
hadoop.ozone.ozShell.TestS3Shell
hadoop.ozone.scm.TestSCMNodeManagerMXBean
hadoop.ozone.scm.TestSCMMXBean
hadoop.ozone.ozShell.TestOzoneShell
hadoop.ozone.web.TestOzoneWebAccess
hadoop.ozone.client.rpc.TestCommitWatcher
hadoop.ozone.om.TestOmMetrics
hadoop.ozone.om.TestContainerReportWithKeys
hadoop.ozone.om.TestOzoneManager
hadoop.ozone.client.rpc.TestOzoneRpcClientWithRatis
hadoop.ozone.client.rpc.TestReadRetries
hadoop.ozone.client.rpc.TestBlockOutputStreamWithFailures
hadoop.ozone.client.rpc.TestOzoneRpcClient
hadoop.ozone.scm.TestContainerSmallFile
hadoop.ozone.scm.node.TestQueryNode
hadoop.hdds.scm.pipeline.TestRatisPipelineUtils
hadoop.ozone.scm.node.TestSCMNodeMetrics
hadoop.ozone.client.rpc.TestBCSID
hadoop.ozone.om.TestOMDbCheckpointServlet
hadoop.hdds.scm.pipeline.TestNodeFailure
hadoop.ozone.scm.TestXceiverClientManager
Subsystem Report/Notes
Docker Client=17.05.0-ce Server=17.05.0-ce base: https://builds.apache.org/job/hadoop-multibranch/job/PR-773/3/artifact/out/Dockerfile
GITHUB PR #773
Optional Tests dupname asflicense compile javac javadoc mvninstall mvnsite unit shadedclient xml findbugs checkstyle
uname Linux 57b7dac76d38 4.4.0-144-generic #170~14.04.1-Ubuntu SMP Mon Mar 18 15:02:05 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Build tool maven
Personality personality/hadoop.sh
git revision trunk / 3cb1d09
maven version: Apache Maven 3.3.9
Default Java 1.8.0_191
mvnsite https://builds.apache.org/job/hadoop-multibranch/job/PR-773/3/artifact/out/branch-mvnsite-hadoop-hdds_server-scm.txt
findbugs v3.1.0-RC1
findbugs https://builds.apache.org/job/hadoop-multibranch/job/PR-773/3/artifact/out/branch-findbugs-hadoop-hdds_server-scm.txt
unit https://builds.apache.org/job/hadoop-multibranch/job/PR-773/3/artifact/out/patch-unit-hadoop-hdds.txt
unit https://builds.apache.org/job/hadoop-multibranch/job/PR-773/3/artifact/out/patch-unit-hadoop-ozone_integration-test.txt
Test Results https://builds.apache.org/job/hadoop-multibranch/job/PR-773/3/testReport/
Max. process+thread count 4551 (vs. ulimit of 5500)
modules C: hadoop-hdds hadoop-hdds/common hadoop-hdds/config hadoop-hdds/server-scm hadoop-ozone/integration-test U: .
Console output https://builds.apache.org/job/hadoop-multibranch/job/PR-773/3/console
Powered by Apache Yetus 0.9.0 http://yetus.apache.org

This message was automatically generated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants