Merge remote-tracking branch 'es/master' into feature/ingest

This commit is contained in:
Martijn van Groningen 2016-01-13 15:51:14 +01:00
commit 5e185befa8
59 changed files with 1535 additions and 898 deletions

View File

@ -23,6 +23,8 @@ import org.gradle.api.Project
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.Input import org.gradle.api.tasks.Input
import java.time.LocalDateTime
/** Configuration for an elasticsearch cluster, used for integration tests. */ /** Configuration for an elasticsearch cluster, used for integration tests. */
class ClusterConfiguration { class ClusterConfiguration {
@ -55,6 +57,7 @@ class ClusterConfiguration {
@Input @Input
Closure waitCondition = { NodeInfo node, AntBuilder ant -> Closure waitCondition = { NodeInfo node, AntBuilder ant ->
File tmpFile = new File(node.cwd, 'wait.success') File tmpFile = new File(node.cwd, 'wait.success')
ant.echo(message: "[${LocalDateTime.now()}] Waiting for elasticsearch node", level: "info")
ant.get(src: "http://${node.httpUri()}", ant.get(src: "http://${node.httpUri()}",
dest: tmpFile.toString(), dest: tmpFile.toString(),
ignoreerrors: true, // do not fail on error, so logging buffers can be flushed by the wait task ignoreerrors: true, // do not fail on error, so logging buffers can be flushed by the wait task

View File

@ -28,13 +28,13 @@ import java.io.IOException;
/** /**
* *
*/ */
public abstract class ActionRequest<T extends ActionRequest> extends TransportRequest { public abstract class ActionRequest<Request extends ActionRequest<Request>> extends TransportRequest {
public ActionRequest() { public ActionRequest() {
super(); super();
} }
protected ActionRequest(ActionRequest request) { protected ActionRequest(ActionRequest<?> request) {
super(request); super(request);
// this does not set the listenerThreaded API, if needed, its up to the caller to set it // this does not set the listenerThreaded API, if needed, its up to the caller to set it
// since most times, we actually want it to not be threaded... // since most times, we actually want it to not be threaded...

View File

@ -146,7 +146,7 @@ public class TransportNodesSnapshotsStatus extends TransportNodesAction<Transpor
public Request() { public Request() {
} }
public Request(ActionRequest request, String[] nodesIds) { public Request(ActionRequest<?> request, String[] nodesIds) {
super(request, nodesIds); super(request, nodesIds);
} }
@ -180,6 +180,7 @@ public class TransportNodesSnapshotsStatus extends TransportNodesAction<Transpor
this.failures = failures; this.failures = failures;
} }
@Override
public FailedNodeException[] failures() { public FailedNodeException[] failures() {
return failures; return failures;
} }

View File

@ -31,7 +31,7 @@ import java.io.IOException;
/** /**
* *
*/ */
public class BroadcastRequest<T extends BroadcastRequest> extends ActionRequest<T> implements IndicesRequest.Replaceable { public class BroadcastRequest<Request extends BroadcastRequest<Request>> extends ActionRequest<Request> implements IndicesRequest.Replaceable {
protected String[] indices; protected String[] indices;
private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpenAndForbidClosed(); private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpenAndForbidClosed();
@ -40,7 +40,7 @@ public class BroadcastRequest<T extends BroadcastRequest> extends ActionRequest<
} }
protected BroadcastRequest(ActionRequest originalRequest) { protected BroadcastRequest(ActionRequest<?> originalRequest) {
super(originalRequest); super(originalRequest);
} }
@ -55,9 +55,9 @@ public class BroadcastRequest<T extends BroadcastRequest> extends ActionRequest<
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public final T indices(String... indices) { public final Request indices(String... indices) {
this.indices = indices; this.indices = indices;
return (T) this; return (Request) this;
} }
@Override @Override
@ -71,9 +71,9 @@ public class BroadcastRequest<T extends BroadcastRequest> extends ActionRequest<
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T indicesOptions(IndicesOptions indicesOptions) { public final Request indicesOptions(IndicesOptions indicesOptions) {
this.indicesOptions = indicesOptions; this.indicesOptions = indicesOptions;
return (T) this; return (Request) this;
} }
@Override @Override

View File

@ -33,7 +33,7 @@ import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
* Abstract class that allows to mark action requests that support acknowledgements. * Abstract class that allows to mark action requests that support acknowledgements.
* Facilitates consistency across different api. * Facilitates consistency across different api.
*/ */
public abstract class AcknowledgedRequest<T extends MasterNodeRequest> extends MasterNodeRequest<T> implements AckedRequest { public abstract class AcknowledgedRequest<Request extends MasterNodeRequest<Request>> extends MasterNodeRequest<Request> implements AckedRequest {
public static final TimeValue DEFAULT_ACK_TIMEOUT = timeValueSeconds(30); public static final TimeValue DEFAULT_ACK_TIMEOUT = timeValueSeconds(30);
@ -42,7 +42,7 @@ public abstract class AcknowledgedRequest<T extends MasterNodeRequest> extends M
protected AcknowledgedRequest() { protected AcknowledgedRequest() {
} }
protected AcknowledgedRequest(ActionRequest request) { protected AcknowledgedRequest(ActionRequest<?> request) {
super(request); super(request);
} }
@ -52,9 +52,9 @@ public abstract class AcknowledgedRequest<T extends MasterNodeRequest> extends M
* @return the request itself * @return the request itself
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T timeout(String timeout) { public final Request timeout(String timeout) {
this.timeout = TimeValue.parseTimeValue(timeout, this.timeout, getClass().getSimpleName() + ".timeout"); this.timeout = TimeValue.parseTimeValue(timeout, this.timeout, getClass().getSimpleName() + ".timeout");
return (T)this; return (Request)this;
} }
/** /**
@ -63,9 +63,9 @@ public abstract class AcknowledgedRequest<T extends MasterNodeRequest> extends M
* @return the request itself * @return the request itself
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T timeout(TimeValue timeout) { public final Request timeout(TimeValue timeout) {
this.timeout = timeout; this.timeout = timeout;
return (T) this; return (Request) this;
} }
/** /**

View File

@ -27,14 +27,14 @@ import java.io.IOException;
/** /**
* Base request for master based read operations that allows to read the cluster state from the local node if needed * Base request for master based read operations that allows to read the cluster state from the local node if needed
*/ */
public abstract class MasterNodeReadRequest<T extends MasterNodeReadRequest> extends MasterNodeRequest<T> { public abstract class MasterNodeReadRequest<Request extends MasterNodeReadRequest<Request>> extends MasterNodeRequest<Request> {
protected boolean local = false; protected boolean local = false;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T local(boolean local) { public final Request local(boolean local) {
this.local = local; this.local = local;
return (T) this; return (Request) this;
} }
public final boolean local() { public final boolean local() {

View File

@ -29,7 +29,7 @@ import java.io.IOException;
/** /**
* A based request for master based operation. * A based request for master based operation.
*/ */
public abstract class MasterNodeRequest<T extends MasterNodeRequest> extends ActionRequest<T> { public abstract class MasterNodeRequest<Request extends MasterNodeRequest<Request>> extends ActionRequest<Request> {
public static final TimeValue DEFAULT_MASTER_NODE_TIMEOUT = TimeValue.timeValueSeconds(30); public static final TimeValue DEFAULT_MASTER_NODE_TIMEOUT = TimeValue.timeValueSeconds(30);
@ -39,7 +39,7 @@ public abstract class MasterNodeRequest<T extends MasterNodeRequest> extends Act
} }
protected MasterNodeRequest(ActionRequest request) { protected MasterNodeRequest(ActionRequest<?> request) {
super(request); super(request);
} }
@ -47,15 +47,15 @@ public abstract class MasterNodeRequest<T extends MasterNodeRequest> extends Act
* A timeout value in case the master has not been discovered yet or disconnected. * A timeout value in case the master has not been discovered yet or disconnected.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T masterNodeTimeout(TimeValue timeout) { public final Request masterNodeTimeout(TimeValue timeout) {
this.masterNodeTimeout = timeout; this.masterNodeTimeout = timeout;
return (T) this; return (Request) this;
} }
/** /**
* A timeout value in case the master has not been discovered yet or disconnected. * A timeout value in case the master has not been discovered yet or disconnected.
*/ */
public final T masterNodeTimeout(String timeout) { public final Request masterNodeTimeout(String timeout) {
return masterNodeTimeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".masterNodeTimeout")); return masterNodeTimeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".masterNodeTimeout"));
} }

View File

@ -30,30 +30,30 @@ import java.io.IOException;
/** /**
*/ */
public abstract class ClusterInfoRequest<T extends ClusterInfoRequest> extends MasterNodeReadRequest<T> implements IndicesRequest.Replaceable { public abstract class ClusterInfoRequest<Request extends ClusterInfoRequest<Request>> extends MasterNodeReadRequest<Request> implements IndicesRequest.Replaceable {
private String[] indices = Strings.EMPTY_ARRAY; private String[] indices = Strings.EMPTY_ARRAY;
private String[] types = Strings.EMPTY_ARRAY; private String[] types = Strings.EMPTY_ARRAY;
private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpen(); private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpen();
@SuppressWarnings("unchecked")
@Override @Override
public T indices(String... indices) { @SuppressWarnings("unchecked")
public Request indices(String... indices) {
this.indices = indices; this.indices = indices;
return (T) this; return (Request) this;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T types(String... types) { public Request types(String... types) {
this.types = types; this.types = types;
return (T) this; return (Request) this;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T indicesOptions(IndicesOptions indicesOptions) { public Request indicesOptions(IndicesOptions indicesOptions) {
this.indicesOptions = indicesOptions; this.indicesOptions = indicesOptions;
return (T) this; return (Request) this;
} }
@Override @Override

View File

@ -31,7 +31,7 @@ import java.io.IOException;
/** /**
* *
*/ */
public abstract class BaseNodesRequest<T extends BaseNodesRequest> extends ActionRequest<T> { public abstract class BaseNodesRequest<Request extends BaseNodesRequest<Request>> extends ActionRequest<Request> {
public static String[] ALL_NODES = Strings.EMPTY_ARRAY; public static String[] ALL_NODES = Strings.EMPTY_ARRAY;
@ -43,7 +43,7 @@ public abstract class BaseNodesRequest<T extends BaseNodesRequest> extends Actio
} }
protected BaseNodesRequest(ActionRequest request, String... nodesIds) { protected BaseNodesRequest(ActionRequest<?> request, String... nodesIds) {
super(request); super(request);
this.nodesIds = nodesIds; this.nodesIds = nodesIds;
} }
@ -57,9 +57,9 @@ public abstract class BaseNodesRequest<T extends BaseNodesRequest> extends Actio
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T nodesIds(String... nodesIds) { public final Request nodesIds(String... nodesIds) {
this.nodesIds = nodesIds; this.nodesIds = nodesIds;
return (T) this; return (Request) this;
} }
public TimeValue timeout() { public TimeValue timeout() {
@ -67,15 +67,15 @@ public abstract class BaseNodesRequest<T extends BaseNodesRequest> extends Actio
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T timeout(TimeValue timeout) { public final Request timeout(TimeValue timeout) {
this.timeout = timeout; this.timeout = timeout;
return (T) this; return (Request) this;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T timeout(String timeout) { public final Request timeout(String timeout) {
this.timeout = TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout"); this.timeout = TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout");
return (T) this; return (Request) this;
} }
@Override @Override

View File

@ -38,7 +38,7 @@ import static org.elasticsearch.action.ValidateActions.addValidationError;
/** /**
* *
*/ */
public class ReplicationRequest<T extends ReplicationRequest> extends ActionRequest<T> implements IndicesRequest { public class ReplicationRequest<Request extends ReplicationRequest<Request>> extends ActionRequest<Request> implements IndicesRequest {
public static final TimeValue DEFAULT_TIMEOUT = new TimeValue(1, TimeUnit.MINUTES); public static final TimeValue DEFAULT_TIMEOUT = new TimeValue(1, TimeUnit.MINUTES);
@ -61,14 +61,14 @@ public class ReplicationRequest<T extends ReplicationRequest> extends ActionRequ
/** /**
* Creates a new request that inherits headers and context from the request provided as argument. * Creates a new request that inherits headers and context from the request provided as argument.
*/ */
public ReplicationRequest(ActionRequest request) { public ReplicationRequest(ActionRequest<?> request) {
super(request); super(request);
} }
/** /**
* Creates a new request with resolved shard id * Creates a new request with resolved shard id
*/ */
public ReplicationRequest(ActionRequest request, ShardId shardId) { public ReplicationRequest(ActionRequest<?> request, ShardId shardId) {
super(request); super(request);
this.index = shardId.getIndex(); this.index = shardId.getIndex();
this.shardId = shardId; this.shardId = shardId;
@ -77,7 +77,7 @@ public class ReplicationRequest<T extends ReplicationRequest> extends ActionRequ
/** /**
* Copy constructor that creates a new request that is a copy of the one provided as an argument. * Copy constructor that creates a new request that is a copy of the one provided as an argument.
*/ */
protected ReplicationRequest(T request) { protected ReplicationRequest(Request request) {
this(request, request); this(request, request);
} }
@ -85,7 +85,7 @@ public class ReplicationRequest<T extends ReplicationRequest> extends ActionRequ
* Copy constructor that creates a new request that is a copy of the one provided as an argument. * Copy constructor that creates a new request that is a copy of the one provided as an argument.
* The new request will inherit though headers and context from the original request that caused it. * The new request will inherit though headers and context from the original request that caused it.
*/ */
protected ReplicationRequest(T request, ActionRequest originalRequest) { protected ReplicationRequest(Request request, ActionRequest<?> originalRequest) {
super(originalRequest); super(originalRequest);
this.timeout = request.timeout(); this.timeout = request.timeout();
this.index = request.index(); this.index = request.index();
@ -96,15 +96,15 @@ public class ReplicationRequest<T extends ReplicationRequest> extends ActionRequ
* A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>. * A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T timeout(TimeValue timeout) { public final Request timeout(TimeValue timeout) {
this.timeout = timeout; this.timeout = timeout;
return (T) this; return (Request) this;
} }
/** /**
* A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>. * A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>.
*/ */
public final T timeout(String timeout) { public final Request timeout(String timeout) {
return timeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout")); return timeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout"));
} }
@ -117,9 +117,9 @@ public class ReplicationRequest<T extends ReplicationRequest> extends ActionRequ
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T index(String index) { public final Request index(String index) {
this.index = index; this.index = index;
return (T) this; return (Request) this;
} }
@Override @Override
@ -150,9 +150,9 @@ public class ReplicationRequest<T extends ReplicationRequest> extends ActionRequ
* Sets the consistency level of write. Defaults to {@link org.elasticsearch.action.WriteConsistencyLevel#DEFAULT} * Sets the consistency level of write. Defaults to {@link org.elasticsearch.action.WriteConsistencyLevel#DEFAULT}
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T consistencyLevel(WriteConsistencyLevel consistencyLevel) { public final Request consistencyLevel(WriteConsistencyLevel consistencyLevel) {
this.consistencyLevel = consistencyLevel; this.consistencyLevel = consistencyLevel;
return (T) this; return (Request) this;
} }
@Override @Override
@ -195,9 +195,10 @@ public class ReplicationRequest<T extends ReplicationRequest> extends ActionRequ
* Sets the target shard id for the request. The shard id is set when a * Sets the target shard id for the request. The shard id is set when a
* index/delete request is resolved by the transport action * index/delete request is resolved by the transport action
*/ */
public T setShardId(ShardId shardId) { @SuppressWarnings("unchecked")
public Request setShardId(ShardId shardId) {
this.shardId = shardId; this.shardId = shardId;
return (T) this; return (Request) this;
} }
@Override @Override

View File

@ -34,7 +34,8 @@ import java.util.concurrent.TimeUnit;
/** /**
* *
*/ */
public abstract class InstanceShardOperationRequest<T extends InstanceShardOperationRequest> extends ActionRequest<T> implements IndicesRequest { public abstract class InstanceShardOperationRequest<Request extends InstanceShardOperationRequest<Request>> extends ActionRequest<Request>
implements IndicesRequest {
public static final TimeValue DEFAULT_TIMEOUT = new TimeValue(1, TimeUnit.MINUTES); public static final TimeValue DEFAULT_TIMEOUT = new TimeValue(1, TimeUnit.MINUTES);
@ -77,9 +78,9 @@ public abstract class InstanceShardOperationRequest<T extends InstanceShardOpera
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T index(String index) { public final Request index(String index) {
this.index = index; this.index = index;
return (T) this; return (Request) this;
} }
public TimeValue timeout() { public TimeValue timeout() {
@ -90,15 +91,15 @@ public abstract class InstanceShardOperationRequest<T extends InstanceShardOpera
* A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>. * A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T timeout(TimeValue timeout) { public final Request timeout(TimeValue timeout) {
this.timeout = timeout; this.timeout = timeout;
return (T) this; return (Request) this;
} }
/** /**
* A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>. * A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>.
*/ */
public final T timeout(String timeout) { public final Request timeout(String timeout) {
return timeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout")); return timeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout"));
} }

View File

@ -34,7 +34,7 @@ import java.io.IOException;
/** /**
* *
*/ */
public abstract class SingleShardRequest<T extends SingleShardRequest> extends ActionRequest<T> implements IndicesRequest { public abstract class SingleShardRequest<Request extends SingleShardRequest<Request>> extends ActionRequest<Request> implements IndicesRequest {
public static final IndicesOptions INDICES_OPTIONS = IndicesOptions.strictSingleIndexNoExpandForbidClosed(); public static final IndicesOptions INDICES_OPTIONS = IndicesOptions.strictSingleIndexNoExpandForbidClosed();
@ -56,11 +56,11 @@ public abstract class SingleShardRequest<T extends SingleShardRequest> extends A
this.index = index; this.index = index;
} }
protected SingleShardRequest(ActionRequest request) { protected SingleShardRequest(ActionRequest<?> request) {
super(request); super(request);
} }
protected SingleShardRequest(ActionRequest request, String index) { protected SingleShardRequest(ActionRequest<?> request, String index) {
super(request); super(request);
this.index = index; this.index = index;
} }
@ -91,9 +91,9 @@ public abstract class SingleShardRequest<T extends SingleShardRequest> extends A
* Sets the index. * Sets the index.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T index(String index) { public final Request index(String index) {
this.index = index; this.index = index;
return (T) this; return (Request) this;
} }
@Override @Override
@ -117,9 +117,9 @@ public abstract class SingleShardRequest<T extends SingleShardRequest> extends A
* Controls if the operation will be executed on a separate thread when executed locally. * Controls if the operation will be executed on a separate thread when executed locally.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T operationThreaded(boolean threadedOperation) { public final Request operationThreaded(boolean threadedOperation) {
this.threadedOperation = threadedOperation; this.threadedOperation = threadedOperation;
return (T) this; return (Request) this;
} }
@Override @Override

View File

@ -34,7 +34,7 @@ import java.io.IOException;
/** /**
* A base class for task requests * A base class for task requests
*/ */
public class BaseTasksRequest<T extends BaseTasksRequest> extends ActionRequest<T> { public class BaseTasksRequest<Request extends BaseTasksRequest<Request>> extends ActionRequest<Request> {
public static final String[] ALL_ACTIONS = Strings.EMPTY_ARRAY; public static final String[] ALL_ACTIONS = Strings.EMPTY_ARRAY;
@ -65,7 +65,7 @@ public class BaseTasksRequest<T extends BaseTasksRequest> extends ActionRequest<
* Get information about tasks from nodes based on the nodes ids specified. * Get information about tasks from nodes based on the nodes ids specified.
* If none are passed, information for all nodes will be returned. * If none are passed, information for all nodes will be returned.
*/ */
public BaseTasksRequest(ActionRequest request, String... nodesIds) { public BaseTasksRequest(ActionRequest<?> request, String... nodesIds) {
super(request); super(request);
this.nodesIds = nodesIds; this.nodesIds = nodesIds;
} }
@ -82,9 +82,9 @@ public class BaseTasksRequest<T extends BaseTasksRequest> extends ActionRequest<
* Sets the list of action masks for the actions that should be returned * Sets the list of action masks for the actions that should be returned
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T actions(String... actions) { public final Request actions(String... actions) {
this.actions = actions; this.actions = actions;
return (T) this; return (Request) this;
} }
/** /**
@ -99,9 +99,9 @@ public class BaseTasksRequest<T extends BaseTasksRequest> extends ActionRequest<
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T nodesIds(String... nodesIds) { public final Request nodesIds(String... nodesIds) {
this.nodesIds = nodesIds; this.nodesIds = nodesIds;
return (T) this; return (Request) this;
} }
/** /**
@ -112,9 +112,9 @@ public class BaseTasksRequest<T extends BaseTasksRequest> extends ActionRequest<
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T parentNode(String parentNode) { public Request parentNode(String parentNode) {
this.parentNode = parentNode; this.parentNode = parentNode;
return (T) this; return (Request) this;
} }
/** /**
@ -125,9 +125,9 @@ public class BaseTasksRequest<T extends BaseTasksRequest> extends ActionRequest<
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T parentTaskId(long parentTaskId) { public Request parentTaskId(long parentTaskId) {
this.parentTaskId = parentTaskId; this.parentTaskId = parentTaskId;
return (T) this; return (Request) this;
} }
@ -136,15 +136,15 @@ public class BaseTasksRequest<T extends BaseTasksRequest> extends ActionRequest<
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T timeout(TimeValue timeout) { public final Request timeout(TimeValue timeout) {
this.timeout = timeout; this.timeout = timeout;
return (T) this; return (Request) this;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final T timeout(String timeout) { public final Request timeout(String timeout) {
this.timeout = TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout"); this.timeout = TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout");
return (T) this; return (Request) this;
} }
@Override @Override

View File

@ -148,7 +148,7 @@ public class ClusterModule extends AbstractModule {
registerIndexDynamicSetting(IndexMetaData.SETTING_SHARED_FS_ALLOW_RECOVERY_ON_ANY_NODE, Validator.EMPTY); registerIndexDynamicSetting(IndexMetaData.SETTING_SHARED_FS_ALLOW_RECOVERY_ON_ANY_NODE, Validator.EMPTY);
registerIndexDynamicSetting(IndexMetaData.SETTING_PRIORITY, Validator.NON_NEGATIVE_INTEGER); registerIndexDynamicSetting(IndexMetaData.SETTING_PRIORITY, Validator.NON_NEGATIVE_INTEGER);
registerIndexDynamicSetting(IndicesTTLService.INDEX_TTL_DISABLE_PURGE, Validator.EMPTY); registerIndexDynamicSetting(IndicesTTLService.INDEX_TTL_DISABLE_PURGE, Validator.EMPTY);
registerIndexDynamicSetting(IndexShard.INDEX_REFRESH_INTERVAL, Validator.TIME); registerIndexDynamicSetting(IndexSettings.INDEX_REFRESH_INTERVAL, Validator.TIME);
registerIndexDynamicSetting(PrimaryShardAllocator.INDEX_RECOVERY_INITIAL_SHARDS, Validator.EMPTY); registerIndexDynamicSetting(PrimaryShardAllocator.INDEX_RECOVERY_INITIAL_SHARDS, Validator.EMPTY);
registerIndexDynamicSetting(EngineConfig.INDEX_GC_DELETES_SETTING, Validator.TIME); registerIndexDynamicSetting(EngineConfig.INDEX_GC_DELETES_SETTING, Validator.TIME);
registerIndexDynamicSetting(IndexShard.INDEX_FLUSH_ON_CLOSE, Validator.BOOLEAN); registerIndexDynamicSetting(IndexShard.INDEX_FLUSH_ON_CLOSE, Validator.BOOLEAN);

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Circle; import com.spatial4j.core.shape.Circle;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.unit.DistanceUnit;
@ -35,12 +36,20 @@ public class CircleBuilder extends ShapeBuilder {
public static final String FIELD_RADIUS = "radius"; public static final String FIELD_RADIUS = "radius";
public static final GeoShapeType TYPE = GeoShapeType.CIRCLE; public static final GeoShapeType TYPE = GeoShapeType.CIRCLE;
public static final CircleBuilder PROTOTYPE = new CircleBuilder(); static final CircleBuilder PROTOTYPE = new CircleBuilder();
private DistanceUnit unit; private DistanceUnit unit = DistanceUnit.DEFAULT;
private double radius; private double radius;
private Coordinate center; private Coordinate center;
/**
* Creates a circle centered at [0.0, 0.0].
* Center can be changed by calling {@link #center(Coordinate)} later.
*/
public CircleBuilder() {
this.center = ZERO_ZERO;
}
/** /**
* Set the center of the circle * Set the center of the circle
* *

View File

@ -20,26 +20,32 @@
package org.elasticsearch.common.geo.builders; package org.elasticsearch.common.geo.builders;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List;
/** /**
* The {@link PointCollection} is an abstract base implementation for all GeoShapes. It simply handles a set of points. * The {@link CoordinateCollection} is an abstract base implementation for {@link LineStringBuilder} and {@link MultiPointBuilder}.
* It holds a common list of {@link Coordinate}, provides setters for adding elements to the list and can render this to XContent.
*/ */
public abstract class PointCollection<E extends PointCollection<E>> extends ShapeBuilder { public abstract class CoordinateCollection<E extends CoordinateCollection<E>> extends ShapeBuilder {
protected final ArrayList<Coordinate> points; protected final List<Coordinate> coordinates;
protected PointCollection() { /**
this(new ArrayList<Coordinate>()); * Construct a new collection of coordinates.
} * @param coordinates an initial list of coordinates
* @throws IllegalArgumentException if coordinates is <tt>null</tt> or empty
protected PointCollection(ArrayList<Coordinate> points) { */
this.points = points; protected CoordinateCollection(List<Coordinate> coordinates) {
if (coordinates == null || coordinates.size() == 0) {
throw new IllegalArgumentException("cannot create point collection with empty set of points");
}
this.coordinates = coordinates;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -48,54 +54,54 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
} }
/** /**
* Add a new point to the collection * Add a new coordinate to the collection
* @param longitude longitude of the coordinate * @param longitude longitude of the coordinate
* @param latitude latitude of the coordinate * @param latitude latitude of the coordinate
* @return this * @return this
*/ */
public E point(double longitude, double latitude) { public E coordinate(double longitude, double latitude) {
return this.point(coordinate(longitude, latitude)); return this.coordinate(new Coordinate(longitude, latitude));
} }
/** /**
* Add a new point to the collection * Add a new coordinate to the collection
* @param coordinate coordinate of the point * @param coordinate coordinate of the point
* @return this * @return this
*/ */
public E point(Coordinate coordinate) { public E coordinate(Coordinate coordinate) {
this.points.add(coordinate); this.coordinates.add(coordinate);
return thisRef(); return thisRef();
} }
/** /**
* Add a array of points to the collection * Add a array of coordinates to the collection
* *
* @param coordinates array of {@link Coordinate}s to add * @param coordinates array of {@link Coordinate}s to add
* @return this * @return this
*/ */
public E points(Coordinate...coordinates) { public E coordinates(Coordinate...coordinates) {
return this.points(Arrays.asList(coordinates)); return this.coordinates(Arrays.asList(coordinates));
} }
/** /**
* Add a collection of points to the collection * Add a collection of coordinates to the collection
* *
* @param coordinates array of {@link Coordinate}s to add * @param coordinates array of {@link Coordinate}s to add
* @return this * @return this
*/ */
public E points(Collection<? extends Coordinate> coordinates) { public E coordinates(Collection<? extends Coordinate> coordinates) {
this.points.addAll(coordinates); this.coordinates.addAll(coordinates);
return thisRef(); return thisRef();
} }
/** /**
* Copy all points to a new Array * Copy all coordinate to a new Array
* *
* @param closed if set to true the first point of the array is repeated as last element * @param closed if set to true the first point of the array is repeated as last element
* @return Array of coordinates * @return Array of coordinates
*/ */
protected Coordinate[] coordinates(boolean closed) { protected Coordinate[] coordinates(boolean closed) {
Coordinate[] result = points.toArray(new Coordinate[points.size() + (closed?1:0)]); Coordinate[] result = coordinates.toArray(new Coordinate[coordinates.size() + (closed?1:0)]);
if(closed) { if(closed) {
result[result.length-1] = result[0]; result[result.length-1] = result[0];
} }
@ -111,14 +117,14 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
*/ */
protected XContentBuilder coordinatesToXcontent(XContentBuilder builder, boolean closed) throws IOException { protected XContentBuilder coordinatesToXcontent(XContentBuilder builder, boolean closed) throws IOException {
builder.startArray(); builder.startArray();
for(Coordinate point : points) { for(Coordinate coord : coordinates) {
toXContent(builder, point); toXContent(builder, coord);
} }
if(closed) { if(closed) {
Coordinate start = points.get(0); Coordinate start = coordinates.get(0);
Coordinate end = points.get(points.size()-1); Coordinate end = coordinates.get(coordinates.size()-1);
if(start.x != end.x || start.y != end.y) { if(start.x != end.x || start.y != end.y) {
toXContent(builder, points.get(0)); toXContent(builder, coordinates.get(0));
} }
} }
builder.endArray(); builder.endArray();

View File

@ -0,0 +1,98 @@
/*
* 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.geo.builders;
import com.vividsolutions.jts.geom.Coordinate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* A builder for a list of coordinates.
* Enables chaining of individual coordinates either as long/lat pairs
* or as {@link Coordinate} elements, arrays or collections.
*/
public class CoordinatesBuilder {
private final List<Coordinate> points = new ArrayList<>();
/**
* Add a new coordinate to the collection
* @param coordinate the coordinate to add
* @return this
*/
public CoordinatesBuilder coordinate(Coordinate coordinate) {
this.points.add(coordinate);
return this;
}
/**
* Add a new coordinate to the collection
* @param longitude longitude of the coordinate
* @param latitude latitude of the coordinate
* @return this
*/
public CoordinatesBuilder coordinate(double longitude, double latitude) {
return this.coordinate(new Coordinate(longitude, latitude));
}
/**
* Add an array of coordinates to the current coordinates
*
* @param coordinates array of {@link Coordinate}s to add
* @return this
*/
public CoordinatesBuilder coordinates(Coordinate...coordinates) {
return this.coordinates(Arrays.asList(coordinates));
}
/**
* Add a collection of coordinates to the current coordinates
*
* @param coordinates collection of {@link Coordinate}s to add
* @return this
*/
public CoordinatesBuilder coordinates(Collection<? extends Coordinate> coordinates) {
this.points.addAll(coordinates);
return this;
}
/**
* Makes a closed ring out of the current coordinates by adding the starting point as the end point.
* Will have no effect of starting and end point are already the same coordinate.
*/
public CoordinatesBuilder close() {
Coordinate start = points.get(0);
Coordinate end = points.get(points.size()-1);
if(start.x != end.x || start.y != end.y) {
points.add(start);
}
return this;
}
/**
* @return a list containing the current coordinates
*/
public List<Coordinate> build() {
return new ArrayList<>(this.points);
}
}

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Rectangle; import com.spatial4j.core.shape.Rectangle;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
@ -32,33 +33,22 @@ public class EnvelopeBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.ENVELOPE; public static final GeoShapeType TYPE = GeoShapeType.ENVELOPE;
public static final EnvelopeBuilder PROTOTYPE = new EnvelopeBuilder(); static final EnvelopeBuilder PROTOTYPE = new EnvelopeBuilder(new Coordinate(-1.0, 1.0), new Coordinate(1.0, -1.0));
private Coordinate topLeft; private Coordinate topLeft;
private Coordinate bottomRight; private Coordinate bottomRight;
public EnvelopeBuilder topLeft(Coordinate topLeft) { public EnvelopeBuilder(Coordinate topLeft, Coordinate bottomRight) {
Objects.requireNonNull(topLeft, "topLeft of envelope cannot be null");
Objects.requireNonNull(bottomRight, "bottomRight of envelope cannot be null");
this.topLeft = topLeft; this.topLeft = topLeft;
return this; this.bottomRight = bottomRight;
}
public EnvelopeBuilder topLeft(double longitude, double latitude) {
return topLeft(coordinate(longitude, latitude));
} }
public Coordinate topLeft() { public Coordinate topLeft() {
return this.topLeft; return this.topLeft;
} }
public EnvelopeBuilder bottomRight(Coordinate bottomRight) {
this.bottomRight = bottomRight;
return this;
}
public EnvelopeBuilder bottomRight(double longitude, double latitude) {
return bottomRight(coordinate(longitude, latitude));
}
public Coordinate bottomRight() { public Coordinate bottomRight() {
return this.bottomRight; return this.bottomRight;
} }
@ -110,8 +100,6 @@ public class EnvelopeBuilder extends ShapeBuilder {
@Override @Override
public EnvelopeBuilder readFrom(StreamInput in) throws IOException { public EnvelopeBuilder readFrom(StreamInput in) throws IOException {
return new EnvelopeBuilder() return new EnvelopeBuilder(readCoordinateFrom(in), readCoordinateFrom(in));
.topLeft(readCoordinateFrom(in))
.bottomRight(readCoordinateFrom(in));
} }
} }

View File

@ -20,6 +20,7 @@
package org.elasticsearch.common.geo.builders; package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Shape; import com.spatial4j.core.shape.Shape;
import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.geo.XShapeCollection; import org.elasticsearch.common.geo.XShapeCollection;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
@ -35,7 +36,7 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.GEOMETRYCOLLECTION; public static final GeoShapeType TYPE = GeoShapeType.GEOMETRYCOLLECTION;
public static final GeometryCollectionBuilder PROTOTYPE = new GeometryCollectionBuilder(); static final GeometryCollectionBuilder PROTOTYPE = new GeometryCollectionBuilder();
protected final ArrayList<ShapeBuilder> shapes = new ArrayList<>(); protected final ArrayList<ShapeBuilder> shapes = new ArrayList<>();

View File

@ -24,6 +24,7 @@ import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LineString;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
@ -31,13 +32,32 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Objects; import java.util.Objects;
public class LineStringBuilder extends PointCollection<LineStringBuilder> { public class LineStringBuilder extends CoordinateCollection<LineStringBuilder> {
/**
* Construct a new LineString.
* Per GeoJSON spec (http://geojson.org/geojson-spec.html#linestring)
* a LineString must contain two or more coordinates
* @param coordinates the initial list of coordinates
* @throws IllegalArgumentException if there are less then two coordinates defined
*/
public LineStringBuilder(List<Coordinate> coordinates) {
super(coordinates);
if (coordinates.size() < 2) {
throw new IllegalArgumentException("invalid number of points in LineString (found [" + coordinates.size()+ "] - must be >= 2)");
}
}
public LineStringBuilder(CoordinatesBuilder coordinates) {
this(coordinates.build());
}
public static final GeoShapeType TYPE = GeoShapeType.LINESTRING; public static final GeoShapeType TYPE = GeoShapeType.LINESTRING;
public static final LineStringBuilder PROTOTYPE = new LineStringBuilder(); static final LineStringBuilder PROTOTYPE = new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0).coordinate(1.0, 1.0));
@Override @Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
@ -50,13 +70,14 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
} }
/** /**
* Closes the current lineString by adding the starting point as the end point * Closes the current lineString by adding the starting point as the end point.
* This will have no effect if starting and end point are already the same.
*/ */
public LineStringBuilder close() { public LineStringBuilder close() {
Coordinate start = points.get(0); Coordinate start = coordinates.get(0);
Coordinate end = points.get(points.size()-1); Coordinate end = coordinates.get(coordinates.size() - 1);
if(start.x != end.x || start.y != end.y) { if(start.x != end.x || start.y != end.y) {
points.add(start); coordinates.add(start);
} }
return this; return this;
} }
@ -68,7 +89,7 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
@Override @Override
public Shape build() { public Shape build() {
Coordinate[] coordinates = points.toArray(new Coordinate[points.size()]); Coordinate[] coordinates = this.coordinates.toArray(new Coordinate[this.coordinates.size()]);
Geometry geometry; Geometry geometry;
if(wrapdateline) { if(wrapdateline) {
ArrayList<LineString> strings = decompose(FACTORY, coordinates, new ArrayList<LineString>()); ArrayList<LineString> strings = decompose(FACTORY, coordinates, new ArrayList<LineString>());
@ -147,7 +168,7 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(points); return Objects.hash(coordinates);
} }
@Override @Override
@ -159,24 +180,25 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
return false; return false;
} }
LineStringBuilder other = (LineStringBuilder) obj; LineStringBuilder other = (LineStringBuilder) obj;
return Objects.equals(points, other.points); return Objects.equals(coordinates, other.coordinates);
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(points.size()); out.writeVInt(coordinates.size());
for (Coordinate point : points) { for (Coordinate point : coordinates) {
writeCoordinateTo(point, out); writeCoordinateTo(point, out);
} }
} }
@Override @Override
public LineStringBuilder readFrom(StreamInput in) throws IOException { public LineStringBuilder readFrom(StreamInput in) throws IOException {
LineStringBuilder lineStringBuilder = new LineStringBuilder(); CoordinatesBuilder coordinates = new CoordinatesBuilder();
int size = in.readVInt(); int size = in.readVInt();
for (int i=0; i < size; i++) { for (int i=0; i < size; i++) {
lineStringBuilder.point(readCoordinateFrom(in)); coordinates.coordinate(readCoordinateFrom(in));
} }
LineStringBuilder lineStringBuilder = new LineStringBuilder(coordinates);
return lineStringBuilder; return lineStringBuilder;
} }
} }

View File

@ -23,6 +23,7 @@ import com.spatial4j.core.shape.Shape;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LineString;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
@ -36,7 +37,7 @@ public class MultiLineStringBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.MULTILINESTRING; public static final GeoShapeType TYPE = GeoShapeType.MULTILINESTRING;
public static final MultiLineStringBuilder PROTOTYPE = new MultiLineStringBuilder(); static final MultiLineStringBuilder PROTOTYPE = new MultiLineStringBuilder();
private final ArrayList<LineStringBuilder> lines = new ArrayList<>(); private final ArrayList<LineStringBuilder> lines = new ArrayList<>();
@ -45,10 +46,6 @@ public class MultiLineStringBuilder extends ShapeBuilder {
return this; return this;
} }
public MultiLineStringBuilder linestring(Coordinate[] coordinates) {
return this.linestring(new LineStringBuilder().points(coordinates));
}
public Coordinate[][] coordinates() { public Coordinate[][] coordinates() {
Coordinate[][] result = new Coordinate[lines.size()][]; Coordinate[][] result = new Coordinate[lines.size()][];
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {

View File

@ -22,6 +22,7 @@ package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Point; import com.spatial4j.core.shape.Point;
import com.spatial4j.core.shape.Shape; import com.spatial4j.core.shape.Shape;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.geo.XShapeCollection; import org.elasticsearch.common.geo.XShapeCollection;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
@ -32,11 +33,19 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
public class MultiPointBuilder extends PointCollection<MultiPointBuilder> { public class MultiPointBuilder extends CoordinateCollection<MultiPointBuilder> {
public static final GeoShapeType TYPE = GeoShapeType.MULTIPOINT; public static final GeoShapeType TYPE = GeoShapeType.MULTIPOINT;
public final static MultiPointBuilder PROTOTYPE = new MultiPointBuilder(); final static MultiPointBuilder PROTOTYPE = new MultiPointBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0).build());
/**
* Create a new {@link MultiPointBuilder}.
* @param coordinates needs at least two coordinates to be valid, otherwise will throw an exception
*/
public MultiPointBuilder(List<Coordinate> coordinates) {
super(coordinates);
}
@Override @Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
@ -52,8 +61,8 @@ public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
public Shape build() { public Shape build() {
//Could wrap JtsGeometry but probably slower due to conversions to/from JTS in relate() //Could wrap JtsGeometry but probably slower due to conversions to/from JTS in relate()
//MultiPoint geometry = FACTORY.createMultiPoint(points.toArray(new Coordinate[points.size()])); //MultiPoint geometry = FACTORY.createMultiPoint(points.toArray(new Coordinate[points.size()]));
List<Point> shapes = new ArrayList<>(points.size()); List<Point> shapes = new ArrayList<>(coordinates.size());
for (Coordinate coord : points) { for (Coordinate coord : coordinates) {
shapes.add(SPATIAL_CONTEXT.makePoint(coord.x, coord.y)); shapes.add(SPATIAL_CONTEXT.makePoint(coord.x, coord.y));
} }
XShapeCollection<Point> multiPoints = new XShapeCollection<>(shapes, SPATIAL_CONTEXT); XShapeCollection<Point> multiPoints = new XShapeCollection<>(shapes, SPATIAL_CONTEXT);
@ -68,7 +77,7 @@ public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(points); return Objects.hash(coordinates);
} }
@Override @Override
@ -80,24 +89,26 @@ public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
return false; return false;
} }
MultiPointBuilder other = (MultiPointBuilder) obj; MultiPointBuilder other = (MultiPointBuilder) obj;
return Objects.equals(points, other.points); return Objects.equals(coordinates, other.coordinates);
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(points.size()); out.writeVInt(coordinates.size());
for (Coordinate point : points) { for (Coordinate point : coordinates) {
writeCoordinateTo(point, out); writeCoordinateTo(point, out);
} }
} }
@Override @Override
public MultiPointBuilder readFrom(StreamInput in) throws IOException { public MultiPointBuilder readFrom(StreamInput in) throws IOException {
MultiPointBuilder multiPointBuilder = new MultiPointBuilder();
int size = in.readVInt(); int size = in.readVInt();
List<Coordinate> points = new ArrayList<Coordinate>(size);
for (int i=0; i < size; i++) { for (int i=0; i < size; i++) {
multiPointBuilder.point(readCoordinateFrom(in)); points.add(readCoordinateFrom(in));
} }
MultiPointBuilder multiPointBuilder = new MultiPointBuilder(points);
return multiPointBuilder; return multiPointBuilder;
} }
} }

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Shape; import com.spatial4j.core.shape.Shape;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.geo.XShapeCollection; import org.elasticsearch.common.geo.XShapeCollection;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
@ -35,7 +36,7 @@ import java.util.Objects;
public class MultiPolygonBuilder extends ShapeBuilder { public class MultiPolygonBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.MULTIPOLYGON; public static final GeoShapeType TYPE = GeoShapeType.MULTIPOLYGON;
public static final MultiPolygonBuilder PROTOTYPE = new MultiPolygonBuilder(); static final MultiPolygonBuilder PROTOTYPE = new MultiPolygonBuilder();
private final ArrayList<PolygonBuilder> polygons = new ArrayList<>(); private final ArrayList<PolygonBuilder> polygons = new ArrayList<>();
@ -58,8 +59,7 @@ public class MultiPolygonBuilder extends ShapeBuilder {
* {@link MultiPolygonBuilder} to the polygon if polygon has different orientation. * {@link MultiPolygonBuilder} to the polygon if polygon has different orientation.
*/ */
public MultiPolygonBuilder polygon(PolygonBuilder polygon) { public MultiPolygonBuilder polygon(PolygonBuilder polygon) {
PolygonBuilder pb = new PolygonBuilder(this.orientation); PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder().coordinates(polygon.shell().coordinates(false)), this.orientation);
pb.points(polygon.shell().coordinates(false));
for (LineStringBuilder hole : polygon.holes()) { for (LineStringBuilder hole : polygon.holes()) {
pb.hole(hole); pb.hole(hole);
} }

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Point; import com.spatial4j.core.shape.Point;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
@ -31,10 +32,17 @@ import java.util.Objects;
public class PointBuilder extends ShapeBuilder { public class PointBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.POINT; public static final GeoShapeType TYPE = GeoShapeType.POINT;
public static final PointBuilder PROTOTYPE = new PointBuilder(); static final PointBuilder PROTOTYPE = new PointBuilder();
private Coordinate coordinate; private Coordinate coordinate;
/**
* Create a point at [0.0,0.0]
*/
public PointBuilder() {
this.coordinate = ZERO_ZERO;
}
public PointBuilder coordinate(Coordinate coordinate) { public PointBuilder coordinate(Coordinate coordinate) {
this.coordinate = coordinate; this.coordinate = coordinate;
return this; return this;

View File

@ -27,6 +27,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.Polygon;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
@ -52,7 +53,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class PolygonBuilder extends ShapeBuilder { public class PolygonBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.POLYGON; public static final GeoShapeType TYPE = GeoShapeType.POLYGON;
public static final PolygonBuilder PROTOTYPE = new PolygonBuilder(); static final PolygonBuilder PROTOTYPE = new PolygonBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0).coordinate(0.0, 1.0)
.coordinate(1.0, 0.0).coordinate(0.0, 0.0));
private static final Coordinate[][] EMPTY = new Coordinate[0][]; private static final Coordinate[][] EMPTY = new Coordinate[0][];
@ -64,54 +66,51 @@ public class PolygonBuilder extends ShapeBuilder {
// List of line strings defining the holes of the polygon // List of line strings defining the holes of the polygon
private final ArrayList<LineStringBuilder> holes = new ArrayList<>(); private final ArrayList<LineStringBuilder> holes = new ArrayList<>();
public PolygonBuilder() { public PolygonBuilder(LineStringBuilder lineString, Orientation orientation, boolean coerce) {
this(Orientation.RIGHT);
}
public PolygonBuilder(Orientation orientation) {
this(new ArrayList<Coordinate>(), orientation);
}
public PolygonBuilder(ArrayList<Coordinate> points, Orientation orientation) {
this.orientation = orientation; this.orientation = orientation;
this.shell = new LineStringBuilder().points(points); if (coerce) {
lineString.close();
}
validateLinearRing(lineString);
this.shell = lineString;
}
public PolygonBuilder(LineStringBuilder lineString, Orientation orientation) {
this(lineString, orientation, false);
}
public PolygonBuilder(CoordinatesBuilder coordinates, Orientation orientation) {
this(new LineStringBuilder(coordinates), orientation, false);
}
public PolygonBuilder(CoordinatesBuilder coordinates) {
this(coordinates, Orientation.RIGHT);
} }
public Orientation orientation() { public Orientation orientation() {
return this.orientation; return this.orientation;
} }
public PolygonBuilder point(double longitude, double latitude) {
shell.point(longitude, latitude);
return this;
}
/**
* Add a point to the shell of the polygon
* @param coordinate coordinate of the new point
* @return this
*/
public PolygonBuilder point(Coordinate coordinate) {
shell.point(coordinate);
return this;
}
/**
* Add an array of points to the shell of the polygon
* @param coordinates coordinates of the new points to add
* @return this
*/
public PolygonBuilder points(Coordinate...coordinates) {
shell.points(coordinates);
return this;
}
/** /**
* Add a new hole to the polygon * Add a new hole to the polygon
* @param hole linear ring defining the hole * @param hole linear ring defining the hole
* @return this * @return this
*/ */
public PolygonBuilder hole(LineStringBuilder hole) { public PolygonBuilder hole(LineStringBuilder hole) {
return this.hole(hole, false);
}
/**
* Add a new hole to the polygon
* @param hole linear ring defining the hole
* @param coerce if set to true, it will try to close the hole by adding starting point as end point
* @return this
*/
public PolygonBuilder hole(LineStringBuilder hole, boolean coerce) {
if (coerce) {
hole.close();
}
validateLinearRing(hole);
holes.add(hole); holes.add(hole);
return this; return this;
} }
@ -138,12 +137,30 @@ public class PolygonBuilder extends ShapeBuilder {
return this; return this;
} }
private static void validateLinearRing(LineStringBuilder lineString) {
/**
* Per GeoJSON spec (http://geojson.org/geojson-spec.html#linestring)
* A LinearRing is closed LineString with 4 or more positions. The first and last positions
* are equivalent (they represent equivalent points). Though a LinearRing is not explicitly
* represented as a GeoJSON geometry type, it is referred to in the Polygon geometry type definition.
*/
List<Coordinate> points = lineString.coordinates;
if (points.size() < 4) {
throw new IllegalArgumentException(
"invalid number of points in LinearRing (found [" + points.size() + "] - must be >= 4)");
}
if (!points.get(0).equals(points.get(points.size() - 1))) {
throw new IllegalArgumentException("invalid LinearRing found (coordinates are not closed)");
}
}
/** /**
* Validates only 1 vertex is tangential (shared) between the interior and exterior of a polygon * Validates only 1 vertex is tangential (shared) between the interior and exterior of a polygon
*/ */
protected void validateHole(LineStringBuilder shell, LineStringBuilder hole) { protected void validateHole(LineStringBuilder shell, LineStringBuilder hole) {
HashSet<Coordinate> exterior = Sets.newHashSet(shell.points); HashSet<Coordinate> exterior = Sets.newHashSet(shell.coordinates);
HashSet<Coordinate> interior = Sets.newHashSet(hole.points); HashSet<Coordinate> interior = Sets.newHashSet(hole.coordinates);
exterior.retainAll(interior); exterior.retainAll(interior);
if (exterior.size() >= 2) { if (exterior.size() >= 2) {
throw new InvalidShapeException("Invalid polygon, interior cannot share more than one point with the exterior"); throw new InvalidShapeException("Invalid polygon, interior cannot share more than one point with the exterior");
@ -161,9 +178,9 @@ public class PolygonBuilder extends ShapeBuilder {
* @return coordinates of the polygon * @return coordinates of the polygon
*/ */
public Coordinate[][][] coordinates() { public Coordinate[][][] coordinates() {
int numEdges = shell.points.size()-1; // Last point is repeated int numEdges = shell.coordinates.size()-1; // Last point is repeated
for (int i = 0; i < holes.size(); i++) { for (int i = 0; i < holes.size(); i++) {
numEdges += holes.get(i).points.size()-1; numEdges += holes.get(i).coordinates.size()-1;
validateHole(shell, this.holes.get(i)); validateHole(shell, this.holes.get(i));
} }
@ -226,16 +243,16 @@ public class PolygonBuilder extends ShapeBuilder {
} }
protected Polygon toPolygon(GeometryFactory factory) { protected Polygon toPolygon(GeometryFactory factory) {
final LinearRing shell = linearRing(factory, this.shell.points); final LinearRing shell = linearRing(factory, this.shell.coordinates);
final LinearRing[] holes = new LinearRing[this.holes.size()]; final LinearRing[] holes = new LinearRing[this.holes.size()];
Iterator<LineStringBuilder> iterator = this.holes.iterator(); Iterator<LineStringBuilder> iterator = this.holes.iterator();
for (int i = 0; iterator.hasNext(); i++) { for (int i = 0; iterator.hasNext(); i++) {
holes[i] = linearRing(factory, iterator.next().points); holes[i] = linearRing(factory, iterator.next().coordinates);
} }
return factory.createPolygon(shell, holes); return factory.createPolygon(shell, holes);
} }
protected static LinearRing linearRing(GeometryFactory factory, ArrayList<Coordinate> coordinates) { protected static LinearRing linearRing(GeometryFactory factory, List<Coordinate> coordinates) {
return factory.createLinearRing(coordinates.toArray(new Coordinate[coordinates.size()])); return factory.createLinearRing(coordinates.toArray(new Coordinate[coordinates.size()]));
} }
@ -711,8 +728,8 @@ public class PolygonBuilder extends ShapeBuilder {
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
orientation.writeTo(out);
shell.writeTo(out); shell.writeTo(out);
orientation.writeTo(out);
out.writeVInt(holes.size()); out.writeVInt(holes.size());
for (LineStringBuilder hole : holes) { for (LineStringBuilder hole : holes) {
hole.writeTo(out); hole.writeTo(out);
@ -721,8 +738,9 @@ public class PolygonBuilder extends ShapeBuilder {
@Override @Override
public PolygonBuilder readFrom(StreamInput in) throws IOException { public PolygonBuilder readFrom(StreamInput in) throws IOException {
PolygonBuilder polyBuilder = new PolygonBuilder(Orientation.readFrom(in)); LineStringBuilder shell = LineStringBuilder.PROTOTYPE.readFrom(in);
polyBuilder.shell = LineStringBuilder.PROTOTYPE.readFrom(in); Orientation orientation = Orientation.readFrom(in);
PolygonBuilder polyBuilder = new PolygonBuilder(shell, orientation);
int holes = in.readVInt(); int holes = in.readVInt();
for (int i = 0; i < holes; i++) { for (int i = 0; i < holes; i++) {
polyBuilder.hole(LineStringBuilder.PROTOTYPE.readFrom(in)); polyBuilder.hole(LineStringBuilder.PROTOTYPE.readFrom(in));

View File

@ -26,6 +26,7 @@ import com.spatial4j.core.shape.jts.JtsGeometry;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.GeometryFactory;
import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.support.ToXContentToBytes; import org.elasticsearch.action.support.ToXContentToBytes;
import org.elasticsearch.common.io.stream.NamedWriteable; import org.elasticsearch.common.io.stream.NamedWriteable;
@ -64,6 +65,11 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
} }
public static final double DATELINE = 180; public static final double DATELINE = 180;
/**
* coordinate at [0.0, 0.0]
*/
public static final Coordinate ZERO_ZERO = new Coordinate(0.0, 0.0);
// TODO how might we use JtsSpatialContextFactory to configure the context (esp. for non-geo)? // TODO how might we use JtsSpatialContextFactory to configure the context (esp. for non-geo)?
public static final JtsSpatialContext SPATIAL_CONTEXT = JtsSpatialContext.GEO; public static final JtsSpatialContext SPATIAL_CONTEXT = JtsSpatialContext.GEO;
public static final GeometryFactory FACTORY = SPATIAL_CONTEXT.getGeometryFactory(); public static final GeometryFactory FACTORY = SPATIAL_CONTEXT.getGeometryFactory();
@ -81,11 +87,6 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
protected final boolean autoIndexJtsGeometry = true;//may want to turn off once SpatialStrategy impls do it. protected final boolean autoIndexJtsGeometry = true;//may want to turn off once SpatialStrategy impls do it.
protected ShapeBuilder() { protected ShapeBuilder() {
}
protected static Coordinate coordinate(double longitude, double latitude) {
return new Coordinate(longitude, latitude);
} }
protected JtsGeometry jtsGeometry(Geometry geom) { protected JtsGeometry jtsGeometry(Geometry geom) {
@ -569,7 +570,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
uL = new Coordinate(Math.min(uL.x, lR.x), Math.max(uL.y, lR.y)); uL = new Coordinate(Math.min(uL.x, lR.x), Math.max(uL.y, lR.y));
lR = new Coordinate(Math.max(uLtmp.x, lR.x), Math.min(uLtmp.y, lR.y)); lR = new Coordinate(Math.max(uLtmp.x, lR.x), Math.min(uLtmp.y, lR.y));
} }
return ShapeBuilders.newEnvelope().topLeft(uL).bottomRight(lR); return ShapeBuilders.newEnvelope(uL, lR);
} }
protected static void validateMultiPointNode(CoordinateNode coordinates) { protected static void validateMultiPointNode(CoordinateNode coordinates) {
@ -589,12 +590,11 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
protected static MultiPointBuilder parseMultiPoint(CoordinateNode coordinates) { protected static MultiPointBuilder parseMultiPoint(CoordinateNode coordinates) {
validateMultiPointNode(coordinates); validateMultiPointNode(coordinates);
CoordinatesBuilder points = new CoordinatesBuilder();
MultiPointBuilder points = new MultiPointBuilder();
for (CoordinateNode node : coordinates.children) { for (CoordinateNode node : coordinates.children) {
points.point(node.coordinate); points.coordinate(node.coordinate);
} }
return points; return new MultiPointBuilder(points.build());
} }
protected static LineStringBuilder parseLineString(CoordinateNode coordinates) { protected static LineStringBuilder parseLineString(CoordinateNode coordinates) {
@ -607,11 +607,11 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
throw new ElasticsearchParseException("invalid number of points in LineString (found [{}] - must be >= 2)", coordinates.children.size()); throw new ElasticsearchParseException("invalid number of points in LineString (found [{}] - must be >= 2)", coordinates.children.size());
} }
LineStringBuilder line = ShapeBuilders.newLineString(); CoordinatesBuilder line = new CoordinatesBuilder();
for (CoordinateNode node : coordinates.children) { for (CoordinateNode node : coordinates.children) {
line.point(node.coordinate); line.coordinate(node.coordinate);
} }
return line; return ShapeBuilders.newLineString(line);
} }
protected static MultiLineStringBuilder parseMultiLine(CoordinateNode coordinates) { protected static MultiLineStringBuilder parseMultiLine(CoordinateNode coordinates) {
@ -659,7 +659,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
} }
LineStringBuilder shell = parseLinearRing(coordinates.children.get(0), coerce); LineStringBuilder shell = parseLinearRing(coordinates.children.get(0), coerce);
PolygonBuilder polygon = new PolygonBuilder(shell.points, orientation); PolygonBuilder polygon = new PolygonBuilder(shell, orientation);
for (int i = 1; i < coordinates.children.size(); i++) { for (int i = 1; i < coordinates.children.size(); i++) {
polygon.hole(parseLinearRing(coordinates.children.get(i), coerce)); polygon.hole(parseLinearRing(coordinates.children.get(i), coerce));
} }

View File

@ -21,6 +21,8 @@ package org.elasticsearch.common.geo.builders;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import java.util.List;
/** /**
* A collection of static methods for creating ShapeBuilders. * A collection of static methods for creating ShapeBuilders.
*/ */
@ -50,16 +52,24 @@ public class ShapeBuilders {
* Create a new set of points * Create a new set of points
* @return new {@link MultiPointBuilder} * @return new {@link MultiPointBuilder}
*/ */
public static MultiPointBuilder newMultiPoint() { public static MultiPointBuilder newMultiPoint(List<Coordinate> points) {
return new MultiPointBuilder(); return new MultiPointBuilder(points);
} }
/** /**
* Create a new lineString * Create a new lineString
* @return a new {@link LineStringBuilder} * @return a new {@link LineStringBuilder}
*/ */
public static LineStringBuilder newLineString() { public static LineStringBuilder newLineString(List<Coordinate> list) {
return new LineStringBuilder(); return new LineStringBuilder(list);
}
/**
* Create a new lineString
* @return a new {@link LineStringBuilder}
*/
public static LineStringBuilder newLineString(CoordinatesBuilder coordinates) {
return new LineStringBuilder(coordinates);
} }
/** /**
@ -71,19 +81,19 @@ public class ShapeBuilders {
} }
/** /**
* Create a new Polygon * Create a new PolygonBuilder
* @return a new {@link PointBuilder} * @return a new {@link PolygonBuilder}
*/ */
public static PolygonBuilder newPolygon() { public static PolygonBuilder newPolygon(List<Coordinate> shell) {
return new PolygonBuilder(); return new PolygonBuilder(new CoordinatesBuilder().coordinates(shell));
} }
/** /**
* Create a new Polygon * Create a new PolygonBuilder
* @return a new {@link PointBuilder} * @return a new {@link PolygonBuilder}
*/ */
public static PolygonBuilder newPolygon(ShapeBuilder.Orientation orientation) { public static PolygonBuilder newPolygon(CoordinatesBuilder shell) {
return new PolygonBuilder(orientation); return new PolygonBuilder(shell);
} }
/** /**
@ -124,7 +134,7 @@ public class ShapeBuilders {
* *
* @return a new {@link EnvelopeBuilder} * @return a new {@link EnvelopeBuilder}
*/ */
public static EnvelopeBuilder newEnvelope() { public static EnvelopeBuilder newEnvelope(Coordinate topLeft, Coordinate bottomRight) {
return new EnvelopeBuilder(); return new EnvelopeBuilder(topLeft, bottomRight);
} }
} }

View File

@ -76,19 +76,6 @@ public final class Settings implements ToXContent {
public static final Settings EMPTY = new Builder().build(); public static final Settings EMPTY = new Builder().build();
private static final Pattern ARRAY_PATTERN = Pattern.compile("(.*)\\.\\d+$"); private static final Pattern ARRAY_PATTERN = Pattern.compile("(.*)\\.\\d+$");
/** Name of the setting to use to disable required units for byte size, time settings. */
public static final String SETTINGS_REQUIRE_UNITS = "settings_require_units";
private static boolean settingsRequireUnits = true;
public static void setSettingsRequireUnits(boolean v) {
settingsRequireUnits = v;
}
public static boolean getSettingsRequireUnits() {
return settingsRequireUnits;
}
private final Map<String, String> forcedUnderscoreSettings; private final Map<String, String> forcedUnderscoreSettings;
private SortedMap<String, String> settings; private SortedMap<String, String> settings;

View File

@ -213,12 +213,7 @@ public class ByteSizeValue implements Streamable {
bytes = 0; bytes = 0;
} else { } else {
// Missing units: // Missing units:
if (Settings.getSettingsRequireUnits()) { throw new ElasticsearchParseException("failed to parse setting [{}] with value [{}] as a size in bytes: unit is missing or unrecognized", settingName, sValue);
throw new ElasticsearchParseException("failed to parse setting [{}] with value [{}] as a size in bytes: unit is missing or unrecognized", settingName, sValue);
} else {
// Leniency default to bytes:
bytes = Long.parseLong(sValue);
}
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ElasticsearchParseException("failed to parse [{}]", e, sValue); throw new ElasticsearchParseException("failed to parse [{}]", e, sValue);

View File

@ -280,13 +280,8 @@ public class TimeValue implements Streamable {
// Allow this special value to be unit-less: // Allow this special value to be unit-less:
millis = 0; millis = 0;
} else { } else {
if (Settings.getSettingsRequireUnits()) { // Missing units:
// Missing units: throw new ElasticsearchParseException("Failed to parse setting [{}] with value [{}] as a time value: unit is missing or unrecognized", settingName, sValue);
throw new ElasticsearchParseException("Failed to parse setting [{}] with value [{}] as a time value: unit is missing or unrecognized", settingName, sValue);
} else {
// Leniency default to msec for bwc:
millis = Long.parseLong(sValue);
}
} }
return new TimeValue(millis, TimeUnit.MILLISECONDS); return new TimeValue(millis, TimeUnit.MILLISECONDS);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {

View File

@ -22,11 +22,11 @@ package org.elasticsearch.index;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -42,6 +42,8 @@ import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.FutureUtils;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.env.NodeEnvironment; import org.elasticsearch.env.NodeEnvironment;
@ -104,6 +106,8 @@ public final class IndexService extends AbstractIndexComponent implements IndexC
private final IndexSettings indexSettings; private final IndexSettings indexSettings;
private final IndexingSlowLog slowLog; private final IndexingSlowLog slowLog;
private final IndexingOperationListener[] listeners; private final IndexingOperationListener[] listeners;
private volatile AsyncRefreshTask refreshTask;
private final AsyncTranslogFSync fsyncTask;
public IndexService(IndexSettings indexSettings, NodeEnvironment nodeEnv, public IndexService(IndexSettings indexSettings, NodeEnvironment nodeEnv,
SimilarityService similarityService, SimilarityService similarityService,
@ -140,6 +144,13 @@ public final class IndexService extends AbstractIndexComponent implements IndexC
this.listeners = new IndexingOperationListener[1+listenersIn.length]; this.listeners = new IndexingOperationListener[1+listenersIn.length];
this.listeners[0] = slowLog; this.listeners[0] = slowLog;
System.arraycopy(listenersIn, 0, this.listeners, 1, listenersIn.length); System.arraycopy(listenersIn, 0, this.listeners, 1, listenersIn.length);
// kick off async ops for the first shard in this index
if (this.indexSettings.getTranslogSyncInterval().millis() != 0) {
this.fsyncTask = new AsyncTranslogFSync(this);
} else {
this.fsyncTask = null;
}
this.refreshTask = new AsyncRefreshTask(this);
} }
public int numberOfShards() { public int numberOfShards() {
@ -215,7 +226,7 @@ public final class IndexService extends AbstractIndexComponent implements IndexC
} }
} }
} finally { } finally {
IOUtils.close(bitsetFilterCache, indexCache, mapperService, indexFieldData, analysisService); IOUtils.close(bitsetFilterCache, indexCache, mapperService, indexFieldData, analysisService, refreshTask, fsyncTask);
} }
} }
} }
@ -306,14 +317,9 @@ public final class IndexService extends AbstractIndexComponent implements IndexC
} else { } else {
indexShard = new IndexShard(shardId, this.indexSettings, path, store, indexCache, mapperService, similarityService, indexFieldData, engineFactory, eventListener, searcherWrapper, nodeServicesProvider, listeners); indexShard = new IndexShard(shardId, this.indexSettings, path, store, indexCache, mapperService, similarityService, indexFieldData, engineFactory, eventListener, searcherWrapper, nodeServicesProvider, listeners);
} }
eventListener.indexShardStateChanged(indexShard, null, indexShard.state(), "shard created"); eventListener.indexShardStateChanged(indexShard, null, indexShard.state(), "shard created");
eventListener.afterIndexShardCreated(indexShard); eventListener.afterIndexShardCreated(indexShard);
indexShard.updateRoutingEntry(routing, true); indexShard.updateRoutingEntry(routing, true);
if (shards.isEmpty() && this.indexSettings.getTranslogSyncInterval().millis() != 0) {
ThreadPool threadPool = nodeServicesProvider.getThreadPool();
new AsyncTranslogFSync(this, threadPool).schedule(); // kick this off if we are the first shard in this service.
}
shards = newMapBuilder(shards).put(shardId.id(), indexShard).immutableMap(); shards = newMapBuilder(shards).put(shardId.id(), indexShard).immutableMap();
success = true; success = true;
return indexShard; return indexShard;
@ -404,6 +410,10 @@ public final class IndexService extends AbstractIndexComponent implements IndexC
return new QueryShardContext(indexSettings, nodeServicesProvider.getClient(), indexCache.bitsetFilterCache(), indexFieldData, mapperService(), similarityService(), nodeServicesProvider.getScriptService(), nodeServicesProvider.getIndicesQueriesRegistry()); return new QueryShardContext(indexSettings, nodeServicesProvider.getClient(), indexCache.bitsetFilterCache(), indexFieldData, mapperService(), similarityService(), nodeServicesProvider.getScriptService(), nodeServicesProvider.getIndicesQueriesRegistry());
} }
ThreadPool getThreadPool() {
return nodeServicesProvider.getThreadPool();
}
private class StoreCloseListener implements Store.OnClose { private class StoreCloseListener implements Store.OnClose {
private final ShardId shardId; private final ShardId shardId;
private final boolean ownsShard; private final boolean ownsShard;
@ -567,9 +577,21 @@ public final class IndexService extends AbstractIndexComponent implements IndexC
} catch (Exception e) { } catch (Exception e) {
logger.warn("failed to refresh slowlog settings", e); logger.warn("failed to refresh slowlog settings", e);
} }
if (refreshTask.getInterval().equals(indexSettings.getRefreshInterval()) == false) {
rescheduleRefreshTasks();
}
} }
} }
private void rescheduleRefreshTasks() {
try {
refreshTask.close();
} finally {
refreshTask = new AsyncRefreshTask(this);
}
}
public interface ShardStoreDeleter { public interface ShardStoreDeleter {
void deleteShardStore(String reason, ShardLock lock, IndexSettings indexSettings) throws IOException; void deleteShardStore(String reason, ShardLock lock, IndexSettings indexSettings) throws IOException;
@ -605,40 +627,170 @@ public final class IndexService extends AbstractIndexComponent implements IndexC
} }
} }
private void maybeRefreshEngine() {
/** if (indexSettings.getRefreshInterval().millis() > 0) {
* FSyncs the translog for all shards of this index in a defined interval. for (IndexShard shard : this.shards.values()) {
*/ switch (shard.state()) {
final static class AsyncTranslogFSync implements Runnable { case CREATED:
private final IndexService indexService; case RECOVERING:
private final ThreadPool threadPool; case CLOSED:
continue;
AsyncTranslogFSync(IndexService indexService, ThreadPool threadPool) { case POST_RECOVERY:
this.indexService = indexService; case STARTED:
this.threadPool = threadPool; case RELOCATED:
} try {
shard.refresh("schedule");
boolean mustRun() { } catch (EngineClosedException | AlreadyClosedException ex) {
// don't re-schedule if its closed or if we dont' have a single shard here..., we are done // fine - continue;
return (indexService.closed.get() || indexService.shards.isEmpty()) == false; }
} continue;
default:
void schedule() { throw new IllegalStateException("unknown state: " + shard.state());
threadPool.schedule(indexService.getIndexSettings().getTranslogSyncInterval(), ThreadPool.Names.SAME, AsyncTranslogFSync.this); }
}
@Override
public void run() {
if (mustRun()) {
threadPool.executor(ThreadPool.Names.FLUSH).execute(() -> {
indexService.maybeFSyncTranslogs();
if (mustRun()) {
schedule();
}
});
} }
} }
} }
static abstract class BaseAsyncTask implements Runnable, Closeable {
protected final IndexService indexService;
protected final ThreadPool threadPool;
private final TimeValue interval;
private ScheduledFuture<?> scheduledFuture;
private final AtomicBoolean closed = new AtomicBoolean(false);
private volatile Exception lastThrownException;
BaseAsyncTask(IndexService indexService, TimeValue interval) {
this.indexService = indexService;
this.threadPool = indexService.getThreadPool();
this.interval = interval;
onTaskCompletion();
}
boolean mustReschedule() {
// don't re-schedule if its closed or if we dont' have a single shard here..., we are done
return indexService.closed.get() == false
&& closed.get() == false && interval.millis() > 0;
}
private synchronized void onTaskCompletion() {
if (mustReschedule()) {
indexService.logger.debug("scheduling {} every {}", toString(), interval);
this.scheduledFuture = threadPool.schedule(interval, getThreadPool(), BaseAsyncTask.this);
} else {
indexService.logger.debug("scheduled {} disabled", toString());
this.scheduledFuture = null;
}
}
boolean isScheduled() {
return scheduledFuture != null;
}
public final void run() {
try {
runInternal();
} catch (Exception ex) {
if (lastThrownException == null || sameException(lastThrownException, ex) == false) {
// prevent the annoying fact of logging the same stuff all the time with an interval of 1 sec will spam all your logs
indexService.logger.warn("failed to run task {} - suppressing re-occurring exceptions unless the exception changes", ex, toString());
lastThrownException = ex;
}
} finally {
onTaskCompletion();
}
}
private static boolean sameException(Exception left, Exception right) {
if (left.getClass() == right.getClass()) {
if ((left.getMessage() != null && left.getMessage().equals(right.getMessage()))
|| left.getMessage() == right.getMessage()) {
StackTraceElement[] stackTraceLeft = left.getStackTrace();
StackTraceElement[] stackTraceRight = right.getStackTrace();
if (stackTraceLeft.length == stackTraceRight.length) {
for (int i = 0; i < stackTraceLeft.length; i++) {
if (stackTraceLeft[i].equals(stackTraceRight[i]) == false) {
return false;
}
}
return true;
}
}
}
return false;
}
protected abstract void runInternal();
protected String getThreadPool() {
return ThreadPool.Names.SAME;
}
@Override
public void close() {
if (closed.compareAndSet(false, true)) {
FutureUtils.cancel(scheduledFuture);
scheduledFuture = null;
}
}
TimeValue getInterval() {
return interval;
}
boolean isClosed() {
return this.closed.get();
}
}
/**
* FSyncs the translog for all shards of this index in a defined interval.
*/
final static class AsyncTranslogFSync extends BaseAsyncTask {
AsyncTranslogFSync(IndexService indexService) {
super(indexService, indexService.getIndexSettings().getTranslogSyncInterval());
}
protected String getThreadPool() {
return ThreadPool.Names.FLUSH;
}
@Override
protected void runInternal() {
indexService.maybeFSyncTranslogs();
}
@Override
public String toString() {
return "translog_sync";
}
}
final class AsyncRefreshTask extends BaseAsyncTask {
AsyncRefreshTask(IndexService indexService) {
super(indexService, indexService.getIndexSettings().getRefreshInterval());
}
@Override
protected void runInternal() {
indexService.maybeRefreshEngine();
}
protected String getThreadPool() {
return ThreadPool.Names.REFRESH;
}
@Override
public String toString() {
return "refresh";
}
}
AsyncRefreshTask getRefreshTask() { // for tests
return refreshTask;
}
AsyncTranslogFSync getFsyncTask() { // for tests
return fsyncTask;
}
} }

View File

@ -26,8 +26,10 @@ import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.FutureUtils;
import org.elasticsearch.index.mapper.internal.AllFieldMapper; import org.elasticsearch.index.mapper.internal.AllFieldMapper;
import org.elasticsearch.index.translog.Translog; import org.elasticsearch.index.translog.Translog;
import org.elasticsearch.threadpool.ThreadPool;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -35,6 +37,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -54,6 +57,8 @@ public final class IndexSettings {
public static final String ALLOW_UNMAPPED = "index.query.parse.allow_unmapped_fields"; public static final String ALLOW_UNMAPPED = "index.query.parse.allow_unmapped_fields";
public static final String INDEX_TRANSLOG_SYNC_INTERVAL = "index.translog.sync_interval"; public static final String INDEX_TRANSLOG_SYNC_INTERVAL = "index.translog.sync_interval";
public static final String INDEX_TRANSLOG_DURABILITY = "index.translog.durability"; public static final String INDEX_TRANSLOG_DURABILITY = "index.translog.durability";
public static final String INDEX_REFRESH_INTERVAL = "index.refresh_interval";
public static final TimeValue DEFAULT_REFRESH_INTERVAL = new TimeValue(1, TimeUnit.SECONDS);
private final String uuid; private final String uuid;
private final List<Consumer<Settings>> updateListeners; private final List<Consumer<Settings>> updateListeners;
@ -76,6 +81,9 @@ public final class IndexSettings {
private final Predicate<String> indexNameMatcher; private final Predicate<String> indexNameMatcher;
private volatile Translog.Durability durability; private volatile Translog.Durability durability;
private final TimeValue syncInterval; private final TimeValue syncInterval;
private volatile TimeValue refreshInterval;
/** /**
* Returns the default search field for this index. * Returns the default search field for this index.
@ -156,7 +164,7 @@ public final class IndexSettings {
final String value = settings.get(INDEX_TRANSLOG_DURABILITY, Translog.Durability.REQUEST.name()); final String value = settings.get(INDEX_TRANSLOG_DURABILITY, Translog.Durability.REQUEST.name());
this.durability = getFromSettings(settings, Translog.Durability.REQUEST); this.durability = getFromSettings(settings, Translog.Durability.REQUEST);
syncInterval = settings.getAsTime(INDEX_TRANSLOG_SYNC_INTERVAL, TimeValue.timeValueSeconds(5)); syncInterval = settings.getAsTime(INDEX_TRANSLOG_SYNC_INTERVAL, TimeValue.timeValueSeconds(5));
refreshInterval = settings.getAsTime(INDEX_REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL);
assert indexNameMatcher.test(indexMetaData.getIndex()); assert indexNameMatcher.test(indexMetaData.getIndex());
} }
@ -346,10 +354,19 @@ public final class IndexSettings {
logger.info("updating durability from [{}] to [{}]", this.durability, durability); logger.info("updating durability from [{}] to [{}]", this.durability, durability);
this.durability = durability; this.durability = durability;
} }
TimeValue refreshInterval = settings.getAsTime(IndexSettings.INDEX_REFRESH_INTERVAL, this.refreshInterval);
if (!refreshInterval.equals(this.refreshInterval)) {
logger.info("updating refresh_interval from [{}] to [{}]", this.refreshInterval, refreshInterval);
this.refreshInterval = refreshInterval;
}
} }
public TimeValue getTranslogSyncInterval() { public TimeValue getTranslogSyncInterval() {
return syncInterval; return syncInterval;
} }
public TimeValue getRefreshInterval() {
return refreshInterval;
}
} }

View File

@ -84,7 +84,6 @@ public final class EngineConfig {
/** if set to true the engine will start even if the translog id in the commit point can not be found */ /** if set to true the engine will start even if the translog id in the commit point can not be found */
public static final String INDEX_FORCE_NEW_TRANSLOG = "index.engine.force_new_translog"; public static final String INDEX_FORCE_NEW_TRANSLOG = "index.engine.force_new_translog";
public static final TimeValue DEFAULT_REFRESH_INTERVAL = new TimeValue(1, TimeUnit.SECONDS);
public static final TimeValue DEFAULT_GC_DELETES = TimeValue.timeValueSeconds(60); public static final TimeValue DEFAULT_GC_DELETES = TimeValue.timeValueSeconds(60);
private static final String DEFAULT_CODEC_NAME = "default"; private static final String DEFAULT_CODEC_NAME = "default";

View File

@ -519,16 +519,17 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
return termsFilter; return termsFilter;
} }
} else { } else {
// Current bool filter requires that at least one should clause matches, even with a must clause. BooleanQuery.Builder typesBool = new BooleanQuery.Builder();
BooleanQuery.Builder bool = new BooleanQuery.Builder();
for (String type : types) { for (String type : types) {
DocumentMapper docMapper = documentMapper(type); DocumentMapper docMapper = documentMapper(type);
if (docMapper == null) { if (docMapper == null) {
bool.add(new TermQuery(new Term(TypeFieldMapper.NAME, type)), BooleanClause.Occur.SHOULD); typesBool.add(new TermQuery(new Term(TypeFieldMapper.NAME, type)), BooleanClause.Occur.SHOULD);
} else { } else {
bool.add(docMapper.typeFilter(), BooleanClause.Occur.SHOULD); typesBool.add(docMapper.typeFilter(), BooleanClause.Occur.SHOULD);
} }
} }
BooleanQuery.Builder bool = new BooleanQuery.Builder();
bool.add(typesBool.build(), Occur.MUST);
if (filterPercolateType) { if (filterPercolateType) {
bool.add(percolatorType, BooleanClause.Occur.MUST_NOT); bool.add(percolatorType, BooleanClause.Occur.MUST_NOT);
} }

View File

@ -44,7 +44,6 @@ import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.lease.Releasables;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.metrics.MeanMetric; import org.elasticsearch.common.metrics.MeanMetric;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -173,8 +172,6 @@ public class IndexShard extends AbstractIndexShardComponent {
* being indexed/deleted. */ * being indexed/deleted. */
private final AtomicLong writingBytes = new AtomicLong(); private final AtomicLong writingBytes = new AtomicLong();
private TimeValue refreshInterval;
private volatile ScheduledFuture<?> refreshScheduledFuture; private volatile ScheduledFuture<?> refreshScheduledFuture;
protected volatile ShardRouting shardRouting; protected volatile ShardRouting shardRouting;
protected volatile IndexShardState state; protected volatile IndexShardState state;
@ -200,7 +197,6 @@ public class IndexShard extends AbstractIndexShardComponent {
*/ */
public static final String INDEX_FLUSH_ON_CLOSE = "index.flush_on_close"; public static final String INDEX_FLUSH_ON_CLOSE = "index.flush_on_close";
public static final String INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE = "index.translog.flush_threshold_size"; public static final String INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE = "index.translog.flush_threshold_size";
public static final String INDEX_REFRESH_INTERVAL = "index.refresh_interval";
private final ShardPath path; private final ShardPath path;
@ -249,7 +245,6 @@ public class IndexShard extends AbstractIndexShardComponent {
this.indexFieldDataService = indexFieldDataService; this.indexFieldDataService = indexFieldDataService;
this.shardBitsetFilterCache = new ShardBitsetFilterCache(shardId, indexSettings); this.shardBitsetFilterCache = new ShardBitsetFilterCache(shardId, indexSettings);
state = IndexShardState.CREATED; state = IndexShardState.CREATED;
this.refreshInterval = settings.getAsTime(INDEX_REFRESH_INTERVAL, EngineConfig.DEFAULT_REFRESH_INTERVAL);
this.flushOnClose = settings.getAsBoolean(INDEX_FLUSH_ON_CLOSE, true); this.flushOnClose = settings.getAsBoolean(INDEX_FLUSH_ON_CLOSE, true);
this.path = path; this.path = path;
this.mergePolicyConfig = new MergePolicyConfig(logger, settings); this.mergePolicyConfig = new MergePolicyConfig(logger, settings);
@ -561,23 +556,25 @@ public class IndexShard extends AbstractIndexShardComponent {
/** Writes all indexing changes to disk and opens a new searcher reflecting all changes. This can throw {@link EngineClosedException}. */ /** Writes all indexing changes to disk and opens a new searcher reflecting all changes. This can throw {@link EngineClosedException}. */
public void refresh(String source) { public void refresh(String source) {
verifyNotClosed(); verifyNotClosed();
if (canIndex()) { if (getEngine().refreshNeeded()) {
long bytes = getEngine().getIndexBufferRAMBytesUsed(); if (canIndex()) {
writingBytes.addAndGet(bytes); long bytes = getEngine().getIndexBufferRAMBytesUsed();
try { writingBytes.addAndGet(bytes);
logger.debug("refresh with source [{}] indexBufferRAMBytesUsed [{}]", source, new ByteSizeValue(bytes)); try {
logger.debug("refresh with source [{}] indexBufferRAMBytesUsed [{}]", source, new ByteSizeValue(bytes));
long time = System.nanoTime();
getEngine().refresh(source);
refreshMetric.inc(System.nanoTime() - time);
} finally {
logger.debug("remove [{}] writing bytes for shard [{}]", new ByteSizeValue(bytes), shardId());
writingBytes.addAndGet(-bytes);
}
} else {
logger.debug("refresh with source [{}]", source);
long time = System.nanoTime(); long time = System.nanoTime();
getEngine().refresh(source); getEngine().refresh(source);
refreshMetric.inc(System.nanoTime() - time); refreshMetric.inc(System.nanoTime() - time);
} finally {
logger.debug("remove [{}] writing bytes for shard [{}]", new ByteSizeValue(bytes), shardId());
writingBytes.addAndGet(-bytes);
} }
} else {
logger.debug("refresh with source [{}]", source);
long time = System.nanoTime();
getEngine().refresh(source);
refreshMetric.inc(System.nanoTime() - time);
} }
} }
@ -954,7 +951,6 @@ public class IndexShard extends AbstractIndexShardComponent {
public void finalizeRecovery() { public void finalizeRecovery() {
recoveryState().setStage(RecoveryState.Stage.FINALIZE); recoveryState().setStage(RecoveryState.Stage.FINALIZE);
getEngine().refresh("recovery_finalization"); getEngine().refresh("recovery_finalization");
startScheduledTasksIfNeeded();
engineConfig.setEnableGcDeletes(true); engineConfig.setEnableGcDeletes(true);
} }
@ -1022,15 +1018,6 @@ public class IndexShard extends AbstractIndexShardComponent {
} }
} }
private void startScheduledTasksIfNeeded() {
if (refreshInterval.millis() > 0) {
refreshScheduledFuture = threadPool.schedule(refreshInterval, ThreadPool.Names.SAME, new EngineRefresher());
logger.debug("scheduling refresher every {}", refreshInterval);
} else {
logger.debug("scheduled refresher disabled");
}
}
/** Returns number of heap bytes used by the indexing buffer for this shard, or 0 if the shard is closed */ /** Returns number of heap bytes used by the indexing buffer for this shard, or 0 if the shard is closed */
public long getIndexBufferRAMBytesUsed() { public long getIndexBufferRAMBytesUsed() {
Engine engine = getEngineOrNull(); Engine engine = getEngineOrNull();
@ -1133,22 +1120,6 @@ public class IndexShard extends AbstractIndexShardComponent {
this.flushOnClose = flushOnClose; this.flushOnClose = flushOnClose;
} }
TimeValue refreshInterval = settings.getAsTime(INDEX_REFRESH_INTERVAL, this.refreshInterval);
if (!refreshInterval.equals(this.refreshInterval)) {
logger.info("updating refresh_interval from [{}] to [{}]", this.refreshInterval, refreshInterval);
if (refreshScheduledFuture != null) {
// NOTE: we pass false here so we do NOT attempt Thread.interrupt if EngineRefresher.run is currently running. This is
// very important, because doing so can cause files to suddenly be closed if they were doing IO when the interrupt
// hit. See https://issues.apache.org/jira/browse/LUCENE-2239
FutureUtils.cancel(refreshScheduledFuture);
refreshScheduledFuture = null;
}
this.refreshInterval = refreshInterval;
if (refreshInterval.millis() > 0) {
refreshScheduledFuture = threadPool.schedule(refreshInterval, ThreadPool.Names.SAME, new EngineRefresher());
}
}
long gcDeletesInMillis = settings.getAsTime(EngineConfig.INDEX_GC_DELETES_SETTING, TimeValue.timeValueMillis(config.getGcDeletesInMillis())).millis(); long gcDeletesInMillis = settings.getAsTime(EngineConfig.INDEX_GC_DELETES_SETTING, TimeValue.timeValueMillis(config.getGcDeletesInMillis())).millis();
if (gcDeletesInMillis != config.getGcDeletesInMillis()) { if (gcDeletesInMillis != config.getGcDeletesInMillis()) {
logger.info("updating {} from [{}] to [{}]", EngineConfig.INDEX_GC_DELETES_SETTING, TimeValue.timeValueMillis(config.getGcDeletesInMillis()), TimeValue.timeValueMillis(gcDeletesInMillis)); logger.info("updating {} from [{}] to [{}]", EngineConfig.INDEX_GC_DELETES_SETTING, TimeValue.timeValueMillis(config.getGcDeletesInMillis()), TimeValue.timeValueMillis(gcDeletesInMillis));
@ -1284,43 +1255,6 @@ public class IndexShard extends AbstractIndexShardComponent {
internalIndexingStats.noopUpdate(type); internalIndexingStats.noopUpdate(type);
} }
final class EngineRefresher implements Runnable {
@Override
public void run() {
// we check before if a refresh is needed, if not, we reschedule, otherwise, we fork, refresh, and then reschedule
if (!getEngine().refreshNeeded()) {
reschedule();
return;
}
threadPool.executor(ThreadPool.Names.REFRESH).execute(new Runnable() {
@Override
public void run() {
try {
// TODO: now that we use refresh to clear the indexing buffer, we should check here if we did that "recently" and
// reschedule if so...
if (getEngine().refreshNeeded()) {
refresh("schedule");
}
} catch (Exception e) {
handleRefreshException(e);
}
reschedule();
}
});
}
/**
* Schedules another (future) refresh, if refresh_interval is still enabled.
*/
private void reschedule() {
synchronized (mutex) {
if (state != IndexShardState.CLOSED && refreshInterval.millis() > 0) {
refreshScheduledFuture = threadPool.schedule(refreshInterval, ThreadPool.Names.SAME, this);
}
}
}
}
private void checkIndex() throws IOException { private void checkIndex() throws IOException {
if (store.tryIncRef()) { if (store.tryIncRef()) {

View File

@ -256,6 +256,8 @@ public class IndexingMemoryController extends AbstractComponent implements Index
} finally { } finally {
runLock.unlock(); runLock.unlock();
} }
// Could be while we were checking, more bytes arrived:
totalBytes = bytesWrittenSinceCheck.addAndGet(bytes);
} else { } else {
break; break;
} }

View File

@ -168,11 +168,6 @@ public class InternalSettingsPreparer {
output.put(ClusterName.SETTING, ClusterName.DEFAULT.value()); output.put(ClusterName.SETTING, ClusterName.DEFAULT.value());
} }
String v = output.get(Settings.SETTINGS_REQUIRE_UNITS);
if (v != null) {
Settings.setSettingsRequireUnits(Booleans.parseBoolean(v, true));
}
replacePromptPlaceholders(output, terminal); replacePromptPlaceholders(output, terminal);
// all settings placeholders have been resolved. resolve the value for the name setting by checking for name, // all settings placeholders have been resolved. resolve the value for the name setting by checking for name,
// then looking for node.name, and finally generate one if needed // then looking for node.name, and finally generate one if needed

View File

@ -46,7 +46,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.env.NodeEnvironment; import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.gateway.MetaDataStateFormat; import org.elasticsearch.gateway.MetaDataStateFormat;
import org.elasticsearch.index.engine.EngineConfig; import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.engine.Segment; import org.elasticsearch.index.engine.Segment;
import org.elasticsearch.index.mapper.string.StringFieldMapperPositionIncrementGapTests; import org.elasticsearch.index.mapper.string.StringFieldMapperPositionIncrementGapTests;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
@ -383,7 +383,7 @@ public class OldIndexBackwardsCompatibilityIT extends ESIntegTestCase {
assertThat(source, Matchers.hasKey("foo")); assertThat(source, Matchers.hasKey("foo"));
assertAcked(client().admin().indices().prepareUpdateSettings(indexName).setSettings(Settings.builder() assertAcked(client().admin().indices().prepareUpdateSettings(indexName).setSettings(Settings.builder()
.put("refresh_interval", EngineConfig.DEFAULT_REFRESH_INTERVAL) .put("refresh_interval", IndexSettings.DEFAULT_REFRESH_INTERVAL)
.build())); .build()));
} }

View File

@ -329,19 +329,6 @@ public class ClusterSettingsIT extends ESIntegTestCase {
} }
} }
public void testMissingUnitsLenient() {
try {
createNode(Settings.builder().put(Settings.SETTINGS_REQUIRE_UNITS, "false").build());
assertAcked(prepareCreate("test"));
ensureGreen();
client().admin().indices().prepareUpdateSettings("test").setSettings(Settings.builder().put("index.refresh_interval", "10")).execute().actionGet();
} finally {
// Restore the default so subsequent tests require units:
assertFalse(Settings.getSettingsRequireUnits());
Settings.setSettingsRequireUnits(true);
}
}
private void createNode(Settings settings) { private void createNode(Settings settings) {
internalCluster().startNode(Settings.builder() internalCluster().startNode(Settings.builder()
.put(ClusterName.SETTING, "ClusterSettingsIT") .put(ClusterName.SETTING, "ClusterSettingsIT")

View File

@ -34,6 +34,7 @@ import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.Polygon;
import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;

View File

@ -28,6 +28,8 @@ import com.spatial4j.core.shape.impl.PointImpl;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.Polygon;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder; import org.elasticsearch.common.geo.builders.LineStringBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder;
@ -50,7 +52,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testNewRectangle() { public void testNewRectangle() {
Rectangle rectangle = ShapeBuilders.newEnvelope().topLeft(-45, 30).bottomRight(45, -30).build(); Rectangle rectangle = ShapeBuilders.newEnvelope(new Coordinate(-45, 30), new Coordinate(45, -30)).build();
assertEquals(-45D, rectangle.getMinX(), 0.0d); assertEquals(-45D, rectangle.getMinX(), 0.0d);
assertEquals(-30D, rectangle.getMinY(), 0.0d); assertEquals(-30D, rectangle.getMinY(), 0.0d);
assertEquals(45D, rectangle.getMaxX(), 0.0d); assertEquals(45D, rectangle.getMaxX(), 0.0d);
@ -58,12 +60,12 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testNewPolygon() { public void testNewPolygon() {
Polygon polygon = ShapeBuilders.newPolygon() Polygon polygon = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-45, 30) .coordinate(-45, 30)
.point(45, 30) .coordinate(45, 30)
.point(45, -30) .coordinate(45, -30)
.point(-45, -30) .coordinate(-45, -30)
.point(-45, 30).toPolygon(); .coordinate(-45, 30)).toPolygon();
LineString exterior = polygon.getExteriorRing(); LineString exterior = polygon.getExteriorRing();
assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30)); assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30));
@ -73,12 +75,12 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testNewPolygon_coordinate() { public void testNewPolygon_coordinate() {
Polygon polygon = ShapeBuilders.newPolygon() Polygon polygon = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(new Coordinate(-45, 30)) .coordinate(new Coordinate(-45, 30))
.point(new Coordinate(45, 30)) .coordinate(new Coordinate(45, 30))
.point(new Coordinate(45, -30)) .coordinate(new Coordinate(45, -30))
.point(new Coordinate(-45, -30)) .coordinate(new Coordinate(-45, -30))
.point(new Coordinate(-45, 30)).toPolygon(); .coordinate(new Coordinate(-45, 30))).toPolygon();
LineString exterior = polygon.getExteriorRing(); LineString exterior = polygon.getExteriorRing();
assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30)); assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30));
@ -88,8 +90,9 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testNewPolygon_coordinates() { public void testNewPolygon_coordinates() {
Polygon polygon = ShapeBuilders.newPolygon() Polygon polygon = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.points(new Coordinate(-45, 30), new Coordinate(45, 30), new Coordinate(45, -30), new Coordinate(-45, -30), new Coordinate(-45, 30)).toPolygon(); .coordinates(new Coordinate(-45, 30), new Coordinate(45, 30), new Coordinate(45, -30), new Coordinate(-45, -30), new Coordinate(-45, 30))
).toPolygon();
LineString exterior = polygon.getExteriorRing(); LineString exterior = polygon.getExteriorRing();
assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30)); assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30));
@ -100,86 +103,93 @@ public class ShapeBuilderTests extends ESTestCase {
public void testLineStringBuilder() { public void testLineStringBuilder() {
// Building a simple LineString // Building a simple LineString
ShapeBuilders.newLineString() ShapeBuilders.newLineString(new CoordinatesBuilder()
.point(-130.0, 55.0) .coordinate(-130.0, 55.0)
.point(-130.0, -40.0) .coordinate(-130.0, -40.0)
.point(-15.0, -40.0) .coordinate(-15.0, -40.0)
.point(-20.0, 50.0) .coordinate(-20.0, 50.0)
.point(-45.0, 50.0) .coordinate(-45.0, 50.0)
.point(-45.0, -15.0) .coordinate(-45.0, -15.0)
.point(-110.0, -15.0) .coordinate(-110.0, -15.0)
.point(-110.0, 55.0).build(); .coordinate(-110.0, 55.0)).build();
// Building a linestring that needs to be wrapped // Building a linestring that needs to be wrapped
ShapeBuilders.newLineString() ShapeBuilders.newLineString(new CoordinatesBuilder()
.point(100.0, 50.0) .coordinate(100.0, 50.0)
.point(110.0, -40.0) .coordinate(110.0, -40.0)
.point(240.0, -40.0) .coordinate(240.0, -40.0)
.point(230.0, 60.0) .coordinate(230.0, 60.0)
.point(200.0, 60.0) .coordinate(200.0, 60.0)
.point(200.0, -30.0) .coordinate(200.0, -30.0)
.point(130.0, -30.0) .coordinate(130.0, -30.0)
.point(130.0, 60.0) .coordinate(130.0, 60.0)
)
.build(); .build();
// Building a lineString on the dateline // Building a lineString on the dateline
ShapeBuilders.newLineString() ShapeBuilders.newLineString(new CoordinatesBuilder()
.point(-180.0, 80.0) .coordinate(-180.0, 80.0)
.point(-180.0, 40.0) .coordinate(-180.0, 40.0)
.point(-180.0, -40.0) .coordinate(-180.0, -40.0)
.point(-180.0, -80.0) .coordinate(-180.0, -80.0)
)
.build(); .build();
// Building a lineString on the dateline // Building a lineString on the dateline
ShapeBuilders.newLineString() ShapeBuilders.newLineString(new CoordinatesBuilder()
.point(180.0, 80.0) .coordinate(180.0, 80.0)
.point(180.0, 40.0) .coordinate(180.0, 40.0)
.point(180.0, -40.0) .coordinate(180.0, -40.0)
.point(180.0, -80.0) .coordinate(180.0, -80.0)
)
.build(); .build();
} }
public void testMultiLineString() { public void testMultiLineString() {
ShapeBuilders.newMultiLinestring() ShapeBuilders.newMultiLinestring()
.linestring(new LineStringBuilder() .linestring(new LineStringBuilder(new CoordinatesBuilder()
.point(-100.0, 50.0) .coordinate(-100.0, 50.0)
.point(50.0, 50.0) .coordinate(50.0, 50.0)
.point(50.0, 20.0) .coordinate(50.0, 20.0)
.point(-100.0, 20.0) .coordinate(-100.0, 20.0)
)
) )
.linestring(new LineStringBuilder() .linestring(new LineStringBuilder(new CoordinatesBuilder()
.point(-100.0, 20.0) .coordinate(-100.0, 20.0)
.point(50.0, 20.0) .coordinate(50.0, 20.0)
.point(50.0, 0.0) .coordinate(50.0, 0.0)
.point(-100.0, 0.0) .coordinate(-100.0, 0.0)
)
) )
.build(); .build();
// LineString that needs to be wrappped // LineString that needs to be wrappped
ShapeBuilders.newMultiLinestring() ShapeBuilders.newMultiLinestring()
.linestring(new LineStringBuilder() .linestring(new LineStringBuilder(new CoordinatesBuilder()
.point(150.0, 60.0) .coordinate(150.0, 60.0)
.point(200.0, 60.0) .coordinate(200.0, 60.0)
.point(200.0, 40.0) .coordinate(200.0, 40.0)
.point(150.0, 40.0) .coordinate(150.0, 40.0)
)
)
.linestring(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(150.0, 20.0)
.coordinate(200.0, 20.0)
.coordinate(200.0, 0.0)
.coordinate(150.0, 0.0)
) )
.linestring(new LineStringBuilder()
.point(150.0, 20.0)
.point(200.0, 20.0)
.point(200.0, 0.0)
.point(150.0, 0.0)
) )
.build(); .build();
} }
public void testPolygonSelfIntersection() { public void testPolygonSelfIntersection() {
try { try {
ShapeBuilders.newPolygon() ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-40.0, 50.0) .coordinate(-40.0, 50.0)
.point(40.0, 50.0) .coordinate(40.0, 50.0)
.point(-40.0, -50.0) .coordinate(-40.0, -50.0)
.point(40.0, -50.0) .coordinate(40.0, -50.0).close())
.close().build(); .build();
fail("Expected InvalidShapeException"); fail("Expected InvalidShapeException");
} catch (InvalidShapeException e) { } catch (InvalidShapeException e) {
assertThat(e.getMessage(), containsString("Self-intersection at or near point (0.0")); assertThat(e.getMessage(), containsString("Self-intersection at or near point (0.0"));
@ -212,22 +222,26 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testPolygonWrapping() { public void testPolygonWrapping() {
Shape shape = ShapeBuilders.newPolygon() Shape shape = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-150.0, 65.0) .coordinate(-150.0, 65.0)
.point(-250.0, 65.0) .coordinate(-250.0, 65.0)
.point(-250.0, -65.0) .coordinate(-250.0, -65.0)
.point(-150.0, -65.0) .coordinate(-150.0, -65.0)
.close().build(); .close()
)
.build();
assertMultiPolygon(shape); assertMultiPolygon(shape);
} }
public void testLineStringWrapping() { public void testLineStringWrapping() {
Shape shape = ShapeBuilders.newLineString() Shape shape = ShapeBuilders.newLineString(new CoordinatesBuilder()
.point(-150.0, 65.0) .coordinate(-150.0, 65.0)
.point(-250.0, 65.0) .coordinate(-250.0, 65.0)
.point(-250.0, -65.0) .coordinate(-250.0, -65.0)
.point(-150.0, -65.0) .coordinate(-150.0, -65.0)
.close()
)
.build(); .build();
assertMultiLineString(shape); assertMultiLineString(shape);
} }
@ -238,36 +252,39 @@ public class ShapeBuilderTests extends ESTestCase {
// expected results: 3 polygons, 1 with a hole // expected results: 3 polygons, 1 with a hole
// a giant c shape // a giant c shape
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(174,0) .coordinate(174,0)
.point(-176,0) .coordinate(-176,0)
.point(-176,3) .coordinate(-176,3)
.point(177,3) .coordinate(177,3)
.point(177,5) .coordinate(177,5)
.point(-176,5) .coordinate(-176,5)
.point(-176,8) .coordinate(-176,8)
.point(174,8) .coordinate(174,8)
.point(174,0); .coordinate(174,0)
);
// 3/4 of an embedded 'c', crossing dateline once // 3/4 of an embedded 'c', crossing dateline once
builder.hole(new LineStringBuilder() builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(175, 1) .coordinate(175, 1)
.point(175, 7) .coordinate(175, 7)
.point(-178, 7) .coordinate(-178, 7)
.point(-178, 6) .coordinate(-178, 6)
.point(176, 6) .coordinate(176, 6)
.point(176, 2) .coordinate(176, 2)
.point(179, 2) .coordinate(179, 2)
.point(179,1) .coordinate(179,1)
.point(175, 1)); .coordinate(175, 1)
));
// embedded hole right of the dateline // embedded hole right of the dateline
builder.hole(new LineStringBuilder() builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-179, 1) .coordinate(-179, 1)
.point(-179, 2) .coordinate(-179, 2)
.point(-177, 2) .coordinate(-177, 2)
.point(-177,1) .coordinate(-177,1)
.point(-179,1)); .coordinate(-179,1)
));
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertMultiPolygon(shape); assertMultiPolygon(shape);
@ -279,141 +296,150 @@ public class ShapeBuilderTests extends ESTestCase {
// expected results: 3 polygons, 1 with a hole // expected results: 3 polygons, 1 with a hole
// a giant c shape // a giant c shape
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-186,0) .coordinate(-186,0)
.point(-176,0) .coordinate(-176,0)
.point(-176,3) .coordinate(-176,3)
.point(-183,3) .coordinate(-183,3)
.point(-183,5) .coordinate(-183,5)
.point(-176,5) .coordinate(-176,5)
.point(-176,8) .coordinate(-176,8)
.point(-186,8) .coordinate(-186,8)
.point(-186,0); .coordinate(-186,0)
);
// 3/4 of an embedded 'c', crossing dateline once // 3/4 of an embedded 'c', crossing dateline once
builder.hole(new LineStringBuilder() builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-185,1) .coordinate(-185,1)
.point(-181,1) .coordinate(-181,1)
.point(-181,2) .coordinate(-181,2)
.point(-184,2) .coordinate(-184,2)
.point(-184,6) .coordinate(-184,6)
.point(-178,6) .coordinate(-178,6)
.point(-178,7) .coordinate(-178,7)
.point(-185,7) .coordinate(-185,7)
.point(-185,1)); .coordinate(-185,1)
));
// embedded hole right of the dateline // embedded hole right of the dateline
builder.hole(new LineStringBuilder() builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-179,1) .coordinate(-179,1)
.point(-177,1) .coordinate(-177,1)
.point(-177,2) .coordinate(-177,2)
.point(-179,2) .coordinate(-179,2)
.point(-179,1)); .coordinate(-179,1)
));
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertMultiPolygon(shape); assertMultiPolygon(shape);
} }
public void testComplexShapeWithHole() { public void testComplexShapeWithHole() {
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-85.0018514,37.1311314) .coordinate(-85.0018514,37.1311314)
.point(-85.0016645,37.1315293) .coordinate(-85.0016645,37.1315293)
.point(-85.0016246,37.1317069) .coordinate(-85.0016246,37.1317069)
.point(-85.0016526,37.1318183) .coordinate(-85.0016526,37.1318183)
.point(-85.0017119,37.1319196) .coordinate(-85.0017119,37.1319196)
.point(-85.0019371,37.1321182) .coordinate(-85.0019371,37.1321182)
.point(-85.0019972,37.1322115) .coordinate(-85.0019972,37.1322115)
.point(-85.0019942,37.1323234) .coordinate(-85.0019942,37.1323234)
.point(-85.0019543,37.1324336) .coordinate(-85.0019543,37.1324336)
.point(-85.001906,37.1324985) .coordinate(-85.001906,37.1324985)
.point(-85.001834,37.1325497) .coordinate(-85.001834,37.1325497)
.point(-85.0016965,37.1325907) .coordinate(-85.0016965,37.1325907)
.point(-85.0016011,37.1325873) .coordinate(-85.0016011,37.1325873)
.point(-85.0014816,37.1325353) .coordinate(-85.0014816,37.1325353)
.point(-85.0011755,37.1323509) .coordinate(-85.0011755,37.1323509)
.point(-85.000955,37.1322802) .coordinate(-85.000955,37.1322802)
.point(-85.0006241,37.1322529) .coordinate(-85.0006241,37.1322529)
.point(-85.0000002,37.1322307) .coordinate(-85.0000002,37.1322307)
.point(-84.9994,37.1323001) .coordinate(-84.9994,37.1323001)
.point(-84.999109,37.1322864) .coordinate(-84.999109,37.1322864)
.point(-84.998934,37.1322415) .coordinate(-84.998934,37.1322415)
.point(-84.9988639,37.1321888) .coordinate(-84.9988639,37.1321888)
.point(-84.9987841,37.1320944) .coordinate(-84.9987841,37.1320944)
.point(-84.9987208,37.131954) .coordinate(-84.9987208,37.131954)
.point(-84.998736,37.1316611) .coordinate(-84.998736,37.1316611)
.point(-84.9988091,37.131334) .coordinate(-84.9988091,37.131334)
.point(-84.9989283,37.1311337) .coordinate(-84.9989283,37.1311337)
.point(-84.9991943,37.1309198) .coordinate(-84.9991943,37.1309198)
.point(-84.9993573,37.1308459) .coordinate(-84.9993573,37.1308459)
.point(-84.9995888,37.1307924) .coordinate(-84.9995888,37.1307924)
.point(-84.9998746,37.130806) .coordinate(-84.9998746,37.130806)
.point(-85.0000002,37.1308358) .coordinate(-85.0000002,37.1308358)
.point(-85.0004984,37.1310658) .coordinate(-85.0004984,37.1310658)
.point(-85.0008008,37.1311625) .coordinate(-85.0008008,37.1311625)
.point(-85.0009461,37.1311684) .coordinate(-85.0009461,37.1311684)
.point(-85.0011373,37.1311515) .coordinate(-85.0011373,37.1311515)
.point(-85.0016455,37.1310491) .coordinate(-85.0016455,37.1310491)
.point(-85.0018514,37.1311314); .coordinate(-85.0018514,37.1311314)
);
builder.hole(new LineStringBuilder() builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-85.0000002,37.1317672) .coordinate(-85.0000002,37.1317672)
.point(-85.0001983,37.1317538) .coordinate(-85.0001983,37.1317538)
.point(-85.0003378,37.1317582) .coordinate(-85.0003378,37.1317582)
.point(-85.0004697,37.131792) .coordinate(-85.0004697,37.131792)
.point(-85.0008048,37.1319439) .coordinate(-85.0008048,37.1319439)
.point(-85.0009342,37.1319838) .coordinate(-85.0009342,37.1319838)
.point(-85.0010184,37.1319463) .coordinate(-85.0010184,37.1319463)
.point(-85.0010618,37.13184) .coordinate(-85.0010618,37.13184)
.point(-85.0010057,37.1315102) .coordinate(-85.0010057,37.1315102)
.point(-85.000977,37.1314403) .coordinate(-85.000977,37.1314403)
.point(-85.0009182,37.1313793) .coordinate(-85.0009182,37.1313793)
.point(-85.0005366,37.1312209) .coordinate(-85.0005366,37.1312209)
.point(-85.000224,37.1311466) .coordinate(-85.000224,37.1311466)
.point(-85.000087,37.1311356) .coordinate(-85.000087,37.1311356)
.point(-85.0000002,37.1311433) .coordinate(-85.0000002,37.1311433)
.point(-84.9995021,37.1312336) .coordinate(-84.9995021,37.1312336)
.point(-84.9993308,37.1312859) .coordinate(-84.9993308,37.1312859)
.point(-84.9992567,37.1313252) .coordinate(-84.9992567,37.1313252)
.point(-84.9991868,37.1314277) .coordinate(-84.9991868,37.1314277)
.point(-84.9991593,37.1315381) .coordinate(-84.9991593,37.1315381)
.point(-84.9991841,37.1316527) .coordinate(-84.9991841,37.1316527)
.point(-84.9992329,37.1317117) .coordinate(-84.9992329,37.1317117)
.point(-84.9993527,37.1317788) .coordinate(-84.9993527,37.1317788)
.point(-84.9994931,37.1318061) .coordinate(-84.9994931,37.1318061)
.point(-84.9996815,37.1317979) .coordinate(-84.9996815,37.1317979)
.point(-85.0000002,37.1317672)); .coordinate(-85.0000002,37.1317672)
)
);
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertPolygon(shape); assertPolygon(shape);
} }
public void testShapeWithHoleAtEdgeEndPoints() { public void testShapeWithHoleAtEdgeEndPoints() {
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-4, 2) .coordinate(-4, 2)
.point(4, 2) .coordinate(4, 2)
.point(6, 0) .coordinate(6, 0)
.point(4, -2) .coordinate(4, -2)
.point(-4, -2) .coordinate(-4, -2)
.point(-6, 0) .coordinate(-6, 0)
.point(-4, 2); .coordinate(-4, 2)
);
builder.hole(new LineStringBuilder() builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(4, 1) .coordinate(4, 1)
.point(4, -1) .coordinate(4, -1)
.point(-4, -1) .coordinate(-4, -1)
.point(-4, 1) .coordinate(-4, 1)
.point(4, 1)); .coordinate(4, 1)
));
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertPolygon(shape); assertPolygon(shape);
} }
public void testShapeWithPointOnDateline() { public void testShapeWithPointOnDateline() {
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(180, 0) .coordinate(180, 0)
.point(176, 4) .coordinate(176, 4)
.point(176, -4) .coordinate(176, -4)
.point(180, 0); .coordinate(180, 0)
);
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertPolygon(shape); assertPolygon(shape);
@ -421,21 +447,23 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithEdgeAlongDateline() { public void testShapeWithEdgeAlongDateline() {
// test case 1: test the positive side of the dateline // test case 1: test the positive side of the dateline
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(180, 0) .coordinate(180, 0)
.point(176, 4) .coordinate(176, 4)
.point(180, -4) .coordinate(180, -4)
.point(180, 0); .coordinate(180, 0)
);
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertPolygon(shape); assertPolygon(shape);
// test case 2: test the negative side of the dateline // test case 2: test the negative side of the dateline
builder = ShapeBuilders.newPolygon() builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-176, 4) .coordinate(-176, 4)
.point(-180, 0) .coordinate(-180, 0)
.point(-180, -4) .coordinate(-180, -4)
.point(-176, 4); .coordinate(-176, 4)
);
shape = builder.close().build(); shape = builder.close().build();
assertPolygon(shape); assertPolygon(shape);
@ -443,73 +471,85 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithBoundaryHoles() { public void testShapeWithBoundaryHoles() {
// test case 1: test the positive side of the dateline // test case 1: test the positive side of the dateline
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-177, 10) .coordinate(-177, 10)
.point(176, 15) .coordinate(176, 15)
.point(172, 0) .coordinate(172, 0)
.point(176, -15) .coordinate(176, -15)
.point(-177, -10) .coordinate(-177, -10)
.point(-177, 10); .coordinate(-177, 10)
builder.hole(new LineStringBuilder() );
.point(176, 10) builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(180, 5) .coordinate(176, 10)
.point(180, -5) .coordinate(180, 5)
.point(176, -10) .coordinate(180, -5)
.point(176, 10)); .coordinate(176, -10)
.coordinate(176, 10)
));
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertMultiPolygon(shape); assertMultiPolygon(shape);
// test case 2: test the negative side of the dateline // test case 2: test the negative side of the dateline
builder = ShapeBuilders.newPolygon() builder = ShapeBuilders.newPolygon(
.point(-176, 15) new CoordinatesBuilder()
.point(179, 10) .coordinate(-176, 15)
.point(179, -10) .coordinate(179, 10)
.point(-176, -15) .coordinate(179, -10)
.point(-172, 0); .coordinate(-176, -15)
builder.hole(new LineStringBuilder() .coordinate(-172, 0)
.point(-176, 10) .close()
.point(-176, -10) );
.point(-180, -5) builder.hole(new LineStringBuilder(
.point(-180, 5) new CoordinatesBuilder()
.point(-176, 10)); .coordinate(-176, 10)
.coordinate(-176, -10)
.coordinate(-180, -5)
.coordinate(-180, 5)
.coordinate(-176, 10)
.close()
));
shape = builder.close().build(); shape = builder.close().build();
assertMultiPolygon(shape); assertMultiPolygon(shape);
} }
public void testShapeWithTangentialHole() { public void testShapeWithTangentialHole() {
// test a shape with one tangential (shared) vertex (should pass) // test a shape with one tangential (shared) vertex (should pass)
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(179, 10) .coordinate(179, 10)
.point(168, 15) .coordinate(168, 15)
.point(164, 0) .coordinate(164, 0)
.point(166, -15) .coordinate(166, -15)
.point(179, -10) .coordinate(179, -10)
.point(179, 10); .coordinate(179, 10)
builder.hole(new LineStringBuilder() );
.point(-177, 10) builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-178, -10) .coordinate(-177, 10)
.point(-180, -5) .coordinate(-178, -10)
.point(-180, 5) .coordinate(-180, -5)
.point(-177, 10)); .coordinate(-180, 5)
.coordinate(-177, 10)
));
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertMultiPolygon(shape); assertMultiPolygon(shape);
} }
public void testShapeWithInvalidTangentialHole() { public void testShapeWithInvalidTangentialHole() {
// test a shape with one invalid tangential (shared) vertex (should throw exception) // test a shape with one invalid tangential (shared) vertex (should throw exception)
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(179, 10) .coordinate(179, 10)
.point(168, 15) .coordinate(168, 15)
.point(164, 0) .coordinate(164, 0)
.point(166, -15) .coordinate(166, -15)
.point(179, -10) .coordinate(179, -10)
.point(179, 10); .coordinate(179, 10)
builder.hole(new LineStringBuilder() );
.point(164, 0) builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(175, 10) .coordinate(164, 0)
.point(175, 5) .coordinate(175, 10)
.point(179, -10) .coordinate(175, 5)
.point(164, 0)); .coordinate(179, -10)
.coordinate(164, 0)
));
try { try {
builder.close().build(); builder.close().build();
fail("Expected InvalidShapeException"); fail("Expected InvalidShapeException");
@ -520,43 +560,48 @@ public class ShapeBuilderTests extends ESTestCase {
public void testBoundaryShapeWithTangentialHole() { public void testBoundaryShapeWithTangentialHole() {
// test a shape with one tangential (shared) vertex for each hole (should pass) // test a shape with one tangential (shared) vertex for each hole (should pass)
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-177, 10) .coordinate(-177, 10)
.point(176, 15) .coordinate(176, 15)
.point(172, 0) .coordinate(172, 0)
.point(176, -15) .coordinate(176, -15)
.point(-177, -10) .coordinate(-177, -10)
.point(-177, 10); .coordinate(-177, 10)
builder.hole(new LineStringBuilder() );
.point(-177, 10) builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-178, -10) .coordinate(-177, 10)
.point(-180, -5) .coordinate(-178, -10)
.point(-180, 5) .coordinate(-180, -5)
.point(-177, 10)); .coordinate(-180, 5)
builder.hole(new LineStringBuilder() .coordinate(-177, 10)
.point(172, 0) ));
.point(176, 10) builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(176, -5) .coordinate(172, 0)
.point(172, 0)); .coordinate(176, 10)
.coordinate(176, -5)
.coordinate(172, 0)
));
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertMultiPolygon(shape); assertMultiPolygon(shape);
} }
public void testBoundaryShapeWithInvalidTangentialHole() { public void testBoundaryShapeWithInvalidTangentialHole() {
// test shape with two tangential (shared) vertices (should throw exception) // test shape with two tangential (shared) vertices (should throw exception)
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-177, 10) .coordinate(-177, 10)
.point(176, 15) .coordinate(176, 15)
.point(172, 0) .coordinate(172, 0)
.point(176, -15) .coordinate(176, -15)
.point(-177, -10) .coordinate(-177, -10)
.point(-177, 10); .coordinate(-177, 10)
builder.hole(new LineStringBuilder() );
.point(-177, 10) builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.point(172, 0) .coordinate(-177, 10)
.point(180, -5) .coordinate(172, 0)
.point(176, -10) .coordinate(180, -5)
.point(-177, 10)); .coordinate(176, -10)
.coordinate(-177, 10)
));
try { try {
builder.close().build(); builder.close().build();
fail("Expected InvalidShapeException"); fail("Expected InvalidShapeException");
@ -569,11 +614,12 @@ public class ShapeBuilderTests extends ESTestCase {
* Test an enveloping polygon around the max mercator bounds * Test an enveloping polygon around the max mercator bounds
*/ */
public void testBoundaryShape() { public void testBoundaryShape() {
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-180, 90) .coordinate(-180, 90)
.point(180, 90) .coordinate(180, 90)
.point(180, -90) .coordinate(180, -90)
.point(-180, -90); .coordinate(-180, 90)
);
Shape shape = builder.close().build(); Shape shape = builder.close().build();
@ -582,21 +628,23 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithAlternateOrientation() { public void testShapeWithAlternateOrientation() {
// cw: should produce a multi polygon spanning hemispheres // cw: should produce a multi polygon spanning hemispheres
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(180, 0) .coordinate(180, 0)
.point(176, 4) .coordinate(176, 4)
.point(-176, 4) .coordinate(-176, 4)
.point(180, 0); .coordinate(180, 0)
);
Shape shape = builder.close().build(); Shape shape = builder.close().build();
assertPolygon(shape); assertPolygon(shape);
// cw: geo core will convert to ccw across the dateline // cw: geo core will convert to ccw across the dateline
builder = ShapeBuilders.newPolygon() builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(180, 0) .coordinate(180, 0)
.point(-176, 4) .coordinate(-176, 4)
.point(176, 4) .coordinate(176, 4)
.point(180, 0); .coordinate(180, 0)
);
shape = builder.close().build(); shape = builder.close().build();
@ -604,12 +652,13 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testInvalidShapeWithConsecutiveDuplicatePoints() { public void testInvalidShapeWithConsecutiveDuplicatePoints() {
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(180, 0) .coordinate(180, 0)
.point(176, 4) .coordinate(176, 4)
.point(176, 4) .coordinate(176, 4)
.point(-176, 4) .coordinate(-176, 4)
.point(180, 0); .coordinate(180, 0)
);
try { try {
builder.close().build(); builder.close().build();
fail("Expected InvalidShapeException"); fail("Expected InvalidShapeException");

View File

@ -40,7 +40,7 @@ import static org.hamcrest.Matchers.not;
public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> extends ESTestCase { public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> extends ESTestCase {
private static final int NUMBER_OF_TESTBUILDERS = 20; private static final int NUMBER_OF_TESTBUILDERS = 100;
private static NamedWriteableRegistry namedWriteableRegistry; private static NamedWriteableRegistry namedWriteableRegistry;
/** /**

View File

@ -42,9 +42,18 @@ public class CircleBuilderTests extends AbstractShapeBuilderTestCase<CircleBuild
DistanceUnit unit = original.unit(); DistanceUnit unit = original.unit();
if (randomBoolean()) { if (randomBoolean()) {
mutation.center(new Coordinate(original.center().x/2, original.center().y/2)); if (original.center().x > 0.0 || original.center().y > 0.0) {
mutation.center(new Coordinate(original.center().x/2, original.center().y/2));
} else {
// original center was 0.0, 0.0
mutation.center(randomDouble() + 0.1, randomDouble() + 0.1);
}
} else if (randomBoolean()) { } else if (randomBoolean()) {
radius = radius/2; if (radius > 0) {
radius = radius/2;
} else {
radius = randomDouble() + 0.1;
}
} else { } else {
DistanceUnit newRandom = unit; DistanceUnit newRandom = unit;
while (newRandom == unit) { while (newRandom == unit) {
@ -56,10 +65,15 @@ public class CircleBuilderTests extends AbstractShapeBuilderTestCase<CircleBuild
} }
static CircleBuilder createRandomShape() { static CircleBuilder createRandomShape() {
double centerX = randomDoubleBetween(-180, 180, false); CircleBuilder circle = new CircleBuilder();
double centerY = randomDoubleBetween(-90, 90, false); if (frequently()) {
return new CircleBuilder() double centerX = randomDoubleBetween(-180, 180, false);
.center(new Coordinate(centerX, centerY)) double centerY = randomDoubleBetween(-90, 90, false);
.radius(randomDoubleBetween(0.1, 10.0, false), randomFrom(DistanceUnit.values())); circle.center(centerX, centerY);
}
if (randomBoolean()) {
circle.radius(randomDoubleBetween(0.1, 10.0, false), randomFrom(DistanceUnit.values()));
}
return circle;
} }
} }

View File

@ -25,8 +25,26 @@ import org.elasticsearch.test.geo.RandomShapeGenerator;
import java.io.IOException; import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
public class EnvelopeBuilderTests extends AbstractShapeBuilderTestCase<EnvelopeBuilder> { public class EnvelopeBuilderTests extends AbstractShapeBuilderTestCase<EnvelopeBuilder> {
public void testInvalidConstructorArgs() {
try {
new EnvelopeBuilder(null, new Coordinate(1.0, -1.0));
fail("Exception expected");
} catch (NullPointerException e) {
assertThat("topLeft of envelope cannot be null", equalTo(e.getMessage()));
}
try {
new EnvelopeBuilder(new Coordinate(1.0, -1.0), null);
fail("Exception expected");
} catch (NullPointerException e) {
assertThat("bottomRight of envelope cannot be null", equalTo(e.getMessage()));
}
}
@Override @Override
protected EnvelopeBuilder createTestShapeBuilder() { protected EnvelopeBuilder createTestShapeBuilder() {
return createRandomShape(); return createRandomShape();
@ -42,26 +60,25 @@ public class EnvelopeBuilderTests extends AbstractShapeBuilderTestCase<EnvelopeB
// move one corner to the middle of original // move one corner to the middle of original
switch (randomIntBetween(0, 3)) { switch (randomIntBetween(0, 3)) {
case 0: case 0:
mutation.topLeft(new Coordinate(randomDoubleBetween(-180.0, original.bottomRight().x, true), original.topLeft().y)); mutation = new EnvelopeBuilder(new Coordinate(randomDoubleBetween(-180.0, original.bottomRight().x, true), original.topLeft().y), original.bottomRight());
break; break;
case 1: case 1:
mutation.topLeft(new Coordinate(original.topLeft().x, randomDoubleBetween(original.bottomRight().y, 90.0, true))); mutation = new EnvelopeBuilder(new Coordinate(original.topLeft().x, randomDoubleBetween(original.bottomRight().y, 90.0, true)), original.bottomRight());
break; break;
case 2: case 2:
mutation.bottomRight(new Coordinate(randomDoubleBetween(original.topLeft().x, 180.0, true), original.bottomRight().y)); mutation = new EnvelopeBuilder(original.topLeft(), new Coordinate(randomDoubleBetween(original.topLeft().x, 180.0, true), original.bottomRight().y));
break; break;
case 3: case 3:
mutation.bottomRight(new Coordinate(original.bottomRight().x, randomDoubleBetween(-90.0, original.topLeft().y, true))); mutation = new EnvelopeBuilder(original.topLeft(), new Coordinate(original.bottomRight().x, randomDoubleBetween(-90.0, original.topLeft().y, true)));
break; break;
} }
return mutation; return mutation;
} }
static EnvelopeBuilder createRandomShape() { static EnvelopeBuilder createRandomShape() {
EnvelopeBuilder envelope = new EnvelopeBuilder();
Rectangle box = RandomShapeGenerator.xRandomRectangle(getRandom(), RandomShapeGenerator.xRandomPoint(getRandom())); Rectangle box = RandomShapeGenerator.xRandomRectangle(getRandom(), RandomShapeGenerator.xRandomPoint(getRandom()));
envelope.topLeft(box.getMinX(), box.getMaxY()) EnvelopeBuilder envelope = new EnvelopeBuilder(new Coordinate(box.getMinX(), box.getMaxY()),
.bottomRight(box.getMaxX(), box.getMinY()); new Coordinate(box.getMaxX(), box.getMinY()));
return envelope; return envelope;
} }
} }

View File

@ -20,13 +20,40 @@
package org.elasticsearch.common.geo.builders; package org.elasticsearch.common.geo.builders;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.test.geo.RandomShapeGenerator; import org.elasticsearch.test.geo.RandomShapeGenerator;
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType; import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
public class LineStringBuilderTests extends AbstractShapeBuilderTestCase<LineStringBuilder> { public class LineStringBuilderTests extends AbstractShapeBuilderTestCase<LineStringBuilder> {
public void testInvalidConstructorArgs() {
try {
new LineStringBuilder((List<Coordinate>) null);
fail("Exception expected");
} catch (IllegalArgumentException e) {
assertThat("cannot create point collection with empty set of points", equalTo(e.getMessage()));
}
try {
new LineStringBuilder(new CoordinatesBuilder());
fail("Exception expected");
} catch (IllegalArgumentException e) {
assertThat("cannot create point collection with empty set of points", equalTo(e.getMessage()));
}
try {
new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0));
fail("Exception expected");
} catch (IllegalArgumentException e) {
assertThat("invalid number of points in LineString (found [1] - must be >= 2)", equalTo(e.getMessage()));
}
}
@Override @Override
protected LineStringBuilder createTestShapeBuilder() { protected LineStringBuilder createTestShapeBuilder() {
return createRandomShape(); return createRandomShape();
@ -54,7 +81,7 @@ public class LineStringBuilderTests extends AbstractShapeBuilderTestCase<LineStr
coordinate.y = randomDoubleBetween(-90.0, 90.0, true); coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
} }
} }
return mutation.points(coordinates); return mutation.coordinates(coordinates);
} }
static LineStringBuilder createRandomShape() { static LineStringBuilder createRandomShape() {

View File

@ -40,30 +40,37 @@ public class MultiLineStringBuilderTests extends AbstractShapeBuilderTestCase<Mu
static MultiLineStringBuilder mutate(MultiLineStringBuilder original) throws IOException { static MultiLineStringBuilder mutate(MultiLineStringBuilder original) throws IOException {
MultiLineStringBuilder mutation = (MultiLineStringBuilder) copyShape(original); MultiLineStringBuilder mutation = (MultiLineStringBuilder) copyShape(original);
Coordinate[][] coordinates = mutation.coordinates(); Coordinate[][] coordinates = mutation.coordinates();
int lineToChange = randomInt(coordinates.length - 1); if (coordinates.length > 0) {
for (int i = 0; i < coordinates.length; i++) { int lineToChange = randomInt(coordinates.length - 1);
Coordinate[] line = coordinates[i]; for (int i = 0; i < coordinates.length; i++) {
if (i == lineToChange) { Coordinate[] line = coordinates[i];
Coordinate coordinate = randomFrom(line); if (i == lineToChange) {
if (randomBoolean()) { Coordinate coordinate = randomFrom(line);
if (coordinate.x != 0.0) { if (randomBoolean()) {
coordinate.x = coordinate.x / 2; if (coordinate.x != 0.0) {
coordinate.x = coordinate.x / 2;
} else {
coordinate.x = randomDoubleBetween(-180.0, 180.0, true);
}
} else { } else {
coordinate.x = randomDoubleBetween(-180.0, 180.0, true); if (coordinate.y != 0.0) {
} coordinate.y = coordinate.y / 2;
} else { } else {
if (coordinate.y != 0.0) { coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
coordinate.y = coordinate.y / 2; }
} else {
coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
} }
} }
} }
} else {
mutation.linestring((LineStringBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.LINESTRING));
} }
return mutation; return mutation;
} }
static MultiLineStringBuilder createRandomShape() { static MultiLineStringBuilder createRandomShape() {
if (true) {
return new MultiLineStringBuilder();
}
return (MultiLineStringBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.MULTILINESTRING); return (MultiLineStringBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.MULTILINESTRING);
} }
} }

View File

@ -25,8 +25,29 @@ import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
import java.io.IOException; import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
public class MultiPointBuilderTests extends AbstractShapeBuilderTestCase<MultiPointBuilder> { public class MultiPointBuilderTests extends AbstractShapeBuilderTestCase<MultiPointBuilder> {
public void testInvalidBuilderException() {
try {
new MultiPointBuilder(null);
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e) {
assertThat("cannot create point collection with empty set of points", equalTo(e.getMessage()));
}
try {
new MultiPointBuilder(new CoordinatesBuilder().build());
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e) {
assertThat("cannot create point collection with empty set of points", equalTo(e.getMessage()));
}
// one point is minimum
new MultiPointBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0).build());
}
@Override @Override
protected MultiPointBuilder createTestShapeBuilder() { protected MultiPointBuilder createTestShapeBuilder() {
return createRandomShape(); return createRandomShape();
@ -40,21 +61,25 @@ public class MultiPointBuilderTests extends AbstractShapeBuilderTestCase<MultiPo
static MultiPointBuilder mutate(MultiPointBuilder original) throws IOException { static MultiPointBuilder mutate(MultiPointBuilder original) throws IOException {
MultiPointBuilder mutation = (MultiPointBuilder) copyShape(original); MultiPointBuilder mutation = (MultiPointBuilder) copyShape(original);
Coordinate[] coordinates = original.coordinates(false); Coordinate[] coordinates = original.coordinates(false);
Coordinate coordinate = randomFrom(coordinates); if (coordinates.length > 0) {
if (randomBoolean()) { Coordinate coordinate = randomFrom(coordinates);
if (coordinate.x != 0.0) { if (randomBoolean()) {
coordinate.x = coordinate.x / 2; if (coordinate.x != 0.0) {
coordinate.x = coordinate.x / 2;
} else {
coordinate.x = randomDoubleBetween(-180.0, 180.0, true);
}
} else { } else {
coordinate.x = randomDoubleBetween(-180.0, 180.0, true); if (coordinate.y != 0.0) {
coordinate.y = coordinate.y / 2;
} else {
coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
}
} }
} else { } else {
if (coordinate.y != 0.0) { coordinates = new Coordinate[]{new Coordinate(1.0, 1.0)};
coordinate.y = coordinate.y / 2;
} else {
coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
}
} }
return mutation.points(coordinates); return mutation.coordinates(coordinates);
} }
static MultiPointBuilder createRandomShape() { static MultiPointBuilder createRandomShape() {

View File

@ -20,12 +20,15 @@
package org.elasticsearch.common.geo.builders; package org.elasticsearch.common.geo.builders;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation; import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
import org.elasticsearch.test.geo.RandomShapeGenerator; import org.elasticsearch.test.geo.RandomShapeGenerator;
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType; import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
import java.io.IOException; import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBuilder> { public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBuilder> {
@Override @Override
@ -77,8 +80,7 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
* This is done so we don't have to expose a setter for orientation in the actual class * This is done so we don't have to expose a setter for orientation in the actual class
*/ */
private static PolygonBuilder polyWithOposingOrientation(PolygonBuilder pb) { private static PolygonBuilder polyWithOposingOrientation(PolygonBuilder pb) {
PolygonBuilder mutation = new PolygonBuilder(pb.orientation() == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT); PolygonBuilder mutation = new PolygonBuilder(pb.shell(), pb.orientation() == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
mutation.points(pb.shell().coordinates(false));
for (LineStringBuilder hole : pb.holes()) { for (LineStringBuilder hole : pb.holes()) {
mutation.hole(hole); mutation.hole(hole);
} }
@ -92,4 +94,33 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
} }
return pgb; return pgb;
} }
public void testCoerceShell() {
try{
new PolygonBuilder(new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0)
.coordinate(1.0, 0.0).coordinate(1.0, 1.0).build()), Orientation.RIGHT);
fail("should raise validation exception");
} catch (IllegalArgumentException e) {
assertEquals("invalid number of points in LinearRing (found [3] - must be >= 4)", e.getMessage());
}
PolygonBuilder pb = new PolygonBuilder(new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0)
.coordinate(1.0, 0.0).coordinate(1.0, 1.0).build()), Orientation.RIGHT, true);
assertThat("Shell should have been closed via coerce", pb.shell().coordinates(false).length, equalTo(4));
}
public void testCoerceHole() {
PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0)
.coordinate(2.0, 0.0).coordinate(2.0, 2.0).coordinate(0.0, 0.0));
try{
pb.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0,0.0).coordinate(1.0,0.0).coordinate(1.0,1.0).build()));
fail("should raise validation exception");
} catch (IllegalArgumentException e) {
assertEquals("invalid number of points in LinearRing (found [3] - must be >= 4)", e.getMessage());
}
pb.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0,0.0).coordinate(1.0,0.0).coordinate(1.0,1.0).build()), true);
assertThat("hole should have been closed via coerce", pb.holes().get(0).coordinates(false).length, equalTo(4));
}
} }

