Merge branch 'master' into ccr

* master:
  Logging: Make node name consistent in logger (#31588)
  Mute SSLTrustRestrictionsTests on JDK 11
  Increase max chunk size to 256Mb for repo-azure (#32101)
  Docs: Fix README upgrade mention (#32313)
  Changed ReindexRequest to use Writeable.Reader (#32401)
  Mute KerberosAuthenticationIT
  Fix AutoIntervalDateHistogram.testReduce random failures (#32301)
  fix no=>not typo (#32463)
  Mute QueryProfilerIT#testProfileMatchesRegular()
  HLRC: Add delete watch action (#32337)
  High-level client: fix clusterAlias parsing in SearchHit (#32465)
  Fix calculation of orientation of polygons (#27967)
  [Kerberos] Add missing javadocs (#32469)
  [Kerberos] Remove Kerberos bootstrap checks (#32451)
  Make get all app privs requires "*" permission (#32460)
  Switch security to new style Requests (#32290)
  Switch security spi example to new style Requests (#32341)
  Painless: Add PainlessConstructor (#32447)
  update rollover to leverage write-alias semantics (#32216)
  Update Fuzzy Query docs to clarify default behavior re max_expansions (#30819)
  INGEST: Clean up Java8 Stream Usage (#32059)
  Ensure KeyStoreWrapper decryption exceptions are handled (#32464)
This commit is contained in:
Nhat Nguyen 2018-07-31 10:56:10 -04:00
commit 036cb3f864
134 changed files with 2263 additions and 827 deletions

View File

@ -209,10 +209,6 @@ The distribution for each project will be created under the @build/distributions
See the "TESTING":TESTING.asciidoc file for more information about running the Elasticsearch test suite.
h3. Upgrading from Elasticsearch 1.x?
h3. Upgrading from older Elasticsearch versions
In order to ensure a smooth upgrade process from earlier versions of
Elasticsearch (1.x), it is required to perform a full cluster restart. Please
see the "setup reference":
https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-upgrade.html
for more details on the upgrade process.
In order to ensure a smooth upgrade process from earlier versions of Elasticsearch, please see our "upgrade documentation":https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-upgrade.html for more details on the upgrade process.

View File

@ -1,7 +1,7 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%node_name]%marker %m%n
# Do not log at all if it is not really critical - we're in a benchmark
rootLogger.level = error

View File

@ -1,7 +1,7 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%node_name]%marker %m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console

View File

@ -107,6 +107,7 @@ import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.index.rankeval.RankEvalRequest;
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.protocol.xpack.XPackUsageRequest;
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
@ -1133,6 +1134,18 @@ final class RequestConverters {
return request;
}
static Request xPackWatcherDeleteWatch(DeleteWatchRequest deleteWatchRequest) {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
.addPathPartAsIs("watcher")
.addPathPartAsIs("watch")
.addPathPart(deleteWatchRequest.getId())
.build();
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
return request;
}
static Request xpackUsage(XPackUsageRequest usageRequest) {
Request request = new Request(HttpGet.METHOD_NAME, "/_xpack/usage");
Params parameters = new Params(request);

View File

@ -19,12 +19,15 @@
package org.elasticsearch.client;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchResponse;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchResponse;
import java.io.IOException;
import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
public final class WatcherClient {
@ -61,4 +64,31 @@ public final class WatcherClient {
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::xPackWatcherPutWatch, options,
PutWatchResponse::fromXContent, listener, emptySet());
}
/**
* Deletes a watch from the cluster
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-delete-watch.html">
* the docs</a> for more.
* @param request the request
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return the response
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public DeleteWatchResponse deleteWatch(DeleteWatchRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::xPackWatcherDeleteWatch, options,
DeleteWatchResponse::fromXContent, singleton(404));
}
/**
* Asynchronously deletes a watch from the cluster
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-delete-watch.html">
* the docs</a> for more.
* @param request the request
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @param listener the listener to be notified upon request completion
*/
public void deleteWatchAsync(DeleteWatchRequest request, RequestOptions options, ActionListener<DeleteWatchResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::xPackWatcherDeleteWatch, options,
DeleteWatchResponse::fromXContent, listener, singleton(404));
}
}

View File

@ -126,6 +126,7 @@ import org.elasticsearch.index.rankeval.RankEvalSpec;
import org.elasticsearch.index.rankeval.RatedRequest;
import org.elasticsearch.index.rankeval.RestRankEvalAction;
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.rest.action.search.RestSearchAction;
@ -2580,6 +2581,17 @@ public class RequestConvertersTests extends ESTestCase {
assertThat(bos.toString("UTF-8"), is(body));
}
public void testXPackDeleteWatch() {
DeleteWatchRequest deleteWatchRequest = new DeleteWatchRequest();
String watchId = randomAlphaOfLength(10);
deleteWatchRequest.setId(watchId);
Request request = RequestConverters.xPackWatcherDeleteWatch(deleteWatchRequest);
assertEquals(HttpDelete.METHOD_NAME, request.getMethod());
assertEquals("/_xpack/watcher/watch/" + watchId, request.getEndpoint());
assertThat(request.getEntity(), nullValue());
}
/**
* Randomize the {@link FetchSourceContext} request parameters.
*/

View File

@ -21,6 +21,8 @@ package org.elasticsearch.client;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchResponse;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchResponse;
@ -30,6 +32,13 @@ public class WatcherIT extends ESRestHighLevelClientTestCase {
public void testPutWatch() throws Exception {
String watchId = randomAlphaOfLength(10);
PutWatchResponse putWatchResponse = createWatch(watchId);
assertThat(putWatchResponse.isCreated(), is(true));
assertThat(putWatchResponse.getId(), is(watchId));
assertThat(putWatchResponse.getVersion(), is(1L));
}
private PutWatchResponse createWatch(String watchId) throws Exception {
String json = "{ \n" +
" \"trigger\": { \"schedule\": { \"interval\": \"10h\" } },\n" +
" \"input\": { \"none\": {} },\n" +
@ -37,10 +46,30 @@ public class WatcherIT extends ESRestHighLevelClientTestCase {
"}";
BytesReference bytesReference = new BytesArray(json);
PutWatchRequest putWatchRequest = new PutWatchRequest(watchId, bytesReference, XContentType.JSON);
PutWatchResponse putWatchResponse = highLevelClient().xpack().watcher().putWatch(putWatchRequest, RequestOptions.DEFAULT);
assertThat(putWatchResponse.isCreated(), is(true));
assertThat(putWatchResponse.getId(), is(watchId));
assertThat(putWatchResponse.getVersion(), is(1L));
return highLevelClient().xpack().watcher().putWatch(putWatchRequest, RequestOptions.DEFAULT);
}
public void testDeleteWatch() throws Exception {
// delete watch that exists
{
String watchId = randomAlphaOfLength(10);
createWatch(watchId);
DeleteWatchResponse deleteWatchResponse = highLevelClient().xpack().watcher().deleteWatch(new DeleteWatchRequest(watchId),
RequestOptions.DEFAULT);
assertThat(deleteWatchResponse.getId(), is(watchId));
assertThat(deleteWatchResponse.getVersion(), is(2L));
assertThat(deleteWatchResponse.isFound(), is(true));
}
// delete watch that does not exist
{
String watchId = randomAlphaOfLength(10);
DeleteWatchResponse deleteWatchResponse = highLevelClient().xpack().watcher().deleteWatch(new DeleteWatchRequest(watchId),
RequestOptions.DEFAULT);
assertThat(deleteWatchResponse.getId(), is(watchId));
assertThat(deleteWatchResponse.getVersion(), is(1L));
assertThat(deleteWatchResponse.isFound(), is(false));
}
}
}

View File

@ -26,6 +26,8 @@ import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchResponse;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchResponse;
@ -34,7 +36,7 @@ import java.util.concurrent.TimeUnit;
public class WatcherDocumentationIT extends ESRestHighLevelClientTestCase {
public void testPutWatch() throws Exception {
public void testWatcher() throws Exception {
RestHighLevelClient client = highLevelClient();
{
@ -88,5 +90,46 @@ public class WatcherDocumentationIT extends ESRestHighLevelClientTestCase {
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
{
//tag::x-pack-delete-watch-execute
DeleteWatchRequest request = new DeleteWatchRequest("my_watch_id");
DeleteWatchResponse response = client.xpack().watcher().deleteWatch(request, RequestOptions.DEFAULT);
//end::x-pack-delete-watch-execute
//tag::x-pack-delete-watch-response
String watchId = response.getId(); // <1>
boolean found = response.isFound(); // <2>
long version = response.getVersion(); // <3>
//end::x-pack-delete-watch-response
}
{
DeleteWatchRequest request = new DeleteWatchRequest("my_other_watch_id");
// tag::x-pack-delete-watch-execute-listener
ActionListener<DeleteWatchResponse> listener = new ActionListener<DeleteWatchResponse>() {
@Override
public void onResponse(DeleteWatchResponse response) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::x-pack-delete-watch-execute-listener
// Replace the empty listener by a blocking listener in test
final CountDownLatch latch = new CountDownLatch(1);
listener = new LatchedActionListener<>(listener, latch);
// tag::x-pack-delete-watch-execute-async
client.xpack().watcher().deleteWatchAsync(request, RequestOptions.DEFAULT, listener); // <1>
// end::x-pack-delete-watch-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
}

View File

@ -7,13 +7,13 @@ logger.action.level = debug
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name]%marker %m%n
appender.rolling.type = RollingFile
appender.rolling.name = rolling
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name]%marker %.-10000m%n
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}-%i.log.gz
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
@ -38,7 +38,7 @@ appender.deprecation_rolling.type = RollingFile
appender.deprecation_rolling.name = deprecation_rolling
appender.deprecation_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log
appender.deprecation_rolling.layout.type = PatternLayout
appender.deprecation_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n
appender.deprecation_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name]%marker %.-10000m%n
appender.deprecation_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation-%i.log.gz
appender.deprecation_rolling.policies.type = Policies
appender.deprecation_rolling.policies.size.type = SizeBasedTriggeringPolicy
@ -55,7 +55,7 @@ appender.index_search_slowlog_rolling.type = RollingFile
appender.index_search_slowlog_rolling.name = index_search_slowlog_rolling
appender.index_search_slowlog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_search_slowlog.log
appender.index_search_slowlog_rolling.layout.type = PatternLayout
appender.index_search_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%.-10000m%n
appender.index_search_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%node_name]%marker %.-10000m%n
appender.index_search_slowlog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_search_slowlog-%i.log.gz
appender.index_search_slowlog_rolling.policies.type = Policies
appender.index_search_slowlog_rolling.policies.size.type = SizeBasedTriggeringPolicy
@ -72,7 +72,7 @@ appender.index_indexing_slowlog_rolling.type = RollingFile
appender.index_indexing_slowlog_rolling.name = index_indexing_slowlog_rolling
appender.index_indexing_slowlog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_indexing_slowlog.log
appender.index_indexing_slowlog_rolling.layout.type = PatternLayout
appender.index_indexing_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%.-10000m%n
appender.index_indexing_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%node_name]%marker %.-10000m%n
appender.index_indexing_slowlog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_indexing_slowlog-%i.log.gz
appender.index_indexing_slowlog_rolling.policies.type = Policies
appender.index_indexing_slowlog_rolling.policies.size.type = SizeBasedTriggeringPolicy

View File

@ -54,11 +54,14 @@ The Java High Level REST Client supports the following Miscellaneous APIs:
* <<java-rest-high-main>>
* <<java-rest-high-ping>>
* <<java-rest-high-x-pack-info>>
* <<java-rest-high-x-pack-watcher-put-watch>>
* <<java-rest-high-x-pack-watcher-delete-watch>>
include::miscellaneous/main.asciidoc[]
include::miscellaneous/ping.asciidoc[]
include::x-pack/x-pack-info.asciidoc[]
include::x-pack/watcher/put-watch.asciidoc[]
include::x-pack/watcher/delete-watch.asciidoc[]
== Indices APIs

View File

@ -0,0 +1,53 @@
[[java-rest-high-x-pack-watcher-delete-watch]]
=== X-Pack Delete Watch API
[[java-rest-high-x-pack-watcher-delete-watch-execution]]
==== Execution
A watch can be deleted as follows:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/WatcherDocumentationIT.java[x-pack-delete-watch-execute]
--------------------------------------------------
[[java-rest-high-x-pack-watcher-delete-watch-response]]
==== Response
The returned `DeleteWatchResponse` contains `found`, `id`,
and `version` information.
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/WatcherDocumentationIT.java[x-pack-put-watch-response]
--------------------------------------------------
<1> `_id` contains id of the watch
<2> `found` is a boolean indicating whether the watch was found
<3> `_version` returns the version of the deleted watch
[[java-rest-high-x-pack-watcher-delete-watch-async]]
==== Asynchronous Execution
This request can be executed asynchronously:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/WatcherDocumentationIT.java[x-pack-delete-watch-execute-async]
--------------------------------------------------
<1> The `DeleteWatchRequest` to execute and the `ActionListener` to use when
the execution completes
The asynchronous method does not block and returns immediately. Once it is
completed the `ActionListener` is called back using the `onResponse` method
if the execution successfully completed or using the `onFailure` method if
it failed.
A typical listener for `DeleteWatchResponse` looks like:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/WatcherDocumentationIT.java[x-pack-delete-watch-execute-listener]
--------------------------------------------------
<1> Called when the execution is successfully completed. The response is
provided as an argument
<2> Called in case of failure. The raised exception is provided as an argument

View File

@ -1,5 +1,5 @@
[[java-rest-high-x-pack-watcher-put-watch]]
=== X-Pack Info API
=== X-Pack Put Watch API
[[java-rest-high-x-pack-watcher-put-watch-execution]]
==== Execution
@ -16,7 +16,7 @@ include-tagged::{doc-tests}/WatcherDocumentationIT.java[x-pack-put-watch-execute
[[java-rest-high-x-pack-watcher-put-watch-response]]
==== Response
The returned `XPackPutWatchResponse` contain `created`, `id`,
The returned `PutWatchResponse` contains `created`, `id`,
and `version` information.
["source","java",subs="attributes,callouts,macros"]
@ -36,7 +36,7 @@ This request can be executed asynchronously:
--------------------------------------------------
include-tagged::{doc-tests}/WatcherDocumentationIT.java[x-pack-put-watch-execute-async]
--------------------------------------------------
<1> The `XPackPutWatchRequest` to execute and the `ActionListener` to use when
<1> The `PutWatchRequest` to execute and the `ActionListener` to use when
the execution completes
The asynchronous method does not block and returns immediately. Once it is
@ -44,7 +44,7 @@ completed the `ActionListener` is called back using the `onResponse` method
if the execution successfully completed or using the `onFailure` method if
it failed.
A typical listener for `XPackPutWatchResponse` looks like:
A typical listener for `PutWatchResponse` looks like:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------

View File

@ -653,7 +653,7 @@ GET /_search
// CONSOLE
In the above example, buckets will be created for all the tags that has the word `sport` in them, except those starting
with `water_` (so the tag `water_sports` will no be aggregated). The `include` regular expression will determine what
with `water_` (so the tag `water_sports` will not be aggregated). The `include` regular expression will determine what
values are "allowed" to be aggregated, while the `exclude` determines the values that should not be aggregated. When
both are defined, the `exclude` has precedence, meaning, the `include` is evaluated first and only then the `exclude`.

View File

@ -50,7 +50,7 @@ appender.index_search_slowlog_rolling.type = RollingFile
appender.index_search_slowlog_rolling.name = index_search_slowlog_rolling
appender.index_search_slowlog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_search_slowlog.log
appender.index_search_slowlog_rolling.layout.type = PatternLayout
appender.index_search_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%.-10000m%n
appender.index_search_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%node_name]%marker %.-10000m%n
appender.index_search_slowlog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_search_slowlog-%i.log.gz
appender.index_search_slowlog_rolling.policies.type = Policies
appender.index_search_slowlog_rolling.policies.size.type = SizeBasedTriggeringPolicy
@ -103,7 +103,7 @@ appender.index_indexing_slowlog_rolling.type = RollingFile
appender.index_indexing_slowlog_rolling.name = index_indexing_slowlog_rolling
appender.index_indexing_slowlog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_indexing_slowlog.log
appender.index_indexing_slowlog_rolling.layout.type = PatternLayout
appender.index_indexing_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%.-10000m%n
appender.index_indexing_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%node_name]%marker %.-10000m%n
appender.index_indexing_slowlog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_indexing_slowlog-%i.log.gz
appender.index_indexing_slowlog_rolling.policies.type = Policies
appender.index_indexing_slowlog_rolling.policies.size.type = SizeBasedTriggeringPolicy

View File

@ -257,6 +257,9 @@ and there are multiple indices referenced by an alias, then writes will not be a
It is possible to specify an index associated with an alias as a write index using both the aliases API
and index creation API.
Setting an index to be the write index with an alias also affects how the alias is manipulated during
Rollover (see <<indices-rollover-index, Rollover With Write Index>>).
[source,js]
--------------------------------------------------
POST /_aliases

View File

@ -4,10 +4,19 @@
The rollover index API rolls an alias over to a new index when the existing
index is considered to be too large or too old.
The API accepts a single alias name and a list of `conditions`. The alias
must point to a single index only. If the index satisfies the specified
conditions then a new index is created and the alias is switched to point to
the new index.
The API accepts a single alias name and a list of `conditions`. The alias must point to a write index for
a Rollover request to be valid. There are two ways this can be achieved, and depending on the configuration, the
alias metadata will be updated differently. The two scenarios are as follows:
- The alias only points to a single index with `is_write_index` not configured (defaults to `null`).
In this scenario, the original index will have their rollover alias will be added to the newly created index, and removed
from the original (rolled-over) index.
- The alias points to one or more indices with `is_write_index` set to `true` on the index to be rolled over (the write index).
In this scenario, the write index will have its rollover alias' `is_write_index` set to `false`, while the newly created index
will now have the rollover alias pointing to it as the write index with `is_write_index` as `true`.
[source,js]
@ -231,3 +240,98 @@ POST /logs_write/_rollover?dry_run
Because the rollover operation creates a new index to rollover to, the
<<create-index-wait-for-active-shards,`wait_for_active_shards`>> setting on
index creation applies to the rollover action as well.
[[indices-rollover-is-write-index]]
[float]
=== Write Index Alias Behavior
The rollover alias when rolling over a write index that has `is_write_index` explicitly set to `true` is not
swapped during rollover actions. Since having an alias point to multiple indices is ambiguous in distinguishing
which is the correct write index to roll over, it is not valid to rollover an alias that points to multiple indices.
For this reason, the default behavior is to swap which index is being pointed to by the write-oriented alias. This
was `logs_write` in some of the above examples. Since setting `is_write_index` enables an alias to point to multiple indices
while also being explicit as to which is the write index that rollover should target, removing the alias from the rolled over
index is not necessary. This simplifies things by allowing for one alias to behave both as the write and read aliases for
indices that are being managed with Rollover.
Look at the behavior of the aliases in the following example where `is_write_index` is set on the rolled over index.
[source,js]
--------------------------------------------------
PUT my_logs_index-000001
{
"aliases": {
"logs": { "is_write_index": true } <1>
}
}
PUT logs/_doc/1
{
"message": "a dummy log"
}
POST logs/_refresh
POST /logs/_rollover
{
"conditions": {
"max_docs": "1"
}
}
PUT logs/_doc/2 <2>
{
"message": "a newer log"
}
--------------------------------------------------
// CONSOLE
<1> configures `my_logs_index` as the write index for the `logs` alias
<2> newly indexed documents against the `logs` alias will write to the new index
[source,js]
--------------------------------------------------
{
"_index" : "my_logs_index-000002",
"_type" : "_doc",
"_id" : "2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
--------------------------------------------------
// TESTRESPONSE
//////////////////////////
[source,js]
--------------------------------------------------
GET _alias
--------------------------------------------------
// CONSOLE
// TEST[continued]
//////////////////////////
After the rollover, the alias metadata for the two indices will have the `is_write_index` setting
reflect each index's role, with the newly created index as the write index.
[source,js]
--------------------------------------------------
{
"my_logs_index-000002": {
"aliases": {
"logs": { "is_write_index": true }
}
},
"my_logs_index-000001": {
"aliases": {
"logs": { "is_write_index" : false }
}
}
}
--------------------------------------------------
// TESTRESPONSE

View File

@ -5,10 +5,10 @@ The fuzzy query uses similarity based on Levenshtein edit distance.
==== String fields
The `fuzzy` query generates all possible matching terms that are within the
The `fuzzy` query generates matching terms that are within the
maximum edit distance specified in `fuzziness` and then checks the term
dictionary to find out which of those generated terms actually exist in the
index.
index. The final query uses up to `max_expansions` matching terms.
Here is a simple example:

View File

@ -25,7 +25,7 @@ appender.rolling.type = RollingFile <1>
appender.rolling.name = rolling
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log <2>
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name]%marker %.-10000m%n
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}-%i.log.gz <3>
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy <4>

View File

@ -68,8 +68,7 @@ public final class GrokProcessor extends AbstractProcessor {
throw new IllegalArgumentException("Provided Grok expressions do not match field value: [" + fieldValue + "]");
}
matches.entrySet().stream()
.forEach((e) -> ingestDocument.setFieldValue(e.getKey(), e.getValue()));
matches.forEach(ingestDocument::setFieldValue);
if (traceMatch) {
if (matchPatterns.size() > 1) {

View File

@ -368,7 +368,7 @@ public final class Def {
ref = new FunctionRef(clazz, interfaceMethod, call, handle.type(), captures.length);
} else {
// whitelist lookup
ref = new FunctionRef(painlessLookup, clazz, type, call, captures.length);
ref = FunctionRef.resolveFromLookup(painlessLookup, clazz, type, call, captures.length);
}
final CallSite callSite = LambdaBootstrap.lambdaBootstrap(
methodHandlesLookup,

View File

@ -20,13 +20,16 @@
package org.elasticsearch.painless;
import org.elasticsearch.painless.lookup.PainlessClass;
import org.elasticsearch.painless.lookup.PainlessConstructor;
import org.elasticsearch.painless.lookup.PainlessLookup;
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
import org.elasticsearch.painless.lookup.PainlessMethod;
import org.objectweb.asm.Type;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.List;
import static org.elasticsearch.painless.WriterConstants.CLASS_NAME;
import static org.objectweb.asm.Opcodes.H_INVOKEINTERFACE;
@ -59,8 +62,10 @@ public class FunctionRef {
/** interface method */
public final PainlessMethod interfaceMethod;
/** delegate method */
public final PainlessMethod delegateMethod;
/** delegate method type parameters */
public final List<Class<?>> delegateTypeParameters;
/** delegate method return type */
public final Class<?> delegateReturnType;
/** factory method type descriptor */
public final String factoryDescriptor;
@ -80,9 +85,47 @@ public class FunctionRef {
* @param call the right hand side of a method reference expression
* @param numCaptures number of captured arguments
*/
public FunctionRef(PainlessLookup painlessLookup, Class<?> expected, String type, String call, int numCaptures) {
this(expected, painlessLookup.getPainlessStructFromJavaClass(expected).functionalMethod,
lookup(painlessLookup, expected, type, call, numCaptures > 0), numCaptures);
public static FunctionRef resolveFromLookup(
PainlessLookup painlessLookup, Class<?> expected, String type, String call, int numCaptures) {
if ("new".equals(call)) {
return new FunctionRef(expected, painlessLookup.getPainlessStructFromJavaClass(expected).functionalMethod,
lookup(painlessLookup, expected, type), numCaptures);
} else {
return new FunctionRef(expected, painlessLookup.getPainlessStructFromJavaClass(expected).functionalMethod,
lookup(painlessLookup, expected, type, call, numCaptures > 0), numCaptures);
}
}
/**
* Creates a new FunctionRef (already resolved)
* @param expected functional interface type to implement
* @param interfaceMethod functional interface method
* @param delegateConstructor implementation constructor
* @param numCaptures number of captured arguments
*/
public FunctionRef(Class<?> expected, PainlessMethod interfaceMethod, PainlessConstructor delegateConstructor, int numCaptures) {
Constructor<?> javaConstructor = delegateConstructor.javaConstructor;
MethodType delegateMethodType = delegateConstructor.methodType;
interfaceMethodName = interfaceMethod.name;
factoryMethodType = MethodType.methodType(expected,
delegateMethodType.dropParameterTypes(numCaptures, delegateMethodType.parameterCount()));
interfaceMethodType = interfaceMethod.methodType.dropParameterTypes(0, 1);
delegateClassName = javaConstructor.getDeclaringClass().getName();
isDelegateInterface = false;
delegateInvokeType = H_NEWINVOKESPECIAL;
delegateMethodName = PainlessLookupUtility.CONSTRUCTOR_NAME;
this.delegateMethodType = delegateMethodType.dropParameterTypes(0, numCaptures);
this.interfaceMethod = interfaceMethod;
delegateTypeParameters = delegateConstructor.typeParameters;
delegateReturnType = void.class;
factoryDescriptor = factoryMethodType.toMethodDescriptorString();
interfaceType = Type.getMethodType(interfaceMethodType.toMethodDescriptorString());
delegateType = Type.getMethodType(this.delegateMethodType.toMethodDescriptorString());
}
/**
@ -112,9 +155,7 @@ public class FunctionRef {
isDelegateInterface = delegateMethod.target.isInterface();
}
if ("<init>".equals(delegateMethod.name)) {
delegateInvokeType = H_NEWINVOKESPECIAL;
} else if (Modifier.isStatic(delegateMethod.modifiers)) {
if (Modifier.isStatic(delegateMethod.modifiers)) {
delegateInvokeType = H_INVOKESTATIC;
} else if (delegateMethod.target.isInterface()) {
delegateInvokeType = H_INVOKEINTERFACE;
@ -126,7 +167,8 @@ public class FunctionRef {
this.delegateMethodType = delegateMethodType.dropParameterTypes(0, numCaptures);
this.interfaceMethod = interfaceMethod;
this.delegateMethod = delegateMethod;
delegateTypeParameters = delegateMethod.arguments;
delegateReturnType = delegateMethod.rtn;
factoryDescriptor = factoryMethodType.toMethodDescriptorString();
interfaceType = Type.getMethodType(interfaceMethodType.toMethodDescriptorString());
@ -151,13 +193,37 @@ public class FunctionRef {
isDelegateInterface = false;
this.interfaceMethod = null;
delegateMethod = null;
delegateTypeParameters = null;
delegateReturnType = null;
factoryDescriptor = null;
interfaceType = null;
delegateType = null;
}
/**
* Looks up {@code type} from the whitelist, and returns a matching constructor.
*/
private static PainlessConstructor lookup(PainlessLookup painlessLookup, Class<?> expected, String type) {
// check its really a functional interface
// for e.g. Comparable
PainlessMethod method = painlessLookup.getPainlessStructFromJavaClass(expected).functionalMethod;
if (method == null) {
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::new] " +
"to [" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "], not a functional interface");
}
// lookup requested constructor
PainlessClass struct = painlessLookup.getPainlessStructFromJavaClass(painlessLookup.getJavaClassFromPainlessType(type));
PainlessConstructor impl = struct.constructors.get(PainlessLookupUtility.buildPainlessConstructorKey(method.arguments.size()));
if (impl == null) {
throw new IllegalArgumentException("Unknown reference [" + type + "::new] matching [" + expected + "]");
}
return impl;
}
/**
* Looks up {@code type::call} from the whitelist, and returns a matching method.
*/
@ -174,27 +240,22 @@ public class FunctionRef {
// lookup requested method
PainlessClass struct = painlessLookup.getPainlessStructFromJavaClass(painlessLookup.getJavaClassFromPainlessType(type));
final PainlessMethod impl;
// ctor ref
if ("new".equals(call)) {
impl = struct.constructors.get(PainlessLookupUtility.buildPainlessMethodKey("<init>", method.arguments.size()));
} else {
// look for a static impl first
PainlessMethod staticImpl =
struct.staticMethods.get(PainlessLookupUtility.buildPainlessMethodKey(call, method.arguments.size()));
if (staticImpl == null) {
// otherwise a virtual impl
final int arity;
if (receiverCaptured) {
// receiver captured
arity = method.arguments.size();
} else {
// receiver passed
arity = method.arguments.size() - 1;
}
impl = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey(call, arity));
// look for a static impl first
PainlessMethod staticImpl =
struct.staticMethods.get(PainlessLookupUtility.buildPainlessMethodKey(call, method.arguments.size()));
if (staticImpl == null) {
// otherwise a virtual impl
final int arity;
if (receiverCaptured) {
// receiver captured
arity = method.arguments.size();
} else {
impl = staticImpl;
// receiver passed
arity = method.arguments.size() - 1;
}
impl = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey(call, arity));
} else {
impl = staticImpl;
}
if (impl == null) {
throw new IllegalArgumentException("Unknown reference [" + type + "::" + call + "] matching " +

View File

@ -24,7 +24,8 @@ import java.util.Collections;
import java.util.Map;
public final class PainlessClass {
public final Map<String, PainlessMethod> constructors;
public final Map<String, PainlessConstructor> constructors;
public final Map<String, PainlessMethod> staticMethods;
public final Map<String, PainlessMethod> methods;
@ -36,13 +37,14 @@ public final class PainlessClass {
public final PainlessMethod functionalMethod;
PainlessClass(Map<String, PainlessMethod> constructors,
PainlessClass(Map<String, PainlessConstructor> constructors,
Map<String, PainlessMethod> staticMethods, Map<String, PainlessMethod> methods,
Map<String, PainlessField> staticFields, Map<String, PainlessField> fields,
Map<String, MethodHandle> getterMethodHandles, Map<String, MethodHandle> setterMethodHandles,
PainlessMethod functionalMethod) {
this.constructors = Collections.unmodifiableMap(constructors);
this.staticMethods = Collections.unmodifiableMap(staticMethods);
this.methods = Collections.unmodifiableMap(methods);

View File

@ -24,7 +24,8 @@ import java.util.HashMap;
import java.util.Map;
final class PainlessClassBuilder {
final Map<String, PainlessMethod> constructors;
final Map<String, PainlessConstructor> constructors;
final Map<String, PainlessMethod> staticMethods;
final Map<String, PainlessMethod> methods;
@ -38,6 +39,7 @@ final class PainlessClassBuilder {
PainlessClassBuilder() {
constructors = new HashMap<>();
staticMethods = new HashMap<>();
methods = new HashMap<>();

View File

@ -0,0 +1,39 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.painless.lookup;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.util.List;
public class PainlessConstructor {
public final Constructor<?> javaConstructor;
public final List<Class<?>> typeParameters;
public final MethodHandle methodHandle;
public final MethodType methodType;
PainlessConstructor(Constructor<?> javaConstructor, List<Class<?>> typeParameters, MethodHandle methodHandle, MethodType methodType) {
this.javaConstructor = javaConstructor;
this.typeParameters = typeParameters;
this.methodHandle = methodHandle;
this.methodType = methodType;
}
}

View File

@ -40,15 +40,47 @@ import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.CONSTRUCTOR_NAME;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.DEF_CLASS_NAME;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.buildPainlessConstructorKey;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.buildPainlessFieldKey;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.buildPainlessMethodKey;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.typeToCanonicalTypeName;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.typeToJavaType;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.typesToCanonicalTypeNames;
public class PainlessLookupBuilder {
public final class PainlessLookupBuilder {
private static class PainlessConstructorCacheKey {
private final Class<?> targetType;
private final List<Class<?>> typeParameters;
private PainlessConstructorCacheKey(Class<?> targetType, List<Class<?>> typeParameters) {
this.targetType = targetType;
this.typeParameters = Collections.unmodifiableList(typeParameters);
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
PainlessConstructorCacheKey that = (PainlessConstructorCacheKey)object;
return Objects.equals(targetType, that.targetType) &&
Objects.equals(typeParameters, that.typeParameters);
}
@Override
public int hashCode() {
return Objects.hash(targetType, typeParameters);
}
}
private static class PainlessMethodCacheKey {
@ -120,8 +152,9 @@ public class PainlessLookupBuilder {
}
}
private static final Map<PainlessMethodCacheKey, PainlessMethod> painlessMethodCache = new HashMap<>();
private static final Map<PainlessFieldCacheKey, PainlessField> painlessFieldCache = new HashMap<>();
private static final Map<PainlessConstructorCacheKey, PainlessConstructor> painlessConstuctorCache = new HashMap<>();
private static final Map<PainlessMethodCacheKey, PainlessMethod> painlessMethodCache = new HashMap<>();
private static final Map<PainlessFieldCacheKey, PainlessField> painlessFieldCache = new HashMap<>();
private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][._a-zA-Z0-9]*$");
private static final Pattern METHOD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$");
@ -343,11 +376,10 @@ public class PainlessLookupBuilder {
"[[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found", nsme);
}
String painlessMethodKey = buildPainlessMethodKey(CONSTRUCTOR_NAME, typeParametersSize);
PainlessMethod painlessConstructor = painlessClassBuilder.constructors.get(painlessMethodKey);
String painlessConstructorKey = buildPainlessConstructorKey(typeParametersSize);
PainlessConstructor painlessConstructor = painlessClassBuilder.constructors.get(painlessConstructorKey);
if (painlessConstructor == null) {
org.objectweb.asm.commons.Method asmConstructor = org.objectweb.asm.commons.Method.getMethod(javaConstructor);
MethodHandle methodHandle;
try {
@ -359,17 +391,16 @@ public class PainlessLookupBuilder {
MethodType methodType = methodHandle.type();
painlessConstructor = painlessMethodCache.computeIfAbsent(
new PainlessMethodCacheKey(targetClass, CONSTRUCTOR_NAME, typeParameters),
key -> new PainlessMethod(CONSTRUCTOR_NAME, targetClass, null, void.class, typeParameters,
asmConstructor, javaConstructor.getModifiers(), methodHandle, methodType)
painlessConstructor = painlessConstuctorCache.computeIfAbsent(
new PainlessConstructorCacheKey(targetClass, typeParameters),
key -> new PainlessConstructor(javaConstructor, typeParameters, methodHandle, methodType)
);
painlessClassBuilder.constructors.put(painlessMethodKey, painlessConstructor);
} else if (painlessConstructor.arguments.equals(typeParameters) == false){
painlessClassBuilder.constructors.put(painlessConstructorKey, painlessConstructor);
} else if (painlessConstructor.typeParameters.equals(typeParameters) == false){
throw new IllegalArgumentException("cannot have constructors " +
"[[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "] and " +
"[[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(painlessConstructor.arguments) + "] " +
"[[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(painlessConstructor.typeParameters) + "] " +
"with the same arity and different type parameters");
}
}

View File

@ -336,6 +336,13 @@ public final class PainlessLookupUtility {
type == String.class;
}
/**
* Constructs a painless constructor key used to lookup painless constructors from a painless class.
*/
public static String buildPainlessConstructorKey(int constructorArity) {
return CONSTRUCTOR_NAME + "/" + constructorArity;
}
/**
* Constructs a painless method key used to lookup painless methods from a painless class.
*/

View File

@ -77,18 +77,18 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
// static case
if (captured.clazz != def.class) {
try {
ref = new FunctionRef(locals.getPainlessLookup(), expected,
ref = FunctionRef.resolveFromLookup(locals.getPainlessLookup(), expected,
PainlessLookupUtility.typeToCanonicalTypeName(captured.clazz), call, 1);
// check casts between the interface method and the delegate method are legal
for (int i = 0; i < ref.interfaceMethod.arguments.size(); ++i) {
Class<?> from = ref.interfaceMethod.arguments.get(i);
Class<?> to = ref.delegateMethod.arguments.get(i);
Class<?> to = ref.delegateTypeParameters.get(i);
AnalyzerCaster.getLegalCast(location, from, to, false, true);
}
if (ref.interfaceMethod.rtn != void.class) {
AnalyzerCaster.getLegalCast(location, ref.delegateMethod.rtn, ref.interfaceMethod.rtn, false, true);
AnalyzerCaster.getLegalCast(location, ref.delegateReturnType, ref.interfaceMethod.rtn, false, true);
}
} catch (IllegalArgumentException e) {
throw createError(e);

View File

@ -90,7 +90,7 @@ public final class EFunctionRef extends AExpression implements ILambda {
}
} else {
// whitelist lookup
ref = new FunctionRef(locals.getPainlessLookup(), expected, type, call, 0);
ref = FunctionRef.resolveFromLookup(locals.getPainlessLookup(), expected, type, call, 0);
}
} catch (IllegalArgumentException e) {

View File

@ -23,10 +23,12 @@ import org.elasticsearch.painless.Globals;
import org.elasticsearch.painless.Locals;
import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.MethodWriter;
import org.elasticsearch.painless.lookup.PainlessConstructor;
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
import org.elasticsearch.painless.lookup.PainlessMethod;
import org.elasticsearch.painless.lookup.def;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.util.ArrayList;
import java.util.List;
@ -38,7 +40,7 @@ import java.util.Set;
public final class EListInit extends AExpression {
private final List<AExpression> values;
private PainlessMethod constructor = null;
private PainlessConstructor constructor = null;
private PainlessMethod method = null;
public EListInit(Location location, List<AExpression> values) {
@ -62,8 +64,8 @@ public final class EListInit extends AExpression {
actual = ArrayList.class;
constructor = locals.getPainlessLookup().getPainlessStructFromJavaClass(actual).constructors
.get(PainlessLookupUtility.buildPainlessMethodKey("<init>", 0));
constructor = locals.getPainlessLookup().getPainlessStructFromJavaClass(actual).constructors.get(
PainlessLookupUtility.buildPainlessConstructorKey(0));
if (constructor == null) {
throw createError(new IllegalStateException("Illegal tree structure."));
@ -92,7 +94,8 @@ public final class EListInit extends AExpression {
writer.newInstance(MethodWriter.getType(actual));
writer.dup();
writer.invokeConstructor(Type.getType(constructor.target), constructor.method);
writer.invokeConstructor(
Type.getType(constructor.javaConstructor.getDeclaringClass()), Method.getMethod(constructor.javaConstructor));
for (AExpression value : values) {
writer.dup();

View File

@ -23,10 +23,12 @@ import org.elasticsearch.painless.Globals;
import org.elasticsearch.painless.Locals;
import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.MethodWriter;
import org.elasticsearch.painless.lookup.PainlessConstructor;
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
import org.elasticsearch.painless.lookup.PainlessMethod;
import org.elasticsearch.painless.lookup.def;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.util.HashMap;
import java.util.List;
@ -39,7 +41,7 @@ public final class EMapInit extends AExpression {
private final List<AExpression> keys;
private final List<AExpression> values;
private PainlessMethod constructor = null;
private PainlessConstructor constructor = null;
private PainlessMethod method = null;
public EMapInit(Location location, List<AExpression> keys, List<AExpression> values) {
@ -68,8 +70,8 @@ public final class EMapInit extends AExpression {
actual = HashMap.class;
constructor = locals.getPainlessLookup().getPainlessStructFromJavaClass(actual).constructors
.get(PainlessLookupUtility.buildPainlessMethodKey("<init>", 0));
constructor = locals.getPainlessLookup().getPainlessStructFromJavaClass(actual).constructors.get(
PainlessLookupUtility.buildPainlessConstructorKey(0));
if (constructor == null) {
throw createError(new IllegalStateException("Illegal tree structure."));
@ -111,7 +113,8 @@ public final class EMapInit extends AExpression {
writer.newInstance(MethodWriter.getType(actual));
writer.dup();
writer.invokeConstructor(Type.getType(constructor.target), constructor.method);
writer.invokeConstructor(
Type.getType(constructor.javaConstructor.getDeclaringClass()), Method.getMethod(constructor.javaConstructor));
for (int index = 0; index < keys.size(); ++index) {
AExpression key = keys.get(index);

View File

@ -24,9 +24,10 @@ import org.elasticsearch.painless.Locals;
import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.MethodWriter;
import org.elasticsearch.painless.lookup.PainlessClass;
import org.elasticsearch.painless.lookup.PainlessConstructor;
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
import org.elasticsearch.painless.lookup.PainlessMethod;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.util.List;
import java.util.Objects;
@ -40,7 +41,7 @@ public final class ENewObj extends AExpression {
private final String type;
private final List<AExpression> arguments;
private PainlessMethod constructor;
private PainlessConstructor constructor;
public ENewObj(Location location, String type, List<AExpression> arguments) {
super(location);
@ -65,16 +66,16 @@ public final class ENewObj extends AExpression {
}
PainlessClass struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(actual);
constructor = struct.constructors.get(PainlessLookupUtility.buildPainlessMethodKey("<init>", arguments.size()));
constructor = struct.constructors.get(PainlessLookupUtility.buildPainlessConstructorKey(arguments.size()));
if (constructor != null) {
Class<?>[] types = new Class<?>[constructor.arguments.size()];
constructor.arguments.toArray(types);
Class<?>[] types = new Class<?>[constructor.typeParameters.size()];
constructor.typeParameters.toArray(types);
if (constructor.arguments.size() != arguments.size()) {
if (constructor.typeParameters.size() != arguments.size()) {
throw createError(new IllegalArgumentException(
"When calling constructor on type [" + PainlessLookupUtility.typeToCanonicalTypeName(actual) + "] " +
"expected [" + constructor.arguments.size() + "] arguments, but found [" + arguments.size() + "]."));
"expected [" + constructor.typeParameters.size() + "] arguments, but found [" + arguments.size() + "]."));
}
for (int argument = 0; argument < arguments.size(); ++argument) {
@ -107,7 +108,8 @@ public final class ENewObj extends AExpression {
argument.write(writer, globals);
}
writer.invokeConstructor(Type.getType(constructor.target), constructor.method);
writer.invokeConstructor(
Type.getType(constructor.javaConstructor.getDeclaringClass()), Method.getMethod(constructor.javaConstructor));
}
@Override

View File

@ -24,6 +24,7 @@ import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.painless.lookup.PainlessClass;
import org.elasticsearch.painless.lookup.PainlessConstructor;
import org.elasticsearch.painless.lookup.PainlessField;
import org.elasticsearch.painless.lookup.PainlessLookup;
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
@ -57,7 +58,8 @@ public class PainlessDocGenerator {
private static final Logger logger = ESLoggerFactory.getLogger(PainlessDocGenerator.class);
private static final Comparator<PainlessField> FIELD_NAME = comparing(f -> f.name);
private static final Comparator<PainlessMethod> METHOD_NAME = comparing(m -> m.name);
private static final Comparator<PainlessMethod> NUMBER_OF_ARGS = comparing(m -> m.arguments.size());
private static final Comparator<PainlessMethod> METHOD_NUMBER_OF_PARAMS = comparing(m -> m.arguments.size());
private static final Comparator<PainlessConstructor> CONSTRUCTOR_NUMBER_OF_PARAMS = comparing(m -> m.typeParameters.size());
public static void main(String[] args) throws IOException {
Path apiRootPath = PathUtils.get(args[0]);
@ -103,12 +105,15 @@ public class PainlessDocGenerator {
Consumer<PainlessField> documentField = field -> PainlessDocGenerator.documentField(typeStream, field);
Consumer<PainlessMethod> documentMethod = method -> PainlessDocGenerator.documentMethod(typeStream, method);
Consumer<PainlessConstructor> documentConstructor =
constructor -> PainlessDocGenerator.documentConstructor(typeStream, constructor);
struct.staticFields.values().stream().sorted(FIELD_NAME).forEach(documentField);
struct.fields.values().stream().sorted(FIELD_NAME).forEach(documentField);
struct.staticMethods.values().stream().sorted(METHOD_NAME.thenComparing(NUMBER_OF_ARGS)).forEach(documentMethod);
struct.constructors.values().stream().sorted(NUMBER_OF_ARGS).forEach(documentMethod);
struct.staticMethods.values().stream().sorted(
METHOD_NAME.thenComparing(METHOD_NUMBER_OF_PARAMS)).forEach(documentMethod);
struct.constructors.values().stream().sorted(CONSTRUCTOR_NUMBER_OF_PARAMS).forEach(documentConstructor);
Map<String, Class<?>> inherited = new TreeMap<>();
struct.methods.values().stream().sorted(METHOD_NAME.thenComparing(NUMBER_OF_ARGS)).forEach(method -> {
struct.methods.values().stream().sorted(METHOD_NAME.thenComparing(METHOD_NUMBER_OF_PARAMS)).forEach(method -> {
if (method.target == clazz) {
documentMethod(typeStream, method);
} else {
@ -164,6 +169,41 @@ public class PainlessDocGenerator {
stream.println();
}
/**
* Document a constructor.
*/
private static void documentConstructor(PrintStream stream, PainlessConstructor constructor) {
stream.print("* ++[[");
emitAnchor(stream, constructor);
stream.print("]]");
String javadocRoot = javadocRoot(constructor.javaConstructor.getDeclaringClass());
emitJavadocLink(stream, javadocRoot, constructor);
stream.print('[');
stream.print(constructorName(constructor));
stream.print("](");
boolean first = true;
for (Class<?> arg : constructor.typeParameters) {
if (first) {
first = false;
} else {
stream.print(", ");
}
emitType(stream, arg);
}
stream.print(")++");
if (javadocRoot.equals("java8")) {
stream.print(" (");
emitJavadocLink(stream, "java9", constructor);
stream.print("[java 9])");
}
stream.println();
}
/**
* Document a method.
*/
@ -176,10 +216,8 @@ public class PainlessDocGenerator {
stream.print("static ");
}
if (false == method.name.equals("<init>")) {
emitType(stream, method.rtn);
stream.print(' ');
}
emitType(stream, method.rtn);
stream.print(' ');
String javadocRoot = javadocRoot(method);
emitJavadocLink(stream, javadocRoot, method);
@ -216,6 +254,17 @@ public class PainlessDocGenerator {
stream.print(PainlessLookupUtility.typeToCanonicalTypeName(clazz).replace('.', '-'));
}
/**
* Anchor text for a {@link PainlessConstructor}.
*/
private static void emitAnchor(PrintStream stream, PainlessConstructor constructor) {
emitAnchor(stream, constructor.javaConstructor.getDeclaringClass());
stream.print('-');
stream.print(constructorName(constructor));
stream.print('-');
stream.print(constructor.typeParameters.size());
}
/**
* Anchor text for a {@link PainlessMethod}.
*/
@ -236,8 +285,12 @@ public class PainlessDocGenerator {
stream.print(field.name);
}
private static String constructorName(PainlessConstructor constructor) {
return PainlessLookupUtility.typeToCanonicalTypeName(constructor.javaConstructor.getDeclaringClass());
}
private static String methodName(PainlessMethod method) {
return method.name.equals("<init>") ? PainlessLookupUtility.typeToCanonicalTypeName(method.target) : method.name;
return PainlessLookupUtility.typeToCanonicalTypeName(method.target);
}
/**
@ -269,6 +322,34 @@ public class PainlessDocGenerator {
}
}
/**
* Emit an external link to Javadoc for a {@link PainlessMethod}.
*
* @param root name of the root uri variable
*/
private static void emitJavadocLink(PrintStream stream, String root, PainlessConstructor constructor) {
stream.print("link:{");
stream.print(root);
stream.print("-javadoc}/");
stream.print(classUrlPath(constructor.javaConstructor.getDeclaringClass()));
stream.print(".html#");
stream.print(constructorName(constructor));
stream.print("%2D");
boolean first = true;
for (Class<?> clazz: constructor.typeParameters) {
if (first) {
first = false;
} else {
stream.print("%2D");
}
stream.print(clazz.getName());
if (clazz.isArray()) {
stream.print(":A");
}
}
stream.print("%2D");
}
/**
* Emit an external link to Javadoc for a {@link PainlessMethod}.
*

View File

@ -27,13 +27,13 @@ import org.elasticsearch.client.ParentTaskAssigningClient;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import java.util.function.Supplier;
public class TransportDeleteByQueryAction extends HandledTransportAction<DeleteByQueryRequest, BulkByScrollResponse> {
@ -46,7 +46,7 @@ public class TransportDeleteByQueryAction extends HandledTransportAction<DeleteB
public TransportDeleteByQueryAction(Settings settings, ThreadPool threadPool, ActionFilters actionFilters, Client client,
TransportService transportService, ScriptService scriptService, ClusterService clusterService) {
super(settings, DeleteByQueryAction.NAME, transportService, actionFilters,
(Supplier<DeleteByQueryRequest>) DeleteByQueryRequest::new);
(Writeable.Reader<DeleteByQueryRequest>) DeleteByQueryRequest::new);
this.threadPool = threadPool;
this.client = client;
this.scriptService = scriptService;

View File

@ -39,6 +39,7 @@ import org.elasticsearch.action.bulk.BackoffPolicy;
import org.elasticsearch.action.bulk.BulkItemResponse.Failure;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.DeprecationHandler;
import org.elasticsearch.index.reindex.ScrollableHitSource.SearchFailure;
import org.elasticsearch.action.index.IndexRequest;
@ -104,7 +105,7 @@ public class TransportReindexAction extends HandledTransportAction<ReindexReques
public TransportReindexAction(Settings settings, ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, ClusterService clusterService, ScriptService scriptService,
AutoCreateIndex autoCreateIndex, Client client, TransportService transportService) {
super(settings, ReindexAction.NAME, transportService, actionFilters, ReindexRequest::new);
super(settings, ReindexAction.NAME, transportService, actionFilters, (Writeable.Reader<ReindexRequest>)ReindexRequest::new);
this.threadPool = threadPool;
this.clusterService = clusterService;
this.scriptService = scriptService;

View File

@ -29,6 +29,7 @@ import org.elasticsearch.client.ParentTaskAssigningClient;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.index.mapper.IdFieldMapper;
@ -43,7 +44,6 @@ import org.elasticsearch.transport.TransportService;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Supplier;
public class TransportUpdateByQueryAction extends HandledTransportAction<UpdateByQueryRequest, BulkByScrollResponse> {
@ -56,7 +56,7 @@ public class TransportUpdateByQueryAction extends HandledTransportAction<UpdateB
public TransportUpdateByQueryAction(Settings settings, ThreadPool threadPool, ActionFilters actionFilters, Client client,
TransportService transportService, ScriptService scriptService, ClusterService clusterService) {
super(settings, UpdateByQueryAction.NAME, transportService, actionFilters,
(Supplier<UpdateByQueryRequest>) UpdateByQueryRequest::new);
(Writeable.Reader<UpdateByQueryRequest>) UpdateByQueryRequest::new);
this.threadPool = threadPool;
this.client = client;
this.scriptService = scriptService;

View File

@ -67,19 +67,17 @@ public class RoundTripTests extends ESTestCase {
new RemoteInfo(randomAlphaOfLength(5), randomAlphaOfLength(5), port, null,
query, username, password, headers, socketTimeout, connectTimeout));
}
ReindexRequest tripped = new ReindexRequest();
roundTrip(reindex, tripped);
ReindexRequest tripped = new ReindexRequest(toInputByteStream(reindex));
assertRequestEquals(reindex, tripped);
// Try slices=auto with a version that doesn't support it, which should fail
reindex.setSlices(AbstractBulkByScrollRequest.AUTO_SLICES);
Exception e = expectThrows(IllegalArgumentException.class, () -> roundTrip(Version.V_6_0_0_alpha1, reindex, null));
Exception e = expectThrows(IllegalArgumentException.class, () -> toInputByteStream(Version.V_6_0_0_alpha1, reindex));
assertEquals("Slices set as \"auto\" are not supported before version [6.1.0]. Found version [6.0.0-alpha1]", e.getMessage());
// Try regular slices with a version that doesn't support slices=auto, which should succeed
tripped = new ReindexRequest();
reindex.setSlices(between(1, Integer.MAX_VALUE));
roundTrip(Version.V_6_0_0_alpha1, reindex, tripped);
tripped = new ReindexRequest(toInputByteStream(reindex));
assertRequestEquals(Version.V_6_0_0_alpha1, reindex, tripped);
}
@ -89,20 +87,18 @@ public class RoundTripTests extends ESTestCase {
if (randomBoolean()) {
update.setPipeline(randomAlphaOfLength(5));
}
UpdateByQueryRequest tripped = new UpdateByQueryRequest();
roundTrip(update, tripped);
UpdateByQueryRequest tripped = new UpdateByQueryRequest(toInputByteStream(update));
assertRequestEquals(update, tripped);
assertEquals(update.getPipeline(), tripped.getPipeline());
// Try slices=auto with a version that doesn't support it, which should fail
update.setSlices(AbstractBulkByScrollRequest.AUTO_SLICES);
Exception e = expectThrows(IllegalArgumentException.class, () -> roundTrip(Version.V_6_0_0_alpha1, update, null));
Exception e = expectThrows(IllegalArgumentException.class, () -> toInputByteStream(Version.V_6_0_0_alpha1, update));
assertEquals("Slices set as \"auto\" are not supported before version [6.1.0]. Found version [6.0.0-alpha1]", e.getMessage());
// Try regular slices with a version that doesn't support slices=auto, which should succeed
tripped = new UpdateByQueryRequest();
update.setSlices(between(1, Integer.MAX_VALUE));
roundTrip(Version.V_6_0_0_alpha1, update, tripped);
tripped = new UpdateByQueryRequest(toInputByteStream(update));
assertRequestEquals(update, tripped);
assertEquals(update.getPipeline(), tripped.getPipeline());
}
@ -110,19 +106,17 @@ public class RoundTripTests extends ESTestCase {
public void testDeleteByQueryRequest() throws IOException {
DeleteByQueryRequest delete = new DeleteByQueryRequest(new SearchRequest());
randomRequest(delete);
DeleteByQueryRequest tripped = new DeleteByQueryRequest();
roundTrip(delete, tripped);
DeleteByQueryRequest tripped = new DeleteByQueryRequest(toInputByteStream(delete));
assertRequestEquals(delete, tripped);
// Try slices=auto with a version that doesn't support it, which should fail
delete.setSlices(AbstractBulkByScrollRequest.AUTO_SLICES);
Exception e = expectThrows(IllegalArgumentException.class, () -> roundTrip(Version.V_6_0_0_alpha1, delete, null));
Exception e = expectThrows(IllegalArgumentException.class, () -> toInputByteStream(Version.V_6_0_0_alpha1, delete));
assertEquals("Slices set as \"auto\" are not supported before version [6.1.0]. Found version [6.0.0-alpha1]", e.getMessage());
// Try regular slices with a version that doesn't support slices=auto, which should succeed
tripped = new DeleteByQueryRequest();
delete.setSlices(between(1, Integer.MAX_VALUE));
roundTrip(Version.V_6_0_0_alpha1, delete, tripped);
tripped = new DeleteByQueryRequest(toInputByteStream(delete));
assertRequestEquals(delete, tripped);
}
@ -198,23 +192,24 @@ public class RoundTripTests extends ESTestCase {
request.setTaskId(new TaskId(randomAlphaOfLength(5), randomLong()));
}
RethrottleRequest tripped = new RethrottleRequest();
roundTrip(request, tripped);
// We use readFrom here because Rethrottle does not support the Writeable.Reader interface
tripped.readFrom(toInputByteStream(request));
assertEquals(request.getRequestsPerSecond(), tripped.getRequestsPerSecond(), 0.00001);
assertArrayEquals(request.getActions(), tripped.getActions());
assertEquals(request.getTaskId(), tripped.getTaskId());
}
private void roundTrip(Streamable example, Streamable empty) throws IOException {
roundTrip(Version.CURRENT, example, empty);
private StreamInput toInputByteStream(Streamable example) throws IOException {
return toInputByteStream(Version.CURRENT, example);
}
private void roundTrip(Version version, Streamable example, Streamable empty) throws IOException {
private StreamInput toInputByteStream(Version version, Streamable example) throws IOException {
BytesStreamOutput out = new BytesStreamOutput();
out.setVersion(version);
example.writeTo(out);
StreamInput in = out.bytes().streamInput();
in.setVersion(version);
empty.readFrom(in);
return in;
}
private Script randomScript() {

View File

@ -23,8 +23,9 @@ esplugin {
}
dependencies {
compile 'com.microsoft.azure:azure-storage:5.0.0'
compile 'com.microsoft.azure:azure-keyvault-core:0.8.0'
compile 'com.microsoft.azure:azure-storage:8.0.0'
compile 'com.microsoft.azure:azure-keyvault-core:1.0.0'
compile 'com.google.guava:guava:20.0'
compile 'org.apache.commons:commons-lang3:3.4'
}
@ -40,6 +41,18 @@ thirdPartyAudit.excludes = [
// Optional and not enabled by Elasticsearch
'org.slf4j.Logger',
'org.slf4j.LoggerFactory',
// uses internal java api: sun.misc.Unsafe
'com.google.common.cache.Striped64',
'com.google.common.cache.Striped64$1',
'com.google.common.cache.Striped64$Cell',
'com.google.common.hash.LittleEndianByteArray$UnsafeByteArray$1',
'com.google.common.hash.LittleEndianByteArray$UnsafeByteArray$2',
'com.google.common.hash.LittleEndianByteArray$UnsafeByteArray$3',
'com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper',
'com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper$1',
'com.google.common.hash.LittleEndianByteArray$UnsafeByteArray',
'com.google.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator',
'com.google.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator$1',
]
check {

View File

@ -1 +0,0 @@
35f7ac687462f491d0f8b0d96733dfe347493d70

View File

@ -0,0 +1 @@
e89dd5e621e21b753096ec6a03f203c01482c612

View File

@ -1 +0,0 @@
ba8f04bfeac08016c0f88423a202d0f3aac03aed

View File

@ -0,0 +1 @@
f6759c16ade4e2a05bc1dfbaf55161b9ed0e78b9

View File

@ -0,0 +1 @@
89507701249388e1ed5ddcf8c41f4ce1be7831ef

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -61,7 +61,10 @@ import static java.util.Collections.emptyMap;
public class AzureStorageService extends AbstractComponent {
public static final ByteSizeValue MIN_CHUNK_SIZE = new ByteSizeValue(1, ByteSizeUnit.BYTES);
public static final ByteSizeValue MAX_CHUNK_SIZE = new ByteSizeValue(64, ByteSizeUnit.MB);
/**
* {@link com.microsoft.azure.storage.blob.BlobConstants#MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES}
*/
public static final ByteSizeValue MAX_CHUNK_SIZE = new ByteSizeValue(256, ByteSizeUnit.MB);
// 'package' for testing
volatile Map<String, AzureStorageSettings> storageSettings = emptyMap();

View File

@ -104,7 +104,7 @@ public class AzureRepositorySettingsTests extends ESTestCase {
assertEquals(AzureStorageService.MAX_CHUNK_SIZE, azureRepository.chunkSize());
// chunk size in settings
int size = randomIntBetween(1, 64);
int size = randomIntBetween(1, 256);
azureRepository = azureRepository(Settings.builder().put("chunk_size", size + "mb").build());
assertEquals(new ByteSizeValue(size, ByteSizeUnit.MB), azureRepository.chunkSize());
@ -120,8 +120,8 @@ public class AzureRepositorySettingsTests extends ESTestCase {
// greater than max chunk size not allowed
e = expectThrows(IllegalArgumentException.class, () ->
azureRepository(Settings.builder().put("chunk_size", "65mb").build()));
assertEquals("failed to parse value [65mb] for setting [chunk_size], must be <= [64mb]", e.getMessage());
azureRepository(Settings.builder().put("chunk_size", "257mb").build()));
assertEquals("failed to parse value [257mb] for setting [chunk_size], must be <= [256mb]", e.getMessage());
}
}

View File

@ -87,7 +87,7 @@ public class EvilBootstrapChecksTests extends ESTestCase {
final boolean enforceLimits = randomBoolean();
final IllegalArgumentException e = expectThrows(
IllegalArgumentException.class,
() -> BootstrapChecks.check(new BootstrapContext(Settings.EMPTY, null), enforceLimits, emptyList(), "testInvalidValue"));
() -> BootstrapChecks.check(new BootstrapContext(Settings.EMPTY, null), enforceLimits, emptyList()));
final Matcher<String> matcher = containsString(
"[es.enforce.bootstrap.checks] must be [true] but was [" + value + "]");
assertThat(e, hasToString(matcher));

View File

@ -56,6 +56,7 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.lessThan;
@ -319,9 +320,11 @@ public class EvilLoggerTests extends ESTestCase {
assertThat(events.size(), equalTo(expectedLogLines + stackTraceLength));
for (int i = 0; i < expectedLogLines; i++) {
if (prefix == null) {
assertThat(events.get(i), startsWith("test"));
assertThat("Contents of [" + path + "] are wrong",
events.get(i), startsWith("[" + getTestName() + "] test"));
} else {
assertThat(events.get(i), startsWith("[" + prefix + "] test"));
assertThat("Contents of [" + path + "] are wrong",
events.get(i), startsWith("[" + getTestName() + "][" + prefix + "] test"));
}
}
}
@ -357,6 +360,24 @@ public class EvilLoggerTests extends ESTestCase {
}
}
public void testNoNodeNameWarning() throws IOException, UserException {
setupLogging("no_node_name");
final String path =
System.getProperty("es.logs.base_path") +
System.getProperty("file.separator") +
System.getProperty("es.logs.cluster_name") + ".log";
final List<String> events = Files.readAllLines(PathUtils.get(path));
assertThat(events.size(), equalTo(2));
final String location = "org.elasticsearch.common.logging.LogConfigurator";
// the first message is a warning for unsupported configuration files
assertLogLine(events.get(0), Level.WARN, location, "\\[null\\] Some logging configurations have %marker but don't "
+ "have %node_name. We will automatically add %node_name to the pattern to ease the migration for users "
+ "who customize log4j2.properties but will stop this behavior in 7.0. You should manually replace "
+ "`%node_name` with `\\[%node_name\\]%marker ` in these locations:");
assertThat(events.get(1), endsWith("no_node_name/log4j2.properties"));
}
private void setupLogging(final String config) throws IOException, UserException {
setupLogging(config, Settings.EMPTY);
}

View File

@ -1,13 +1,13 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%test_thread_info]%marker %m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%p][%l] %marker%m%n
appender.file.layout.pattern = [%p][%l] [%test_thread_info]%marker %m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console
@ -23,10 +23,9 @@ appender.deprecation_file.type = File
appender.deprecation_file.name = deprecation_file
appender.deprecation_file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log
appender.deprecation_file.layout.type = PatternLayout
appender.deprecation_file.layout.pattern = [%p][%l] %marker%m%n
appender.deprecation_file.layout.pattern = [%p][%l] [%test_thread_info]%marker %m%n
logger.deprecation.name = deprecation
logger.deprecation.level = warn
logger.deprecation.appenderRef.deprecation_file.ref = deprecation_file
logger.deprecation.additivity = false

View File

@ -1,7 +1,7 @@
appender.console3.type = Console
appender.console3.name = console3
appender.console3.layout.type = PatternLayout
appender.console3.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console3.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%test_thread_info]%marker %m%n
logger.third.name = third
logger.third.level = debug

View File

@ -1,13 +1,13 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%test_thread_info]%marker %m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%p][%l] %marker%m%n
appender.file.layout.pattern = [%p][%l] [%test_thread_info]%marker %m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console
@ -17,7 +17,7 @@ appender.deprecation_file.type = File
appender.deprecation_file.name = deprecation_file
appender.deprecation_file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log
appender.deprecation_file.layout.type = PatternLayout
appender.deprecation_file.layout.pattern = [%p][%l] %marker%m%n
appender.deprecation_file.layout.pattern = [%p][%l] [%test_thread_info]%marker %m%n
logger.deprecation.name = deprecation
logger.deprecation.level = warn

View File

@ -1,7 +1,7 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%test_thread_info]%marker %m%n
logger.has_console_appender.name = has_console_appender
logger.has_console_appender.level = trace

View File

@ -1,13 +1,13 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%test_thread_info]%marker %m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%p][%l] %marker%m%n
appender.file.layout.pattern = [%p][%l] [%test_thread_info]%marker %m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console

View File

@ -0,0 +1,25 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%p][%l] %marker%m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console
rootLogger.appenderRef.file.ref = file
appender.deprecation_file.type = File
appender.deprecation_file.name = deprecation_file
appender.deprecation_file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log
appender.deprecation_file.layout.type = PatternLayout
appender.deprecation_file.layout.pattern = [%p][%l] %marker%m%n
logger.deprecation.name = deprecation
logger.deprecation.level = warn
logger.deprecation.appenderRef.deprecation_file.ref = deprecation_file
logger.deprecation.additivity = false

View File

@ -1,13 +1,13 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%test_thread_info]%marker %m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = %marker%m%n
appender.file.layout.pattern = [%test_thread_info]%marker %m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console

View File

@ -1,13 +1,13 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] [%test_thread_info]%marker %m%n
appender.file.type = File
appender.file.name = file
appender.file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%p][%l] %marker%m%n
appender.file.layout.pattern = [%p][%l] [%test_thread_info]%marker %m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console
@ -17,7 +17,7 @@ appender.deprecation_file.type = File
appender.deprecation_file.name = deprecation_file
appender.deprecation_file.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log
appender.deprecation_file.layout.type = PatternLayout
appender.deprecation_file.layout.pattern = [%p][%l] %marker%m%n
appender.deprecation_file.layout.pattern = [%p][%l] [%test_thread_info]%marker %m%n
logger.deprecation.name = org.elasticsearch.deprecation.common.settings
logger.deprecation.level = warn

View File

@ -109,8 +109,9 @@ public class TransportRolloverAction extends TransportMasterNodeAction<RolloverR
final ActionListener<RolloverResponse> listener) {
final MetaData metaData = state.metaData();
validate(metaData, rolloverRequest);
final AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(rolloverRequest.getAlias());
final IndexMetaData indexMetaData = aliasOrIndex.getIndices().get(0);
final AliasOrIndex.Alias alias = (AliasOrIndex.Alias) metaData.getAliasAndIndexLookup().get(rolloverRequest.getAlias());
final IndexMetaData indexMetaData = alias.getWriteIndex();
final boolean explicitWriteIndex = Boolean.TRUE.equals(indexMetaData.getAliases().get(alias.getAliasName()).writeIndex());
final String sourceProvidedName = indexMetaData.getSettings().get(IndexMetaData.SETTING_INDEX_PROVIDED_NAME,
indexMetaData.getIndex().getName());
final String sourceIndexName = indexMetaData.getIndex().getName();
@ -138,10 +139,15 @@ public class TransportRolloverAction extends TransportMasterNodeAction<RolloverR
CreateIndexClusterStateUpdateRequest updateRequest = prepareCreateIndexRequest(unresolvedName, rolloverIndexName,
rolloverRequest);
createIndexService.createIndex(updateRequest, ActionListener.wrap(createIndexClusterStateUpdateResponse -> {
// switch the alias to point to the newly created index
indexAliasesService.indicesAliases(
prepareRolloverAliasesUpdateRequest(sourceIndexName, rolloverIndexName,
rolloverRequest),
final IndicesAliasesClusterStateUpdateRequest aliasesUpdateRequest;
if (explicitWriteIndex) {
aliasesUpdateRequest = prepareRolloverAliasesWriteIndexUpdateRequest(sourceIndexName,
rolloverIndexName, rolloverRequest);
} else {
aliasesUpdateRequest = prepareRolloverAliasesUpdateRequest(sourceIndexName,
rolloverIndexName, rolloverRequest);
}
indexAliasesService.indicesAliases(aliasesUpdateRequest,
ActionListener.wrap(aliasClusterStateUpdateResponse -> {
if (aliasClusterStateUpdateResponse.isAcknowledged()) {
clusterService.submitStateUpdateTask("update_rollover_info", new ClusterStateUpdateTask() {
@ -196,8 +202,19 @@ public class TransportRolloverAction extends TransportMasterNodeAction<RolloverR
static IndicesAliasesClusterStateUpdateRequest prepareRolloverAliasesUpdateRequest(String oldIndex, String newIndex,
RolloverRequest request) {
List<AliasAction> actions = unmodifiableList(Arrays.asList(
new AliasAction.Add(newIndex, request.getAlias(), null, null, null, null),
new AliasAction.Remove(oldIndex, request.getAlias())));
new AliasAction.Add(newIndex, request.getAlias(), null, null, null, null),
new AliasAction.Remove(oldIndex, request.getAlias())));
final IndicesAliasesClusterStateUpdateRequest updateRequest = new IndicesAliasesClusterStateUpdateRequest(actions)
.ackTimeout(request.ackTimeout())
.masterNodeTimeout(request.masterNodeTimeout());
return updateRequest;
}
static IndicesAliasesClusterStateUpdateRequest prepareRolloverAliasesWriteIndexUpdateRequest(String oldIndex, String newIndex,
RolloverRequest request) {
List<AliasAction> actions = unmodifiableList(Arrays.asList(
new AliasAction.Add(newIndex, request.getAlias(), null, null, null, true),
new AliasAction.Add(oldIndex, request.getAlias(), null, null, null, false)));
final IndicesAliasesClusterStateUpdateRequest updateRequest = new IndicesAliasesClusterStateUpdateRequest(actions)
.ackTimeout(request.ackTimeout())
.masterNodeTimeout(request.masterNodeTimeout());
@ -244,8 +261,9 @@ public class TransportRolloverAction extends TransportMasterNodeAction<RolloverR
if (aliasOrIndex.isAlias() == false) {
throw new IllegalArgumentException("source alias is a concrete index");
}
if (aliasOrIndex.getIndices().size() != 1) {
throw new IllegalArgumentException("source alias maps to multiple indices");
final AliasOrIndex.Alias alias = (AliasOrIndex.Alias) aliasOrIndex;
if (alias.getWriteIndex() == null) {
throw new IllegalArgumentException("source alias [" + alias.getAliasName() + "] does not point to a write index");
}
}

View File

@ -37,6 +37,7 @@ import org.elasticsearch.common.inject.CreationException;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.logging.LogConfigurator;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.logging.NodeNamePatternConverter;
import org.elasticsearch.common.network.IfConfig;
import org.elasticsearch.common.settings.KeyStoreWrapper;
import org.elasticsearch.common.settings.SecureSettings;
@ -287,6 +288,10 @@ final class Bootstrap {
final SecureSettings keystore = loadSecureSettings(initialEnv);
final Environment environment = createEnvironment(pidFile, keystore, initialEnv.settings(), initialEnv.configFile());
String nodeName = Node.NODE_NAME_SETTING.get(environment.settings());
NodeNamePatternConverter.setNodeName(nodeName);
try {
LogConfigurator.configure(environment);
} catch (IOException e) {
@ -317,8 +322,7 @@ final class Bootstrap {
// install the default uncaught exception handler; must be done before security is
// initialized as we do not want to grant the runtime permission
// setDefaultUncaughtExceptionHandler
Thread.setDefaultUncaughtExceptionHandler(
new ElasticsearchUncaughtExceptionHandler(() -> Node.NODE_NAME_SETTING.get(environment.settings())));
Thread.setDefaultUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler());
INSTANCE.setup(true, environment);

View File

@ -30,7 +30,6 @@ import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.discovery.DiscoveryModule;
import org.elasticsearch.monitor.jvm.JvmInfo;
import org.elasticsearch.monitor.process.ProcessProbe;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeValidationException;
import java.io.BufferedReader;
@ -74,8 +73,7 @@ final class BootstrapChecks {
combinedChecks.addAll(additionalChecks);
check( context,
enforceLimits(boundTransportAddress, DiscoveryModule.DISCOVERY_TYPE_SETTING.get(context.settings)),
Collections.unmodifiableList(combinedChecks),
Node.NODE_NAME_SETTING.get(context.settings));
Collections.unmodifiableList(combinedChecks));
}
/**
@ -86,14 +84,12 @@ final class BootstrapChecks {
* @param context the current node boostrap context
* @param enforceLimits {@code true} if the checks should be enforced or otherwise warned
* @param checks the checks to execute
* @param nodeName the node name to be used as a logging prefix
*/
static void check(
final BootstrapContext context,
final boolean enforceLimits,
final List<BootstrapCheck> checks,
final String nodeName) throws NodeValidationException {
check(context, enforceLimits, checks, Loggers.getLogger(BootstrapChecks.class, nodeName));
final List<BootstrapCheck> checks) throws NodeValidationException {
check(context, enforceLimits, checks, Loggers.getLogger(BootstrapChecks.class));
}
/**

View File

@ -27,16 +27,9 @@ import org.elasticsearch.common.logging.Loggers;
import java.io.IOError;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Objects;
import java.util.function.Supplier;
class ElasticsearchUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private final Supplier<String> loggingPrefixSupplier;
ElasticsearchUncaughtExceptionHandler(final Supplier<String> loggingPrefixSupplier) {
this.loggingPrefixSupplier = Objects.requireNonNull(loggingPrefixSupplier);
}
private static final Logger logger = Loggers.getLogger(ElasticsearchUncaughtExceptionHandler.class);
@Override
public void uncaughtException(Thread t, Throwable e) {
@ -70,12 +63,10 @@ class ElasticsearchUncaughtExceptionHandler implements Thread.UncaughtExceptionH
}
void onFatalUncaught(final String threadName, final Throwable t) {
final Logger logger = Loggers.getLogger(ElasticsearchUncaughtExceptionHandler.class, loggingPrefixSupplier.get());
logger.error(() -> new ParameterizedMessage("fatal error in thread [{}], exiting", threadName), t);
}
void onNonFatalUncaught(final String threadName, final Throwable t) {
final Logger logger = Loggers.getLogger(ElasticsearchUncaughtExceptionHandler.class, loggingPrefixSupplier.get());
logger.warn(() -> new ParameterizedMessage("uncaught exception in thread [{}]", threadName), t);
}

View File

@ -46,6 +46,8 @@ import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.lucene.geo.GeoUtils.orient;
/**
* The {@link PolygonBuilder} implements the groundwork to create polygons. This contains
* Methods to wrap polygons at the dateline and building shapes from the data held by the
@ -642,14 +644,8 @@ public class PolygonBuilder extends ShapeBuilder<JtsGeometry, PolygonBuilder> {
*/
private static Edge[] ring(int component, boolean direction, boolean handedness,
Coordinate[] points, int offset, Edge[] edges, int toffset, int length, final AtomicBoolean translated) {
// calculate the direction of the points:
// find the point a the top of the set and check its
// neighbors orientation. So direction is equivalent
// to clockwise/counterclockwise
final int top = top(points, offset, length);
final int prev = (offset + ((top + length - 1) % length));
final int next = (offset + ((top + 1) % length));
boolean orientation = points[offset + prev].x > points[offset + next].x;
boolean orientation = getOrientation(points, offset, length);
// OGC requires shell as ccw (Right-Handedness) and holes as cw (Left-Handedness)
// since GeoJSON doesn't specify (and doesn't need to) GEO core will assume OGC standards
@ -678,6 +674,35 @@ public class PolygonBuilder extends ShapeBuilder<JtsGeometry, PolygonBuilder> {
return concat(component, direction ^ orientation, points, offset, edges, toffset, length);
}
/**
* @return whether the points are clockwise (true) or anticlockwise (false)
*/
private static boolean getOrientation(Coordinate[] points, int offset, int length) {
// calculate the direction of the points: find the southernmost point
// and check its neighbors orientation.
final int top = top(points, offset, length);
final int prev = (top + length - 1) % length;
final int next = (top + 1) % length;
final int determinantSign = orient(
points[offset + prev].x, points[offset + prev].y,
points[offset + top].x, points[offset + top].y,
points[offset + next].x, points[offset + next].y);
if (determinantSign == 0) {
// Points are collinear, but `top` is not in the middle if so, so the edges either side of `top` are intersecting.
throw new InvalidShapeException("Cannot determine orientation: edges adjacent to ("
+ points[offset + top].x + "," + points[offset +top].y + ") coincide");
}
return determinantSign < 0;
}
/**
* @return the (offset) index of the point that is furthest west amongst
* those points that are the furthest south in the set.
*/
private static int top(Coordinate[] points, int offset, int length) {
int top = 0; // we start at 1 here since top points to 0
for (int i = 1; i < length; i++) {

View File

@ -46,6 +46,15 @@ public final class ESLoggerFactory {
}
public static Logger getLogger(String prefix, Logger logger) {
/*
* In a followup we'll throw an exception if prefix is null or empty
* redirecting folks to LogManager.getLogger.
*
* This and more is tracked in https://github.com/elastic/elasticsearch/issues/32174
*/
if (prefix == null || prefix.length() == 0) {
return logger;
}
return new PrefixLogger((ExtendedLogger)logger, logger.getName(), prefix);
}

View File

@ -23,12 +23,16 @@ import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
import org.apache.logging.log4j.core.config.ConfigurationException;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
import org.apache.logging.log4j.core.config.properties.PropertiesConfiguration;
import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationBuilder;
import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory;
import org.apache.logging.log4j.status.StatusConsoleListener;
import org.apache.logging.log4j.status.StatusData;
@ -43,6 +47,7 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.node.Node;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
@ -50,9 +55,12 @@ import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.StreamSupport;
@ -119,6 +127,13 @@ public class LogConfigurator {
configure(environment.settings(), environment.configFile(), environment.logsFile());
}
/**
* Load logging plugins so we can have {@code node_name} in the pattern.
*/
public static void loadLog4jPlugins() {
PluginManager.addPackage(LogConfigurator.class.getPackage().getName());
}
private static void checkErrorListener() {
assert errorListenerIsRegistered() : "expected error listener to be registered";
if (error.get()) {
@ -135,6 +150,8 @@ public class LogConfigurator {
Objects.requireNonNull(configsPath);
Objects.requireNonNull(logsPath);
loadLog4jPlugins();
setLogConfigurationSystemProperty(logsPath, settings);
// we initialize the status logger immediately otherwise Log4j will complain when we try to get the context
configureStatusLogger();
@ -142,7 +159,53 @@ public class LogConfigurator {
final LoggerContext context = (LoggerContext) LogManager.getContext(false);
final List<AbstractConfiguration> configurations = new ArrayList<>();
final PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory();
/*
* Subclass the properties configurator to hack the new pattern in
* place so users don't have to change log4j2.properties in
* a minor release. In 7.0 we'll remove this and force users to
* change log4j2.properties. If they don't customize log4j2.properties
* then they won't have to do anything anyway.
*
* Everything in this subclass that isn't marked as a hack is copied
* from log4j2's source.
*/
Set<String> locationsWithDeprecatedPatterns = Collections.synchronizedSet(new HashSet<>());
final PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory() {
@Override
public PropertiesConfiguration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
final Properties properties = new Properties();
try (InputStream configStream = source.getInputStream()) {
properties.load(configStream);
} catch (final IOException ioe) {
throw new ConfigurationException("Unable to load " + source.toString(), ioe);
}
// Hack the new pattern into place
for (String name : properties.stringPropertyNames()) {
if (false == name.endsWith(".pattern")) continue;
// Null is weird here but we can't do anything with it so ignore it
String value = properties.getProperty(name);
if (value == null) continue;
// Tests don't need to be changed
if (value.contains("%test_thread_info")) continue;
/*
* Patterns without a marker are sufficiently customized
* that we don't have an opinion about them.
*/
if (false == value.contains("%marker")) continue;
if (false == value.contains("%node_name")) {
locationsWithDeprecatedPatterns.add(source.getLocation());
properties.setProperty(name, value.replace("%marker", "[%node_name]%marker "));
}
}
// end hack
return new PropertiesConfigurationBuilder()
.setConfigurationSource(source)
.setRootProperties(properties)
.setLoggerContext(loggerContext)
.build();
}
};
final Set<FileVisitOption> options = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
Files.walkFileTree(configsPath, options, Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
@Override
@ -163,6 +226,14 @@ public class LogConfigurator {
context.start(new CompositeConfiguration(configurations));
configureLoggerLevels(settings);
final String deprecatedLocationsString = String.join("\n ", locationsWithDeprecatedPatterns);
if (deprecatedLocationsString.length() > 0) {
LogManager.getLogger(LogConfigurator.class).warn("Some logging configurations have %marker but don't have %node_name. "
+ "We will automatically add %node_name to the pattern to ease the migration for users who customize "
+ "log4j2.properties but will stop this behavior in 7.0. You should manually replace `%node_name` with "
+ "`[%node_name]%marker ` in these locations:\n {}", deprecatedLocationsString);
}
}
private static void configureStatusLogger() {

View File

@ -31,13 +31,9 @@ import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.node.Node;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static java.util.Arrays.asList;
import static org.elasticsearch.common.util.CollectionUtils.asArrayList;
/**
@ -71,29 +67,19 @@ public class Loggers {
}
public static Logger getLogger(Class<?> clazz, Settings settings, String... prefixes) {
final List<String> prefixesList = prefixesList(settings, prefixes);
return Loggers.getLogger(clazz, prefixesList.toArray(new String[prefixesList.size()]));
return Loggers.getLogger(clazz, prefixes);
}
public static Logger getLogger(String loggerName, Settings settings, String... prefixes) {
final List<String> prefixesList = prefixesList(settings, prefixes);
return Loggers.getLogger(loggerName, prefixesList.toArray(new String[prefixesList.size()]));
}
private static List<String> prefixesList(Settings settings, String... prefixes) {
List<String> prefixesList = new ArrayList<>();
if (Node.NODE_NAME_SETTING.exists(settings)) {
prefixesList.add(Node.NODE_NAME_SETTING.get(settings));
}
if (prefixes != null && prefixes.length > 0) {
prefixesList.addAll(asList(prefixes));
}
return prefixesList;
return Loggers.getLogger(loggerName, prefixes);
}
public static Logger getLogger(Logger parentLogger, String s) {
assert parentLogger instanceof PrefixLogger;
return ESLoggerFactory.getLogger(((PrefixLogger)parentLogger).prefix(), parentLogger.getName() + s);
String prefix = null;
if (parentLogger instanceof PrefixLogger) {
prefix = ((PrefixLogger)parentLogger).prefix();
}
return ESLoggerFactory.getLogger(prefix, parentLogger.getName() + s);
}
public static Logger getLogger(String s) {
@ -126,7 +112,6 @@ public class Loggers {
}
}
if (sb.length() > 0) {
sb.append(" ");
prefix = sb.toString();
}
}

View File

@ -0,0 +1,72 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.common.logging;
import java.util.Arrays;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternConverter;
import org.apache.lucene.util.SetOnce;
/**
* Converts {@code %node_name} in log4j patterns into the current node name.
* We *could* use a system property lookup instead but this is very explicit
* and fails fast if we try to use the logger without initializing the node
* name. As a bonus it ought to be ever so slightly faster because it doesn't
* have to look up the system property every time.
*/
@Plugin(category = PatternConverter.CATEGORY, name = "NodeNamePatternConverter")
@ConverterKeys({"node_name"})
public class NodeNamePatternConverter extends LogEventPatternConverter {
private static final SetOnce<String> NODE_NAME = new SetOnce<>();
/**
* Set the name of this node.
*/
public static void setNodeName(String nodeName) {
NODE_NAME.set(nodeName);
}
/**
* Called by log4j2 to initialize this converter.
*/
public static NodeNamePatternConverter newInstance(final String[] options) {
if (options.length > 0) {
throw new IllegalArgumentException("no options supported but options provided: "
+ Arrays.toString(options));
}
return new NodeNamePatternConverter(NODE_NAME.get());
}
private final String nodeName;
private NodeNamePatternConverter(String nodeName) {
super("NodeName", "node_name");
this.nodeName = nodeName;
}
@Override
public void format(LogEvent event, StringBuilder toAppendTo) {
toAppendTo.append(nodeName);
}
}

View File

@ -359,7 +359,7 @@ public class KeyStoreWrapper implements SecureSettings {
if (input.read() != -1) {
throw new SecurityException("Keystore has been corrupted or tampered with");
}
} catch (EOFException e) {
} catch (IOException e) {
throw new SecurityException("Keystore has been corrupted or tampered with", e);
}
}

View File

@ -23,8 +23,11 @@ import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.tasks.TaskId;
import java.io.IOException;
import static org.elasticsearch.action.ValidateActions.addValidationError;
/**
@ -53,6 +56,10 @@ public class DeleteByQueryRequest extends AbstractBulkByScrollRequest<DeleteByQu
this(search, true);
}
public DeleteByQueryRequest(StreamInput in) throws IOException {
super.readFrom(in);
}
private DeleteByQueryRequest(SearchRequest search, boolean setDefaults) {
super(search, setDefaults);
// Delete-By-Query does not require the source

View File

@ -59,6 +59,13 @@ public class ReindexRequest extends AbstractBulkIndexByScrollRequest<ReindexRequ
this.destination = destination;
}
public ReindexRequest(StreamInput in) throws IOException {
super.readFrom(in);
destination = new IndexRequest();
destination.readFrom(in);
remoteInfo = in.readOptionalWriteable(RemoteInfo::new);
}
@Override
protected ReindexRequest self() {
return this;
@ -135,10 +142,7 @@ public class ReindexRequest extends AbstractBulkIndexByScrollRequest<ReindexRequ
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
destination = new IndexRequest();
destination.readFrom(in);
remoteInfo = in.readOptionalWriteable(RemoteInfo::new);
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
}
@Override

View File

@ -47,6 +47,11 @@ public class UpdateByQueryRequest extends AbstractBulkIndexByScrollRequest<Updat
this(search, true);
}
public UpdateByQueryRequest(StreamInput in) throws IOException {
super.readFrom(in);
pipeline = in.readOptionalString();
}
private UpdateByQueryRequest(SearchRequest search, boolean setDefaults) {
super(search, setDefaults);
}
@ -108,8 +113,7 @@ public class UpdateByQueryRequest extends AbstractBulkIndexByScrollRequest<Updat
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
pipeline = in.readOptionalString();
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
}
@Override

View File

@ -527,8 +527,7 @@ public final class IngestDocument {
private static void appendValues(List<Object> list, Object value) {
if (value instanceof List) {
List<?> valueList = (List<?>) value;
valueList.stream().forEach(list::add);
list.addAll((List<?>) value);
} else {
list.add(value);
}

View File

@ -231,7 +231,14 @@ public class Node implements Closeable {
}
private static final String CLIENT_TYPE = "node";
private final Lifecycle lifecycle = new Lifecycle();
/**
* Logger initialized in the ctor because if it were initialized statically
* then it wouldn't get the node name.
*/
private final Logger logger;
private final Injector injector;
private final Settings settings;
private final Settings originalSettings;
@ -257,13 +264,9 @@ public class Node implements Closeable {
}
protected Node(final Environment environment, Collection<Class<? extends Plugin>> classpathPlugins) {
logger = Loggers.getLogger(Node.class);
final List<Closeable> resourcesToClose = new ArrayList<>(); // register everything we need to release in the case of an error
boolean success = false;
{
// use temp logger just to say we are starting. we can't use it later on because the node name might not be set
Logger logger = Loggers.getLogger(Node.class, NODE_NAME_SETTING.get(environment.settings()));
logger.info("initializing ...");
}
try {
originalSettings = environment.settings();
Settings tmpSettings = Settings.builder().put(environment.settings())
@ -279,7 +282,6 @@ public class Node implements Closeable {
final boolean hadPredefinedNodeName = NODE_NAME_SETTING.exists(tmpSettings);
final String nodeId = nodeEnvironment.nodeId();
tmpSettings = addNodeNameIfNeeded(tmpSettings, nodeId);
final Logger logger = Loggers.getLogger(Node.class, tmpSettings);
// this must be captured after the node name is possibly added to the settings
final String nodeName = NODE_NAME_SETTING.get(tmpSettings);
if (hadPredefinedNodeName == false) {
@ -630,7 +632,6 @@ public class Node implements Closeable {
return this;
}
Logger logger = Loggers.getLogger(Node.class, NODE_NAME_SETTING.get(settings));
logger.info("starting ...");
pluginLifecycleComponents.forEach(LifecycleComponent::start);
@ -741,7 +742,6 @@ public class Node implements Closeable {
if (!lifecycle.moveToStopped()) {
return this;
}
Logger logger = Loggers.getLogger(Node.class, NODE_NAME_SETTING.get(settings));
logger.info("stopping ...");
injector.getInstance(ResourceWatcherService.class).stop();
@ -784,7 +784,6 @@ public class Node implements Closeable {
return;
}
Logger logger = Loggers.getLogger(Node.class, NODE_NAME_SETTING.get(settings));
logger.info("closing ...");
List<Closeable> toClose = new ArrayList<>();
StopWatch stopWatch = new StopWatch("node_close");

View File

@ -19,6 +19,16 @@
package org.elasticsearch.search;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.lucene.search.Explanation;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.OriginalIndices;
@ -51,16 +61,6 @@ import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.lookup.SourceLookup;
import org.elasticsearch.transport.RemoteClusterAware;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableMap;
@ -107,6 +107,9 @@ public final class SearchHit implements Streamable, ToXContentObject, Iterable<D
@Nullable
private SearchShardTarget shard;
//These two fields normally get set when setting the shard target, so they hold the same values as the target thus don't get
//serialized over the wire. When parsing hits back from xcontent though, in most of the cases (whenever explanation is disabled)
//we can't rebuild the shard target object so we need to set these manually for users retrieval.
private transient String index;
private transient String clusterAlias;
@ -551,7 +554,26 @@ public final class SearchHit implements Streamable, ToXContentObject, Iterable<D
Map<String, DocumentField> fields = get(Fields.FIELDS, values, Collections.emptyMap());
SearchHit searchHit = new SearchHit(-1, id, type, nestedIdentity, fields);
searchHit.index = get(Fields._INDEX, values, null);
String index = get(Fields._INDEX, values, null);
String clusterAlias = null;
if (index != null) {
int indexOf = index.indexOf(RemoteClusterAware.REMOTE_CLUSTER_INDEX_SEPARATOR);
if (indexOf > 0) {
clusterAlias = index.substring(0, indexOf);
index = index.substring(indexOf + 1);
}
}
ShardId shardId = get(Fields._SHARD, values, null);
String nodeId = get(Fields._NODE, values, null);
if (shardId != null && nodeId != null) {
assert shardId.getIndexName().equals(index);
searchHit.shard(new SearchShardTarget(nodeId, shardId, clusterAlias, OriginalIndices.NONE));
} else {
//these fields get set anyways when setting the shard target,
//but we set them explicitly when we don't have enough info to rebuild the shard target
searchHit.index = index;
searchHit.clusterAlias = clusterAlias;
}
searchHit.score(get(Fields._SCORE, values, DEFAULT_SCORE));
searchHit.version(get(Fields._VERSION, values, -1L));
searchHit.sortValues(get(Fields.SORT, values, SearchSortValues.EMPTY));
@ -561,12 +583,7 @@ public final class SearchHit implements Streamable, ToXContentObject, Iterable<D
searchHit.setInnerHits(get(Fields.INNER_HITS, values, null));
List<String> matchedQueries = get(Fields.MATCHED_QUERIES, values, null);
if (matchedQueries != null) {
searchHit.matchedQueries(matchedQueries.toArray(new String[matchedQueries.size()]));
}
ShardId shardId = get(Fields._SHARD, values, null);
String nodeId = get(Fields._NODE, values, null);
if (shardId != null && nodeId != null) {
searchHit.shard(new SearchShardTarget(nodeId, shardId, null, OriginalIndices.NONE));
searchHit.matchedQueries(matchedQueries.toArray(new String[0]));
}
return searchHit;
}
@ -842,13 +859,15 @@ public final class SearchHit implements Streamable, ToXContentObject, Iterable<D
&& Arrays.equals(matchedQueries, other.matchedQueries)
&& Objects.equals(explanation, other.explanation)
&& Objects.equals(shard, other.shard)
&& Objects.equals(innerHits, other.innerHits);
&& Objects.equals(innerHits, other.innerHits)
&& Objects.equals(index, other.index)
&& Objects.equals(clusterAlias, other.clusterAlias);
}
@Override
public int hashCode() {
return Objects.hash(id, type, nestedIdentity, version, source, fields, getHighlightFields(), Arrays.hashCode(matchedQueries),
explanation, shard, innerHits);
explanation, shard, innerHits, index, clusterAlias);
}
/**

View File

@ -19,6 +19,8 @@
package org.elasticsearch.search;
import java.io.IOException;
import org.elasticsearch.Version;
import org.elasticsearch.action.OriginalIndices;
import org.elasticsearch.common.Nullable;
@ -30,8 +32,6 @@ import org.elasticsearch.index.Index;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.transport.RemoteClusterAware;
import java.io.IOException;
/**
* The target that the search request was executed on.
*/
@ -39,7 +39,7 @@ public final class SearchShardTarget implements Writeable, Comparable<SearchShar
private final Text nodeId;
private final ShardId shardId;
//original indices and cluster alias are only needed in the coordinating node throughout the search request execution.
//original indices are only needed in the coordinating node throughout the search request execution.
//no need to serialize them as part of SearchShardTarget.
private final transient OriginalIndices originalIndices;
private final String clusterAlias;

View File

@ -42,6 +42,7 @@ import org.elasticsearch.search.aggregations.support.ValuesSourceConfig;
import org.elasticsearch.search.aggregations.support.ValuesSourceParserHelper;
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
import org.elasticsearch.search.internal.SearchContext;
import org.joda.time.DateTimeZone;
import java.io.IOException;
import java.util.Arrays;
@ -53,7 +54,7 @@ public class AutoDateHistogramAggregationBuilder
public static final String NAME = "auto_date_histogram";
public static final ParseField NUM_BUCKETS_FIELD = new ParseField("buckets");
private static final ParseField NUM_BUCKETS_FIELD = new ParseField("buckets");
private static final ObjectParser<AutoDateHistogramAggregationBuilder, Void> PARSER;
static {
@ -63,6 +64,29 @@ public class AutoDateHistogramAggregationBuilder
PARSER.declareInt(AutoDateHistogramAggregationBuilder::setNumBuckets, NUM_BUCKETS_FIELD);
}
/**
*
* Build roundings, computed dynamically as roundings are time zone dependent.
* The current implementation probably should not be invoked in a tight loop.
* @return Array of RoundingInfo
*/
static RoundingInfo[] buildRoundings(DateTimeZone timeZone) {
RoundingInfo[] roundings = new RoundingInfo[6];
roundings[0] = new RoundingInfo(createRounding(DateTimeUnit.SECOND_OF_MINUTE, timeZone),
1000L, 1, 5, 10, 30);
roundings[1] = new RoundingInfo(createRounding(DateTimeUnit.MINUTES_OF_HOUR, timeZone),
60 * 1000L, 1, 5, 10, 30);
roundings[2] = new RoundingInfo(createRounding(DateTimeUnit.HOUR_OF_DAY, timeZone),
60 * 60 * 1000L, 1, 3, 12);
roundings[3] = new RoundingInfo(createRounding(DateTimeUnit.DAY_OF_MONTH, timeZone),
24 * 60 * 60 * 1000L, 1, 7);
roundings[4] = new RoundingInfo(createRounding(DateTimeUnit.MONTH_OF_YEAR, timeZone),
30 * 24 * 60 * 60 * 1000L, 1, 3);
roundings[5] = new RoundingInfo(createRounding(DateTimeUnit.YEAR_OF_CENTURY, timeZone),
365 * 24 * 60 * 60 * 1000L, 1, 5, 10, 20, 50, 100);
return roundings;
}
public static AutoDateHistogramAggregationBuilder parse(String aggregationName, XContentParser parser) throws IOException {
return PARSER.parse(parser, new AutoDateHistogramAggregationBuilder(aggregationName), null);
}
@ -116,14 +140,7 @@ public class AutoDateHistogramAggregationBuilder
@Override
protected ValuesSourceAggregatorFactory<Numeric, ?> innerBuild(SearchContext context, ValuesSourceConfig<Numeric> config,
AggregatorFactory<?> parent, Builder subFactoriesBuilder) throws IOException {
RoundingInfo[] roundings = new RoundingInfo[6];
roundings[0] = new RoundingInfo(createRounding(DateTimeUnit.SECOND_OF_MINUTE), 1000L, 1, 5, 10, 30);
roundings[1] = new RoundingInfo(createRounding(DateTimeUnit.MINUTES_OF_HOUR), 60 * 1000L, 1, 5, 10, 30);
roundings[2] = new RoundingInfo(createRounding(DateTimeUnit.HOUR_OF_DAY), 60 * 60 * 1000L, 1, 3, 12);
roundings[3] = new RoundingInfo(createRounding(DateTimeUnit.DAY_OF_MONTH), 24 * 60 * 60 * 1000L, 1, 7);
roundings[4] = new RoundingInfo(createRounding(DateTimeUnit.MONTH_OF_YEAR), 30 * 24 * 60 * 60 * 1000L, 1, 3);
roundings[5] = new RoundingInfo(createRounding(DateTimeUnit.YEAR_OF_CENTURY), 365 * 24 * 60 * 60 * 1000L, 1, 5, 10, 20, 50, 100);
RoundingInfo[] roundings = buildRoundings(timeZone());
int maxRoundingInterval = Arrays.stream(roundings,0, roundings.length-1)
.map(rounding -> rounding.innerIntervals)
.flatMapToInt(Arrays::stream)
@ -139,10 +156,10 @@ public class AutoDateHistogramAggregationBuilder
return new AutoDateHistogramAggregatorFactory(name, config, numBuckets, roundings, context, parent, subFactoriesBuilder, metaData);
}
private Rounding createRounding(DateTimeUnit interval) {
private static Rounding createRounding(DateTimeUnit interval, DateTimeZone timeZone) {
Rounding.Builder tzRoundingBuilder = Rounding.builder(interval);
if (timeZone() != null) {
tzRoundingBuilder.timeZone(timeZone());
if (timeZone != null) {
tzRoundingBuilder.timeZone(timeZone);
}
Rounding rounding = tzRoundingBuilder.build();
return rounding;

View File

@ -447,7 +447,8 @@ public final class InternalAutoDateHistogram extends
return new BucketReduceResult(list, roundingInfo, roundingIdx);
}
private int getAppropriateRounding(long minKey, long maxKey, int roundingIdx, RoundingInfo[] roundings) {
private int getAppropriateRounding(long minKey, long maxKey, int roundingIdx,
RoundingInfo[] roundings) {
if (roundingIdx == roundings.length - 1) {
return roundingIdx;
}
@ -509,7 +510,8 @@ public final class InternalAutoDateHistogram extends
pipelineAggregators(), getMetaData());
}
private BucketReduceResult maybeMergeConsecutiveBuckets(BucketReduceResult reducedBucketsResult, ReduceContext reduceContext) {
private BucketReduceResult maybeMergeConsecutiveBuckets(BucketReduceResult reducedBucketsResult,
ReduceContext reduceContext) {
List<Bucket> buckets = reducedBucketsResult.buckets;
RoundingInfo roundingInfo = reducedBucketsResult.roundingInfo;
int roundingIdx = reducedBucketsResult.roundingIdx;
@ -539,7 +541,7 @@ public final class InternalAutoDateHistogram extends
key = roundingInfo.rounding.round(bucket.key);
}
reduceContext.consumeBucketsAndMaybeBreak(-countInnerBucket(bucket) - 1);
sameKeyedBuckets.add(createBucket(key, bucket.docCount, bucket.aggregations));
sameKeyedBuckets.add(new Bucket(Math.round(key), bucket.docCount, format, bucket.aggregations));
}
if (sameKeyedBuckets.isEmpty() == false) {
reduceContext.consumeBucketsAndMaybeBreak(1);

View File

@ -32,7 +32,6 @@ import org.elasticsearch.plugins.PluginsService;
import org.elasticsearch.plugins.ReloadablePlugin;
import org.elasticsearch.test.ESIntegTestCase;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
@ -205,14 +204,7 @@ public class ReloadSecureSettingsIT extends ESIntegTestCase {
assertThat(nodesMap.size(), equalTo(cluster().size()));
for (final NodesReloadSecureSettingsResponse.NodeResponse nodeResponse : nodesReloadResponse.getNodes()) {
assertThat(nodeResponse.reloadException(), notNullValue());
// Running in a JVM with a BouncyCastle FIPS Security Provider, decrypting the Keystore with the wrong
// password returns a SecurityException if the DataInputStream can't be fully consumed
if (inFipsJvm()) {
assertThat(nodeResponse.reloadException(), instanceOf(SecurityException.class));
} else {
assertThat(nodeResponse.reloadException(), instanceOf(IOException.class));
}
}
} catch (final AssertionError e) {
reloadSettingsError.set(e);

View File

@ -60,7 +60,12 @@ public class RolloverIT extends ESIntegTestCase {
public void testRolloverOnEmptyIndex() throws Exception {
assertAcked(prepareCreate("test_index-1").addAlias(new Alias("test_alias")).get());
Alias testAlias = new Alias("test_alias");
boolean explicitWriteIndex = randomBoolean();
if (explicitWriteIndex) {
testAlias.writeIndex(true);
}
assertAcked(prepareCreate("test_index-1").addAlias(testAlias).get());
final RolloverResponse response = client().admin().indices().prepareRolloverIndex("test_alias").get();
assertThat(response.getOldIndex(), equalTo("test_index-1"));
assertThat(response.getNewIndex(), equalTo("test_index-000002"));
@ -69,7 +74,12 @@ public class RolloverIT extends ESIntegTestCase {
assertThat(response.getConditionStatus().size(), equalTo(0));
final ClusterState state = client().admin().cluster().prepareState().get().getState();
final IndexMetaData oldIndex = state.metaData().index("test_index-1");
assertFalse(oldIndex.getAliases().containsKey("test_alias"));
if (explicitWriteIndex) {
assertTrue(oldIndex.getAliases().containsKey("test_alias"));
assertFalse(oldIndex.getAliases().get("test_alias").writeIndex());
} else {
assertFalse(oldIndex.getAliases().containsKey("test_alias"));
}
final IndexMetaData newIndex = state.metaData().index("test_index-000002");
assertTrue(newIndex.getAliases().containsKey("test_alias"));
}
@ -97,8 +107,49 @@ public class RolloverIT extends ESIntegTestCase {
is(both(greaterThanOrEqualTo(beforeTime)).and(lessThanOrEqualTo(client().threadPool().absoluteTimeInMillis() + 1000L))));
}
public void testRolloverWithExplicitWriteIndex() throws Exception {
long beforeTime = client().threadPool().absoluteTimeInMillis() - 1000L;
assertAcked(prepareCreate("test_index-2").addAlias(new Alias("test_alias").writeIndex(true)).get());
index("test_index-2", "type1", "1", "field", "value");
flush("test_index-2");
final RolloverResponse response = client().admin().indices().prepareRolloverIndex("test_alias").get();
assertThat(response.getOldIndex(), equalTo("test_index-2"));
assertThat(response.getNewIndex(), equalTo("test_index-000003"));
assertThat(response.isDryRun(), equalTo(false));
assertThat(response.isRolledOver(), equalTo(true));
assertThat(response.getConditionStatus().size(), equalTo(0));
final ClusterState state = client().admin().cluster().prepareState().get().getState();
final IndexMetaData oldIndex = state.metaData().index("test_index-2");
assertTrue(oldIndex.getAliases().containsKey("test_alias"));
assertFalse(oldIndex.getAliases().get("test_alias").writeIndex());
final IndexMetaData newIndex = state.metaData().index("test_index-000003");
assertTrue(newIndex.getAliases().containsKey("test_alias"));
assertTrue(newIndex.getAliases().get("test_alias").writeIndex());
assertThat(oldIndex.getRolloverInfos().size(), equalTo(1));
assertThat(oldIndex.getRolloverInfos().get("test_alias").getAlias(), equalTo("test_alias"));
assertThat(oldIndex.getRolloverInfos().get("test_alias").getMetConditions(), is(empty()));
assertThat(oldIndex.getRolloverInfos().get("test_alias").getTime(),
is(both(greaterThanOrEqualTo(beforeTime)).and(lessThanOrEqualTo(client().threadPool().absoluteTimeInMillis() + 1000L))));
}
public void testRolloverWithNoWriteIndex() {
Boolean firstIsWriteIndex = randomFrom(false, null);
assertAcked(prepareCreate("index1").addAlias(new Alias("alias").writeIndex(firstIsWriteIndex)).get());
if (firstIsWriteIndex == null) {
assertAcked(prepareCreate("index2").addAlias(new Alias("alias").writeIndex(randomFrom(false, null))).get());
}
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
() -> client().admin().indices().prepareRolloverIndex("alias").dryRun(randomBoolean()).get());
assertThat(exception.getMessage(), equalTo("source alias [alias] does not point to a write index"));
}
public void testRolloverWithIndexSettings() throws Exception {
assertAcked(prepareCreate("test_index-2").addAlias(new Alias("test_alias")).get());
Alias testAlias = new Alias("test_alias");
boolean explicitWriteIndex = randomBoolean();
if (explicitWriteIndex) {
testAlias.writeIndex(true);
}
assertAcked(prepareCreate("test_index-2").addAlias(testAlias).get());
index("test_index-2", "type1", "1", "field", "value");
flush("test_index-2");
final Settings settings = Settings.builder()
@ -114,12 +165,17 @@ public class RolloverIT extends ESIntegTestCase {
assertThat(response.getConditionStatus().size(), equalTo(0));
final ClusterState state = client().admin().cluster().prepareState().get().getState();
final IndexMetaData oldIndex = state.metaData().index("test_index-2");
assertFalse(oldIndex.getAliases().containsKey("test_alias"));
final IndexMetaData newIndex = state.metaData().index("test_index-000003");
assertThat(newIndex.getNumberOfShards(), equalTo(1));
assertThat(newIndex.getNumberOfReplicas(), equalTo(0));
assertTrue(newIndex.getAliases().containsKey("test_alias"));
assertTrue(newIndex.getAliases().containsKey("extra_alias"));
if (explicitWriteIndex) {
assertFalse(oldIndex.getAliases().get("test_alias").writeIndex());
assertTrue(newIndex.getAliases().get("test_alias").writeIndex());
} else {
assertFalse(oldIndex.getAliases().containsKey("test_alias"));
}
}
public void testRolloverDryRun() throws Exception {
@ -140,7 +196,12 @@ public class RolloverIT extends ESIntegTestCase {
}
public void testRolloverConditionsNotMet() throws Exception {
assertAcked(prepareCreate("test_index-0").addAlias(new Alias("test_alias")).get());
boolean explicitWriteIndex = randomBoolean();
Alias testAlias = new Alias("test_alias");
if (explicitWriteIndex) {
testAlias.writeIndex(true);
}
assertAcked(prepareCreate("test_index-0").addAlias(testAlias).get());
index("test_index-0", "type1", "1", "field", "value");
flush("test_index-0");
final RolloverResponse response = client().admin().indices().prepareRolloverIndex("test_alias")
@ -160,12 +221,22 @@ public class RolloverIT extends ESIntegTestCase {
final ClusterState state = client().admin().cluster().prepareState().get().getState();
final IndexMetaData oldIndex = state.metaData().index("test_index-0");
assertTrue(oldIndex.getAliases().containsKey("test_alias"));
if (explicitWriteIndex) {
assertTrue(oldIndex.getAliases().get("test_alias").writeIndex());
} else {
assertNull(oldIndex.getAliases().get("test_alias").writeIndex());
}
final IndexMetaData newIndex = state.metaData().index("test_index-000001");
assertNull(newIndex);
}
public void testRolloverWithNewIndexName() throws Exception {
assertAcked(prepareCreate("test_index").addAlias(new Alias("test_alias")).get());
Alias testAlias = new Alias("test_alias");
boolean explicitWriteIndex = randomBoolean();
if (explicitWriteIndex) {
testAlias.writeIndex(true);
}
assertAcked(prepareCreate("test_index").addAlias(testAlias).get());
index("test_index", "type1", "1", "field", "value");
flush("test_index");
final RolloverResponse response = client().admin().indices().prepareRolloverIndex("test_alias")
@ -177,9 +248,14 @@ public class RolloverIT extends ESIntegTestCase {
assertThat(response.getConditionStatus().size(), equalTo(0));
final ClusterState state = client().admin().cluster().prepareState().get().getState();
final IndexMetaData oldIndex = state.metaData().index("test_index");
assertFalse(oldIndex.getAliases().containsKey("test_alias"));
final IndexMetaData newIndex = state.metaData().index("test_new_index");
assertTrue(newIndex.getAliases().containsKey("test_alias"));
if (explicitWriteIndex) {
assertFalse(oldIndex.getAliases().get("test_alias").writeIndex());
assertTrue(newIndex.getAliases().get("test_alias").writeIndex());
} else {
assertFalse(oldIndex.getAliases().containsKey("test_alias"));
}
}
public void testRolloverOnExistingIndex() throws Exception {

View File

@ -172,39 +172,75 @@ public class TransportRolloverActionTests extends ESTestCase {
assertTrue(foundRemove);
}
public void testCreateUpdateAliasRequestWithExplicitWriteIndex() {
String sourceAlias = randomAlphaOfLength(10);
String sourceIndex = randomAlphaOfLength(10);
String targetIndex = randomAlphaOfLength(10);
final RolloverRequest rolloverRequest = new RolloverRequest(sourceAlias, targetIndex);
final IndicesAliasesClusterStateUpdateRequest updateRequest =
TransportRolloverAction.prepareRolloverAliasesWriteIndexUpdateRequest(sourceIndex, targetIndex, rolloverRequest);
List<AliasAction> actions = updateRequest.actions();
assertThat(actions, hasSize(2));
boolean foundAddWrite = false;
boolean foundRemoveWrite = false;
for (AliasAction action : actions) {
AliasAction.Add addAction = (AliasAction.Add) action;
if (action.getIndex().equals(targetIndex)) {
assertEquals(sourceAlias, addAction.getAlias());
assertTrue(addAction.writeIndex());
foundAddWrite = true;
} else if (action.getIndex().equals(sourceIndex)) {
assertEquals(sourceAlias, addAction.getAlias());
assertFalse(addAction.writeIndex());
foundRemoveWrite = true;
} else {
throw new AssertionError("Unknow index [" + action.getIndex() + "]");
}
}
assertTrue(foundAddWrite);
assertTrue(foundRemoveWrite);
}
public void testValidation() {
String index1 = randomAlphaOfLength(10);
String alias = randomAlphaOfLength(10);
String aliasWithWriteIndex = randomAlphaOfLength(10);
String index2 = randomAlphaOfLength(10);
String aliasWithMultipleIndices = randomAlphaOfLength(10);
String aliasWithNoWriteIndex = randomAlphaOfLength(10);
Boolean firstIsWriteIndex = randomFrom(false, null);
final Settings settings = Settings.builder()
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
.put(IndexMetaData.SETTING_INDEX_UUID, UUIDs.randomBase64UUID())
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
.build();
final MetaData metaData = MetaData.builder()
MetaData.Builder metaDataBuilder = MetaData.builder()
.put(IndexMetaData.builder(index1)
.settings(settings)
.putAlias(AliasMetaData.builder(alias))
.putAlias(AliasMetaData.builder(aliasWithMultipleIndices))
)
.put(IndexMetaData.builder(index2)
.settings(settings)
.putAlias(AliasMetaData.builder(aliasWithMultipleIndices))
).build();
.putAlias(AliasMetaData.builder(aliasWithWriteIndex))
.putAlias(AliasMetaData.builder(aliasWithNoWriteIndex).writeIndex(firstIsWriteIndex))
);
IndexMetaData.Builder indexTwoBuilder = IndexMetaData.builder(index2).settings(settings);
if (firstIsWriteIndex == null) {
indexTwoBuilder.putAlias(AliasMetaData.builder(aliasWithNoWriteIndex).writeIndex(randomFrom(false, null)));
}
metaDataBuilder.put(indexTwoBuilder);
MetaData metaData = metaDataBuilder.build();
expectThrows(IllegalArgumentException.class, () ->
TransportRolloverAction.validate(metaData, new RolloverRequest(aliasWithMultipleIndices,
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () ->
TransportRolloverAction.validate(metaData, new RolloverRequest(aliasWithNoWriteIndex,
randomAlphaOfLength(10))));
expectThrows(IllegalArgumentException.class, () ->
assertThat(exception.getMessage(), equalTo("source alias [" + aliasWithNoWriteIndex + "] does not point to a write index"));
exception = expectThrows(IllegalArgumentException.class, () ->
TransportRolloverAction.validate(metaData, new RolloverRequest(randomFrom(index1, index2),
randomAlphaOfLength(10))));
expectThrows(IllegalArgumentException.class, () ->
assertThat(exception.getMessage(), equalTo("source alias is a concrete index"));
exception = expectThrows(IllegalArgumentException.class, () ->
TransportRolloverAction.validate(metaData, new RolloverRequest(randomAlphaOfLength(5),
randomAlphaOfLength(10)))
);
TransportRolloverAction.validate(metaData, new RolloverRequest(alias, randomAlphaOfLength(10)));
assertThat(exception.getMessage(), equalTo("source alias does not exist"));
TransportRolloverAction.validate(metaData, new RolloverRequest(aliasWithWriteIndex, randomAlphaOfLength(10)));
}
public void testGenerateRolloverIndexName() {
@ -248,7 +284,7 @@ public class TransportRolloverActionTests extends ESTestCase {
public void testRejectDuplicateAlias() {
final IndexTemplateMetaData template = IndexTemplateMetaData.builder("test-template")
.patterns(Arrays.asList("foo-*", "bar-*"))
.putAlias(AliasMetaData.builder("foo-write")).putAlias(AliasMetaData.builder("bar-write"))
.putAlias(AliasMetaData.builder("foo-write")).putAlias(AliasMetaData.builder("bar-write").writeIndex(randomBoolean()))
.build();
final MetaData metaData = MetaData.builder().put(createMetaData(), false).put(template).build();
String indexName = randomFrom("foo-123", "bar-xyz");

View File

@ -131,7 +131,7 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e =
expectThrows(NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, checks, "testExceptionAggregation"));
() -> BootstrapChecks.check(defaultContext, true, checks));
assertThat(e, hasToString(allOf(containsString("bootstrap checks failed"), containsString("first"), containsString("second"))));
final Throwable[] suppressed = e.getSuppressed();
assertThat(suppressed.length, equalTo(2));
@ -162,7 +162,7 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e =
expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testHeapSizeCheck"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check)));
assertThat(
e.getMessage(),
containsString("initial heap size [" + initialHeapSize.get() + "] " +
@ -170,7 +170,7 @@ public class BootstrapChecksTests extends ESTestCase {
initialHeapSize.set(maxHeapSize.get());
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testHeapSizeCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
// nothing should happen if the initial heap size or the max
// heap size is not available
@ -179,7 +179,7 @@ public class BootstrapChecksTests extends ESTestCase {
} else {
maxHeapSize.set(0);
}
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testHeapSizeCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
}
public void testFileDescriptorLimits() throws NodeValidationException {
@ -205,17 +205,17 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e =
expectThrows(NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testFileDescriptorLimits"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check)));
assertThat(e.getMessage(), containsString("max file descriptors"));
maxFileDescriptorCount.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testFileDescriptorLimits");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
// nothing should happen if current file descriptor count is
// not available
maxFileDescriptorCount.set(-1);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testFileDescriptorLimits");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
}
public void testFileDescriptorLimitsThrowsOnInvalidLimit() {
@ -262,15 +262,13 @@ public class BootstrapChecksTests extends ESTestCase {
() -> BootstrapChecks.check(
bootstrapContext,
true,
Collections.singletonList(check),
"testFileDescriptorLimitsThrowsOnInvalidLimit"));
Collections.singletonList(check)));
assertThat(
e.getMessage(),
containsString("memory locking requested for elasticsearch process but memory is not locked"));
} else {
// nothing should happen
BootstrapChecks.check(bootstrapContext, true, Collections.singletonList(check),
"testFileDescriptorLimitsThrowsOnInvalidLimit");
BootstrapChecks.check(bootstrapContext, true, Collections.singletonList(check));
}
}
}
@ -287,17 +285,17 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check)));
assertThat(e.getMessage(), containsString("max number of threads"));
maxNumberOfThreads.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
// nothing should happen if current max number of threads is
// not available
maxNumberOfThreads.set(-1);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
}
public void testMaxSizeVirtualMemory() throws NodeValidationException {
@ -317,16 +315,16 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxSizeVirtualMemory"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check)));
assertThat(e.getMessage(), containsString("max size virtual memory"));
maxSizeVirtualMemory.set(rlimInfinity);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxSizeVirtualMemory");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
// nothing should happen if max size virtual memory is not available
maxSizeVirtualMemory.set(Long.MIN_VALUE);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxSizeVirtualMemory");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
}
public void testMaxFileSizeCheck() throws NodeValidationException {
@ -346,16 +344,16 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxFileSize"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check)));
assertThat(e.getMessage(), containsString("max file size"));
maxFileSize.set(rlimInfinity);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxFileSize");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
// nothing should happen if max file size is not available
maxFileSize.set(Long.MIN_VALUE);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxFileSize");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
}
public void testMaxMapCountCheck() throws NodeValidationException {
@ -370,17 +368,17 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxMapCountCheck"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check)));
assertThat(e.getMessage(), containsString("max virtual memory areas vm.max_map_count"));
maxMapCount.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxMapCountCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
// nothing should happen if current vm.max_map_count is not
// available
maxMapCount.set(-1);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxMapCountCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
}
public void testClientJvmCheck() throws NodeValidationException {
@ -394,14 +392,14 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testClientJvmCheck"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check)));
assertThat(
e.getMessage(),
containsString("JVM is using the client VM [Java HotSpot(TM) 32-Bit Client VM] " +
"but should be using a server VM for the best performance"));
vmName.set("Java HotSpot(TM) 32-Bit Server VM");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testClientJvmCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
}
public void testUseSerialGCCheck() throws NodeValidationException {
@ -415,14 +413,14 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testUseSerialGCCheck"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check)));
assertThat(
e.getMessage(),
containsString("JVM is using the serial collector but should not be for the best performance; " + "" +
"either it's the default for the VM [" + JvmInfo.jvmInfo().getVmName() +"] or -XX:+UseSerialGC was explicitly specified"));
useSerialGC.set("false");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testUseSerialGCCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
}
public void testSystemCallFilterCheck() throws NodeValidationException {
@ -439,15 +437,14 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(context, true, Collections.singletonList(systemCallFilterEnabledCheck),
"testSystemCallFilterCheck"));
() -> BootstrapChecks.check(context, true, Collections.singletonList(systemCallFilterEnabledCheck)));
assertThat(
e.getMessage(),
containsString("system call filters failed to install; " +
"check the logs and fix your configuration or disable system call filters at your own risk"));
isSystemCallFilterInstalled.set(true);
BootstrapChecks.check(context, true, Collections.singletonList(systemCallFilterEnabledCheck), "testSystemCallFilterCheck");
BootstrapChecks.check(context, true, Collections.singletonList(systemCallFilterEnabledCheck));
BootstrapContext context_1 = new BootstrapContext(Settings.builder().put("bootstrap.system_call_filter", false).build(), null);
final BootstrapChecks.SystemCallFilterCheck systemCallFilterNotEnabledCheck = new BootstrapChecks.SystemCallFilterCheck() {
@Override
@ -456,9 +453,9 @@ public class BootstrapChecksTests extends ESTestCase {
}
};
isSystemCallFilterInstalled.set(false);
BootstrapChecks.check(context_1, true, Collections.singletonList(systemCallFilterNotEnabledCheck), "testSystemCallFilterCheck");
BootstrapChecks.check(context_1, true, Collections.singletonList(systemCallFilterNotEnabledCheck));
isSystemCallFilterInstalled.set(true);
BootstrapChecks.check(context_1, true, Collections.singletonList(systemCallFilterNotEnabledCheck), "testSystemCallFilterCheck");
BootstrapChecks.check(context_1, true, Collections.singletonList(systemCallFilterNotEnabledCheck));
}
public void testMightForkCheck() throws NodeValidationException {
@ -553,8 +550,6 @@ public class BootstrapChecksTests extends ESTestCase {
final Runnable enableMightFork,
final Consumer<NodeValidationException> consumer) throws NodeValidationException {
final String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
// if system call filter is disabled, nothing should happen
isSystemCallFilterInstalled.set(false);
if (randomBoolean()) {
@ -562,13 +557,13 @@ public class BootstrapChecksTests extends ESTestCase {
} else {
enableMightFork.run();
}
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), methodName);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
// if system call filter is enabled, but we will not fork, nothing should
// happen
isSystemCallFilterInstalled.set(true);
disableMightFork.run();
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), methodName);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check));
// if system call filter is enabled, and we might fork, the check should be enforced, regardless of bootstrap checks being enabled
// or not
@ -577,7 +572,7 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, randomBoolean(), Collections.singletonList(check), methodName));
() -> BootstrapChecks.check(defaultContext, randomBoolean(), Collections.singletonList(check)));
consumer.accept(e);
}
@ -602,7 +597,7 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> {
BootstrapChecks.check(defaultContext, true, checks, "testEarlyAccessCheck");
BootstrapChecks.check(defaultContext, true, checks);
});
assertThat(
e.getMessage(),
@ -613,7 +608,7 @@ public class BootstrapChecksTests extends ESTestCase {
// if not on an early-access build, nothing should happen
javaVersion.set(randomFrom("1.8.0_152", "9"));
BootstrapChecks.check(defaultContext, true, checks, "testEarlyAccessCheck");
BootstrapChecks.check(defaultContext, true, checks);
}
@ -649,7 +644,7 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException e =
expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck), "testG1GCCheck"));
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck)));
assertThat(
e.getMessage(),
containsString(
@ -657,12 +652,12 @@ public class BootstrapChecksTests extends ESTestCase {
// if G1GC is disabled, nothing should happen
isG1GCEnabled.set(false);
BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck), "testG1GCCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck));
// if on or after update 40, nothing should happen independent of whether or not G1GC is enabled
isG1GCEnabled.set(randomBoolean());
jvmVersion.set(String.format(Locale.ROOT, "25.%d-b%d", randomIntBetween(40, 112), randomIntBetween(1, 128)));
BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck), "testG1GCCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck));
final BootstrapChecks.G1GCCheck nonOracleCheck = new BootstrapChecks.G1GCCheck() {
@ -674,7 +669,7 @@ public class BootstrapChecksTests extends ESTestCase {
};
// if not on an Oracle JVM, nothing should happen
BootstrapChecks.check(defaultContext, true, Collections.singletonList(nonOracleCheck), "testG1GCCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(nonOracleCheck));
final BootstrapChecks.G1GCCheck nonJava8Check = new BootstrapChecks.G1GCCheck() {
@ -686,7 +681,7 @@ public class BootstrapChecksTests extends ESTestCase {
};
// if not Java 8, nothing should happen
BootstrapChecks.check(defaultContext, true, Collections.singletonList(nonJava8Check), "testG1GCCheck");
BootstrapChecks.check(defaultContext, true, Collections.singletonList(nonJava8Check));
}
public void testAllPermissionCheck() throws NodeValidationException {
@ -701,12 +696,12 @@ public class BootstrapChecksTests extends ESTestCase {
final List<BootstrapCheck> checks = Collections.singletonList(allPermissionCheck);
final NodeValidationException e = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, true, checks, "testIsAllPermissionCheck"));
() -> BootstrapChecks.check(defaultContext, true, checks));
assertThat(e, hasToString(containsString("granting the all permission effectively disables security")));
// if all permissions are not granted, nothing should happen
isAllPermissionGranted.set(false);
BootstrapChecks.check(defaultContext, true, checks, "testIsAllPermissionCheck");
BootstrapChecks.check(defaultContext, true, checks);
}
public void testAlwaysEnforcedChecks() {
@ -724,7 +719,7 @@ public class BootstrapChecksTests extends ESTestCase {
final NodeValidationException alwaysEnforced = expectThrows(
NodeValidationException.class,
() -> BootstrapChecks.check(defaultContext, randomBoolean(), Collections.singletonList(check), "testAlwaysEnforcedChecks"));
() -> BootstrapChecks.check(defaultContext, randomBoolean(), Collections.singletonList(check)));
assertThat(alwaysEnforced, hasToString(containsString("error")));
}

View File

@ -65,7 +65,7 @@ public class ElasticsearchUncaughtExceptionHandlerTests extends ESTestCase {
final AtomicInteger observedStatus = new AtomicInteger();
final AtomicReference<String> threadNameReference = new AtomicReference<>();
final AtomicReference<Throwable> throwableReference = new AtomicReference<>();
thread.setUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler(() -> "testUncaughtError") {
thread.setUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler() {
@Override
void halt(int status) {
@ -106,7 +106,7 @@ public class ElasticsearchUncaughtExceptionHandlerTests extends ESTestCase {
thread.setName(name);
final AtomicReference<String> threadNameReference = new AtomicReference<>();
final AtomicReference<Throwable> throwableReference = new AtomicReference<>();
thread.setUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler(() -> "testUncaughtException") {
thread.setUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler() {
@Override
void halt(int status) {
fail();

View File

@ -143,4 +143,22 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
assertEquals("Hole lies outside shell at or near point (4.0, 3.0, NaN)", e.getMessage());
}
public void testWidePolygonWithConfusingOrientation() {
// A valid polygon that is oriented correctly (anticlockwise) but which
// confounds a naive algorithm for determining its orientation leading
// ES to believe that it crosses the dateline and "fixing" it in a way
// that self-intersects.
PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder()
.coordinate(10, -20).coordinate(100, 0).coordinate(-100, 0).coordinate(20, -45).coordinate(40, -60).close());
pb.build(); // Should not throw an exception
}
public void testPolygonWithUndefinedOrientationDueToCollinearPoints() {
PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder()
.coordinate(0.0, 0.0).coordinate(1.0, 1.0).coordinate(-1.0, -1.0).close());
InvalidShapeException e = expectThrows(InvalidShapeException.class, pb::build);
assertEquals("Cannot determine orientation: edges adjacent to (-1.0,-1.0) coincide", e.getMessage());
}
}

View File

@ -99,6 +99,15 @@ public class KeyStoreWrapperTests extends ESTestCase {
assertTrue(keystore.getSettingNames().contains(KeyStoreWrapper.SEED_SETTING.getKey()));
}
public void testDecryptKeyStoreWithWrongPassword() throws Exception {
KeyStoreWrapper keystore = KeyStoreWrapper.create();
keystore.save(env.configFile(), new char[0]);
final KeyStoreWrapper loadedkeystore = KeyStoreWrapper.load(env.configFile());
final SecurityException exception = expectThrows(SecurityException.class,
() -> loadedkeystore.decrypt(new char[]{'i', 'n', 'v', 'a', 'l', 'i', 'd'}));
assertThat(exception.getMessage(), containsString("Keystore has been corrupted or tampered with"));
}
public void testCannotReadStringFromClosedKeystore() throws Exception {
KeyStoreWrapper keystore = KeyStoreWrapper.create();
assertThat(keystore.getSettingNames(), Matchers.hasItem(KeyStoreWrapper.SEED_SETTING.getKey()));

View File

@ -2003,7 +2003,7 @@ public class InternalEngineTests extends EngineTestCase {
@Override
public void append(LogEvent event) {
final String formattedMessage = event.getMessage().getFormattedMessage();
if (event.getLevel() == Level.TRACE && event.getMarker().getName().contains("[index][0] ")) {
if (event.getLevel() == Level.TRACE && event.getMarker().getName().contains("[index][0]")) {
if (event.getLoggerName().endsWith(".IW") &&
formattedMessage.contains("IW: now apply all deletes")) {
sawIndexWriterMessage = true;

View File

@ -119,9 +119,10 @@ public class SearchHitTests extends ESTestCase {
hit.setInnerHits(innerHits);
}
if (randomBoolean()) {
String index = randomAlphaOfLengthBetween(5, 10);
String clusterAlias = randomBoolean() ? null : randomAlphaOfLengthBetween(5, 10);
hit.shard(new SearchShardTarget(randomAlphaOfLengthBetween(5, 10),
new ShardId(new Index(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 10)), randomInt()), null,
OriginalIndices.NONE));
new ShardId(new Index(index, randomAlphaOfLengthBetween(5, 10)), randomInt()), clusterAlias, OriginalIndices.NONE));
}
return hit;
}

View File

@ -20,8 +20,6 @@
package org.elasticsearch.search.aggregations.bucket.histogram;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.rounding.DateTimeUnit;
import org.elasticsearch.common.rounding.Rounding;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.InternalAggregations;
import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation;
@ -51,14 +49,6 @@ public class InternalAutoDateHistogramTests extends InternalMultiBucketAggregati
public void setUp() throws Exception {
super.setUp();
format = randomNumericDocValueFormat();
roundingInfos = new RoundingInfo[6];
roundingInfos[0] = new RoundingInfo(Rounding.builder(DateTimeUnit.SECOND_OF_MINUTE).build(), 1, 5, 10, 30);
roundingInfos[1] = new RoundingInfo(Rounding.builder(DateTimeUnit.MINUTES_OF_HOUR).build(), 1, 5, 10, 30);
roundingInfos[2] = new RoundingInfo(Rounding.builder(DateTimeUnit.HOUR_OF_DAY).build(), 1, 3, 12);
roundingInfos[3] = new RoundingInfo(Rounding.builder(DateTimeUnit.DAY_OF_MONTH).build(), 1, 7);
roundingInfos[4] = new RoundingInfo(Rounding.builder(DateTimeUnit.MONTH_OF_YEAR).build(), 1, 3);
roundingInfos[5] = new RoundingInfo(Rounding.builder(DateTimeUnit.YEAR_OF_CENTURY).build(), 1, 10, 20, 50, 100);
}
@Override
@ -66,6 +56,8 @@ public class InternalAutoDateHistogramTests extends InternalMultiBucketAggregati
List<PipelineAggregator> pipelineAggregators,
Map<String, Object> metaData,
InternalAggregations aggregations) {
roundingInfos = AutoDateHistogramAggregationBuilder.buildRoundings(null);
int nbBuckets = randomNumberOfBuckets();
int targetBuckets = randomIntBetween(1, nbBuckets * 2 + 1);
List<InternalAutoDateHistogram.Bucket> buckets = new ArrayList<>(nbBuckets);
@ -81,6 +73,7 @@ public class InternalAutoDateHistogramTests extends InternalMultiBucketAggregati
InternalAggregations subAggregations = new InternalAggregations(Collections.emptyList());
BucketInfo bucketInfo = new BucketInfo(roundingInfos, randomIntBetween(0, roundingInfos.length - 1), subAggregations);
return new InternalAutoDateHistogram(name, buckets, targetBuckets, bucketInfo, format, pipelineAggregators, metaData);
}
@ -92,13 +85,50 @@ public class InternalAutoDateHistogramTests extends InternalMultiBucketAggregati
roundingIdx = histogram.getBucketInfo().roundingIdx;
}
}
Map<Long, Long> expectedCounts = new TreeMap<>();
for (Histogram histogram : inputs) {
RoundingInfo roundingInfo = roundingInfos[roundingIdx];
long lowest = Long.MAX_VALUE;
long highest = 0;
for (InternalAutoDateHistogram histogram : inputs) {
for (Histogram.Bucket bucket : histogram.getBuckets()) {
expectedCounts.compute(roundingInfos[roundingIdx].rounding.round(((DateTime) bucket.getKey()).getMillis()),
(key, oldValue) -> (oldValue == null ? 0 : oldValue) + bucket.getDocCount());
long bucketKey = ((DateTime) bucket.getKey()).getMillis();
if (bucketKey < lowest) {
lowest = bucketKey;
}
if (bucketKey > highest) {
highest = bucketKey;
}
}
}
long normalizedDuration = (highest - lowest) / roundingInfo.getRoughEstimateDurationMillis();
long innerIntervalToUse = 0;
for (int interval : roundingInfo.innerIntervals) {
if (normalizedDuration / interval < maxNumberOfBuckets()) {
innerIntervalToUse = interval;
}
}
Map<Long, Long> expectedCounts = new TreeMap<>();
long intervalInMillis = innerIntervalToUse*roundingInfo.getRoughEstimateDurationMillis();
for (long keyForBucket = roundingInfo.rounding.round(lowest);
keyForBucket <= highest;
keyForBucket = keyForBucket + intervalInMillis) {
expectedCounts.put(keyForBucket, 0L);
for (InternalAutoDateHistogram histogram : inputs) {
for (Histogram.Bucket bucket : histogram.getBuckets()) {
long bucketKey = ((DateTime) bucket.getKey()).getMillis();
long roundedBucketKey = roundingInfo.rounding.round(bucketKey);
if (roundedBucketKey >= keyForBucket
&& roundedBucketKey < keyForBucket + intervalInMillis) {
long count = bucket.getDocCount();
expectedCounts.compute(keyForBucket,
(key, oldValue) -> (oldValue == null ? 0 : oldValue) + count);
}
}
}
}
Map<Long, Long> actualCounts = new TreeMap<>();
for (Histogram.Bucket bucket : reduced.getBuckets()) {
actualCounts.compute(((DateTime) bucket.getKey()).getMillis(),
@ -117,12 +147,6 @@ public class InternalAutoDateHistogramTests extends InternalMultiBucketAggregati
return ParsedAutoDateHistogram.class;
}
@Override
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/32215")
public void testReduceRandom() {
super.testReduceRandom();
}
@Override
protected InternalAutoDateHistogram mutateInstance(InternalAutoDateHistogram instance) {
String name = instance.getName();

View File

@ -105,6 +105,7 @@ public class QueryProfilerIT extends ESIntegTestCase {
* search for each query. It then does some basic sanity checking of score and hits
* to make sure the profiling doesn't interfere with the hits being returned
*/
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/32492")
public void testProfileMatchesRegular() throws Exception {
createIndex("test");
ensureGreen();

View File

@ -0,0 +1,111 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.common.logging;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternConverter;
import org.elasticsearch.test.ESIntegTestCase;
/**
* Converts {@code %test_thread_info} in log4j patterns into information
* based on the loggin thread's name. If that thread is part of an
* {@link ESIntegTestCase} then this information is the node name.
*/
@Plugin(category = PatternConverter.CATEGORY, name = "TestInfoPatternConverter")
@ConverterKeys({"test_thread_info"})
public class TestThreadInfoPatternConverter extends LogEventPatternConverter {
/**
* Called by log4j2 to initialize this converter.
*/
public static TestThreadInfoPatternConverter newInstance(final String[] options) {
if (options.length > 0) {
throw new IllegalArgumentException("no options supported but options provided: "
+ Arrays.toString(options));
}
return new TestThreadInfoPatternConverter();
}
private TestThreadInfoPatternConverter() {
super("TestInfo", "test_thread_info");
}
@Override
public void format(LogEvent event, StringBuilder toAppendTo) {
toAppendTo.append(threadInfo(event.getThreadName()));
}
private static final Pattern ELASTICSEARCH_THREAD_NAME_PATTERN =
Pattern.compile("elasticsearch\\[(.+)\\]\\[.+\\].+");
private static final Pattern TEST_THREAD_NAME_PATTERN =
Pattern.compile("TEST-.+\\.(.+)-seed#\\[.+\\]");
private static final Pattern TEST_SUITE_INIT_THREAD_NAME_PATTERN =
Pattern.compile("SUITE-.+-worker");
private static final Pattern NOT_YET_NAMED_NODE_THREAD_NAME_PATTERN =
Pattern.compile("test_SUITE-CHILD_VM.+cluster\\[T#(.+)\\]");
static String threadInfo(String threadName) {
Matcher m = ELASTICSEARCH_THREAD_NAME_PATTERN.matcher(threadName);
if (m.matches()) {
// Thread looks like a node thread so use the node name
return m.group(1);
}
m = TEST_THREAD_NAME_PATTERN.matcher(threadName);
if (m.matches()) {
/*
* Thread looks like a test thread so use the test method name.
* It'd be pretty reasonable not to use a prefix at all here but
* the logger layout pretty much expects one and the test method
* can be pretty nice to have around anyway.
*/
return m.group(1);
}
m = TEST_SUITE_INIT_THREAD_NAME_PATTERN.matcher(threadName);
if (m.matches()) {
/*
* Thread looks like test suite initialization or tead down and
* we don't have any more information to give. Like above, we
* could spit out nothing here but the logger layout expect
* something and it *is* nice to know what lines come from test
* teardown and initialization.
*/
return "suite";
}
m = NOT_YET_NAMED_NODE_THREAD_NAME_PATTERN.matcher(threadName);
if (m.matches()) {
/*
* These are as yet unnamed integ test nodes. I'd prefer to log
* the node name but I don't have it yet.
*/
return "integ_" + m.group(1) + "";
}
/*
* These are uncategorized threads. We log the entire thread name in
* case it is useful. We wrap it in `[]` so you tell that it is a
* thread name rather than a node name or something.
*/
return "[" + threadName + "]";
}
}

View File

@ -65,6 +65,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.Streamable;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.LogConfigurator;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
@ -200,6 +201,8 @@ public abstract class ESTestCase extends LuceneTestCase {
System.setProperty("log4j.shutdownHookEnabled", "false");
System.setProperty("log4j2.disable.jmx", "true");
LogConfigurator.loadLog4jPlugins();
// Enable Netty leak detection and monitor logger for logged leak errors
System.setProperty("io.netty.leakDetection.level", "paranoid");
String leakLoggerName = "io.netty.util.ResourceLeakDetector";
@ -321,7 +324,7 @@ public abstract class ESTestCase extends LuceneTestCase {
@Before
public final void before() {
logger.info("[{}]: before test", getTestName());
logger.info("{}before test", getTestParamsForLogging());
assertNull("Thread context initialized twice", threadContext);
if (enableWarningsCheck()) {
this.threadContext = new ThreadContext(Settings.EMPTY);
@ -350,7 +353,16 @@ public abstract class ESTestCase extends LuceneTestCase {
}
ensureAllSearchContextsReleased();
ensureCheckIndexPassed();
logger.info("[{}]: after test", getTestName());
logger.info("{}after test", getTestParamsForLogging());
}
private String getTestParamsForLogging() {
String name = getTestName();
int start = name.indexOf('{');
if (start < 0) return "";
int end = name.lastIndexOf('}');
if (end < 0) return "";
return "[" + name.substring(start + 1, end) + "] ";
}
private void ensureNoWarnings() throws IOException {

View File

@ -1,7 +1,7 @@
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%test_thread_info]%marker %m%n
rootLogger.level = ${sys:tests.es.logger.level:-info}
rootLogger.appenderRef.console.ref = console

View File

@ -0,0 +1,9 @@
# RandomizedRunner renames threads and we'd like to look at accurate thread
# names. Also, this is the default in log4j2's master branch for versions of
# Java after 1.8_102 which most of the versions we use are anyway. After that
# version of Java calling `Thread.getName()` doesn't allocate so UNCACHED
# ought to be faster than CACHED because it doesn't have to deal with
# ThreadLocals.
# While we don't use AsyncLogger, we do end up with mutable log events and
# those use this key for configuration.
AsyncLogger.ThreadNameStrategy = UNCACHED

View File

@ -0,0 +1,53 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.common.logging;
import org.elasticsearch.common.util.concurrent.EsExecutors;
import org.elasticsearch.test.ESTestCase;
import org.junit.BeforeClass;
import static org.elasticsearch.common.logging.TestThreadInfoPatternConverter.threadInfo;
public class TestThreadInfoPatternConverterTests extends ESTestCase {
private static String suiteInfo;
@BeforeClass
public static void captureSuiteInfo() {
suiteInfo = threadInfo(Thread.currentThread().getName());
}
public void testThreadInfo() {
// Threads that are part of a node get the node name
String nodeName = randomAlphaOfLength(5);
String threadName = EsExecutors.threadName(nodeName, randomAlphaOfLength(20))
+ "[T#" + between(0, 1000) + "]";
assertEquals(nodeName, threadInfo(threadName));
// Test threads get the test name
assertEquals(getTestName(), threadInfo(Thread.currentThread().getName()));
// Suite initalization gets "suite"
assertEquals("suite", suiteInfo);
// And stuff that doesn't match anything gets wrapped in [] so we can see it
String unmatched = randomAlphaOfLength(5);
assertEquals("[" + unmatched + "]", threadInfo(unmatched));
}
}

View File

@ -50,7 +50,7 @@ public final class GetPrivilegesRequest extends ActionRequest implements Applica
@Override
public Collection<String> getApplicationNames() {
return Collections.singleton(application);
return application == null ? Collections.emptySet() : Collections.singleton(application);
}
public void privileges(String... privileges) {

View File

@ -135,7 +135,9 @@ public final class ConditionalClusterPrivileges {
this.requestPredicate = request -> {
if (request instanceof ApplicationPrivilegesRequest) {
final ApplicationPrivilegesRequest privRequest = (ApplicationPrivilegesRequest) request;
return privRequest.getApplicationNames().stream().allMatch(application -> applicationPredicate.test(application));
final Collection<String> requestApplicationNames = privRequest.getApplicationNames();
return requestApplicationNames.isEmpty() ? this.applicationNames.contains("*")
: requestApplicationNames.stream().allMatch(application -> applicationPredicate.test(application));
}
return false;
};

View File

@ -19,9 +19,9 @@ import org.elasticsearch.xpack.core.watcher.transport.actions.activate.ActivateW
import org.elasticsearch.xpack.core.watcher.transport.actions.activate.ActivateWatchRequestBuilder;
import org.elasticsearch.xpack.core.watcher.transport.actions.activate.ActivateWatchResponse;
import org.elasticsearch.xpack.core.watcher.transport.actions.delete.DeleteWatchAction;
import org.elasticsearch.xpack.core.watcher.transport.actions.delete.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.xpack.core.watcher.transport.actions.delete.DeleteWatchRequestBuilder;
import org.elasticsearch.xpack.core.watcher.transport.actions.delete.DeleteWatchResponse;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchResponse;
import org.elasticsearch.xpack.core.watcher.transport.actions.execute.ExecuteWatchAction;
import org.elasticsearch.xpack.core.watcher.transport.actions.execute.ExecuteWatchRequest;
import org.elasticsearch.xpack.core.watcher.transport.actions.execute.ExecuteWatchRequestBuilder;

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.core.watcher.transport.actions.delete;
import org.elasticsearch.action.Action;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchResponse;
/**
* This action deletes an watch from in memory, the scheduler and the index

View File

@ -7,6 +7,8 @@ package org.elasticsearch.xpack.core.watcher.transport.actions.delete;
import org.elasticsearch.action.ActionRequestBuilder;
import org.elasticsearch.client.ElasticsearchClient;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchResponse;
/**
* A delete document action request builder.

View File

@ -1,56 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.core.watcher.transport.actions.delete;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
public class DeleteWatchResponse extends ActionResponse {
private String id;
private long version;
private boolean found;
public DeleteWatchResponse() {
}
public DeleteWatchResponse(String id, long version, boolean found) {
this.id = id;
this.version = version;
this.found = found;
}
public String getId() {
return id;
}
public long getVersion() {
return version;
}
public boolean isFound() {
return found;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
id = in.readString();
version = in.readVLong();
found = in.readBoolean();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeString(id);
out.writeVLong(version);
out.writeBoolean(found);
}
}

View File

@ -50,6 +50,7 @@ import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
public class ManageApplicationPrivilegesTests extends ESTestCase {
@ -140,6 +141,19 @@ public class ManageApplicationPrivilegesTests extends ESTestCase {
assertThat(cloudAndSwiftypePredicate, not(predicateMatches(putKibana)));
}
public void testSecurityForGetAllApplicationPrivileges() {
final GetPrivilegesRequest getAll = new GetPrivilegesRequest();
getAll.application(null);
getAll.privileges(new String[0]);
assertThat(getAll.validate(), nullValue());
final ManageApplicationPrivileges kibanaOnly = new ManageApplicationPrivileges(Sets.newHashSet("kibana-*"));
final ManageApplicationPrivileges allApps = new ManageApplicationPrivileges(Sets.newHashSet("*"));
assertThat(kibanaOnly.getRequestPredicate(), not(predicateMatches(getAll)));
assertThat(allApps.getRequestPredicate(), predicateMatches(getAll));
}
private ManageApplicationPrivileges clone(ManageApplicationPrivileges original) {
return new ManageApplicationPrivileges(new LinkedHashSet<>(original.getApplicationNames()));

View File

@ -46,7 +46,7 @@ import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.core.monitoring.exporter.MonitoringTemplateUtils;
import org.elasticsearch.xpack.core.watcher.client.WatcherClient;
import org.elasticsearch.xpack.core.watcher.transport.actions.delete.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.xpack.core.watcher.transport.actions.get.GetWatchRequest;
import org.elasticsearch.xpack.core.watcher.transport.actions.get.GetWatchResponse;
import org.elasticsearch.xpack.core.watcher.watch.Watch;

View File

@ -176,7 +176,6 @@ import org.elasticsearch.xpack.security.authc.Realms;
import org.elasticsearch.xpack.security.authc.TokenService;
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
import org.elasticsearch.xpack.security.authc.kerberos.KerberosRealmBootstrapCheck;
import org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.SecuritySearchOperationListener;
@ -306,8 +305,7 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
new PasswordHashingAlgorithmBootstrapCheck(),
new FIPS140SecureSettingsBootstrapCheck(settings, env),
new FIPS140JKSKeystoreBootstrapCheck(settings),
new FIPS140PasswordHashingAlgorithmBootstrapCheck(settings),
new KerberosRealmBootstrapCheck(env)));
new FIPS140PasswordHashingAlgorithmBootstrapCheck(settings)));
checks.addAll(InternalRealms.getBootstrapChecks(settings, env));
this.bootstrapChecks = Collections.unmodifiableList(checks);
Automatons.updateMaxDeterminizedStates(settings);

Some files were not shown because too many files have changed in this diff Show More