{"action":"created","comment":{"url":"https://api.github.com/repos/elastic/elasticsearch/pulls/comments/47012509","id":47012509,"diff_hunk":"@@ -0,0 +1,394 @@\n+/*\n+ * Licensed to Elasticsearch under one or more contributor\n+ * license agreements. See the NOTICE file distributed with\n+ * this work for additional information regarding copyright\n+ * ownership. Elasticsearch licenses this file to you under\n+ * the Apache License, Version 2.0 (the \"License\"); you may\n+ * not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *    http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing,\n+ * software distributed under the License is distributed on an\n+ * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n+ * KIND, either express or implied.  See the License for the\n+ * specific language governing permissions and limitations\n+ * under the License.\n+ */\n+package org.elasticsearch.common.settings;\n+\n+import org.elasticsearch.ElasticsearchParseException;\n+import org.elasticsearch.action.support.ToXContentToBytes;\n+import org.elasticsearch.common.Booleans;\n+import org.elasticsearch.common.logging.ESLogger;\n+import org.elasticsearch.common.regex.Regex;\n+import org.elasticsearch.common.unit.ByteSizeValue;\n+import org.elasticsearch.common.unit.MemorySizeValue;\n+import org.elasticsearch.common.unit.TimeValue;\n+import org.elasticsearch.common.xcontent.*;\n+\n+import java.io.IOException;\n+import java.util.concurrent.atomic.AtomicReference;\n+import java.util.function.BiConsumer;\n+import java.util.function.Consumer;\n+import java.util.function.Function;\n+import java.util.function.Predicate;\n+\n+/**\n+ */\n+public class Setting<T> extends ToXContentToBytes {\n+    private final String key;\n+    private final String description;\n+    private final Function<Settings, String> defaultValue;\n+    private final Function<String, T> parser;\n+    private final boolean dynamic;\n+    private final Scope scope;\n+\n+    public Setting(String key, String description, Function<Settings, String> defaultValue, Function<String, T> parser, boolean dynamic, Scope scope) {\n+        this.key = key;\n+        this.description = description;\n+        this.defaultValue = defaultValue;\n+        this.parser = parser;\n+        this.dynamic = dynamic;\n+        this.scope = scope;\n+    }\n+\n+    /**\n+     * Returns the settings key or a prefix if this setting is a group setting\n+     * @see #isGroupSetting()\n+     */\n+    public String getKey() {\n+        return key;\n+    }\n+\n+    /**\n+     * Returns a human readable description of this setting\n+     */\n+    public String getDescription() {\n+        return description;\n+    }\n+\n+    /**\n+     * Returns <code>true</code> iff this setting is dynamically updateable, otherwise <code>false</code>\n+     */\n+    public boolean isDynamic() {\n+        return dynamic;\n+    }\n+\n+    /**\n+     * Returns the settings scope\n+     */\n+    public Scope getScope() {\n+        return scope;\n+    }\n+\n+    /**\n+     * Returns <code>true</code> iff this setting is a group setting. Group settings represent a set of settings\n+     * rather than a single value. The key, see {@link #getKey()}, in contrast to non-group settings is a prefix like <tt>cluster.store.</tt>\n+     * that matches all settings with this prefix.\n+     */\n+    public boolean isGroupSetting() {\n+        return false;\n+    }\n+\n+    /**\n+     * Returns the default values string representation for this setting.\n+     * @param settings a settings object for settings that has a default value depending on another setting if available\n+     */\n+    public String getDefault(Settings settings) {\n+        return defaultValue.apply(settings);\n+    }\n+\n+    /**\n+     * Returns <code>true</code> iff this setting is present in the given settings object. Otherwise <code>false</code>\n+     */\n+    public boolean exists(Settings settings) {\n+        return settings.get(key) != null;\n+    }\n+\n+    /**\n+     * Returns the settings value. If the setting is not present in the given settings object the default value is returned\n+     * instead.\n+     */\n+    public T get(Settings settings) {\n+        String value = getRaw(settings);\n+        try {\n+            return parser.apply(value);\n+        } catch (ElasticsearchParseException ex) {\n+            throw ex;\n+        } catch (Throwable t) {\n+            throw new IllegalArgumentException(\"Failed to parse value [\" + value + \"] for setting [\" + getKey() + \"]\", t);\n+        }\n+    }\n+\n+    /**\n+     * Returns the raw (string) settings value. If the setting is not present in the given settings object the default value is returned\n+     * instead. This is useful if the value can't be parsed due to an invalid value to access the actual value.\n+     */\n+    public String getRaw(Settings settings) {\n+        return settings.get(key, defaultValue.apply(settings));\n+    }\n+\n+    /**\n+     * Returns <code>true</code> iff the given key matches the settings key or if this setting is a group setting if the\n+     * given key is part of the settings group.\n+     * @see #isGroupSetting()\n+     */\n+    public boolean match(String toTest) {\n+        return Regex.simpleMatch(key, toTest);\n+    }\n+\n+    @Override\n+    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n+        builder.startObject();\n+        builder.field(\"key\", key);\n+        builder.field(\"description\", description);\n+        builder.field(\"type\", scope.name());\n+        builder.field(\"dynamic\", dynamic);\n+        builder.field(\"default\", defaultValue.apply(Settings.EMPTY));","path":"core/src/main/java/org/elasticsearch/common/settings/Setting.java","position":149,"original_position":149,"commit_id":"6c7e5069d4aa841646e3069466fa93c945accfc8","original_commit_id":"5d7f4ef3943dcbd14e85021075f59c9b7cc7b262","user":{"login":"nik9000","id":215970,"avatar_url":"https://avatars.githubusercontent.com/u/215970?v=3","gravatar_id":"","url":"https://api.github.com/users/nik9000","html_url":"https://github.com/nik9000","followers_url":"https://api.github.com/users/nik9000/followers","following_url":"https://api.github.com/users/nik9000/following{/other_user}","gists_url":"https://api.github.com/users/nik9000/gists{/gist_id}","starred_url":"https://api.github.com/users/nik9000/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nik9000/subscriptions","organizations_url":"https://api.github.com/users/nik9000/orgs","repos_url":"https://api.github.com/users/nik9000/repos","events_url":"https://api.github.com/users/nik9000/events{/privacy}","received_events_url":"https://api.github.com/users/nik9000/received_events","type":"User","site_admin":false},"body":"It squashes the brains out of `defaultValue`. It only returns the default used when other settings don't exist. I can see that being fine for now but catching someone unexpectedly in three years.","created_at":"2015-12-08T20:58:03Z","updated_at":"2015-12-08T20:58:03Z","html_url":"https://github.com/elastic/elasticsearch/pull/15278#discussion_r47012509","pull_request_url":"https://api.github.com/repos/elastic/elasticsearch/pulls/15278","_links":{"self":{"href":"https://api.github.com/repos/elastic/elasticsearch/pulls/comments/47012509"},"html":{"href":"https://github.com/elastic/elasticsearch/pull/15278#discussion_r47012509"},"pull_request":{"href":"https://api.github.com/repos/elastic/elasticsearch/pulls/15278"}}},"pull_request":{"url":"https://api.github.com/repos/elastic/elasticsearch/pulls/15278","id":52835348,"html_url":"https://github.com/elastic/elasticsearch/pull/15278","diff_url":"https://github.com/elastic/elasticsearch/pull/15278.diff","patch_url":"https://github.com/elastic/elasticsearch/pull/15278.patch","issue_url":"https://api.github.com/repos/elastic/elasticsearch/issues/15278","number":15278,"state":"open","locked":false,"title":"Add infrastructure to transactionally apply and reset dynamic settings","user":{"login":"s1monw","id":973334,"avatar_url":"https://avatars.githubusercontent.com/u/973334?v=3","gravatar_id":"","url":"https://api.github.com/users/s1monw","html_url":"https://github.com/s1monw","followers_url":"https://api.github.com/users/s1monw/followers","following_url":"https://api.github.com/users/s1monw/following{/other_user}","gists_url":"https://api.github.com/users/s1monw/gists{/gist_id}","starred_url":"https://api.github.com/users/s1monw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/s1monw/subscriptions","organizations_url":"https://api.github.com/users/s1monw/orgs","repos_url":"https://api.github.com/users/s1monw/repos","events_url":"https://api.github.com/users/s1monw/events{/privacy}","received_events_url":"https://api.github.com/users/s1monw/received_events","type":"User","site_admin":false},"body":"This commit adds the infrastructure to make settings that are updateable\r\nresetable and changes the application of updates to be transactional. This means\r\nsetting updates are either applied or not. If the application failes all values are rejected.\r\n\r\nThis initial commit converts all dynamic cluster settings to make use of the new infrastructure.\r\nAll cluster level dynamic settings are not resettable to their defaults or to the node level settings.\r\nThe infrastructure also allows to list default values and descriptions which is not fully implemented yet.\r\n\r\nValues can be reset using a list of key or simple regular expressions. This has only been implemented on the java\r\nlayer yet. For instance to reset all recovery settings to their defaults a user can just specify `indices.recovery.*`.\r\n\r\nThis commit also adds strict settings validation, if a setting is unknown or if a setting can not be applied the entire\r\nsettings update request will fail.","created_at":"2015-12-07T11:50:39Z","updated_at":"2015-12-08T20:58:03Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b0720f3f0c43ed4a7cebaa836f2d4d0f7fec3cfd","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/elastic/elasticsearch/pulls/15278/commits","review_comments_url":"https://api.github.com/repos/elastic/elasticsearch/pulls/15278/comments","review_comment_url":"https://api.github.com/repos/elastic/elasticsearch/pulls/comments{/number}","comments_url":"https://api.github.com/repos/elastic/elasticsearch/issues/15278/comments","statuses_url":"https://api.github.com/repos/elastic/elasticsearch/statuses/6c7e5069d4aa841646e3069466fa93c945accfc8","head":{"label":"s1monw:settings_prototype","ref":"settings_prototype","sha":"6c7e5069d4aa841646e3069466fa93c945accfc8","user":{"login":"s1monw","id":973334,"avatar_url":"https://avatars.githubusercontent.com/u/973334?v=3","gravatar_id":"","url":"https://api.github.com/users/s1monw","html_url":"https://github.com/s1monw","followers_url":"https://api.github.com/users/s1monw/followers","following_url":"https://api.github.com/users/s1monw/following{/other_user}","gists_url":"https://api.github.com/users/s1monw/gists{/gist_id}","starred_url":"https://api.github.com/users/s1monw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/s1monw/subscriptions","organizations_url":"https://api.github.com/users/s1monw/orgs","repos_url":"https://api.github.com/users/s1monw/repos","events_url":"https://api.github.com/users/s1monw/events{/privacy}","received_events_url":"https://api.github.com/users/s1monw/received_events","type":"User","site_admin":false},"repo":{"id":4663744,"name":"elasticsearch","full_name":"s1monw/elasticsearch","owner":{"login":"s1monw","id":973334,"avatar_url":"https://avatars.githubusercontent.com/u/973334?v=3","gravatar_id":"","url":"https://api.github.com/users/s1monw","html_url":"https://github.com/s1monw","followers_url":"https://api.github.com/users/s1monw/followers","following_url":"https://api.github.com/users/s1monw/following{/other_user}","gists_url":"https://api.github.com/users/s1monw/gists{/gist_id}","starred_url":"https://api.github.com/users/s1monw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/s1monw/subscriptions","organizations_url":"https://api.github.com/users/s1monw/orgs","repos_url":"https://api.github.com/users/s1monw/repos","events_url":"https://api.github.com/users/s1monw/events{/privacy}","received_events_url":"https://api.github.com/users/s1monw/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/s1monw/elasticsearch","description":"Open Source, Distributed, RESTful Search Engine","fork":true,"url":"https://api.github.com/repos/s1monw/elasticsearch","forks_url":"https://api.github.com/repos/s1monw/elasticsearch/forks","keys_url":"https://api.github.com/repos/s1monw/elasticsearch/keys{/key_id}","collaborators_url":"https://api.github.com/repos/s1monw/elasticsearch/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/s1monw/elasticsearch/teams","hooks_url":"https://api.github.com/repos/s1monw/elasticsearch/hooks","issue_events_url":"https://api.github.com/repos/s1monw/elasticsearch/issues/events{/number}","events_url":"https://api.github.com/repos/s1monw/elasticsearch/events","assignees_url":"https://api.github.com/repos/s1monw/elasticsearch/assignees{/user}","branches_url":"https://api.github.com/repos/s1monw/elasticsearch/branches{/branch}","tags_url":"https://api.github.com/repos/s1monw/elasticsearch/tags","blobs_url":"https://api.github.com/repos/s1monw/elasticsearch/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/s1monw/elasticsearch/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/s1monw/elasticsearch/git/refs{/sha}","trees_url":"https://api.github.com/repos/s1monw/elasticsearch/git/trees{/sha}","statuses_url":"https://api.github.com/repos/s1monw/elasticsearch/statuses/{sha}","languages_url":"https://api.github.com/repos/s1monw/elasticsearch/languages","stargazers_url":"https://api.github.com/repos/s1monw/elasticsearch/stargazers","contributors_url":"https://api.github.com/repos/s1monw/elasticsearch/contributors","subscribers_url":"https://api.github.com/repos/s1monw/elasticsearch/subscribers","subscription_url":"https://api.github.com/repos/s1monw/elasticsearch/subscription","commits_url":"https://api.github.com/repos/s1monw/elasticsearch/commits{/sha}","git_commits_url":"https://api.github.com/repos/s1monw/elasticsearch/git/commits{/sha}","comments_url":"https://api.github.com/repos/s1monw/elasticsearch/comments{/number}","issue_comment_url":"https://api.github.com/repos/s1monw/elasticsearch/issues/comments{/number}","contents_url":"https://api.github.com/repos/s1monw/elasticsearch/contents/{+path}","compare_url":"https://api.github.com/repos/s1monw/elasticsearch/compare/{base}...{head}","merges_url":"https://api.github.com/repos/s1monw/elasticsearch/merges","archive_url":"https://api.github.com/repos/s1monw/elasticsearch/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/s1monw/elasticsearch/downloads","issues_url":"https://api.github.com/repos/s1monw/elasticsearch/issues{/number}","pulls_url":"https://api.github.com/repos/s1monw/elasticsearch/pulls{/number}","milestones_url":"https://api.github.com/repos/s1monw/elasticsearch/milestones{/number}","notifications_url":"https://api.github.com/repos/s1monw/elasticsearch/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/s1monw/elasticsearch/labels{/name}","releases_url":"https://api.github.com/repos/s1monw/elasticsearch/releases{/id}","created_at":"2012-06-14T13:44:13Z","updated_at":"2015-05-07T08:25:29Z","pushed_at":"2015-12-08T20:50:35Z","git_url":"git://github.com/s1monw/elasticsearch.git","ssh_url":"git@github.com:s1monw/elasticsearch.git","clone_url":"https://github.com/s1monw/elasticsearch.git","svn_url":"https://github.com/s1monw/elasticsearch","homepage":"http://elasticsearch.org","size":182279,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"elastic:master","ref":"master","sha":"c6938896aa59624dcdb57c89253ad3de3e165f17","user":{"login":"elastic","id":6764390,"avatar_url":"https://avatars.githubusercontent.com/u/6764390?v=3","gravatar_id":"","url":"https://api.github.com/users/elastic","html_url":"https://github.com/elastic","followers_url":"https://api.github.com/users/elastic/followers","following_url":"https://api.github.com/users/elastic/following{/other_user}","gists_url":"https://api.github.com/users/elastic/gists{/gist_id}","starred_url":"https://api.github.com/users/elastic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elastic/subscriptions","organizations_url":"https://api.github.com/users/elastic/orgs","repos_url":"https://api.github.com/users/elastic/repos","events_url":"https://api.github.com/users/elastic/events{/privacy}","received_events_url":"https://api.github.com/users/elastic/received_events","type":"Organization","site_admin":false},"repo":{"id":507775,"name":"elasticsearch","full_name":"elastic/elasticsearch","owner":{"login":"elastic","id":6764390,"avatar_url":"https://avatars.githubusercontent.com/u/6764390?v=3","gravatar_id":"","url":"https://api.github.com/users/elastic","html_url":"https://github.com/elastic","followers_url":"https://api.github.com/users/elastic/followers","following_url":"https://api.github.com/users/elastic/following{/other_user}","gists_url":"https://api.github.com/users/elastic/gists{/gist_id}","starred_url":"https://api.github.com/users/elastic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elastic/subscriptions","organizations_url":"https://api.github.com/users/elastic/orgs","repos_url":"https://api.github.com/users/elastic/repos","events_url":"https://api.github.com/users/elastic/events{/privacy}","received_events_url":"https://api.github.com/users/elastic/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/elastic/elasticsearch","description":"Open Source, Distributed, RESTful Search Engine","fork":false,"url":"https://api.github.com/repos/elastic/elasticsearch","forks_url":"https://api.github.com/repos/elastic/elasticsearch/forks","keys_url":"https://api.github.com/repos/elastic/elasticsearch/keys{/key_id}","collaborators_url":"https://api.github.com/repos/elastic/elasticsearch/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/elastic/elasticsearch/teams","hooks_url":"https://api.github.com/repos/elastic/elasticsearch/hooks","issue_events_url":"https://api.github.com/repos/elastic/elasticsearch/issues/events{/number}","events_url":"https://api.github.com/repos/elastic/elasticsearch/events","assignees_url":"https://api.github.com/repos/elastic/elasticsearch/assignees{/user}","branches_url":"https://api.github.com/repos/elastic/elasticsearch/branches{/branch}","tags_url":"https://api.github.com/repos/elastic/elasticsearch/tags","blobs_url":"https://api.github.com/repos/elastic/elasticsearch/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/elastic/elasticsearch/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/elastic/elasticsearch/git/refs{/sha}","trees_url":"https://api.github.com/repos/elastic/elasticsearch/git/trees{/sha}","statuses_url":"https://api.github.com/repos/elastic/elasticsearch/statuses/{sha}","languages_url":"https://api.github.com/repos/elastic/elasticsearch/languages","stargazers_url":"https://api.github.com/repos/elastic/elasticsearch/stargazers","contributors_url":"https://api.github.com/repos/elastic/elasticsearch/contributors","subscribers_url":"https://api.github.com/repos/elastic/elasticsearch/subscribers","subscription_url":"https://api.github.com/repos/elastic/elasticsearch/subscription","commits_url":"https://api.github.com/repos/elastic/elasticsearch/commits{/sha}","git_commits_url":"https://api.github.com/repos/elastic/elasticsearch/git/commits{/sha}","comments_url":"https://api.github.com/repos/elastic/elasticsearch/comments{/number}","issue_comment_url":"https://api.github.com/repos/elastic/elasticsearch/issues/comments{/number}","contents_url":"https://api.github.com/repos/elastic/elasticsearch/contents/{+path}","compare_url":"https://api.github.com/repos/elastic/elasticsearch/compare/{base}...{head}","merges_url":"https://api.github.com/repos/elastic/elasticsearch/merges","archive_url":"https://api.github.com/repos/elastic/elasticsearch/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/elastic/elasticsearch/downloads","issues_url":"https://api.github.com/repos/elastic/elasticsearch/issues{/number}","pulls_url":"https://api.github.com/repos/elastic/elasticsearch/pulls{/number}","milestones_url":"https://api.github.com/repos/elastic/elasticsearch/milestones{/number}","notifications_url":"https://api.github.com/repos/elastic/elasticsearch/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/elastic/elasticsearch/labels{/name}","releases_url":"https://api.github.com/repos/elastic/elasticsearch/releases{/id}","created_at":"2010-02-08T13:20:56Z","updated_at":"2015-12-08T19:36:12Z","pushed_at":"2015-12-08T20:50:40Z","git_url":"git://github.com/elastic/elasticsearch.git","ssh_url":"git@github.com:elastic/elasticsearch.git","clone_url":"https://github.com/elastic/elasticsearch.git","svn_url":"https://github.com/elastic/elasticsearch","homepage":"https://www.elastic.co/products/elasticsearch","size":226923,"stargazers_count":13906,"watchers_count":13906,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":4610,"mirror_url":null,"open_issues_count":1194,"forks":4610,"open_issues":1194,"watchers":13906,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/elastic/elasticsearch/pulls/15278"},"html":{"href":"https://github.com/elastic/elasticsearch/pull/15278"},"issue":{"href":"https://api.github.com/repos/elastic/elasticsearch/issues/15278"},"comments":{"href":"https://api.github.com/repos/elastic/elasticsearch/issues/15278/comments"},"review_comments":{"href":"https://api.github.com/repos/elastic/elasticsearch/pulls/15278/comments"},"review_comment":{"href":"https://api.github.com/repos/elastic/elasticsearch/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/elastic/elasticsearch/pulls/15278/commits"},"statuses":{"href":"https://api.github.com/repos/elastic/elasticsearch/statuses/6c7e5069d4aa841646e3069466fa93c945accfc8"}}}}