View File

@ -19,20 +19,29 @@
package org.elasticsearch.index; package org.elasticsearch.index;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.TopDocs;
import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.translog.Translog;
import org.elasticsearch.indices.InvalidAliasNameException; import org.elasticsearch.indices.InvalidAliasNameException;
import org.elasticsearch.test.ESSingleNodeTestCase; import org.elasticsearch.test.ESSingleNodeTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
@ -151,4 +160,175 @@ public class IndexServiceTests extends ESSingleNodeTestCase {
IndexMetaData build = IndexMetaData.builder(service.getMetaData()).putAlias(AliasMetaData.builder(alias).filter(filter).build()).build(); IndexMetaData build = IndexMetaData.builder(service.getMetaData()).putAlias(AliasMetaData.builder(alias).filter(filter).build()).build();
service.updateMetaData(build); service.updateMetaData(build);
} }
public void testBaseAsyncTask() throws InterruptedException, IOException {
IndexService indexService = newIndexService();
AtomicReference<CountDownLatch> latch = new AtomicReference<>(new CountDownLatch(1));
AtomicReference<CountDownLatch> latch2 = new AtomicReference<>(new CountDownLatch(1));
final AtomicInteger count = new AtomicInteger();
IndexService.BaseAsyncTask task = new IndexService.BaseAsyncTask(indexService, TimeValue.timeValueMillis(1)) {
@Override
protected void runInternal() {
count.incrementAndGet();
assertTrue("generic threadpool is configured", Thread.currentThread().getName().contains("[generic]"));
latch.get().countDown();
try {
latch2.get().await();
} catch (InterruptedException e) {
fail("interrupted");
}
if (randomBoolean()) { // task can throw exceptions!!
if (randomBoolean()) {
throw new RuntimeException("foo");
} else {
throw new RuntimeException("bar");
}
}
}
@Override
protected String getThreadPool() {
return ThreadPool.Names.GENERIC;
}
};
latch.get().await();
latch.set(new CountDownLatch(1));
assertEquals(1, count.get());
latch2.get().countDown();
latch2.set(new CountDownLatch(1));
latch.get().await();
assertEquals(2, count.get());
task.close();
latch2.get().countDown();
assertEquals(2, count.get());
task = new IndexService.BaseAsyncTask(indexService, TimeValue.timeValueMillis(1000000)) {
@Override
protected void runInternal() {
}
};
assertTrue(task.mustReschedule());
indexService.close("simon says", false);
assertFalse("no shards left", task.mustReschedule());
assertTrue(task.isScheduled());
task.close();
assertFalse(task.isScheduled());
}
public void testRefreshTaskIsUpdated() throws IOException {
IndexService indexService = newIndexService();
IndexService.AsyncRefreshTask refreshTask = indexService.getRefreshTask();
assertEquals(1000, refreshTask.getInterval().millis());
assertTrue(indexService.getRefreshTask().mustReschedule());
// now disable
IndexMetaData metaData = IndexMetaData.builder(indexService.getMetaData()).settings(Settings.builder().put(indexService.getMetaData().getSettings()).put(IndexSettings.INDEX_REFRESH_INTERVAL, -1)).build();
indexService.updateMetaData(metaData);
assertNotSame(refreshTask, indexService.getRefreshTask());
assertTrue(refreshTask.isClosed());
assertFalse(refreshTask.isScheduled());
assertFalse(indexService.getRefreshTask().mustReschedule());
// set it to 100ms
metaData = IndexMetaData.builder(indexService.getMetaData()).settings(Settings.builder().put(indexService.getMetaData().getSettings()).put(IndexSettings.INDEX_REFRESH_INTERVAL, "100ms")).build();
indexService.updateMetaData(metaData);
assertNotSame(refreshTask, indexService.getRefreshTask());
assertTrue(refreshTask.isClosed());
refreshTask = indexService.getRefreshTask();
assertTrue(refreshTask.mustReschedule());
assertTrue(refreshTask.isScheduled());
assertEquals(100, refreshTask.getInterval().millis());
// set it to 200ms
metaData = IndexMetaData.builder(indexService.getMetaData()).settings(Settings.builder().put(indexService.getMetaData().getSettings()).put(IndexSettings.INDEX_REFRESH_INTERVAL, "200ms")).build();
indexService.updateMetaData(metaData);
assertNotSame(refreshTask, indexService.getRefreshTask());
assertTrue(refreshTask.isClosed());
refreshTask = indexService.getRefreshTask();
assertTrue(refreshTask.mustReschedule());
assertTrue(refreshTask.isScheduled());
assertEquals(200, refreshTask.getInterval().millis());
// set it to 200ms again
metaData = IndexMetaData.builder(indexService.getMetaData()).settings(Settings.builder().put(indexService.getMetaData().getSettings()).put(IndexSettings.INDEX_REFRESH_INTERVAL, "200ms")).build();
indexService.updateMetaData(metaData);
assertSame(refreshTask, indexService.getRefreshTask());
assertTrue(indexService.getRefreshTask().mustReschedule());
assertTrue(refreshTask.isScheduled());
assertFalse(refreshTask.isClosed());
assertEquals(200, refreshTask.getInterval().millis());
indexService.close("simon says", false);
assertFalse(refreshTask.isScheduled());
assertTrue(refreshTask.isClosed());
}
public void testFsyncTaskIsRunning() throws IOException {
IndexService indexService = newIndexService();
IndexService.AsyncTranslogFSync fsyncTask = indexService.getFsyncTask();
assertNotNull(fsyncTask);
assertEquals(5000, fsyncTask.getInterval().millis());
assertTrue(fsyncTask.mustReschedule());
assertTrue(fsyncTask.isScheduled());
indexService.close("simon says", false);
assertFalse(fsyncTask.isScheduled());
assertTrue(fsyncTask.isClosed());
}
public void testRefreshActuallyWorks() throws Exception {
IndexService indexService = newIndexService();
ensureGreen("test");
IndexService.AsyncRefreshTask refreshTask = indexService.getRefreshTask();
assertEquals(1000, refreshTask.getInterval().millis());
assertTrue(indexService.getRefreshTask().mustReschedule());
// now disable
IndexMetaData metaData = IndexMetaData.builder(indexService.getMetaData()).settings(Settings.builder().put(indexService.getMetaData().getSettings()).put(IndexSettings.INDEX_REFRESH_INTERVAL, -1)).build();
indexService.updateMetaData(metaData);
client().prepareIndex("test", "test", "1").setSource("{\"foo\": \"bar\"}").get();
IndexShard shard = indexService.getShard(0);
try (Engine.Searcher searcher = shard.acquireSearcher("test")) {
TopDocs search = searcher.searcher().search(new MatchAllDocsQuery(), 10);
assertEquals(0, search.totalHits);
}
// refresh every millisecond
metaData = IndexMetaData.builder(indexService.getMetaData()).settings(Settings.builder().put(indexService.getMetaData().getSettings()).put(IndexSettings.INDEX_REFRESH_INTERVAL, "1ms")).build();
indexService.updateMetaData(metaData);
assertBusy(() -> {
try (Engine.Searcher searcher = shard.acquireSearcher("test")) {
TopDocs search = searcher.searcher().search(new MatchAllDocsQuery(), 10);
assertEquals(1, search.totalHits);
} catch (IOException e) {
fail(e.getMessage());
}
});
}
public void testAsyncFsyncActuallyWorks() throws Exception {
Settings settings = Settings.builder()
.put(IndexSettings.INDEX_TRANSLOG_SYNC_INTERVAL, "10ms") // very often :)
.put(IndexSettings.INDEX_TRANSLOG_DURABILITY, Translog.Durability.ASYNC)
.build();
IndexService indexService = createIndex("test", settings);
ensureGreen("test");
assertTrue(indexService.getRefreshTask().mustReschedule());
client().prepareIndex("test", "test", "1").setSource("{\"foo\": \"bar\"}").get();
IndexShard shard = indexService.getShard(0);
assertBusy(() -> {
assertFalse(shard.getTranslog().syncNeeded());
});
}
public void testNoFsyncTaskIfDisabled() {
Settings settings = Settings.builder()
.put(IndexSettings.INDEX_TRANSLOG_SYNC_INTERVAL, "0ms") // disable
.build();
IndexService indexService = createIndex("test", settings);
assertNull(indexService.getFsyncTask());
}
} }

View File

@ -19,9 +19,17 @@
package org.elasticsearch.index.mapper; package org.elasticsearch.index.mapper;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.internal.TypeFieldMapper;
import org.elasticsearch.test.ESSingleNodeTestCase; import org.elasticsearch.test.ESSingleNodeTestCase;
import org.junit.Rule; import org.junit.Rule;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
@ -32,6 +40,7 @@ import java.util.HashSet;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasToString; import static org.hamcrest.Matchers.hasToString;
public class MapperServiceTests extends ESSingleNodeTestCase { public class MapperServiceTests extends ESSingleNodeTestCase {
@ -122,4 +131,22 @@ public class MapperServiceTests extends ESSingleNodeTestCase {
} }
assertFalse(indexService.mapperService().hasMapping(MapperService.DEFAULT_MAPPING)); assertFalse(indexService.mapperService().hasMapping(MapperService.DEFAULT_MAPPING));
} }
public void testSearchFilter() {
IndexService indexService = createIndex("index1", client().admin().indices().prepareCreate("index1")
.addMapping("type1", "field1", "type=nested")
.addMapping("type2", new Object[0])
);
Query searchFilter = indexService.mapperService().searchFilter("type1", "type3");
Query expectedQuery = new BooleanQuery.Builder()
.add(new BooleanQuery.Builder()
.add(new ConstantScoreQuery(new TermQuery(new Term(TypeFieldMapper.NAME, "type1"))), BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term(TypeFieldMapper.NAME, "type3")), BooleanClause.Occur.SHOULD)
.build(), BooleanClause.Occur.MUST
)
.add(Queries.newNonNestedFilter(), BooleanClause.Occur.MUST)
.build();
assertThat(searchFilter, equalTo(new ConstantScoreQuery(expectedQuery)));
}
} }

View File

@ -204,6 +204,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
double distance = queryBuilder.distance(); double distance = queryBuilder.distance();
if (queryBuilder.geoDistance() != null) { if (queryBuilder.geoDistance() != null) {
distance = queryBuilder.geoDistance().normalize(distance, DistanceUnit.DEFAULT); distance = queryBuilder.geoDistance().normalize(distance, DistanceUnit.DEFAULT);
distance = org.elasticsearch.common.geo.GeoUtils.maxRadialDistance(queryBuilder.point(), distance);
assertThat(geoQuery.getRadiusMeters(), closeTo(distance, GeoUtils.TOLERANCE)); assertThat(geoQuery.getRadiusMeters(), closeTo(distance, GeoUtils.TOLERANCE));
} }
} }

View File

@ -19,6 +19,8 @@
package org.elasticsearch.index.query; package org.elasticsearch.index.query;
import com.vividsolutions.jts.geom.Coordinate;
import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery; import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
@ -215,7 +217,7 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
// see #3878 // see #3878
public void testThatXContentSerializationInsideOfArrayWorks() throws Exception { public void testThatXContentSerializationInsideOfArrayWorks() throws Exception {
EnvelopeBuilder envelopeBuilder = ShapeBuilders.newEnvelope().topLeft(0, 0).bottomRight(10, 10); EnvelopeBuilder envelopeBuilder = ShapeBuilders.newEnvelope(new Coordinate(0, 0), new Coordinate(10, 10));
GeoShapeQueryBuilder geoQuery = QueryBuilders.geoShapeQuery("searchGeometry", envelopeBuilder); GeoShapeQueryBuilder geoQuery = QueryBuilders.geoShapeQuery("searchGeometry", envelopeBuilder);
JsonXContent.contentBuilder().startArray().value(geoQuery).endArray(); JsonXContent.contentBuilder().startArray().value(geoQuery).endArray();
} }

View File

@ -23,6 +23,7 @@ import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.common.geo.GeoDistance; import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders; import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder.Item; import org.elasticsearch.index.query.MoreLikeThisQueryBuilder.Item;
@ -174,12 +175,14 @@ public class QueryDSLDocumentationTests extends ESTestCase {
public void testGeoShape() throws IOException { public void testGeoShape() throws IOException {
GeoShapeQueryBuilder qb = geoShapeQuery( GeoShapeQueryBuilder qb = geoShapeQuery(
"pin.location", "pin.location",
ShapeBuilders.newMultiPoint() ShapeBuilders.newMultiPoint(
.point(0, 0) new CoordinatesBuilder()
.point(0, 10) .coordinate(0, 0)
.point(10, 10) .coordinate(0, 10)
.point(10, 0) .coordinate(10, 10)
.point(0, 0)); .coordinate(10, 0)
.coordinate(0, 0)
.build()));
qb.relation(ShapeRelation.WITHIN); qb.relation(ShapeRelation.WITHIN);
qb = geoShapeQuery( qb = geoShapeQuery(

View File

@ -38,6 +38,8 @@ import org.elasticsearch.test.ESIntegTestCase.Scope;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate; import java.util.function.Predicate;
import static org.elasticsearch.action.percolate.PercolateSourceBuilder.docBuilder; import static org.elasticsearch.action.percolate.PercolateSourceBuilder.docBuilder;
@ -249,6 +251,7 @@ public class RecoveryPercolatorIT extends ESIntegTestCase {
.setSource(document) .setSource(document)
.get(); .get();
final Lock lock = new ReentrantLock();
final AtomicBoolean run = new AtomicBoolean(true); final AtomicBoolean run = new AtomicBoolean(true);
final AtomicReference<Throwable> error = new AtomicReference<>(); final AtomicReference<Throwable> error = new AtomicReference<>();
Runnable r = () -> { Runnable r = () -> {
@ -261,7 +264,13 @@ public class RecoveryPercolatorIT extends ESIntegTestCase {
} else { } else {
percolateBuilder.setGetRequest(Requests.getRequest("test").type("type").id("1")); percolateBuilder.setGetRequest(Requests.getRequest("test").type("type").id("1"));
} }
PercolateResponse response = percolateBuilder.get(); PercolateResponse response;
try {
lock.lock();
response = percolateBuilder.get();
} finally {
lock.unlock();
}
assertNoFailures(response); assertNoFailures(response);
assertThat(response.getSuccessfulShards(), equalTo(response.getTotalShards())); assertThat(response.getSuccessfulShards(), equalTo(response.getTotalShards()));
assertThat(response.getCount(), equalTo((long) numQueries)); assertThat(response.getCount(), equalTo((long) numQueries));
@ -279,7 +288,12 @@ public class RecoveryPercolatorIT extends ESIntegTestCase {
try { try {
// 1 index, 2 primaries, 2 replicas per primary // 1 index, 2 primaries, 2 replicas per primary
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
internalCluster().stopRandomNode(nodePredicate); try {
lock.lock();
internalCluster().stopRandomNode(nodePredicate);
} finally {
lock.unlock();
}
client.admin().cluster().prepareHealth("test") client.admin().cluster().prepareHealth("test")
.setWaitForEvents(Priority.LANGUID) .setWaitForEvents(Priority.LANGUID)
.setTimeout(TimeValue.timeValueMinutes(2)) .setTimeout(TimeValue.timeValueMinutes(2))
@ -287,7 +301,12 @@ public class RecoveryPercolatorIT extends ESIntegTestCase {
.setWaitForActiveShards(4) // 2 nodes, so 4 shards (2 primaries, 2 replicas) .setWaitForActiveShards(4) // 2 nodes, so 4 shards (2 primaries, 2 replicas)
.get(); .get();
assertThat(error.get(), nullValue()); assertThat(error.get(), nullValue());
internalCluster().stopRandomNode(nodePredicate); try {
lock.lock();
internalCluster().stopRandomNode(nodePredicate);
} finally {
lock.unlock();
}
client.admin().cluster().prepareHealth("test") client.admin().cluster().prepareHealth("test")
.setWaitForEvents(Priority.LANGUID) .setWaitForEvents(Priority.LANGUID)
.setTimeout(TimeValue.timeValueMinutes(2)) .setTimeout(TimeValue.timeValueMinutes(2))
@ -295,7 +314,7 @@ public class RecoveryPercolatorIT extends ESIntegTestCase {
.setWaitForActiveShards(2) // 1 node, so 2 shards (2 primaries, 0 replicas) .setWaitForActiveShards(2) // 1 node, so 2 shards (2 primaries, 0 replicas)
.get(); .get();
assertThat(error.get(), nullValue()); assertThat(error.get(), nullValue());
internalCluster().startNode(); internalCluster().startNode(settingsBuilder().put("node.stay", false));
client.admin().cluster().prepareHealth("test") client.admin().cluster().prepareHealth("test")
.setWaitForEvents(Priority.LANGUID) .setWaitForEvents(Priority.LANGUID)
.setTimeout(TimeValue.timeValueMinutes(2)) .setTimeout(TimeValue.timeValueMinutes(2))
@ -303,7 +322,7 @@ public class RecoveryPercolatorIT extends ESIntegTestCase {
.setWaitForActiveShards(4) // 2 nodes, so 4 shards (2 primaries, 2 replicas) .setWaitForActiveShards(4) // 2 nodes, so 4 shards (2 primaries, 2 replicas)
.get(); .get();
assertThat(error.get(), nullValue()); assertThat(error.get(), nullValue());
internalCluster().startNode(); internalCluster().startNode(settingsBuilder().put("node.stay", false));
client.admin().cluster().prepareHealth("test") client.admin().cluster().prepareHealth("test")
.setWaitForEvents(Priority.LANGUID) .setWaitForEvents(Priority.LANGUID)
.setTimeout(TimeValue.timeValueMinutes(2)) .setTimeout(TimeValue.timeValueMinutes(2))

View File

@ -27,10 +27,10 @@ import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.shard.MergePolicyConfig; import org.elasticsearch.index.shard.MergePolicyConfig;
import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase;
@ -47,7 +47,7 @@ public class ParentFieldLoadingIT extends ESIntegTestCase {
private final Settings indexSettings = Settings.builder() private final Settings indexSettings = Settings.builder()
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
.put(IndexShard.INDEX_REFRESH_INTERVAL, -1) .put(IndexSettings.INDEX_REFRESH_INTERVAL, -1)
// We never want merges in this test to ensure we have two segments for the last validation // We never want merges in this test to ensure we have two segments for the last validation
.put(MergePolicyConfig.INDEX_MERGE_ENABLED, false) .put(MergePolicyConfig.INDEX_MERGE_ENABLED, false)
.build(); .build();

View File

@ -23,6 +23,7 @@ import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.distance.DistanceUtils; import com.spatial4j.core.distance.DistanceUtils;
import com.spatial4j.core.exception.InvalidShapeException; import com.spatial4j.core.exception.InvalidShapeException;
import com.spatial4j.core.shape.Shape; import com.spatial4j.core.shape.Shape;
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy; import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs; import org.apache.lucene.spatial.query.SpatialArgs;
@ -40,6 +41,7 @@ import org.elasticsearch.common.Priority;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder; import org.elasticsearch.common.geo.builders.LineStringBuilder;
import org.elasticsearch.common.geo.builders.MultiPolygonBuilder; import org.elasticsearch.common.geo.builders.MultiPolygonBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.PolygonBuilder;
@ -119,30 +121,29 @@ public class GeoFilterIT extends ESIntegTestCase {
public void testShapeBuilders() { public void testShapeBuilders() {
try { try {
// self intersection polygon // self intersection polygon
ShapeBuilders.newPolygon() ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-10, -10) .coordinate(-10, -10)
.point(10, 10) .coordinate(10, 10)
.point(-10, 10) .coordinate(-10, 10)
.point(10, -10) .coordinate(10, -10)
.close().build(); .close())
.build();
fail("Self intersection not detected"); fail("Self intersection not detected");
} catch (InvalidShapeException e) { } catch (InvalidShapeException e) {
} }
// polygon with hole // polygon with hole
ShapeBuilders.newPolygon() ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder() .hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close()))
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5) .build();
.close()).close().build();
try { try {
// polygon with overlapping hole // polygon with overlapping hole
ShapeBuilders.newPolygon() ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder() .hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-5, -5).point(-5, 11).point(5, 11).point(5, -5) .coordinate(-5, -5).coordinate(-5, 11).coordinate(5, 11).coordinate(5, -5).close()))
.close()).close().build(); .build();
fail("Self intersection not detected"); fail("Self intersection not detected");
} catch (InvalidShapeException e) { } catch (InvalidShapeException e) {
@ -150,30 +151,27 @@ public class GeoFilterIT extends ESIntegTestCase {
try { try {
// polygon with intersection holes // polygon with intersection holes
ShapeBuilders.newPolygon() ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder() .hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close()))
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5) .hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -6).coordinate(5, -6).coordinate(5, -4).coordinate(-5, -4).close()))
.close()) .build();
.hole(new LineStringBuilder()
.point(-5, -6).point(5, -6).point(5, -4).point(-5, -4)
.close())
.close().build();
fail("Intersection of holes not detected"); fail("Intersection of holes not detected");
} catch (InvalidShapeException e) { } catch (InvalidShapeException e) {
} }
try { try {
// Common line in polygon // Common line in polygon
ShapeBuilders.newPolygon() ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-10, -10) .coordinate(-10, -10)
.point(-10, 10) .coordinate(-10, 10)
.point(-5, 10) .coordinate(-5, 10)
.point(-5, -5) .coordinate(-5, -5)
.point(-5, 20) .coordinate(-5, 20)
.point(10, 20) .coordinate(10, 20)
.point(10, -10) .coordinate(10, -10)
.close().build(); .close())
.build();
fail("Self intersection not detected"); fail("Self intersection not detected");
} catch (InvalidShapeException e) { } catch (InvalidShapeException e) {
} }
@ -181,23 +179,22 @@ public class GeoFilterIT extends ESIntegTestCase {
// Multipolygon: polygon with hole and polygon within the whole // Multipolygon: polygon with hole and polygon within the whole
ShapeBuilders ShapeBuilders
.newMultiPolygon() .newMultiPolygon()
.polygon(new PolygonBuilder() .polygon(new PolygonBuilder(
.point(-10, -10) new CoordinatesBuilder().coordinate(-10, -10)
.point(-10, 10) .coordinate(-10, 10)
.point(10, 10) .coordinate(10, 10)
.point(10, -10) .coordinate(10, -10).close())
.hole(new LineStringBuilder().point(-5, -5) .hole(new LineStringBuilder(
.point(-5, 5) new CoordinatesBuilder().coordinate(-5, -5)
.point(5, 5) .coordinate(-5, 5)
.point(5, -5) .coordinate(5, 5)
.close()) .coordinate(5, -5).close())))
.close()) .polygon(new PolygonBuilder(
.polygon(new PolygonBuilder() new CoordinatesBuilder()
.point(-4, -4) .coordinate(-4, -4)
.point(-4, 4) .coordinate(-4, 4)
.point(4, 4) .coordinate(4, 4)
.point(4, -4) .coordinate(4, -4).close()))
.close())
.build(); .build();
} }
@ -226,14 +223,12 @@ public class GeoFilterIT extends ESIntegTestCase {
// with a hole of size 5x5 equidistant from all sides. This hole in turn contains // with a hole of size 5x5 equidistant from all sides. This hole in turn contains
// the second polygon of size 4x4 equidistant from all sites // the second polygon of size 4x4 equidistant from all sites
MultiPolygonBuilder polygon = ShapeBuilders.newMultiPolygon() MultiPolygonBuilder polygon = ShapeBuilders.newMultiPolygon()
.polygon(new PolygonBuilder() .polygon(new PolygonBuilder(
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder() .hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5).close()) .coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close())))
.close()) .polygon(new PolygonBuilder(
.polygon(new PolygonBuilder() new CoordinatesBuilder().coordinate(-4, -4).coordinate(-4, 4).coordinate(4, 4).coordinate(4, -4).close()));
.point(-4, -4).point(-4, 4).point(4, 4).point(4, -4).close());
BytesReference data = jsonBuilder().startObject().field("area", polygon).endObject().bytes(); BytesReference data = jsonBuilder().startObject().field("area", polygon).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet(); client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet();
@ -292,11 +287,10 @@ public class GeoFilterIT extends ESIntegTestCase {
} }
// Create a polygon that fills the empty area of the polygon defined above // Create a polygon that fills the empty area of the polygon defined above
PolygonBuilder inverse = ShapeBuilders.newPolygon() PolygonBuilder inverse = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5) .coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close())
.hole(new LineStringBuilder() .hole(new LineStringBuilder(
.point(-4, -4).point(-4, 4).point(4, 4).point(4, -4).close()) new CoordinatesBuilder().coordinate(-4, -4).coordinate(-4, 4).coordinate(4, 4).coordinate(4, -4).close()));
.close();
data = jsonBuilder().startObject().field("area", inverse).endObject().bytes(); data = jsonBuilder().startObject().field("area", inverse).endObject().bytes();
client().prepareIndex("shapes", "polygon", "2").setSource(data).execute().actionGet(); client().prepareIndex("shapes", "polygon", "2").setSource(data).execute().actionGet();
@ -311,16 +305,15 @@ public class GeoFilterIT extends ESIntegTestCase {
assertFirstHit(result, hasId("2")); assertFirstHit(result, hasId("2"));
// Create Polygon with hole and common edge // Create Polygon with hole and common edge
PolygonBuilder builder = ShapeBuilders.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder() .hole(new LineStringBuilder(new CoordinatesBuilder()
.point(-5, -5).point(-5, 5).point(10, 5).point(10, -5).close()) .coordinate(-5, -5).coordinate(-5, 5).coordinate(10, 5).coordinate(10, -5).close()));
.close();
if (withinSupport) { if (withinSupport) {
// Polygon WithIn Polygon // Polygon WithIn Polygon
builder = ShapeBuilders.newPolygon() builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(-30, -30).point(-30, 30).point(30, 30).point(30, -30).close(); .coordinate(-30, -30).coordinate(-30, 30).coordinate(30, 30).coordinate(30, -30).close());
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
@ -330,19 +323,17 @@ public class GeoFilterIT extends ESIntegTestCase {
} }
// Create a polygon crossing longitude 180. // Create a polygon crossing longitude 180.
builder = ShapeBuilders.newPolygon() builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10) .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close());
.close();
data = jsonBuilder().startObject().field("area", builder).endObject().bytes(); data = jsonBuilder().startObject().field("area", builder).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet(); client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet();
client().admin().indices().prepareRefresh().execute().actionGet(); client().admin().indices().prepareRefresh().execute().actionGet();
// Create a polygon crossing longitude 180 with hole. // Create a polygon crossing longitude 180 with hole.
builder = ShapeBuilders.newPolygon() builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10) .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close())
.hole(new LineStringBuilder().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close()) .hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(175, -5).coordinate(185, -5).coordinate(185, 5).coordinate(175, 5).close()));
.close();
data = jsonBuilder().startObject().field("area", builder).endObject().bytes(); data = jsonBuilder().startObject().field("area", builder).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet(); client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet();

View File

@ -20,9 +20,12 @@
package org.elasticsearch.search.geo; package org.elasticsearch.search.geo;
import com.spatial4j.core.shape.Rectangle; import com.spatial4j.core.shape.Rectangle;
import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.EnvelopeBuilder; import org.elasticsearch.common.geo.builders.EnvelopeBuilder;
import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder; import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder; import org.elasticsearch.common.geo.builders.LineStringBuilder;
@ -94,7 +97,7 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
.endObject() .endObject()
.endObject()).setRefresh(true).execute().actionGet(); .endObject()).setRefresh(true).execute().actionGet();
ShapeBuilder shape = ShapeBuilders.newEnvelope().topLeft(-45, 45).bottomRight(45, -45); ShapeBuilder shape = ShapeBuilders.newEnvelope(new Coordinate(-45, 45), new Coordinate(45, -45));
SearchResponse searchResponse = client().prepareSearch("test").setTypes("type1") SearchResponse searchResponse = client().prepareSearch("test").setTypes("type1")
.setQuery(geoIntersectionQuery("location", shape)) .setQuery(geoIntersectionQuery("location", shape))
@ -138,7 +141,7 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
.endObject() .endObject()
.endObject()).setRefresh(true).execute().actionGet(); .endObject()).setRefresh(true).execute().actionGet();
ShapeBuilder query = ShapeBuilders.newEnvelope().topLeft(-122.88, 48.62).bottomRight(-122.82, 48.54); ShapeBuilder query = ShapeBuilders.newEnvelope(new Coordinate(-122.88, 48.62), new Coordinate(-122.82, 48.54));
// This search would fail if both geoshape indexing and geoshape filtering // This search would fail if both geoshape indexing and geoshape filtering
// used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes.
@ -163,7 +166,7 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
createIndex("shapes"); createIndex("shapes");
ensureGreen(); ensureGreen();
ShapeBuilder shape = ShapeBuilders.newEnvelope().topLeft(-45, 45).bottomRight(45, -45); ShapeBuilder shape = ShapeBuilders.newEnvelope(new Coordinate(-45, 45), new Coordinate(45, -45));
client().prepareIndex("shapes", "shape_type", "Big_Rectangle").setSource(jsonBuilder().startObject() client().prepareIndex("shapes", "shape_type", "Big_Rectangle").setSource(jsonBuilder().startObject()
.field("shape", shape).endObject()).setRefresh(true).execute().actionGet(); .field("shape", shape).endObject()).setRefresh(true).execute().actionGet();
@ -195,14 +198,13 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
} }
public void testReusableBuilder() throws IOException { public void testReusableBuilder() throws IOException {
ShapeBuilder polygon = ShapeBuilders.newPolygon() ShapeBuilder polygon = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10) .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close())
.hole(new LineStringBuilder().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close()) .hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(175, -5).coordinate(185, -5).coordinate(185, 5).coordinate(175, 5).close()));
.close();
assertUnmodified(polygon); assertUnmodified(polygon);
ShapeBuilder linestring = ShapeBuilders.newLineString() ShapeBuilder linestring = ShapeBuilders.newLineString(new CoordinatesBuilder()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10); .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close());
assertUnmodified(linestring); assertUnmodified(linestring);
} }
@ -327,7 +329,7 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
client().prepareIndex("test", "type", "1").setSource(docSource).setRefresh(true).execute().actionGet(); client().prepareIndex("test", "type", "1").setSource(docSource).setRefresh(true).execute().actionGet();
// index the mbr of the collection // index the mbr of the collection
EnvelopeBuilder env = new EnvelopeBuilder().topLeft(mbr.getMinX(), mbr.getMaxY()).bottomRight(mbr.getMaxX(), mbr.getMinY()); EnvelopeBuilder env = new EnvelopeBuilder(new Coordinate(mbr.getMinX(), mbr.getMaxY()), new Coordinate(mbr.getMaxX(), mbr.getMinY()));
docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject();
client().prepareIndex("test", "type", "2").setSource(docSource).setRefresh(true).execute().actionGet(); client().prepareIndex("test", "type", "2").setSource(docSource).setRefresh(true).execute().actionGet();
@ -375,8 +377,8 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
"location", "location",
ShapeBuilders.newGeometryCollection() ShapeBuilders.newGeometryCollection()
.polygon( .polygon(
ShapeBuilders.newPolygon().point(99.0, -1.0).point(99.0, 3.0).point(103.0, 3.0).point(103.0, -1.0) ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0).coordinate(103.0, -1.0)
.point(99.0, -1.0))).relation(ShapeRelation.INTERSECTS); .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS);
SearchResponse result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery()) SearchResponse result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get(); .setPostFilter(filter).get();
assertSearchResponse(result); assertSearchResponse(result);
@ -384,17 +386,17 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
filter = QueryBuilders.geoShapeQuery( filter = QueryBuilders.geoShapeQuery(
"location", "location",
ShapeBuilders.newGeometryCollection().polygon( ShapeBuilders.newGeometryCollection().polygon(
ShapeBuilders.newPolygon().point(199.0, -11.0).point(199.0, 13.0).point(193.0, 13.0).point(193.0, -11.0) ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0).coordinate(193.0, 13.0).coordinate(193.0, -11.0)
.point(199.0, -11.0))).relation(ShapeRelation.INTERSECTS); .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS);
result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery()) result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get(); .setPostFilter(filter).get();
assertSearchResponse(result); assertSearchResponse(result);
assertHitCount(result, 0); assertHitCount(result, 0);
filter = QueryBuilders.geoShapeQuery("location", ShapeBuilders.newGeometryCollection() filter = QueryBuilders.geoShapeQuery("location", ShapeBuilders.newGeometryCollection()
.polygon(ShapeBuilders.newPolygon().point(99.0, -1.0).point(99.0, 3.0).point(103.0, 3.0).point(103.0, -1.0).point(99.0, -1.0)) .polygon(ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0).coordinate(103.0, -1.0).coordinate(99.0, -1.0)))
.polygon( .polygon(
ShapeBuilders.newPolygon().point(199.0, -11.0).point(199.0, 13.0).point(193.0, 13.0).point(193.0, -11.0) ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0).coordinate(193.0, 13.0).coordinate(193.0, -11.0)
.point(199.0, -11.0))).relation(ShapeRelation.INTERSECTS); .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS);
result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery()) result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get(); .setPostFilter(filter).get();
assertSearchResponse(result); assertSearchResponse(result);

View File

@ -81,7 +81,7 @@ import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS; import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS;
import static org.elasticsearch.common.settings.Settings.settingsBuilder; import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery; import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.index.shard.IndexShard.INDEX_REFRESH_INTERVAL; import static org.elasticsearch.index.IndexSettings.INDEX_REFRESH_INTERVAL;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAliasesExist; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAliasesExist;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAliasesMissing; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAliasesMissing;

View File

@ -29,13 +29,15 @@ import com.spatial4j.core.shape.impl.Range;
import com.vividsolutions.jts.algorithm.ConvexHull; import com.vividsolutions.jts.algorithm.ConvexHull;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.geo.builders.CoordinateCollection;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder; import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder; import org.elasticsearch.common.geo.builders.LineStringBuilder;
import org.elasticsearch.common.geo.builders.MultiLineStringBuilder; import org.elasticsearch.common.geo.builders.MultiLineStringBuilder;
import org.elasticsearch.common.geo.builders.MultiPointBuilder; import org.elasticsearch.common.geo.builders.MultiPointBuilder;
import org.elasticsearch.common.geo.builders.PointBuilder; import org.elasticsearch.common.geo.builders.PointBuilder;
import org.elasticsearch.common.geo.builders.PointCollection;
import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.search.geo.GeoShapeQueryTests; import org.elasticsearch.search.geo.GeoShapeQueryTests;
@ -187,11 +189,12 @@ public class RandomShapeGenerator extends RandomGeoGenerator {
// if this number gets out of hand, the number of self intersections for a linestring can become // if this number gets out of hand, the number of self intersections for a linestring can become
// (n^2-n)/2 and computing the relation intersection matrix will become NP-Hard // (n^2-n)/2 and computing the relation intersection matrix will become NP-Hard
int numPoints = RandomInts.randomIntBetween(r, 3, 10); int numPoints = RandomInts.randomIntBetween(r, 3, 10);
PointCollection pcb = (st == ShapeType.MULTIPOINT) ? new MultiPointBuilder() : new LineStringBuilder(); CoordinatesBuilder coordinatesBuilder = new CoordinatesBuilder();
for (int i=0; i<numPoints; ++i) { for (int i=0; i<numPoints; ++i) {
p = xRandomPointIn(r, within); p = xRandomPointIn(r, within);
pcb.point(p.getX(), p.getY()); coordinatesBuilder.coordinate(p.getX(), p.getY());
} }
CoordinateCollection pcb = (st == ShapeType.MULTIPOINT) ? new MultiPointBuilder(coordinatesBuilder.build()) : new LineStringBuilder(coordinatesBuilder);
return pcb; return pcb;
case MULTILINESTRING: case MULTILINESTRING:
MultiLineStringBuilder mlsb = new MultiLineStringBuilder(); MultiLineStringBuilder mlsb = new MultiLineStringBuilder();
@ -219,7 +222,7 @@ public class RandomShapeGenerator extends RandomGeoGenerator {
shellCoords[2] = new Coordinate(within.getMaxX(), within.getMaxY()); shellCoords[2] = new Coordinate(within.getMaxX(), within.getMaxY());
shellCoords[3] = new Coordinate(within.getMaxX(), within.getMinY()); shellCoords[3] = new Coordinate(within.getMaxX(), within.getMinY());
} }
PolygonBuilder pgb = new PolygonBuilder().points(shellCoords).close(); PolygonBuilder pgb = new PolygonBuilder(new CoordinatesBuilder().coordinates(shellCoords).close());
if (validate) { if (validate) {
// This test framework builds semi-random geometry (in the sense that points are not truly random due to spatial // This test framework builds semi-random geometry (in the sense that points are not truly random due to spatial
// auto-correlation) As a result of the semi-random nature of the geometry, one can not predict the orientation // auto-correlation) As a result of the semi-random nature of the geometry, one can not predict the orientation