diff --git a/buildSrc/src/main/resources/checkstyle_suppressions.xml b/buildSrc/src/main/resources/checkstyle_suppressions.xml
index d16383cb87a..7c5803e19c3 100644
--- a/buildSrc/src/main/resources/checkstyle_suppressions.xml
+++ b/buildSrc/src/main/resources/checkstyle_suppressions.xml
@@ -1084,13 +1084,6 @@
-
-
-
-
-
-
-
diff --git a/core/src/main/java/org/elasticsearch/action/DocWriteResponse.java b/core/src/main/java/org/elasticsearch/action/DocWriteResponse.java
index 9335c4ac403..0b64f3afa7d 100644
--- a/core/src/main/java/org/elasticsearch/action/DocWriteResponse.java
+++ b/core/src/main/java/org/elasticsearch/action/DocWriteResponse.java
@@ -40,16 +40,21 @@ import java.util.Locale;
*/
public abstract class DocWriteResponse extends ReplicationResponse implements WriteResponse, StatusToXContent {
- public enum Operation implements Writeable {
- CREATE(0),
- INDEX(1),
- DELETE(2),
- NOOP(3);
+ /**
+ * An enum that represents the the results of CRUD operations, primarily used to communicate the type of
+ * operation that occurred.
+ */
+ public enum Result implements Writeable {
+ CREATED(0),
+ UPDATED(1),
+ DELETED(2),
+ NOT_FOUND(3),
+ NOOP(4);
private final byte op;
private final String lowercase;
- Operation(int op) {
+ Result(int op) {
this.op = (byte) op;
this.lowercase = this.toString().toLowerCase(Locale.ENGLISH);
}
@@ -62,19 +67,21 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
return lowercase;
}
- public static Operation readFrom(StreamInput in) throws IOException{
+ public static Result readFrom(StreamInput in) throws IOException{
Byte opcode = in.readByte();
switch(opcode){
case 0:
- return CREATE;
+ return CREATED;
case 1:
- return INDEX;
+ return UPDATED;
case 2:
- return DELETE;
+ return DELETED;
case 3:
+ return NOT_FOUND;
+ case 4:
return NOOP;
default:
- throw new IllegalArgumentException("Unknown operation code: " + opcode);
+ throw new IllegalArgumentException("Unknown result code: " + opcode);
}
}
@@ -89,14 +96,14 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
private String type;
private long version;
private boolean forcedRefresh;
- protected Operation operation;
+ protected Result result;
- public DocWriteResponse(ShardId shardId, String type, String id, long version, Operation operation) {
+ public DocWriteResponse(ShardId shardId, String type, String id, long version, Result result) {
this.shardId = shardId;
this.type = type;
this.id = id;
this.version = version;
- this.operation = operation;
+ this.result = result;
}
// needed for deserialization
@@ -106,8 +113,8 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
/**
* The change that occurred to the document.
*/
- public Operation getOperation() {
- return operation;
+ public Result getResult() {
+ return result;
}
/**
@@ -198,7 +205,7 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
id = in.readString();
version = in.readZLong();
forcedRefresh = in.readBoolean();
- operation = Operation.readFrom(in);
+ result = Result.readFrom(in);
}
@Override
@@ -209,7 +216,7 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
out.writeString(id);
out.writeZLong(version);
out.writeBoolean(forcedRefresh);
- operation.writeTo(out);
+ result.writeTo(out);
}
@Override
@@ -219,7 +226,7 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
.field("_type", type)
.field("_id", id)
.field("_version", version)
- .field("_operation", getOperation().getLowercase());
+ .field("result", getResult().getLowercase());
if (forcedRefresh) {
builder.field("forced_refresh", forcedRefresh);
}
diff --git a/core/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java b/core/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java
index d20ee500cda..745449c0a7b 100644
--- a/core/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java
+++ b/core/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java
@@ -239,16 +239,16 @@ public class TransportShardBulkAction extends TransportWriteAction result = updateResult.writeResult;
IndexRequest indexRequest = updateResult.request();
BytesReference indexSourceAsBytes = indexRequest.source();
// add the response
IndexResponse indexResponse = result.getResponse();
- UpdateResponse updateResponse = new UpdateResponse(indexResponse.getShardInfo(), indexResponse.getShardId(), indexResponse.getType(), indexResponse.getId(), indexResponse.getVersion(), indexResponse.getOperation());
+ UpdateResponse updateResponse = new UpdateResponse(indexResponse.getShardInfo(), indexResponse.getShardId(), indexResponse.getType(), indexResponse.getId(), indexResponse.getVersion(), indexResponse.getResult());
if (updateRequest.fields() != null && updateRequest.fields().length > 0) {
Tuple> sourceAndContent = XContentHelper.convertToMap(indexSourceAsBytes, true);
updateResponse.setGetResult(updateHelper.extractGetResult(updateRequest, request.index(), indexResponse.getVersion(), sourceAndContent.v2(), sourceAndContent.v1(), indexSourceAsBytes));
@@ -256,12 +256,12 @@ public class TransportShardBulkAction extends TransportWriteAction writeResult = updateResult.writeResult;
DeleteResponse response = writeResult.getResponse();
DeleteRequest deleteRequest = updateResult.request();
- updateResponse = new UpdateResponse(response.getShardInfo(), response.getShardId(), response.getType(), response.getId(), response.getVersion(), response.getOperation());
+ updateResponse = new UpdateResponse(response.getShardInfo(), response.getShardId(), response.getType(), response.getId(), response.getVersion(), response.getResult());
updateResponse.setGetResult(updateHelper.extractGetResult(updateRequest, request.index(), response.getVersion(), updateResult.result.updatedSourceAsMap(), updateResult.result.updateSourceContentType(), null));
// Replace the update request to the translated delete request to execute on the replica.
item = request.items()[requestIndex] = new BulkItemRequest(request.items()[requestIndex].id(), deleteRequest);
@@ -271,6 +271,8 @@ public class TransportShardBulkAction extends TransportWriteAction result = TransportDeleteAction.executeDeleteRequestOnPrimary(deleteRequest, indexShard);
@@ -432,7 +436,7 @@ public class TransportShardBulkAction extends TransportWriteAction() {
@Override
public void onResponse(IndexResponse response) {
- UpdateResponse update = new UpdateResponse(response.getShardInfo(), response.getShardId(), response.getType(), response.getId(), response.getVersion(), response.getOperation());
+ UpdateResponse update = new UpdateResponse(response.getShardInfo(), response.getShardId(), response.getType(), response.getId(), response.getVersion(), response.getResult());
if (request.fields() != null && request.fields().length > 0) {
Tuple> sourceAndContent = XContentHelper.convertToMap(upsertSourceBytes, true);
update.setGetResult(updateHelper.extractGetResult(request, request.concreteIndex(), response.getVersion(), sourceAndContent.v2(), sourceAndContent.v1(), upsertSourceBytes));
@@ -217,14 +216,14 @@ public class TransportUpdateAction extends TransportInstanceSingleOperationActio
}
});
break;
- case INDEX:
+ case UPDATED:
IndexRequest indexRequest = result.action();
// we fetch it from the index request so we don't generate the bytes twice, its already done in the index request
final BytesReference indexSourceBytes = indexRequest.source();
indexAction.execute(indexRequest, new ActionListener() {
@Override
public void onResponse(IndexResponse response) {
- UpdateResponse update = new UpdateResponse(response.getShardInfo(), response.getShardId(), response.getType(), response.getId(), response.getVersion(), response.getOperation());
+ UpdateResponse update = new UpdateResponse(response.getShardInfo(), response.getShardId(), response.getType(), response.getId(), response.getVersion(), response.getResult());
update.setGetResult(updateHelper.extractGetResult(request, request.concreteIndex(), response.getVersion(), result.updatedSourceAsMap(), result.updateSourceContentType(), indexSourceBytes));
update.setForcedRefresh(response.forcedRefresh());
listener.onResponse(update);
@@ -248,12 +247,12 @@ public class TransportUpdateAction extends TransportInstanceSingleOperationActio
}
});
break;
- case DELETE:
+ case DELETED:
DeleteRequest deleteRequest = result.action();
deleteAction.execute(deleteRequest, new ActionListener() {
@Override
public void onResponse(DeleteResponse response) {
- UpdateResponse update = new UpdateResponse(response.getShardInfo(), response.getShardId(), response.getType(), response.getId(), response.getVersion(), response.getOperation());
+ UpdateResponse update = new UpdateResponse(response.getShardInfo(), response.getShardId(), response.getType(), response.getId(), response.getVersion(), response.getResult());
update.setGetResult(updateHelper.extractGetResult(request, request.concreteIndex(), response.getVersion(), result.updatedSourceAsMap(), result.updateSourceContentType(), null));
update.setForcedRefresh(response.forcedRefresh());
listener.onResponse(update);
@@ -289,7 +288,7 @@ public class TransportUpdateAction extends TransportInstanceSingleOperationActio
listener.onResponse(update);
break;
default:
- throw new IllegalStateException("Illegal operation " + result.operation());
+ throw new IllegalStateException("Illegal result " + result.getResponseResult());
}
}
}
diff --git a/core/src/main/java/org/elasticsearch/action/update/UpdateHelper.java b/core/src/main/java/org/elasticsearch/action/update/UpdateHelper.java
index 209d95530c7..03600461599 100644
--- a/core/src/main/java/org/elasticsearch/action/update/UpdateHelper.java
+++ b/core/src/main/java/org/elasticsearch/action/update/UpdateHelper.java
@@ -117,9 +117,9 @@ public class UpdateHelper extends AbstractComponent {
request.script.getScript());
}
UpdateResponse update = new UpdateResponse(shardId, getResult.getType(), getResult.getId(),
- getResult.getVersion(), DocWriteResponse.Operation.NOOP);
+ getResult.getVersion(), DocWriteResponse.Result.NOOP);
update.setGetResult(getResult);
- return new Result(update, DocWriteResponse.Operation.NOOP, upsertDoc, XContentType.JSON);
+ return new Result(update, DocWriteResponse.Result.NOOP, upsertDoc, XContentType.JSON);
}
indexRequest.source((Map) ctx.get("_source"));
}
@@ -136,7 +136,7 @@ public class UpdateHelper extends AbstractComponent {
// in all but the internal versioning mode, we want to create the new document using the given version.
indexRequest.version(request.version()).versionType(request.versionType());
}
- return new Result(indexRequest, DocWriteResponse.Operation.CREATE, null, null);
+ return new Result(indexRequest, DocWriteResponse.Result.CREATED, null, null);
}
long updateVersion = getResult.getVersion();
@@ -227,21 +227,21 @@ public class UpdateHelper extends AbstractComponent {
.consistencyLevel(request.consistencyLevel())
.timestamp(timestamp).ttl(ttl)
.setRefreshPolicy(request.getRefreshPolicy());
- return new Result(indexRequest, DocWriteResponse.Operation.INDEX, updatedSourceAsMap, updateSourceContentType);
+ return new Result(indexRequest, DocWriteResponse.Result.UPDATED, updatedSourceAsMap, updateSourceContentType);
} else if ("delete".equals(operation)) {
DeleteRequest deleteRequest = Requests.deleteRequest(request.index()).type(request.type()).id(request.id()).routing(routing).parent(parent)
.version(updateVersion).versionType(request.versionType())
.consistencyLevel(request.consistencyLevel())
.setRefreshPolicy(request.getRefreshPolicy());
- return new Result(deleteRequest, DocWriteResponse.Operation.DELETE, updatedSourceAsMap, updateSourceContentType);
+ return new Result(deleteRequest, DocWriteResponse.Result.DELETED, updatedSourceAsMap, updateSourceContentType);
} else if ("none".equals(operation)) {
- UpdateResponse update = new UpdateResponse(shardId, getResult.getType(), getResult.getId(), getResult.getVersion(), DocWriteResponse.Operation.NOOP);
+ UpdateResponse update = new UpdateResponse(shardId, getResult.getType(), getResult.getId(), getResult.getVersion(), DocWriteResponse.Result.NOOP);
update.setGetResult(extractGetResult(request, request.index(), getResult.getVersion(), updatedSourceAsMap, updateSourceContentType, getResult.internalSourceRef()));
- return new Result(update, DocWriteResponse.Operation.NOOP, updatedSourceAsMap, updateSourceContentType);
+ return new Result(update, DocWriteResponse.Result.NOOP, updatedSourceAsMap, updateSourceContentType);
} else {
logger.warn("Used update operation [{}] for script [{}], doing nothing...", operation, request.script.getScript());
- UpdateResponse update = new UpdateResponse(shardId, getResult.getType(), getResult.getId(), getResult.getVersion(), DocWriteResponse.Operation.NOOP);
- return new Result(update, DocWriteResponse.Operation.NOOP, updatedSourceAsMap, updateSourceContentType);
+ UpdateResponse update = new UpdateResponse(shardId, getResult.getType(), getResult.getId(), getResult.getVersion(), DocWriteResponse.Result.NOOP);
+ return new Result(update, DocWriteResponse.Result.NOOP, updatedSourceAsMap, updateSourceContentType);
}
}
@@ -310,13 +310,13 @@ public class UpdateHelper extends AbstractComponent {
public static class Result {
private final Streamable action;
- private final DocWriteResponse.Operation operation;
+ private final DocWriteResponse.Result result;
private final Map updatedSourceAsMap;
private final XContentType updateSourceContentType;
- public Result(Streamable action, DocWriteResponse.Operation operation, Map updatedSourceAsMap, XContentType updateSourceContentType) {
+ public Result(Streamable action, DocWriteResponse.Result result, Map updatedSourceAsMap, XContentType updateSourceContentType) {
this.action = action;
- this.operation = operation;
+ this.result = result;
this.updatedSourceAsMap = updatedSourceAsMap;
this.updateSourceContentType = updateSourceContentType;
}
@@ -326,8 +326,8 @@ public class UpdateHelper extends AbstractComponent {
return (T) action;
}
- public DocWriteResponse.Operation operation() {
- return operation;
+ public DocWriteResponse.Result getResponseResult() {
+ return result;
}
public Map updatedSourceAsMap() {
diff --git a/core/src/main/java/org/elasticsearch/action/update/UpdateResponse.java b/core/src/main/java/org/elasticsearch/action/update/UpdateResponse.java
index 2183dfe4f90..8061174d091 100644
--- a/core/src/main/java/org/elasticsearch/action/update/UpdateResponse.java
+++ b/core/src/main/java/org/elasticsearch/action/update/UpdateResponse.java
@@ -40,13 +40,13 @@ public class UpdateResponse extends DocWriteResponse {
* Constructor to be used when a update didn't translate in a write.
* For example: update script with operation set to none
*/
- public UpdateResponse(ShardId shardId, String type, String id, long version, Operation operation) {
- this(new ShardInfo(0, 0), shardId, type, id, version, operation);
+ public UpdateResponse(ShardId shardId, String type, String id, long version, Result result) {
+ this(new ShardInfo(0, 0), shardId, type, id, version, result);
}
public UpdateResponse(ShardInfo shardInfo, ShardId shardId, String type, String id,
- long version, Operation operation) {
- super(shardId, type, id, version, operation);
+ long version, Result result) {
+ super(shardId, type, id, version, result);
setShardInfo(shardInfo);
}
@@ -60,7 +60,7 @@ public class UpdateResponse extends DocWriteResponse {
@Override
public RestStatus status() {
- return this.operation == Operation.CREATE ? RestStatus.CREATED : super.status();
+ return this.result == Result.CREATED ? RestStatus.CREATED : super.status();
}
@Override
@@ -106,7 +106,7 @@ public class UpdateResponse extends DocWriteResponse {
builder.append(",type=").append(getType());
builder.append(",id=").append(getId());
builder.append(",version=").append(getVersion());
- builder.append(",operation=").append(getOperation().getLowercase());
+ builder.append(",result=").append(getResult().getLowercase());
builder.append(",shards=").append(getShardInfo());
return builder.append("]").toString();
}
diff --git a/core/src/main/java/org/elasticsearch/cluster/SnapshotsInProgress.java b/core/src/main/java/org/elasticsearch/cluster/SnapshotsInProgress.java
index f0a0fdec665..70880373530 100644
--- a/core/src/main/java/org/elasticsearch/cluster/SnapshotsInProgress.java
+++ b/core/src/main/java/org/elasticsearch/cluster/SnapshotsInProgress.java
@@ -29,6 +29,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.shard.ShardId;
+import org.elasticsearch.repositories.IndexId;
import org.elasticsearch.snapshots.Snapshot;
import java.io.IOException;
@@ -70,12 +71,12 @@ public class SnapshotsInProgress extends AbstractDiffable implements Cus
private final boolean includeGlobalState;
private final boolean partial;
private final ImmutableOpenMap shards;
- private final List indices;
+ private final List indices;
private final ImmutableOpenMap> waitingIndices;
private final long startTime;
- public Entry(Snapshot snapshot, boolean includeGlobalState, boolean partial, State state, List indices, long startTime,
- ImmutableOpenMap shards) {
+ public Entry(Snapshot snapshot, boolean includeGlobalState, boolean partial, State state, List indices,
+ long startTime, ImmutableOpenMap shards) {
this.state = state;
this.snapshot = snapshot;
this.includeGlobalState = includeGlobalState;
@@ -111,7 +112,7 @@ public class SnapshotsInProgress extends AbstractDiffable implements Cus
return state;
}
- public List indices() {
+ public List indices() {
return indices;
}
@@ -377,9 +378,9 @@ public class SnapshotsInProgress extends AbstractDiffable implements Cus
boolean partial = in.readBoolean();
State state = State.fromValue(in.readByte());
int indices = in.readVInt();
- List indexBuilder = new ArrayList<>();
+ List indexBuilder = new ArrayList<>();
for (int j = 0; j < indices; j++) {
- indexBuilder.add(in.readString());
+ indexBuilder.add(new IndexId(in.readString(), in.readString()));
}
long startTime = in.readLong();
ImmutableOpenMap.Builder builder = ImmutableOpenMap.builder();
@@ -410,8 +411,8 @@ public class SnapshotsInProgress extends AbstractDiffable implements Cus
out.writeBoolean(entry.partial());
out.writeByte(entry.state().value());
out.writeVInt(entry.indices().size());
- for (String index : entry.indices()) {
- out.writeString(index);
+ for (IndexId index : entry.indices()) {
+ index.writeTo(out);
}
out.writeLong(entry.startTime());
out.writeVInt(entry.shards().size());
@@ -458,8 +459,8 @@ public class SnapshotsInProgress extends AbstractDiffable implements Cus
builder.field(STATE, entry.state());
builder.startArray(INDICES);
{
- for (String index : entry.indices()) {
- builder.value(index);
+ for (IndexId index : entry.indices()) {
+ index.toXContent(builder, params);
}
}
builder.endArray();
diff --git a/core/src/main/java/org/elasticsearch/common/blobstore/BlobContainer.java b/core/src/main/java/org/elasticsearch/common/blobstore/BlobContainer.java
index 024a882a7de..4229ee954d4 100644
--- a/core/src/main/java/org/elasticsearch/common/blobstore/BlobContainer.java
+++ b/core/src/main/java/org/elasticsearch/common/blobstore/BlobContainer.java
@@ -23,7 +23,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Collection;
+import java.nio.file.NoSuchFileException;
import java.util.Map;
/**
@@ -53,7 +53,8 @@ public interface BlobContainer {
* @param blobName
* The name of the blob to get an {@link InputStream} for.
* @return The {@code InputStream} to read the blob.
- * @throws IOException if the blob does not exist or can not be read.
+ * @throws NoSuchFileException if the blob does not exist
+ * @throws IOException if the blob can not be read.
*/
InputStream readBlob(String blobName) throws IOException;
@@ -95,7 +96,8 @@ public interface BlobContainer {
*
* @param blobName
* The name of the blob to delete.
- * @throws IOException if the blob does not exist, or if the blob exists but could not be deleted.
+ * @throws NoSuchFileException if the blob does not exist
+ * @throws IOException if the blob exists but could not be deleted.
*/
void deleteBlob(String blobName) throws IOException;
diff --git a/core/src/main/java/org/elasticsearch/common/blobstore/fs/FsBlobContainer.java b/core/src/main/java/org/elasticsearch/common/blobstore/fs/FsBlobContainer.java
index 822f8d1721a..02a5aa357df 100644
--- a/core/src/main/java/org/elasticsearch/common/blobstore/fs/FsBlobContainer.java
+++ b/core/src/main/java/org/elasticsearch/common/blobstore/fs/FsBlobContainer.java
@@ -27,13 +27,16 @@ import org.elasticsearch.common.blobstore.support.PlainBlobMetaData;
import org.elasticsearch.common.io.Streams;
import java.io.BufferedInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
@@ -85,7 +88,7 @@ public class FsBlobContainer extends AbstractBlobContainer {
@Override
public void deleteBlob(String blobName) throws IOException {
Path blobPath = path.resolve(blobName);
- Files.deleteIfExists(blobPath);
+ Files.delete(blobPath);
}
@Override
@@ -95,14 +98,18 @@ public class FsBlobContainer extends AbstractBlobContainer {
@Override
public InputStream readBlob(String name) throws IOException {
- return new BufferedInputStream(Files.newInputStream(path.resolve(name)), blobStore.bufferSizeInBytes());
+ final Path resolvedPath = path.resolve(name);
+ try {
+ return new BufferedInputStream(Files.newInputStream(resolvedPath), blobStore.bufferSizeInBytes());
+ } catch (FileNotFoundException fnfe) {
+ throw new NoSuchFileException("[" + name + "] blob not found");
+ }
}
@Override
public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException {
final Path file = path.resolve(blobName);
- // TODO: why is this not specifying CREATE_NEW? Do we really need to be able to truncate existing files?
- try (OutputStream outputStream = Files.newOutputStream(file)) {
+ try (OutputStream outputStream = Files.newOutputStream(file, StandardOpenOption.CREATE_NEW)) {
Streams.copy(inputStream, outputStream, new byte[blobStore.bufferSizeInBytes()]);
}
IOUtils.fsync(file, false);
diff --git a/core/src/main/java/org/elasticsearch/common/blobstore/support/AbstractBlobContainer.java b/core/src/main/java/org/elasticsearch/common/blobstore/support/AbstractBlobContainer.java
index 60be21127bf..1c4652c9f10 100644
--- a/core/src/main/java/org/elasticsearch/common/blobstore/support/AbstractBlobContainer.java
+++ b/core/src/main/java/org/elasticsearch/common/blobstore/support/AbstractBlobContainer.java
@@ -20,14 +20,11 @@
package org.elasticsearch.common.blobstore.support;
import org.elasticsearch.common.blobstore.BlobContainer;
-import org.elasticsearch.common.blobstore.BlobMetaData;
import org.elasticsearch.common.blobstore.BlobPath;
import org.elasticsearch.common.bytes.BytesReference;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Collection;
-import java.util.Map;
/**
* A base abstract blob container that implements higher level container methods.
diff --git a/core/src/main/java/org/elasticsearch/common/util/CancellableThreads.java b/core/src/main/java/org/elasticsearch/common/util/CancellableThreads.java
index 2e5ee110d60..4399ba6a8fe 100644
--- a/core/src/main/java/org/elasticsearch/common/util/CancellableThreads.java
+++ b/core/src/main/java/org/elasticsearch/common/util/CancellableThreads.java
@@ -30,11 +30,14 @@ import java.util.Set;
/**
* A utility class for multi threaded operation that needs to be cancellable via interrupts. Every cancellable operation should be
* executed via {@link #execute(Interruptable)}, which will capture the executing thread and make sure it is interrupted in the case
- * cancellation.
+ * of cancellation.
+ *
+ * Cancellation policy: This class does not support external interruption via Thread#interrupt(). Always use #cancel() instead.
*/
public class CancellableThreads {
private final Set threads = new HashSet<>();
- private boolean cancelled = false;
+ // needs to be volatile as it is also read outside of synchronized blocks.
+ private volatile boolean cancelled = false;
private String reason;
public synchronized boolean isCancelled() {
@@ -94,13 +97,18 @@ public class CancellableThreads {
*/
public void executeIO(IOInterruptable interruptable) throws IOException {
boolean wasInterrupted = add();
+ boolean cancelledByExternalInterrupt = false;
RuntimeException runtimeException = null;
IOException ioException = null;
try {
interruptable.run();
} catch (InterruptedException | ThreadInterruptedException e) {
- // assume this is us and ignore
+ // ignore, this interrupt has been triggered by us in #cancel()...
+ assert cancelled : "Interruption via Thread#interrupt() is unsupported. Use CancellableThreads#cancel() instead";
+ // we can only reach here if assertions are disabled. If we reach this code and cancelled is false, this means that we've
+ // been interrupted externally (which we don't support).
+ cancelledByExternalInterrupt = !cancelled;
} catch (RuntimeException t) {
runtimeException = t;
} catch (IOException e) {
@@ -128,6 +136,12 @@ public class CancellableThreads {
throw runtimeException;
}
}
+ if (cancelledByExternalInterrupt) {
+ // restore interrupt flag to at least adhere to expected behavior
+ Thread.currentThread().interrupt();
+ throw new RuntimeException("Interruption via Thread#interrupt() is unsupported. Use CancellableThreads#cancel() instead");
+ }
+
}
diff --git a/core/src/main/java/org/elasticsearch/discovery/zen/NodeJoinController.java b/core/src/main/java/org/elasticsearch/discovery/zen/NodeJoinController.java
index c86e80e289b..ff5cdd4e31e 100644
--- a/core/src/main/java/org/elasticsearch/discovery/zen/NodeJoinController.java
+++ b/core/src/main/java/org/elasticsearch/discovery/zen/NodeJoinController.java
@@ -281,16 +281,16 @@ public class NodeJoinController extends AbstractComponent {
Map tasks = getPendingAsTasks();
final String source = "zen-disco-elected-as-master ([" + tasks.size() + "] nodes joined)";
- tasks.put(BECOME_MASTER_TASK, joinProcessedListener);
+ tasks.put(BECOME_MASTER_TASK, (source1, e) -> {}); // noop listener, the election finished listener determines result
+ tasks.put(FINISH_ELECTION_TASK, electionFinishedListener);
clusterService.submitStateUpdateTasks(source, tasks, ClusterStateTaskConfig.build(Priority.URGENT), joinTaskExecutor);
}
public synchronized void closeAndProcessPending(String reason) {
innerClose();
Map tasks = getPendingAsTasks();
- final String source = "zen-disco-process-pending-joins [" + reason + "]";
-
- tasks.put(FINISH_ELECTION_NOT_MASTER_TASK, joinProcessedListener);
+ final String source = "zen-disco-election-stop [" + reason + "]";
+ tasks.put(FINISH_ELECTION_TASK, electionFinishedListener);
clusterService.submitStateUpdateTasks(source, tasks, ClusterStateTaskConfig.build(Priority.URGENT), joinTaskExecutor);
}
@@ -327,12 +327,15 @@ public class NodeJoinController extends AbstractComponent {
}
}
- private final ClusterStateTaskListener joinProcessedListener = new ClusterStateTaskListener() {
+ private final ClusterStateTaskListener electionFinishedListener = new ClusterStateTaskListener() {
@Override
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
- assert newState.nodes().isLocalNodeElectedMaster() : "should have become a master but isn't " + newState.prettyPrint();
- onElectedAsMaster(newState);
+ if (newState.nodes().isLocalNodeElectedMaster()) {
+ ElectionContext.this.onElectedAsMaster(newState);
+ } else {
+ onFailure(source, new NotMasterException("election stopped [" + source + "]"));
+ }
}
@Override
@@ -379,7 +382,9 @@ public class NodeJoinController extends AbstractComponent {
}
}
- // a task indicated that the current node should become master, if no current master is known
+ /**
+ * a task indicated that the current node should become master, if no current master is known
+ */
private static final DiscoveryNode BECOME_MASTER_TASK = new DiscoveryNode("_BECOME_MASTER_TASK_", LocalTransportAddress.buildUnique(),
Collections.emptyMap(), Collections.emptySet(), Version.CURRENT) {
@Override
@@ -388,9 +393,11 @@ public class NodeJoinController extends AbstractComponent {
}
};
- // a task that is used to process pending joins without explicitly becoming a master and listening to the results
- // this task is used when election is stop without the local node becoming a master per se (though it might
- private static final DiscoveryNode FINISH_ELECTION_NOT_MASTER_TASK = new DiscoveryNode("_NOT_MASTER_TASK_",
+ /**
+ * a task that is used to signal the election is stopped and we should process pending joins.
+ * it may be use in combination with {@link #BECOME_MASTER_TASK}
+ */
+ private static final DiscoveryNode FINISH_ELECTION_TASK = new DiscoveryNode("_FINISH_ELECTION_",
LocalTransportAddress.buildUnique(), Collections.emptyMap(), Collections.emptySet(), Version.CURRENT) {
@Override
public String toString() {
@@ -402,31 +409,35 @@ public class NodeJoinController extends AbstractComponent {
@Override
public BatchResult execute(ClusterState currentState, List joiningNodes) throws Exception {
- final DiscoveryNodes currentNodes = currentState.nodes();
final BatchResult.Builder results = BatchResult.builder();
+
+ final DiscoveryNodes currentNodes = currentState.nodes();
boolean nodesChanged = false;
ClusterState.Builder newState = ClusterState.builder(currentState);
DiscoveryNodes.Builder nodesBuilder = DiscoveryNodes.builder(currentNodes);
- if (currentNodes.getMasterNode() == null && joiningNodes.contains(BECOME_MASTER_TASK)) {
+ if (joiningNodes.size() == 1 && joiningNodes.get(0).equals(FINISH_ELECTION_TASK)) {
+ return results.successes(joiningNodes).build(currentState);
+ } else if (currentNodes.getMasterNode() == null && joiningNodes.contains(BECOME_MASTER_TASK)) {
+ assert joiningNodes.contains(FINISH_ELECTION_TASK) : "becoming a master but election is not finished " + joiningNodes;
// use these joins to try and become the master.
// Note that we don't have to do any validation of the amount of joining nodes - the commit
// during the cluster state publishing guarantees that we have enough
-
nodesBuilder.masterNodeId(currentNodes.getLocalNodeId());
ClusterBlocks clusterBlocks = ClusterBlocks.builder().blocks(currentState.blocks())
.removeGlobalBlock(discoverySettings.getNoMasterBlock()).build();
newState.blocks(clusterBlocks);
nodesChanged = true;
- }
-
- if (nodesBuilder.isLocalNodeElectedMaster() == false) {
+ } else if (nodesBuilder.isLocalNodeElectedMaster() == false) {
logger.trace("processing node joins, but we are not the master. current master: {}", currentNodes.getMasterNode());
throw new NotMasterException("Node [" + currentNodes.getLocalNode() + "] not master for join request");
}
+ assert nodesBuilder.isLocalNodeElectedMaster();
+
+ // processing any joins
for (final DiscoveryNode node : joiningNodes) {
- if (node.equals(BECOME_MASTER_TASK) || node.equals(FINISH_ELECTION_NOT_MASTER_TASK)) {
+ if (node.equals(BECOME_MASTER_TASK) || node.equals(FINISH_ELECTION_TASK)) {
// noop
} else if (currentNodes.nodeExists(node)) {
logger.debug("received a join request for an existing node [{}]", node);
diff --git a/core/src/main/java/org/elasticsearch/index/shard/StoreRecovery.java b/core/src/main/java/org/elasticsearch/index/shard/StoreRecovery.java
index ff2d1d298a5..e08130d9d8d 100644
--- a/core/src/main/java/org/elasticsearch/index/shard/StoreRecovery.java
+++ b/core/src/main/java/org/elasticsearch/index/shard/StoreRecovery.java
@@ -43,6 +43,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.snapshots.IndexShardRestoreFailedException;
import org.elasticsearch.index.store.Store;
import org.elasticsearch.indices.recovery.RecoveryState;
+import org.elasticsearch.repositories.IndexId;
import org.elasticsearch.repositories.Repository;
import java.io.IOException;
@@ -394,10 +395,12 @@ final class StoreRecovery {
translogState.totalOperationsOnStart(0);
indexShard.prepareForIndexRecovery();
ShardId snapshotShardId = shardId;
- if (!shardId.getIndexName().equals(restoreSource.index())) {
- snapshotShardId = new ShardId(restoreSource.index(), IndexMetaData.INDEX_UUID_NA_VALUE, shardId.id());
+ final String indexName = restoreSource.index();
+ if (!shardId.getIndexName().equals(indexName)) {
+ snapshotShardId = new ShardId(indexName, IndexMetaData.INDEX_UUID_NA_VALUE, shardId.id());
}
- repository.restoreShard(indexShard, restoreSource.snapshot().getSnapshotId(), restoreSource.version(), snapshotShardId, indexShard.recoveryState());
+ final IndexId indexId = repository.getRepositoryData().resolveIndexId(indexName);
+ repository.restoreShard(indexShard, restoreSource.snapshot().getSnapshotId(), restoreSource.version(), indexId, snapshotShardId, indexShard.recoveryState());
indexShard.skipTranslogRecovery();
indexShard.finalizeRecovery();
indexShard.postRecovery("restore done");
diff --git a/core/src/main/java/org/elasticsearch/index/translog/TranslogReader.java b/core/src/main/java/org/elasticsearch/index/translog/TranslogReader.java
index 581e8d6a903..41a430d0c82 100644
--- a/core/src/main/java/org/elasticsearch/index/translog/TranslogReader.java
+++ b/core/src/main/java/org/elasticsearch/index/translog/TranslogReader.java
@@ -113,8 +113,7 @@ public class TranslogReader extends BaseTranslogReader implements Closeable {
headerStream.read(ref.bytes, ref.offset, ref.length);
BytesRef uuidBytes = new BytesRef(translogUUID);
if (uuidBytes.bytesEquals(ref) == false) {
- throw new TranslogCorruptedException("expected shard UUID " + uuidBytes + "/" + uuidBytes.utf8ToString() +
- " but got: " + ref + "/" + ref.utf8ToString() +
+ throw new TranslogCorruptedException("expected shard UUID " + uuidBytes + " but got: " + ref +
" this translog file belongs to a different translog. path:" + path);
}
return new TranslogReader(checkpoint.generation, channel, path, ref.length + CodecUtil.headerLength(TranslogWriter.TRANSLOG_CODEC) + Integer.BYTES, checkpoint.offset, checkpoint.numOps);
diff --git a/core/src/main/java/org/elasticsearch/repositories/IndexId.java b/core/src/main/java/org/elasticsearch/repositories/IndexId.java
new file mode 100644
index 00000000000..434582e61ed
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/repositories/IndexId.java
@@ -0,0 +1,110 @@
+/*
+ * 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.repositories;
+
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.io.stream.Writeable;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.index.Index;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Represents a single snapshotted index in the repository.
+ */
+public final class IndexId implements Writeable, ToXContent {
+ protected static final String NAME = "name";
+ protected static final String ID = "id";
+
+ private final String name;
+ private final String id;
+
+ public IndexId(final String name, final String id) {
+ this.name = name;
+ this.id = id;
+ }
+
+ public IndexId(final StreamInput in) throws IOException {
+ this.name = in.readString();
+ this.id = in.readString();
+ }
+
+ /**
+ * The name of the index.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * The unique ID for the index within the repository. This is *not* the same as the
+ * index's UUID, but merely a unique file/URL friendly identifier that a repository can
+ * use to name blobs for the index.
+ *
+ * We could not use the index's actual UUID (See {@link Index#getUUID()}) because in the
+ * case of snapshot/restore, the index UUID in the snapshotted index will be different
+ * from the index UUID assigned to it when it is restored. Hence, the actual index UUID
+ * is not useful in the context of snapshot/restore for tying a snapshotted index to the
+ * index it was snapshot from, and so we are using a separate UUID here.
+ */
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + name + "/" + id + "]";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ @SuppressWarnings("unchecked") IndexId that = (IndexId) o;
+ return Objects.equals(name, that.name) && Objects.equals(id, that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, id);
+ }
+
+ @Override
+ public void writeTo(final StreamOutput out) throws IOException {
+ out.writeString(name);
+ out.writeString(id);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
+ builder.startObject();
+ builder.field(NAME, name);
+ builder.field(ID, id);
+ builder.endObject();
+ return builder;
+ }
+}
diff --git a/core/src/main/java/org/elasticsearch/repositories/Repository.java b/core/src/main/java/org/elasticsearch/repositories/Repository.java
index 11a060d73e8..544f757737c 100644
--- a/core/src/main/java/org/elasticsearch/repositories/Repository.java
+++ b/core/src/main/java/org/elasticsearch/repositories/Repository.java
@@ -47,7 +47,7 @@ import java.util.List;
*
*
Master calls {@link #initializeSnapshot(SnapshotId, List, org.elasticsearch.cluster.metadata.MetaData)}
* with list of indices that will be included into the snapshot
- *
Data nodes call {@link Repository#snapshotShard(IndexShard, SnapshotId, IndexCommit, IndexShardSnapshotStatus)}
+ *
Data nodes call {@link Repository#snapshotShard(IndexShard, SnapshotId, IndexId, IndexCommit, IndexShardSnapshotStatus)}
* for each shard
*
When all shard calls return master calls {@link #finalizeSnapshot} with possible list of failures
*
@@ -88,15 +88,14 @@ public interface Repository extends LifecycleComponent {
* @param indices list of indices
* @return information about snapshot
*/
- MetaData getSnapshotMetaData(SnapshotInfo snapshot, List indices) throws IOException;
+ MetaData getSnapshotMetaData(SnapshotInfo snapshot, List indices) throws IOException;
/**
- * Returns the list of snapshots currently stored in the repository that match the given predicate on the snapshot name.
- * To get all snapshots, the predicate filter should return true regardless of the input.
- *
- * @return snapshot list
+ * Returns a {@link RepositoryData} to describe the data in the repository, including the snapshots
+ * and the indices across all snapshots found in the repository. Throws a {@link RepositoryException}
+ * if there was an error in reading the data.
*/
- List getSnapshots();
+ RepositoryData getRepositoryData();
/**
* Starts snapshotting process
@@ -105,7 +104,7 @@ public interface Repository extends LifecycleComponent {
* @param indices list of indices to be snapshotted
* @param metaData cluster metadata
*/
- void initializeSnapshot(SnapshotId snapshotId, List indices, MetaData metaData);
+ void initializeSnapshot(SnapshotId snapshotId, List indices, MetaData metaData);
/**
* Finalizes snapshotting process
@@ -113,12 +112,14 @@ public interface Repository extends LifecycleComponent {
* This method is called on master after all shards are snapshotted.
*
* @param snapshotId snapshot id
+ * @param indices list of indices in the snapshot
+ * @param startTime start time of the snapshot
* @param failure global failure reason or null
* @param totalShards total number of shards
* @param shardFailures list of shard failures
* @return snapshot description
*/
- SnapshotInfo finalizeSnapshot(SnapshotId snapshotId, List indices, long startTime, String failure, int totalShards, List shardFailures);
+ SnapshotInfo finalizeSnapshot(SnapshotId snapshotId, List indices, long startTime, String failure, int totalShards, List shardFailures);
/**
* Deletes snapshot
@@ -181,10 +182,11 @@ public interface Repository extends LifecycleComponent {
*
* @param shard shard to be snapshotted
* @param snapshotId snapshot id
+ * @param indexId id for the index being snapshotted
* @param snapshotIndexCommit commit point
* @param snapshotStatus snapshot status
*/
- void snapshotShard(IndexShard shard, SnapshotId snapshotId, IndexCommit snapshotIndexCommit, IndexShardSnapshotStatus snapshotStatus);
+ void snapshotShard(IndexShard shard, SnapshotId snapshotId, IndexId indexId, IndexCommit snapshotIndexCommit, IndexShardSnapshotStatus snapshotStatus);
/**
* Restores snapshot of the shard.
@@ -194,20 +196,22 @@ public interface Repository extends LifecycleComponent {
* @param shard the shard to restore the index into
* @param snapshotId snapshot id
* @param version version of elasticsearch that created this snapshot
+ * @param indexId id of the index in the repository from which the restore is occurring
* @param snapshotShardId shard id (in the snapshot)
* @param recoveryState recovery state
*/
- void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, ShardId snapshotShardId, RecoveryState recoveryState);
+ void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, IndexId indexId, ShardId snapshotShardId, RecoveryState recoveryState);
/**
* Retrieve shard snapshot status for the stored snapshot
*
* @param snapshotId snapshot id
* @param version version of elasticsearch that created this snapshot
+ * @param indexId the snapshotted index id for the shard to get status for
* @param shardId shard id
* @return snapshot status
*/
- IndexShardSnapshotStatus getShardSnapshotStatus(SnapshotId snapshotId, Version version, ShardId shardId);
+ IndexShardSnapshotStatus getShardSnapshotStatus(SnapshotId snapshotId, Version version, IndexId indexId, ShardId shardId);
}
diff --git a/core/src/main/java/org/elasticsearch/repositories/RepositoryData.java b/core/src/main/java/org/elasticsearch/repositories/RepositoryData.java
new file mode 100644
index 00000000000..4927e2b41b7
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/repositories/RepositoryData.java
@@ -0,0 +1,311 @@
+/*
+ * 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.repositories;
+
+import org.elasticsearch.ElasticsearchParseException;
+import org.elasticsearch.common.UUIDs;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.snapshots.SnapshotId;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * A class that represents the data in a repository, as captured in the
+ * repository's index blob.
+ */
+public final class RepositoryData implements ToXContent {
+
+ public static final RepositoryData EMPTY = new RepositoryData(Collections.emptyList(), Collections.emptyMap());
+
+ /**
+ * The ids of the snapshots in the repository.
+ */
+ private final List snapshotIds;
+ /**
+ * The indices found in the repository across all snapshots, as a name to {@link IndexId} mapping
+ */
+ private final Map indices;
+ /**
+ * The snapshots that each index belongs to.
+ */
+ private final Map> indexSnapshots;
+
+ public RepositoryData(List snapshotIds, Map> indexSnapshots) {
+ this.snapshotIds = Collections.unmodifiableList(snapshotIds);
+ this.indices = Collections.unmodifiableMap(indexSnapshots.keySet()
+ .stream()
+ .collect(Collectors.toMap(IndexId::getName, Function.identity())));
+ this.indexSnapshots = Collections.unmodifiableMap(indexSnapshots);
+ }
+
+ protected RepositoryData copy() {
+ return new RepositoryData(snapshotIds, indexSnapshots);
+ }
+
+ /**
+ * Returns an unmodifiable list of the snapshot ids.
+ */
+ public List getSnapshotIds() {
+ return snapshotIds;
+ }
+
+ /**
+ * Returns an unmodifiable map of the index names to {@link IndexId} in the repository.
+ */
+ public Map getIndices() {
+ return indices;
+ }
+
+ /**
+ * Add a snapshot and its indices to the repository; returns a new instance. If the snapshot
+ * already exists in the repository data, this method throws an IllegalArgumentException.
+ */
+ public RepositoryData addSnapshot(final SnapshotId snapshotId, final List snapshottedIndices) {
+ if (snapshotIds.contains(snapshotId)) {
+ throw new IllegalArgumentException("[" + snapshotId + "] already exists in the repository data");
+ }
+ List snapshots = new ArrayList<>(snapshotIds);
+ snapshots.add(snapshotId);
+ Map> allIndexSnapshots = new HashMap<>(indexSnapshots);
+ for (final IndexId indexId : snapshottedIndices) {
+ if (allIndexSnapshots.containsKey(indexId)) {
+ Set ids = allIndexSnapshots.get(indexId);
+ if (ids == null) {
+ ids = new LinkedHashSet<>();
+ allIndexSnapshots.put(indexId, ids);
+ }
+ ids.add(snapshotId);
+ } else {
+ Set ids = new LinkedHashSet<>();
+ ids.add(snapshotId);
+ allIndexSnapshots.put(indexId, ids);
+ }
+ }
+ return new RepositoryData(snapshots, allIndexSnapshots);
+ }
+
+ /**
+ * Initializes the indices in the repository metadata; returns a new instance.
+ */
+ public RepositoryData initIndices(final Map> indexSnapshots) {
+ return new RepositoryData(snapshotIds, indexSnapshots);
+ }
+
+ /**
+ * Remove a snapshot and remove any indices that no longer exist in the repository due to the deletion of the snapshot.
+ */
+ public RepositoryData removeSnapshot(final SnapshotId snapshotId) {
+ List newSnapshotIds = snapshotIds
+ .stream()
+ .filter(id -> snapshotId.equals(id) == false)
+ .collect(Collectors.toList());
+ Map> indexSnapshots = new HashMap<>();
+ for (final IndexId indexId : indices.values()) {
+ Set set;
+ Set snapshotIds = this.indexSnapshots.get(indexId);
+ assert snapshotIds != null;
+ if (snapshotIds.contains(snapshotId)) {
+ if (snapshotIds.size() == 1) {
+ // removing the snapshot will mean no more snapshots have this index, so just skip over it
+ continue;
+ }
+ set = new LinkedHashSet<>(snapshotIds);
+ set.remove(snapshotId);
+ } else {
+ set = snapshotIds;
+ }
+ indexSnapshots.put(indexId, set);
+ }
+
+ return new RepositoryData(newSnapshotIds, indexSnapshots);
+ }
+
+ /**
+ * Returns an immutable collection of the snapshot ids for the snapshots that contain the given index.
+ */
+ public Set getSnapshots(final IndexId indexId) {
+ Set snapshotIds = indexSnapshots.get(indexId);
+ if (snapshotIds == null) {
+ throw new IllegalArgumentException("unknown snapshot index " + indexId + "");
+ }
+ return snapshotIds;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ @SuppressWarnings("unchecked") RepositoryData that = (RepositoryData) obj;
+ return snapshotIds.equals(that.snapshotIds)
+ && indices.equals(that.indices)
+ && indexSnapshots.equals(that.indexSnapshots);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(snapshotIds, indices, indexSnapshots);
+ }
+
+ /**
+ * Resolve the index name to the index id specific to the repository,
+ * throwing an exception if the index could not be resolved.
+ */
+ public IndexId resolveIndexId(final String indexName) {
+ if (indices.containsKey(indexName)) {
+ return indices.get(indexName);
+ } else {
+ // on repositories created before 5.0, there was no indices information in the index
+ // blob, so if the repository hasn't been updated with new snapshots, no new index blob
+ // would have been written, so we only have old snapshots without the index information.
+ // in this case, the index id is just the index name
+ return new IndexId(indexName, indexName);
+ }
+ }
+
+ /**
+ * Resolve the given index names to index ids.
+ */
+ public List resolveIndices(final List indices) {
+ List resolvedIndices = new ArrayList<>(indices.size());
+ for (final String indexName : indices) {
+ resolvedIndices.add(resolveIndexId(indexName));
+ }
+ return resolvedIndices;
+ }
+
+ /**
+ * Resolve the given index names to index ids, creating new index ids for
+ * new indices in the repository.
+ */
+ public List resolveNewIndices(final List indicesToResolve) {
+ List snapshotIndices = new ArrayList<>();
+ for (String index : indicesToResolve) {
+ final IndexId indexId;
+ if (indices.containsKey(index)) {
+ indexId = indices.get(index);
+ } else {
+ indexId = new IndexId(index, UUIDs.randomBase64UUID());
+ }
+ snapshotIndices.add(indexId);
+ }
+ return snapshotIndices;
+ }
+
+ private static final String SNAPSHOTS = "snapshots";
+ private static final String INDICES = "indices";
+ private static final String INDEX_ID = "id";
+
+ @Override
+ public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
+ builder.startObject();
+ // write the snapshots list
+ builder.startArray(SNAPSHOTS);
+ for (final SnapshotId snapshot : getSnapshotIds()) {
+ snapshot.toXContent(builder, params);
+ }
+ builder.endArray();
+ // write the indices map
+ builder.startObject(INDICES);
+ for (final IndexId indexId : getIndices().values()) {
+ builder.startObject(indexId.getName());
+ builder.field(INDEX_ID, indexId.getId());
+ builder.startArray(SNAPSHOTS);
+ Set snapshotIds = indexSnapshots.get(indexId);
+ assert snapshotIds != null;
+ for (final SnapshotId snapshotId : snapshotIds) {
+ snapshotId.toXContent(builder, params);
+ }
+ builder.endArray();
+ builder.endObject();
+ }
+ builder.endObject();
+ builder.endObject();
+ return builder;
+ }
+
+ public static RepositoryData fromXContent(final XContentParser parser) throws IOException {
+ List snapshots = new ArrayList<>();
+ Map> indexSnapshots = new HashMap<>();
+ if (parser.nextToken() == XContentParser.Token.START_OBJECT) {
+ while (parser.nextToken() == XContentParser.Token.FIELD_NAME) {
+ String currentFieldName = parser.currentName();
+ if (SNAPSHOTS.equals(currentFieldName)) {
+ if (parser.nextToken() == XContentParser.Token.START_ARRAY) {
+ while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
+ snapshots.add(SnapshotId.fromXContent(parser));
+ }
+ } else {
+ throw new ElasticsearchParseException("expected array for [" + currentFieldName + "]");
+ }
+ } else if (INDICES.equals(currentFieldName)) {
+ if (parser.nextToken() != XContentParser.Token.START_OBJECT) {
+ throw new ElasticsearchParseException("start object expected [indices]");
+ }
+ while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
+ String indexName = parser.currentName();
+ String indexId = null;
+ Set snapshotIds = new LinkedHashSet<>();
+ if (parser.nextToken() != XContentParser.Token.START_OBJECT) {
+ throw new ElasticsearchParseException("start object expected index[" + indexName + "]");
+ }
+ while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
+ String indexMetaFieldName = parser.currentName();
+ parser.nextToken();
+ if (INDEX_ID.equals(indexMetaFieldName)) {
+ indexId = parser.text();
+ } else if (SNAPSHOTS.equals(indexMetaFieldName)) {
+ if (parser.currentToken() != XContentParser.Token.START_ARRAY) {
+ throw new ElasticsearchParseException("start array expected [snapshots]");
+ }
+ while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
+ snapshotIds.add(SnapshotId.fromXContent(parser));
+ }
+ }
+ }
+ assert indexId != null;
+ indexSnapshots.put(new IndexId(indexName, indexId), snapshotIds);
+ }
+ } else {
+ throw new ElasticsearchParseException("unknown field name [" + currentFieldName + "]");
+ }
+ }
+ } else {
+ throw new ElasticsearchParseException("start object expected");
+ }
+ return new RepositoryData(snapshots, indexSnapshots);
+ }
+
+}
diff --git a/core/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java b/core/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java
index 06e2b8ff97a..fe11a502c42 100644
--- a/core/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java
+++ b/core/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java
@@ -45,6 +45,8 @@ import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.lucene.store.InputStreamIndexInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.iterable.Iterables;
+import org.elasticsearch.common.util.set.Sets;
+import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.snapshots.IndexShardRestoreFailedException;
import org.elasticsearch.index.snapshots.IndexShardSnapshotException;
@@ -58,6 +60,8 @@ import org.elasticsearch.index.snapshots.blobstore.SnapshotFiles;
import org.elasticsearch.index.store.Store;
import org.elasticsearch.index.store.StoreFileMetaData;
import org.elasticsearch.indices.recovery.RecoveryState;
+import org.elasticsearch.repositories.IndexId;
+import org.elasticsearch.repositories.RepositoryData;
import org.elasticsearch.snapshots.SnapshotId;
import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.Strings;
@@ -103,6 +107,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.stream.Collectors;
import static java.util.Collections.emptyMap;
@@ -119,14 +124,14 @@ import static java.util.Collections.unmodifiableMap;
* {@code
* STORE_ROOT
* |- index-N - list of all snapshot name as JSON array, N is the generation of the file
- * |- index-latest - contains the numeric value of the latest generation of the index file (i.e. N from above)
- * |- snapshot-20131010 - JSON serialized Snapshot for snapshot "20131010"
+ * |- index.latest - contains the numeric value of the latest generation of the index file (i.e. N from above)
+ * |- snap-20131010 - JSON serialized Snapshot for snapshot "20131010"
* |- meta-20131010.dat - JSON serialized MetaData for snapshot "20131010" (includes only global metadata)
- * |- snapshot-20131011 - JSON serialized Snapshot for snapshot "20131011"
+ * |- snap-20131011 - JSON serialized Snapshot for snapshot "20131011"
* |- meta-20131011.dat - JSON serialized MetaData for snapshot "20131011"
* .....
* |- indices/ - data for all indices
- * |- foo/ - data for index "foo"
+ * |- Ac1342-B_x/ - data for index "foo" which was assigned the unique id of Ac1342-B_x in the repository
* | |- meta-20131010.dat - JSON Serialized IndexMetaData for index "foo"
* | |- 0/ - data for shard "0" of index "foo"
* | | |- __1 \
@@ -146,7 +151,7 @@ import static java.util.Collections.unmodifiableMap;
* | |-2/
* | ......
* |
- * |- bar/ - data for index bar
+ * |- 1xB0D8_B3y/ - data for index "bar" which was assigned the unique id of 1xB0D8_B3y in the repository
* ......
* }
*
@@ -163,13 +168,13 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
private static final String SNAPSHOT_PREFIX = "snap-";
- protected static final String SNAPSHOT_CODEC = "snapshot";
+ private static final String SNAPSHOT_CODEC = "snapshot";
static final String SNAPSHOTS_FILE = "index"; // package private for unit testing
- private static final String SNAPSHOTS_FILE_PREFIX = "index-";
+ private static final String INDEX_FILE_PREFIX = "index-";
- private static final String SNAPSHOTS_INDEX_LATEST_BLOB = "index.latest";
+ private static final String INDEX_LATEST_BLOB = "index.latest";
private static final String TESTS_FILE = "tests-";
@@ -305,7 +310,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
@Override
- public void initializeSnapshot(SnapshotId snapshotId, List indices, MetaData clusterMetadata) {
+ public void initializeSnapshot(SnapshotId snapshotId, List indices, MetaData clusterMetaData) {
if (isReadOnly()) {
throw new RepositoryException(metadata.name(), "cannot create snapshot in a readonly repository");
}
@@ -315,28 +320,69 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
if (getSnapshots().stream().anyMatch(s -> s.getName().equals(snapshotName))) {
throw new SnapshotCreationException(metadata.name(), snapshotId, "snapshot with the same name already exists");
}
- if (snapshotFormat.exists(snapshotsBlobContainer, blobId(snapshotId)) ||
+ if (snapshotFormat.exists(snapshotsBlobContainer, snapshotId.getUUID()) ||
snapshotLegacyFormat.exists(snapshotsBlobContainer, snapshotName)) {
throw new SnapshotCreationException(metadata.name(), snapshotId, "snapshot with such name already exists");
}
+
// Write Global MetaData
- globalMetaDataFormat.write(clusterMetadata, snapshotsBlobContainer, snapshotName);
- for (String index : indices) {
- final IndexMetaData indexMetaData = clusterMetadata.index(index);
- final BlobPath indexPath = basePath().add("indices").add(index);
+ globalMetaDataFormat.write(clusterMetaData, snapshotsBlobContainer, snapshotId.getUUID());
+
+ // write the index metadata for each index in the snapshot
+ for (IndexId index : indices) {
+ final IndexMetaData indexMetaData = clusterMetaData.index(index.getName());
+ final BlobPath indexPath = basePath().add("indices").add(index.getId());
final BlobContainer indexMetaDataBlobContainer = blobStore().blobContainer(indexPath);
- indexMetaDataFormat.write(indexMetaData, indexMetaDataBlobContainer, snapshotName);
+ indexMetaDataFormat.write(indexMetaData, indexMetaDataBlobContainer, snapshotId.getUUID());
}
} catch (IOException ex) {
throw new SnapshotCreationException(metadata.name(), snapshotId, ex);
}
}
+ // Older repository index files (index-N) only contain snapshot info, not indices info,
+ // so if the repository data is of the older format, populate it with the indices entries
+ // so we know which indices of snapshots have blob ids in the older format.
+ private RepositoryData upgradeRepositoryData(final RepositoryData repositoryData) throws IOException {
+ final Map> indexToSnapshots = new HashMap<>();
+ for (final SnapshotId snapshotId : repositoryData.getSnapshotIds()) {
+ final SnapshotInfo snapshotInfo;
+ try {
+ snapshotInfo = getSnapshotInfo(snapshotId);
+ } catch (SnapshotException e) {
+ logger.warn("[{}] repository is on a pre-5.0 format with an index file that contains snapshot [{}] but " +
+ "the corresponding snap-{}.dat file cannot be read. The snapshot will no longer be included in " +
+ "the repository but its data directories will remain.", e, getMetadata().name(),
+ snapshotId, snapshotId.getUUID());
+ continue;
+ }
+ for (final String indexName : snapshotInfo.indices()) {
+ final IndexId indexId = new IndexId(indexName, indexName);
+ if (indexToSnapshots.containsKey(indexId)) {
+ indexToSnapshots.get(indexId).add(snapshotId);
+ } else {
+ indexToSnapshots.put(indexId, Sets.newHashSet(snapshotId));
+ }
+ }
+ }
+ try {
+ final RepositoryData updatedRepoData = repositoryData.initIndices(indexToSnapshots);
+ if (isReadOnly() == false) {
+ // write the new index gen file with the indices included
+ writeIndexGen(updatedRepoData);
+ }
+ return updatedRepoData;
+ } catch (IOException e) {
+ throw new RepositoryException(metadata.name(), "failed to update the repository index blob with indices data on startup", e);
+ }
+ }
+
@Override
public void deleteSnapshot(SnapshotId snapshotId) {
if (isReadOnly()) {
throw new RepositoryException(metadata.name(), "cannot delete snapshot from a readonly repository");
}
+ final RepositoryData repositoryData = getRepositoryData();
List indices = Collections.emptyList();
SnapshotInfo snapshot = null;
try {
@@ -350,36 +396,29 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
MetaData metaData = null;
try {
if (snapshot != null) {
- metaData = readSnapshotMetaData(snapshotId, snapshot.version(), indices, true);
+ metaData = readSnapshotMetaData(snapshotId, snapshot.version(), repositoryData.resolveIndices(indices), true);
} else {
- metaData = readSnapshotMetaData(snapshotId, null, indices, true);
+ metaData = readSnapshotMetaData(snapshotId, null, repositoryData.resolveIndices(indices), true);
}
} catch (IOException | SnapshotException ex) {
logger.warn("cannot read metadata for snapshot [{}]", ex, snapshotId);
}
try {
- final String snapshotName = snapshotId.getName();
- // Delete snapshot file first so we wouldn't end up with partially deleted snapshot that looks OK
- if (snapshot != null) {
- snapshotFormat(snapshot.version()).delete(snapshotsBlobContainer, blobId(snapshotId));
- globalMetaDataFormat(snapshot.version()).delete(snapshotsBlobContainer, snapshotName);
- } else {
- // We don't know which version was the snapshot created with - try deleting both current and legacy formats
- snapshotFormat.delete(snapshotsBlobContainer, blobId(snapshotId));
- snapshotLegacyFormat.delete(snapshotsBlobContainer, snapshotName);
- globalMetaDataLegacyFormat.delete(snapshotsBlobContainer, snapshotName);
- globalMetaDataFormat.delete(snapshotsBlobContainer, snapshotName);
- }
- // Delete snapshot from the snapshot list
- List snapshotIds = getSnapshots().stream().filter(id -> snapshotId.equals(id) == false).collect(Collectors.toList());
- writeSnapshotsToIndexGen(snapshotIds);
+ // Delete snapshot from the index file, since it is the maintainer of truth of active snapshots
+ writeIndexGen(repositoryData.removeSnapshot(snapshotId));
+
+ // delete the snapshot file
+ safeSnapshotBlobDelete(snapshot, snapshotId.getUUID());
+ // delete the global metadata file
+ safeGlobalMetaDataBlobDelete(snapshot, snapshotId.getUUID());
// Now delete all indices
for (String index : indices) {
- BlobPath indexPath = basePath().add("indices").add(index);
+ final IndexId indexId = repositoryData.resolveIndexId(index);
+ BlobPath indexPath = basePath().add("indices").add(indexId.getId());
BlobContainer indexMetaDataBlobContainer = blobStore().blobContainer(indexPath);
try {
- indexMetaDataFormat(snapshot.version()).delete(indexMetaDataBlobContainer, snapshotId.getName());
+ indexMetaDataFormat(snapshot.version()).delete(indexMetaDataBlobContainer, snapshotId.getUUID());
} catch (IOException ex) {
logger.warn("[{}] failed to delete metadata for index [{}]", ex, snapshotId, index);
}
@@ -388,7 +427,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
if (indexMetaData != null) {
for (int shardId = 0; shardId < indexMetaData.getNumberOfShards(); shardId++) {
try {
- delete(snapshotId, snapshot.version(), new ShardId(indexMetaData.getIndex(), shardId));
+ delete(snapshotId, snapshot.version(), indexId, new ShardId(indexMetaData.getIndex(), shardId));
} catch (SnapshotException ex) {
logger.warn("[{}] failed to delete shard data for shard [{}][{}]", ex, snapshotId, index, shardId);
}
@@ -401,28 +440,77 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
}
+ private void safeSnapshotBlobDelete(final SnapshotInfo snapshotInfo, final String blobId) {
+ if (snapshotInfo != null) {
+ // we know the version the snapshot was created with
+ try {
+ snapshotFormat(snapshotInfo.version()).delete(snapshotsBlobContainer, blobId);
+ } catch (IOException e) {
+ logger.warn("[{}] Unable to delete snapshot file [{}]", e, snapshotInfo.snapshotId(), blobId);
+ }
+ } else {
+ // we don't know the version, first try the current format, then the legacy format
+ try {
+ snapshotFormat.delete(snapshotsBlobContainer, blobId);
+ } catch (IOException e) {
+ // now try legacy format
+ try {
+ snapshotLegacyFormat.delete(snapshotsBlobContainer, blobId);
+ } catch (IOException e2) {
+ // neither snapshot file could be deleted, log the error
+ logger.warn("Unable to delete snapshot file [{}]", e, blobId);
+ }
+ }
+ }
+ }
+
+ private void safeGlobalMetaDataBlobDelete(final SnapshotInfo snapshotInfo, final String blobId) {
+ if (snapshotInfo != null) {
+ // we know the version the snapshot was created with
+ try {
+ globalMetaDataFormat(snapshotInfo.version()).delete(snapshotsBlobContainer, blobId);
+ } catch (IOException e) {
+ logger.warn("[{}] Unable to delete global metadata file [{}]", e, snapshotInfo.snapshotId(), blobId);
+ }
+ } else {
+ // we don't know the version, first try the current format, then the legacy format
+ try {
+ globalMetaDataFormat.delete(snapshotsBlobContainer, blobId);
+ } catch (IOException e) {
+ // now try legacy format
+ try {
+ globalMetaDataLegacyFormat.delete(snapshotsBlobContainer, blobId);
+ } catch (IOException e2) {
+ // neither global metadata file could be deleted, log the error
+ logger.warn("Unable to delete global metadata file [{}]", e, blobId);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override
public SnapshotInfo finalizeSnapshot(final SnapshotId snapshotId,
- final List indices,
+ final List indices,
final long startTime,
final String failure,
final int totalShards,
final List shardFailures) {
try {
SnapshotInfo blobStoreSnapshot = new SnapshotInfo(snapshotId,
- indices,
+ indices.stream().map(IndexId::getName).collect(Collectors.toList()),
startTime,
failure,
System.currentTimeMillis(),
totalShards,
shardFailures);
- snapshotFormat.write(blobStoreSnapshot, snapshotsBlobContainer, blobId(snapshotId));
- List snapshotIds = getSnapshots();
+ snapshotFormat.write(blobStoreSnapshot, snapshotsBlobContainer, snapshotId.getUUID());
+ final RepositoryData repositoryData = getRepositoryData();
+ List snapshotIds = repositoryData.getSnapshotIds();
if (!snapshotIds.contains(snapshotId)) {
- snapshotIds = new ArrayList<>(snapshotIds);
- snapshotIds.add(snapshotId);
- snapshotIds = Collections.unmodifiableList(snapshotIds);
- writeSnapshotsToIndexGen(snapshotIds);
+ writeIndexGen(repositoryData.addSnapshot(snapshotId, indices));
}
return blobStoreSnapshot;
} catch (IOException ex) {
@@ -430,27 +518,19 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
}
- @Override
public List getSnapshots() {
- try {
- return Collections.unmodifiableList(readSnapshotsFromIndex());
- } catch (NoSuchFileException | FileNotFoundException e) {
- // its a fresh repository, no index file exists, so return an empty list
- return Collections.emptyList();
- } catch (IOException ioe) {
- throw new RepositoryException(metadata.name(), "failed to list snapshots in repository", ioe);
- }
+ return getRepositoryData().getSnapshotIds();
}
@Override
- public MetaData getSnapshotMetaData(SnapshotInfo snapshot, List indices) throws IOException {
+ public MetaData getSnapshotMetaData(SnapshotInfo snapshot, List indices) throws IOException {
return readSnapshotMetaData(snapshot.snapshotId(), snapshot.version(), indices, false);
}
@Override
public SnapshotInfo getSnapshotInfo(final SnapshotId snapshotId) {
try {
- return snapshotFormat.read(snapshotsBlobContainer, blobId(snapshotId));
+ return snapshotFormat.read(snapshotsBlobContainer, snapshotId.getUUID());
} catch (FileNotFoundException | NoSuchFileException ex) {
// File is missing - let's try legacy format instead
try {
@@ -465,13 +545,13 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
}
- private MetaData readSnapshotMetaData(SnapshotId snapshotId, Version snapshotVersion, List indices, boolean ignoreIndexErrors) throws IOException {
+ private MetaData readSnapshotMetaData(SnapshotId snapshotId, Version snapshotVersion, List indices, boolean ignoreIndexErrors) throws IOException {
MetaData metaData;
if (snapshotVersion == null) {
// When we delete corrupted snapshots we might not know which version we are dealing with
// We can try detecting the version based on the metadata file format
assert ignoreIndexErrors;
- if (globalMetaDataFormat.exists(snapshotsBlobContainer, snapshotId.getName())) {
+ if (globalMetaDataFormat.exists(snapshotsBlobContainer, snapshotId.getUUID())) {
snapshotVersion = Version.CURRENT;
} else if (globalMetaDataLegacyFormat.exists(snapshotsBlobContainer, snapshotId.getName())) {
throw new SnapshotException(metadata.name(), snapshotId, "snapshot is too old");
@@ -480,21 +560,21 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
}
try {
- metaData = globalMetaDataFormat(snapshotVersion).read(snapshotsBlobContainer, snapshotId.getName());
+ metaData = globalMetaDataFormat(snapshotVersion).read(snapshotsBlobContainer, snapshotId.getUUID());
} catch (FileNotFoundException | NoSuchFileException ex) {
throw new SnapshotMissingException(metadata.name(), snapshotId, ex);
} catch (IOException ex) {
throw new SnapshotException(metadata.name(), snapshotId, "failed to get snapshots", ex);
}
MetaData.Builder metaDataBuilder = MetaData.builder(metaData);
- for (String index : indices) {
- BlobPath indexPath = basePath().add("indices").add(index);
+ for (IndexId index : indices) {
+ BlobPath indexPath = basePath().add("indices").add(index.getId());
BlobContainer indexMetaDataBlobContainer = blobStore().blobContainer(indexPath);
try {
- metaDataBuilder.put(indexMetaDataFormat(snapshotVersion).read(indexMetaDataBlobContainer, snapshotId.getName()), false);
+ metaDataBuilder.put(indexMetaDataFormat(snapshotVersion).read(indexMetaDataBlobContainer, snapshotId.getUUID()), false);
} catch (ElasticsearchParseException | IOException ex) {
if (ignoreIndexErrors) {
- logger.warn("[{}] [{}] failed to read metadata for index", ex, snapshotId, index);
+ logger.warn("[{}] [{}] failed to read metadata for index", ex, snapshotId, index.getName());
} else {
throw ex;
}
@@ -562,10 +642,6 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
}
- private static final String SNAPSHOTS = "snapshots";
- private static final String NAME = "name";
- private static final String UUID = "uuid";
-
@Override
public long getSnapshotThrottleTimeInNanos() {
return snapshotRateLimitingTimeInNanos.count();
@@ -609,6 +685,43 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
}
+ @Override
+ public RepositoryData getRepositoryData() {
+ try {
+ final long indexGen = latestIndexBlobId();
+ final String snapshotsIndexBlobName;
+ final boolean legacyFormat;
+ if (indexGen == -1) {
+ // index-N file doesn't exist, either its a fresh repository, or its in the
+ // old format, so look for the older index file before returning an empty list
+ snapshotsIndexBlobName = SNAPSHOTS_FILE;
+ legacyFormat = true;
+ } else {
+ snapshotsIndexBlobName = INDEX_FILE_PREFIX + Long.toString(indexGen);
+ legacyFormat = false;
+ }
+
+ RepositoryData repositoryData;
+ try (InputStream blob = snapshotsBlobContainer.readBlob(snapshotsIndexBlobName)) {
+ BytesStreamOutput out = new BytesStreamOutput();
+ Streams.copy(blob, out);
+ try (XContentParser parser = XContentHelper.createParser(out.bytes())) {
+ repositoryData = RepositoryData.fromXContent(parser);
+ }
+ }
+ if (legacyFormat) {
+ // pre 5.0 repository data needs to be updated to include the indices
+ repositoryData = upgradeRepositoryData(repositoryData);
+ }
+ return repositoryData;
+ } catch (NoSuchFileException nsfe) {
+ // repository doesn't have an index blob, its a new blank repo
+ return RepositoryData.EMPTY;
+ } catch (IOException ioe) {
+ throw new RepositoryException(metadata.name(), "could not read repository data from index blob", ioe);
+ }
+ }
+
public static String testBlobPrefix(String seed) {
return TESTS_FILE + seed;
}
@@ -623,35 +736,30 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
return snapshotsBlobContainer;
}
- protected void writeSnapshotsToIndexGen(final List snapshots) throws IOException {
+ protected void writeIndexGen(final RepositoryData repositoryData) throws IOException {
assert isReadOnly() == false; // can not write to a read only repository
final BytesReference snapshotsBytes;
try (BytesStreamOutput bStream = new BytesStreamOutput()) {
try (StreamOutput stream = new OutputStreamStreamOutput(bStream)) {
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, stream);
- builder.startObject();
- builder.startArray(SNAPSHOTS);
- for (SnapshotId snapshot : snapshots) {
- builder.startObject();
- builder.field(NAME, snapshot.getName());
- builder.field(UUID, snapshot.getUUID());
- builder.endObject();
- }
- builder.endArray();
- builder.endObject();
+ repositoryData.toXContent(builder, ToXContent.EMPTY_PARAMS);
builder.close();
}
snapshotsBytes = bStream.bytes();
}
final long gen = latestIndexBlobId() + 1;
// write the index file
- writeAtomic(SNAPSHOTS_FILE_PREFIX + Long.toString(gen), snapshotsBytes);
+ writeAtomic(INDEX_FILE_PREFIX + Long.toString(gen), snapshotsBytes);
// delete the N-2 index file if it exists, keep the previous one around as a backup
if (isReadOnly() == false && gen - 2 >= 0) {
- final String oldSnapshotIndexFile = SNAPSHOTS_FILE_PREFIX + Long.toString(gen - 2);
+ final String oldSnapshotIndexFile = INDEX_FILE_PREFIX + Long.toString(gen - 2);
if (snapshotsBlobContainer.blobExists(oldSnapshotIndexFile)) {
snapshotsBlobContainer.deleteBlob(oldSnapshotIndexFile);
}
+ // delete the old index file (non-generational) if it exists
+ if (snapshotsBlobContainer.blobExists(SNAPSHOTS_FILE)) {
+ snapshotsBlobContainer.deleteBlob(SNAPSHOTS_FILE);
+ }
}
// write the current generation to the index-latest file
@@ -660,72 +768,10 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
bStream.writeLong(gen);
genBytes = bStream.bytes();
}
- if (snapshotsBlobContainer.blobExists(SNAPSHOTS_INDEX_LATEST_BLOB)) {
- snapshotsBlobContainer.deleteBlob(SNAPSHOTS_INDEX_LATEST_BLOB);
+ if (snapshotsBlobContainer.blobExists(INDEX_LATEST_BLOB)) {
+ snapshotsBlobContainer.deleteBlob(INDEX_LATEST_BLOB);
}
- writeAtomic(SNAPSHOTS_INDEX_LATEST_BLOB, genBytes);
- }
-
- protected List readSnapshotsFromIndex() throws IOException {
- final long indexGen = latestIndexBlobId();
- final String snapshotsIndexBlobName;
- if (indexGen == -1) {
- // index-N file doesn't exist, either its a fresh repository, or its in the
- // old format, so look for the older index file before returning an empty list
- snapshotsIndexBlobName = SNAPSHOTS_FILE;
- } else {
- snapshotsIndexBlobName = SNAPSHOTS_FILE_PREFIX + Long.toString(indexGen);
- }
-
- try (InputStream blob = snapshotsBlobContainer.readBlob(snapshotsIndexBlobName)) {
- BytesStreamOutput out = new BytesStreamOutput();
- Streams.copy(blob, out);
- ArrayList snapshots = new ArrayList<>();
- try (XContentParser parser = XContentHelper.createParser(out.bytes())) {
- if (parser.nextToken() == XContentParser.Token.START_OBJECT) {
- if (parser.nextToken() == XContentParser.Token.FIELD_NAME) {
- String currentFieldName = parser.currentName();
- if (SNAPSHOTS.equals(currentFieldName)) {
- if (parser.nextToken() == XContentParser.Token.START_ARRAY) {
- while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
- // the new format from 5.0 which contains the snapshot name and uuid
- String name = null;
- String uuid = null;
- if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
- while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
- currentFieldName = parser.currentName();
- parser.nextToken();
- if (NAME.equals(currentFieldName)) {
- name = parser.text();
- } else if (UUID.equals(currentFieldName)) {
- uuid = parser.text();
- }
- }
- snapshots.add(new SnapshotId(name, uuid));
- }
- // the old format pre 5.0 that only contains the snapshot name, use the name as the uuid too
- else {
- name = parser.text();
- snapshots.add(new SnapshotId(name, SnapshotId.UNASSIGNED_UUID));
- }
- }
- }
- }
- }
- }
- }
- return Collections.unmodifiableList(snapshots);
- }
- }
-
- // Package private for testing
- static String blobId(final SnapshotId snapshotId) {
- final String uuid = snapshotId.getUUID();
- if (uuid.equals(SnapshotId.UNASSIGNED_UUID)) {
- // the old snapshot blob naming
- return snapshotId.getName();
- }
- return snapshotId.getName() + "-" + uuid;
+ writeAtomic(INDEX_LATEST_BLOB, genBytes);
}
/**
@@ -762,7 +808,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
// package private for testing
long readSnapshotIndexLatestBlob() throws IOException {
- try (InputStream blob = snapshotsBlobContainer.readBlob(SNAPSHOTS_INDEX_LATEST_BLOB)) {
+ try (InputStream blob = snapshotsBlobContainer.readBlob(INDEX_LATEST_BLOB)) {
BytesStreamOutput out = new BytesStreamOutput();
Streams.copy(blob, out);
return Numbers.bytesToLong(out.bytes().toBytesRef());
@@ -770,7 +816,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
private long listBlobsToGetLatestIndexId() throws IOException {
- Map blobs = snapshotsBlobContainer.listBlobsByPrefix(SNAPSHOTS_FILE_PREFIX);
+ Map blobs = snapshotsBlobContainer.listBlobsByPrefix(INDEX_FILE_PREFIX);
long latest = -1;
if (blobs.isEmpty()) {
// no snapshot index blobs have been written yet
@@ -779,7 +825,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
for (final BlobMetaData blobMetaData : blobs.values()) {
final String blobName = blobMetaData.name();
try {
- final long curr = Long.parseLong(blobName.substring(SNAPSHOTS_FILE_PREFIX.length()));
+ final long curr = Long.parseLong(blobName.substring(INDEX_FILE_PREFIX.length()));
latest = Math.max(latest, curr);
} catch (NumberFormatException nfe) {
// the index- blob wasn't of the format index-N where N is a number,
@@ -802,9 +848,11 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
}
+
+
@Override
- public void snapshotShard(IndexShard shard, SnapshotId snapshotId, IndexCommit snapshotIndexCommit, IndexShardSnapshotStatus snapshotStatus) {
- SnapshotContext snapshotContext = new SnapshotContext(shard, snapshotId, snapshotStatus);
+ public void snapshotShard(IndexShard shard, SnapshotId snapshotId, IndexId indexId, IndexCommit snapshotIndexCommit, IndexShardSnapshotStatus snapshotStatus) {
+ SnapshotContext snapshotContext = new SnapshotContext(shard, snapshotId, indexId, snapshotStatus);
snapshotStatus.startTime(System.currentTimeMillis());
try {
@@ -824,8 +872,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
@Override
- public void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, ShardId snapshotShardId, RecoveryState recoveryState) {
- final RestoreContext snapshotContext = new RestoreContext(shard, snapshotId, version, snapshotShardId, recoveryState);
+ public void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, IndexId indexId, ShardId snapshotShardId, RecoveryState recoveryState) {
+ final RestoreContext snapshotContext = new RestoreContext(shard, snapshotId, version, indexId, snapshotShardId, recoveryState);
try {
snapshotContext.restore();
} catch (Exception e) {
@@ -834,8 +882,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
@Override
- public IndexShardSnapshotStatus getShardSnapshotStatus(SnapshotId snapshotId, Version version, ShardId shardId) {
- Context context = new Context(snapshotId, version, shardId);
+ public IndexShardSnapshotStatus getShardSnapshotStatus(SnapshotId snapshotId, Version version, IndexId indexId, ShardId shardId) {
+ Context context = new Context(snapshotId, version, indexId, shardId);
BlobStoreIndexShardSnapshot snapshot = context.loadSnapshot();
IndexShardSnapshotStatus status = new IndexShardSnapshotStatus();
status.updateStage(IndexShardSnapshotStatus.Stage.DONE);
@@ -869,8 +917,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
* @param snapshotId snapshot id
* @param shardId shard id
*/
- public void delete(SnapshotId snapshotId, Version version, ShardId shardId) {
- Context context = new Context(snapshotId, version, shardId, shardId);
+ private void delete(SnapshotId snapshotId, Version version, IndexId indexId, ShardId shardId) {
+ Context context = new Context(snapshotId, version, indexId, shardId, shardId);
context.delete();
}
@@ -903,15 +951,15 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
protected final Version version;
- public Context(SnapshotId snapshotId, Version version, ShardId shardId) {
- this(snapshotId, version, shardId, shardId);
+ public Context(SnapshotId snapshotId, Version version, IndexId indexId, ShardId shardId) {
+ this(snapshotId, version, indexId, shardId, shardId);
}
- public Context(SnapshotId snapshotId, Version version, ShardId shardId, ShardId snapshotShardId) {
+ public Context(SnapshotId snapshotId, Version version, IndexId indexId, ShardId shardId, ShardId snapshotShardId) {
this.snapshotId = snapshotId;
this.version = version;
this.shardId = shardId;
- blobContainer = blobStore().blobContainer(basePath().add("indices").add(snapshotShardId.getIndexName()).add(Integer.toString(snapshotShardId.getId())));
+ blobContainer = blobStore().blobContainer(basePath().add("indices").add(indexId.getId()).add(Integer.toString(snapshotShardId.getId())));
}
/**
@@ -930,7 +978,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
int fileListGeneration = tuple.v2();
try {
- indexShardSnapshotFormat(version).delete(blobContainer, snapshotId.getName());
+ indexShardSnapshotFormat(version).delete(blobContainer, snapshotId.getUUID());
} catch (IOException e) {
logger.debug("[{}] [{}] failed to delete shard snapshot file", shardId, snapshotId);
}
@@ -951,7 +999,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
*/
public BlobStoreIndexShardSnapshot loadSnapshot() {
try {
- return indexShardSnapshotFormat(version).read(blobContainer, snapshotId.getName());
+ return indexShardSnapshotFormat(version).read(blobContainer, snapshotId.getUUID());
} catch (IOException ex) {
throw new IndexShardRestoreFailedException(shardId, "failed to read shard snapshot file", ex);
}
@@ -1080,7 +1128,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
try {
BlobStoreIndexShardSnapshot snapshot = null;
if (name.startsWith(SNAPSHOT_PREFIX)) {
- snapshot = indexShardSnapshotFormat.readBlob(blobContainer, name);
+ snapshot = indexShardSnapshotFormat.readBlob(blobContainer, snapshotId.getUUID());
} else if (name.startsWith(LEGACY_SNAPSHOT_PREFIX)) {
snapshot = indexShardSnapshotLegacyFormat.readBlob(blobContainer, name);
}
@@ -1109,10 +1157,11 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
*
* @param shard shard to be snapshotted
* @param snapshotId snapshot id
+ * @param indexId the id of the index being snapshotted
* @param snapshotStatus snapshot status to report progress
*/
- public SnapshotContext(IndexShard shard, SnapshotId snapshotId, IndexShardSnapshotStatus snapshotStatus) {
- super(snapshotId, Version.CURRENT, shard.shardId());
+ public SnapshotContext(IndexShard shard, SnapshotId snapshotId, IndexId indexId, IndexShardSnapshotStatus snapshotStatus) {
+ super(snapshotId, Version.CURRENT, indexId, shard.shardId());
this.snapshotStatus = snapshotStatus;
this.store = shard.store();
}
@@ -1220,7 +1269,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
//TODO: The time stored in snapshot doesn't include cleanup time.
logger.trace("[{}] [{}] writing shard snapshot file", shardId, snapshotId);
try {
- indexShardSnapshotFormat.write(snapshot, blobContainer, snapshotId.getName());
+ indexShardSnapshotFormat.write(snapshot, blobContainer, snapshotId.getUUID());
} catch (IOException e) {
throw new IndexShardSnapshotFailedException(shardId, "Failed to write commit point", e);
}
@@ -1396,11 +1445,12 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
*
* @param shard shard to restore into
* @param snapshotId snapshot id
+ * @param indexId id of the index being restored
* @param snapshotShardId shard in the snapshot that data should be restored from
* @param recoveryState recovery state to report progress
*/
- public RestoreContext(IndexShard shard, SnapshotId snapshotId, Version version, ShardId snapshotShardId, RecoveryState recoveryState) {
- super(snapshotId, version, shard.shardId(), snapshotShardId);
+ public RestoreContext(IndexShard shard, SnapshotId snapshotId, Version version, IndexId indexId, ShardId snapshotShardId, RecoveryState recoveryState) {
+ super(snapshotId, version, indexId, shard.shardId(), snapshotShardId);
this.recoveryState = recoveryState;
store = shard.store();
}
@@ -1574,6 +1624,6 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
}
}
-
}
+
}
diff --git a/core/src/main/java/org/elasticsearch/script/ScriptService.java b/core/src/main/java/org/elasticsearch/script/ScriptService.java
index a1aff430f26..e4b80b5dc80 100644
--- a/core/src/main/java/org/elasticsearch/script/ScriptService.java
+++ b/core/src/main/java/org/elasticsearch/script/ScriptService.java
@@ -34,7 +34,6 @@ import org.elasticsearch.cluster.ClusterStateListener;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.ParseField;
-import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.cache.Cache;
@@ -101,7 +100,6 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
private final ScriptModes scriptModes;
private final ScriptContextRegistry scriptContextRegistry;
- private final ParseFieldMatcher parseFieldMatcher;
private final ScriptMetrics scriptMetrics = new ScriptMetrics();
private ClusterState clusterState;
@@ -113,7 +111,6 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
Objects.requireNonNull(scriptEngineRegistry);
Objects.requireNonNull(scriptContextRegistry);
Objects.requireNonNull(scriptSettings);
- this.parseFieldMatcher = new ParseFieldMatcher(settings);
if (Strings.hasLength(settings.get(DISABLE_DYNAMIC_SCRIPTING_SETTING))) {
throw new IllegalArgumentException(DISABLE_DYNAMIC_SCRIPTING_SETTING + " is not a supported setting, replace with fine-grained script settings. \n" +
"Dynamic scripts can be enabled for all languages and all operations by replacing `script.disable_dynamic: false` with `script.inline: true` and `script.stored: true` in elasticsearch.yml");
diff --git a/core/src/main/java/org/elasticsearch/script/ScriptSettings.java b/core/src/main/java/org/elasticsearch/script/ScriptSettings.java
index 41b19a3e572..e315f8d816c 100644
--- a/core/src/main/java/org/elasticsearch/script/ScriptSettings.java
+++ b/core/src/main/java/org/elasticsearch/script/ScriptSettings.java
@@ -19,11 +19,9 @@
package org.elasticsearch.script;
-import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.script.ScriptService;
import java.util.ArrayList;
import java.util.Collections;
@@ -31,7 +29,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
-import java.util.stream.Collectors;
public class ScriptSettings {
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/package-info.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/package-info.java
new file mode 100644
index 00000000000..ba529e687c8
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Support for limiting the completion suggesters results to within a "context" like a geographic location or a category.
+ */
+package org.elasticsearch.search.suggest.completion.context;
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/package-info.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/package-info.java
new file mode 100644
index 00000000000..dfa3f548e86
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Suggests alternate queries by fancy prefix matching.
+ */
+package org.elasticsearch.search.suggest.completion;
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion2x/context/package-info.java b/core/src/main/java/org/elasticsearch/search/suggest/completion2x/context/package-info.java
new file mode 100644
index 00000000000..0d9a9e71963
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/search/suggest/completion2x/context/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Support for completion suggesters with contexts built on 2.x indices.
+ */
+package org.elasticsearch.search.suggest.completion2x.context;
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion2x/package-info.java b/core/src/main/java/org/elasticsearch/search/suggest/completion2x/package-info.java
new file mode 100644
index 00000000000..b8b14aa7c3f
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/search/suggest/completion2x/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Support for completion suggesters built on 2.x indices.
+ */
+package org.elasticsearch.search.suggest.completion2x;
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/package-info.java b/core/src/main/java/org/elasticsearch/search/suggest/package-info.java
new file mode 100644
index 00000000000..b2da9561083
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/search/suggest/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Support for suggesting alternate queries.
+ */
+package org.elasticsearch.search.suggest;
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/package-info.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/package-info.java
new file mode 100644
index 00000000000..b721881b769
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Suggests alternate queries by breaking the query into terms and suggesting terms that are frequently found together.
+ */
+package org.elasticsearch.search.suggest.phrase;
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/term/package-info.java b/core/src/main/java/org/elasticsearch/search/suggest/term/package-info.java
new file mode 100644
index 00000000000..fb568d405e8
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/search/suggest/term/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Suggests alternate queries by breaking the query into terms and suggesting more popular terms.
+ */
+package org.elasticsearch.search.suggest.term;
diff --git a/core/src/main/java/org/elasticsearch/snapshots/RestoreService.java b/core/src/main/java/org/elasticsearch/snapshots/RestoreService.java
index dedcc6d8d21..7ab579aa455 100644
--- a/core/src/main/java/org/elasticsearch/snapshots/RestoreService.java
+++ b/core/src/main/java/org/elasticsearch/snapshots/RestoreService.java
@@ -63,8 +63,10 @@ import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.shard.ShardId;
+import org.elasticsearch.repositories.IndexId;
import org.elasticsearch.repositories.RepositoriesService;
import org.elasticsearch.repositories.Repository;
+import org.elasticsearch.repositories.RepositoryData;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.EmptyTransportResponseHandler;
import org.elasticsearch.transport.TransportChannel;
@@ -185,7 +187,8 @@ public class RestoreService extends AbstractComponent implements ClusterStateLis
try {
// Read snapshot info and metadata from the repository
Repository repository = repositoriesService.repository(request.repositoryName);
- final Optional matchingSnapshotId = repository.getSnapshots().stream()
+ final RepositoryData repositoryData = repository.getRepositoryData();
+ final Optional matchingSnapshotId = repositoryData.getSnapshotIds().stream()
.filter(s -> request.snapshotName.equals(s.getName())).findFirst();
if (matchingSnapshotId.isPresent() == false) {
throw new SnapshotRestoreException(request.repositoryName, request.snapshotName, "snapshot does not exist");
@@ -194,7 +197,7 @@ public class RestoreService extends AbstractComponent implements ClusterStateLis
final SnapshotInfo snapshotInfo = repository.getSnapshotInfo(snapshotId);
final Snapshot snapshot = new Snapshot(request.repositoryName, snapshotId);
List filteredIndices = SnapshotUtils.filterIndices(snapshotInfo.indices(), request.indices(), request.indicesOptions());
- MetaData metaDataIn = repository.getSnapshotMetaData(snapshotInfo, filteredIndices);
+ MetaData metaDataIn = repository.getSnapshotMetaData(snapshotInfo, repositoryData.resolveIndices(filteredIndices));
final MetaData metaData;
if (snapshotInfo.version().before(Version.V_2_0_0_beta1)) {
diff --git a/core/src/main/java/org/elasticsearch/snapshots/SnapshotId.java b/core/src/main/java/org/elasticsearch/snapshots/SnapshotId.java
index 16f371b28f7..4866a79afb9 100644
--- a/core/src/main/java/org/elasticsearch/snapshots/SnapshotId.java
+++ b/core/src/main/java/org/elasticsearch/snapshots/SnapshotId.java
@@ -22,6 +22,9 @@ package org.elasticsearch.snapshots;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.Objects;
@@ -29,12 +32,10 @@ import java.util.Objects;
/**
* SnapshotId - snapshot name + snapshot UUID
*/
-public final class SnapshotId implements Writeable {
+public final class SnapshotId implements Writeable, ToXContent {
- /**
- * This value is for older snapshots that don't have a UUID.
- */
- public static final String UNASSIGNED_UUID = "_na_";
+ private static final String NAME = "name";
+ private static final String UUID = "uuid";
private final String name;
private final String uuid;
@@ -115,4 +116,35 @@ public final class SnapshotId implements Writeable {
out.writeString(uuid);
}
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(NAME, name);
+ builder.field(UUID, uuid);
+ builder.endObject();
+ return builder;
+ }
+
+ public static SnapshotId fromXContent(XContentParser parser) throws IOException {
+ // the new format from 5.0 which contains the snapshot name and uuid
+ if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
+ String name = null;
+ String uuid = null;
+ while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
+ String currentFieldName = parser.currentName();
+ parser.nextToken();
+ if (NAME.equals(currentFieldName)) {
+ name = parser.text();
+ } else if (UUID.equals(currentFieldName)) {
+ uuid = parser.text();
+ }
+ }
+ return new SnapshotId(name, uuid);
+ } else {
+ // the old format pre 5.0 that only contains the snapshot name, use the name as the uuid too
+ final String name = parser.text();
+ return new SnapshotId(name, name);
+ }
+ }
+
}
diff --git a/core/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java b/core/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java
index 2159fda2237..ddcee4b0353 100644
--- a/core/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java
+++ b/core/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java
@@ -458,7 +458,7 @@ public final class SnapshotInfo implements Comparable, ToXContent,
}
if (uuid == null) {
// the old format where there wasn't a UUID
- uuid = SnapshotId.UNASSIGNED_UUID;
+ uuid = name;
}
return new SnapshotInfo(new SnapshotId(name, uuid),
indices,
diff --git a/core/src/main/java/org/elasticsearch/snapshots/SnapshotShardsService.java b/core/src/main/java/org/elasticsearch/snapshots/SnapshotShardsService.java
index 7741ef1c0e6..136f37eee71 100644
--- a/core/src/main/java/org/elasticsearch/snapshots/SnapshotShardsService.java
+++ b/core/src/main/java/org/elasticsearch/snapshots/SnapshotShardsService.java
@@ -46,6 +46,7 @@ import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.snapshots.IndexShardSnapshotFailedException;
import org.elasticsearch.index.snapshots.IndexShardSnapshotStatus;
import org.elasticsearch.indices.IndicesService;
+import org.elasticsearch.repositories.IndexId;
import org.elasticsearch.repositories.Repository;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.EmptyTransportResponseHandler;
@@ -66,6 +67,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;
@@ -208,8 +211,11 @@ public class SnapshotShardsService extends AbstractLifecycleComponent implements
Map> newSnapshots = new HashMap<>();
// Now go through all snapshots and update existing or create missing
final String localNodeId = clusterService.localNode().getId();
+ final Map> snapshotIndices = new HashMap<>();
if (snapshotsInProgress != null) {
for (SnapshotsInProgress.Entry entry : snapshotsInProgress.entries()) {
+ snapshotIndices.put(entry.snapshot(),
+ entry.indices().stream().collect(Collectors.toMap(IndexId::getName, Function.identity())));
if (entry.state() == SnapshotsInProgress.State.STARTED) {
Map startedShards = new HashMap<>();
SnapshotShards snapshotShards = shardSnapshots.get(entry.snapshot());
@@ -289,14 +295,18 @@ public class SnapshotShardsService extends AbstractLifecycleComponent implements
if (newSnapshots.isEmpty() == false) {
Executor executor = threadPool.executor(ThreadPool.Names.SNAPSHOT);
for (final Map.Entry> entry : newSnapshots.entrySet()) {
+ Map indicesMap = snapshotIndices.get(entry.getKey());
+ assert indicesMap != null;
for (final Map.Entry shardEntry : entry.getValue().entrySet()) {
final ShardId shardId = shardEntry.getKey();
try {
final IndexShard indexShard = indicesService.indexServiceSafe(shardId.getIndex()).getShardOrNull(shardId.id());
+ final IndexId indexId = indicesMap.get(shardId.getIndexName());
+ assert indexId != null;
executor.execute(new AbstractRunnable() {
@Override
public void doRun() {
- snapshot(indexShard, entry.getKey(), shardEntry.getValue());
+ snapshot(indexShard, entry.getKey(), indexId, shardEntry.getValue());
updateIndexShardSnapshotStatus(entry.getKey(), shardId, new SnapshotsInProgress.ShardSnapshotStatus(localNodeId, SnapshotsInProgress.State.SUCCESS));
}
@@ -321,7 +331,7 @@ public class SnapshotShardsService extends AbstractLifecycleComponent implements
* @param snapshot snapshot
* @param snapshotStatus snapshot status
*/
- private void snapshot(final IndexShard indexShard, final Snapshot snapshot, final IndexShardSnapshotStatus snapshotStatus) {
+ private void snapshot(final IndexShard indexShard, final Snapshot snapshot, final IndexId indexId, final IndexShardSnapshotStatus snapshotStatus) {
Repository repository = snapshotsService.getRepositoriesService().repository(snapshot.getRepository());
ShardId shardId = indexShard.shardId();
if (!indexShard.routingEntry().primary()) {
@@ -340,7 +350,7 @@ public class SnapshotShardsService extends AbstractLifecycleComponent implements
// we flush first to make sure we get the latest writes snapshotted
IndexCommit snapshotIndexCommit = indexShard.snapshotIndex(true);
try {
- repository.snapshotShard(indexShard, snapshot.getSnapshotId(), snapshotIndexCommit, snapshotStatus);
+ repository.snapshotShard(indexShard, snapshot.getSnapshotId(), indexId, snapshotIndexCommit, snapshotStatus);
if (logger.isDebugEnabled()) {
StringBuilder sb = new StringBuilder();
sb.append(" index : version [").append(snapshotStatus.indexVersion()).append("], number_of_files [").append(snapshotStatus.numberOfFiles()).append("] with total_size [").append(new ByteSizeValue(snapshotStatus.totalSize())).append("]\n");
diff --git a/core/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java b/core/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java
index df56f2a24a6..1725536205f 100644
--- a/core/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java
+++ b/core/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java
@@ -56,8 +56,10 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.snapshots.IndexShardSnapshotStatus;
+import org.elasticsearch.repositories.IndexId;
import org.elasticsearch.repositories.RepositoriesService;
import org.elasticsearch.repositories.Repository;
+import org.elasticsearch.repositories.RepositoryData;
import org.elasticsearch.repositories.RepositoryMissingException;
import org.elasticsearch.search.SearchShardTarget;
import org.elasticsearch.threadpool.ThreadPool;
@@ -132,7 +134,7 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
public List snapshotIds(final String repositoryName) {
Repository repository = repositoriesService.repository(repositoryName);
assert repository != null; // should only be called once we've validated the repository exists
- return repository.getSnapshots();
+ return repository.getRepositoryData().getSnapshotIds();
}
/**
@@ -218,6 +220,7 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
final String snapshotName = request.snapshotName;
validate(repositoryName, snapshotName);
final SnapshotId snapshotId = new SnapshotId(snapshotName, UUIDs.randomBase64UUID()); // new UUID for the snapshot
+ final RepositoryData repositoryData = repositoriesService.repository(repositoryName).getRepositoryData();
clusterService.submitStateUpdateTask(request.cause(), new ClusterStateUpdateTask() {
@@ -232,11 +235,12 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
// Store newSnapshot here to be processed in clusterStateProcessed
List indices = Arrays.asList(indexNameExpressionResolver.concreteIndexNames(currentState, request.indicesOptions(), request.indices()));
logger.trace("[{}][{}] creating snapshot for indices [{}]", repositoryName, snapshotName, indices);
+ List snapshotIndices = repositoryData.resolveNewIndices(indices);
newSnapshot = new SnapshotsInProgress.Entry(new Snapshot(repositoryName, snapshotId),
request.includeGlobalState(),
request.partial(),
State.INIT,
- indices,
+ snapshotIndices,
System.currentTimeMillis(),
null);
snapshots = new SnapshotsInProgress(newSnapshot);
@@ -334,8 +338,8 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
if (!snapshot.includeGlobalState()) {
// Remove global state from the cluster state
MetaData.Builder builder = MetaData.builder();
- for (String index : snapshot.indices()) {
- builder.put(metaData.index(index), false);
+ for (IndexId index : snapshot.indices()) {
+ builder.put(metaData.index(index.getName()), false);
}
metaData = builder.build();
}
@@ -473,7 +477,9 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
}
private SnapshotInfo inProgressSnapshot(SnapshotsInProgress.Entry entry) {
- return new SnapshotInfo(entry.snapshot().getSnapshotId(), entry.indices(), entry.startTime());
+ return new SnapshotInfo(entry.snapshot().getSnapshotId(),
+ entry.indices().stream().map(IndexId::getName).collect(Collectors.toList()),
+ entry.startTime());
}
/**
@@ -546,8 +552,10 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
final SnapshotInfo snapshotInfo) throws IOException {
Map shardStatus = new HashMap<>();
Repository repository = repositoriesService.repository(repositoryName);
- MetaData metaData = repository.getSnapshotMetaData(snapshotInfo, snapshotInfo.indices());
+ RepositoryData repositoryData = repository.getRepositoryData();
+ MetaData metaData = repository.getSnapshotMetaData(snapshotInfo, repositoryData.resolveIndices(snapshotInfo.indices()));
for (String index : snapshotInfo.indices()) {
+ IndexId indexId = repositoryData.resolveIndexId(index);
IndexMetaData indexMetaData = metaData.indices().get(index);
if (indexMetaData != null) {
int numberOfShards = indexMetaData.getNumberOfShards();
@@ -561,7 +569,7 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
shardStatus.put(shardId, shardSnapshotStatus);
} else {
IndexShardSnapshotStatus shardSnapshotStatus =
- repository.getShardSnapshotStatus(snapshotInfo.snapshotId(), snapshotInfo.version(), shardId);
+ repository.getShardSnapshotStatus(snapshotInfo.snapshotId(), snapshotInfo.version(), indexId, shardId);
shardStatus.put(shardId, shardSnapshotStatus);
}
}
@@ -953,7 +961,10 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
public void deleteSnapshot(final String repositoryName, final String snapshotName, final DeleteSnapshotListener listener) {
// First, look for the snapshot in the repository
final Repository repository = repositoriesService.repository(repositoryName);
- Optional matchedEntry = repository.getSnapshots().stream().filter(s -> s.getName().equals(snapshotName)).findFirst();
+ Optional matchedEntry = repository.getRepositoryData().getSnapshotIds()
+ .stream()
+ .filter(s -> s.getName().equals(snapshotName))
+ .findFirst();
// if nothing found by the same name, then look in the cluster state for current in progress snapshots
if (matchedEntry.isPresent() == false) {
matchedEntry = currentSnapshots(repositoryName, Collections.emptyList()).stream()
@@ -1121,21 +1132,22 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
* @param indices list of indices to be snapshotted
* @return list of shard to be included into current snapshot
*/
- private ImmutableOpenMap shards(ClusterState clusterState, List indices) {
+ private ImmutableOpenMap shards(ClusterState clusterState, List indices) {
ImmutableOpenMap.Builder builder = ImmutableOpenMap.builder();
MetaData metaData = clusterState.metaData();
- for (String index : indices) {
- IndexMetaData indexMetaData = metaData.index(index);
+ for (IndexId index : indices) {
+ final String indexName = index.getName();
+ IndexMetaData indexMetaData = metaData.index(indexName);
if (indexMetaData == null) {
// The index was deleted before we managed to start the snapshot - mark it as missing.
- builder.put(new ShardId(index, IndexMetaData.INDEX_UUID_NA_VALUE, 0), new SnapshotsInProgress.ShardSnapshotStatus(null, State.MISSING, "missing index"));
+ builder.put(new ShardId(indexName, IndexMetaData.INDEX_UUID_NA_VALUE, 0), new SnapshotsInProgress.ShardSnapshotStatus(null, State.MISSING, "missing index"));
} else if (indexMetaData.getState() == IndexMetaData.State.CLOSE) {
for (int i = 0; i < indexMetaData.getNumberOfShards(); i++) {
ShardId shardId = new ShardId(indexMetaData.getIndex(), i);
builder.put(shardId, new SnapshotsInProgress.ShardSnapshotStatus(null, State.MISSING, "index is closed"));
}
} else {
- IndexRoutingTable indexRoutingTable = clusterState.getRoutingTable().index(index);
+ IndexRoutingTable indexRoutingTable = clusterState.getRoutingTable().index(indexName);
for (int i = 0; i < indexMetaData.getNumberOfShards(); i++) {
ShardId shardId = new ShardId(indexMetaData.getIndex(), i);
if (indexRoutingTable != null) {
@@ -1191,8 +1203,8 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus
for (final SnapshotsInProgress.Entry entry : snapshots.entries()) {
if (entry.partial() == false) {
if (entry.state() == State.INIT) {
- for (String index : entry.indices()) {
- IndexMetaData indexMetaData = currentState.metaData().index(index);
+ for (IndexId index : entry.indices()) {
+ IndexMetaData indexMetaData = currentState.metaData().index(index.getName());
if (indexMetaData != null && indices.contains(indexMetaData)) {
if (indicesToFail == null) {
indicesToFail = new HashSet<>();
diff --git a/core/src/main/java/org/elasticsearch/tasks/package-info.java b/core/src/main/java/org/elasticsearch/tasks/package-info.java
new file mode 100644
index 00000000000..c967aaca508
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/tasks/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+/**
+ * Support for viewing and modifying in flight actions ({@link org.elasticsearch.tasks.Task}s) and saving their results to an index. This
+ * includes getting detailed descriptions and canceling tasks that support it.
+ */
+package org.elasticsearch.tasks;
diff --git a/core/src/test/java/org/elasticsearch/action/DocWriteResponseTests.java b/core/src/test/java/org/elasticsearch/action/DocWriteResponseTests.java
index b30b978eddf..ce50fbc7e5d 100644
--- a/core/src/test/java/org/elasticsearch/action/DocWriteResponseTests.java
+++ b/core/src/test/java/org/elasticsearch/action/DocWriteResponseTests.java
@@ -19,7 +19,7 @@
package org.elasticsearch.action;
-import org.elasticsearch.action.DocWriteResponse.Operation;
+import org.elasticsearch.action.DocWriteResponse.Result;
import org.elasticsearch.action.support.replication.ReplicationResponse.ShardInfo;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -36,7 +36,7 @@ import static org.hamcrest.Matchers.not;
public class DocWriteResponseTests extends ESTestCase {
public void testGetLocation() {
- DocWriteResponse response = new DocWriteResponse(new ShardId("index", "uuid", 0), "type", "id", 0, Operation.CREATE) {
+ DocWriteResponse response = new DocWriteResponse(new ShardId("index", "uuid", 0), "type", "id", 0, Result.CREATED) {
// DocWriteResponse is abstract so we have to sneak a subclass in here to test it.
};
assertEquals("/index/type/id", response.getLocation(null));
@@ -48,7 +48,7 @@ public class DocWriteResponseTests extends ESTestCase {
* is true. We can't assert this in the yaml tests because "not found" is also "false" there....
*/
public void testToXContentDoesntIncludeForcedRefreshUnlessForced() throws IOException {
- DocWriteResponse response = new DocWriteResponse(new ShardId("index", "uuid", 0), "type", "id", 0, Operation.CREATE) {
+ DocWriteResponse response = new DocWriteResponse(new ShardId("index", "uuid", 0), "type", "id", 0, Result.CREATED) {
// DocWriteResponse is abstract so we have to sneak a subclass in here to test it.
};
response.setShardInfo(new ShardInfo(1, 1));
diff --git a/core/src/test/java/org/elasticsearch/action/IndicesRequestIT.java b/core/src/test/java/org/elasticsearch/action/IndicesRequestIT.java
index 8b6cfc08276..07931c54b06 100644
--- a/core/src/test/java/org/elasticsearch/action/IndicesRequestIT.java
+++ b/core/src/test/java/org/elasticsearch/action/IndicesRequestIT.java
@@ -234,7 +234,7 @@ public class IndicesRequestIT extends ESIntegTestCase {
client().prepareIndex(indexOrAlias, "type", "id").setSource("field", "value").get();
UpdateRequest updateRequest = new UpdateRequest(indexOrAlias, "type", "id").doc("field1", "value1");
UpdateResponse updateResponse = internalCluster().coordOnlyNodeClient().update(updateRequest).actionGet();
- assertEquals(DocWriteResponse.Operation.INDEX, updateResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.UPDATED, updateResponse.getResult());
clearInterceptedActions();
assertSameIndices(updateRequest, updateShardActions);
@@ -248,7 +248,7 @@ public class IndicesRequestIT extends ESIntegTestCase {
String indexOrAlias = randomIndexOrAlias();
UpdateRequest updateRequest = new UpdateRequest(indexOrAlias, "type", "id").upsert("field", "value").doc("field1", "value1");
UpdateResponse updateResponse = internalCluster().coordOnlyNodeClient().update(updateRequest).actionGet();
- assertEquals(DocWriteResponse.Operation.CREATE, updateResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, updateResponse.getResult());
clearInterceptedActions();
assertSameIndices(updateRequest, updateShardActions);
@@ -264,7 +264,7 @@ public class IndicesRequestIT extends ESIntegTestCase {
UpdateRequest updateRequest = new UpdateRequest(indexOrAlias, "type", "id")
.script(new Script("ctx.op='delete'", ScriptService.ScriptType.INLINE, CustomScriptPlugin.NAME, Collections.emptyMap()));
UpdateResponse updateResponse = internalCluster().coordOnlyNodeClient().update(updateRequest).actionGet();
- assertEquals(DocWriteResponse.Operation.DELETE, updateResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, updateResponse.getResult());
clearInterceptedActions();
assertSameIndices(updateRequest, updateShardActions);
diff --git a/core/src/test/java/org/elasticsearch/action/bulk/BulkWithUpdatesIT.java b/core/src/test/java/org/elasticsearch/action/bulk/BulkWithUpdatesIT.java
index cea238db9ce..16502ff92b1 100644
--- a/core/src/test/java/org/elasticsearch/action/bulk/BulkWithUpdatesIT.java
+++ b/core/src/test/java/org/elasticsearch/action/bulk/BulkWithUpdatesIT.java
@@ -207,11 +207,11 @@ public class BulkWithUpdatesIT extends ESIntegTestCase {
.add(client().prepareIndex("test", "type", "2").setCreate(true).setSource("field", "1"))
.add(client().prepareIndex("test", "type", "1").setSource("field", "2")).get();
- assertEquals(DocWriteResponse.Operation.CREATE, bulkResponse.getItems()[0].getResponse().getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, bulkResponse.getItems()[0].getResponse().getResult());
assertThat(bulkResponse.getItems()[0].getResponse().getVersion(), equalTo(1L));
- assertEquals(DocWriteResponse.Operation.CREATE, bulkResponse.getItems()[1].getResponse().getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, bulkResponse.getItems()[1].getResponse().getResult());
assertThat(bulkResponse.getItems()[1].getResponse().getVersion(), equalTo(1L));
- assertEquals(DocWriteResponse.Operation.INDEX, bulkResponse.getItems()[2].getResponse().getOperation());
+ assertEquals(DocWriteResponse.Result.UPDATED, bulkResponse.getItems()[2].getResponse().getResult());
assertThat(bulkResponse.getItems()[2].getResponse().getVersion(), equalTo(2L));
bulkResponse = client().prepareBulk()
@@ -232,11 +232,11 @@ public class BulkWithUpdatesIT extends ESIntegTestCase {
.setSource("field", "2").setVersion(12).setVersionType(VersionType.EXTERNAL))
.get();
- assertEquals(DocWriteResponse.Operation.CREATE, bulkResponse.getItems()[0].getResponse().getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, bulkResponse.getItems()[0].getResponse().getResult());
assertThat(bulkResponse.getItems()[0].getResponse().getVersion(), equalTo(10L));
- assertEquals(DocWriteResponse.Operation.CREATE, bulkResponse.getItems()[1].getResponse().getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, bulkResponse.getItems()[1].getResponse().getResult());
assertThat(bulkResponse.getItems()[1].getResponse().getVersion(), equalTo(10L));
- assertEquals(DocWriteResponse.Operation.INDEX, bulkResponse.getItems()[2].getResponse().getOperation());
+ assertEquals(DocWriteResponse.Result.UPDATED, bulkResponse.getItems()[2].getResponse().getResult());
assertThat(bulkResponse.getItems()[2].getResponse().getVersion(), equalTo(12L));
bulkResponse = client().prepareBulk()
diff --git a/core/src/test/java/org/elasticsearch/action/support/master/IndexingMasterFailoverIT.java b/core/src/test/java/org/elasticsearch/action/support/master/IndexingMasterFailoverIT.java
index 9b67f128183..81b5290f63b 100644
--- a/core/src/test/java/org/elasticsearch/action/support/master/IndexingMasterFailoverIT.java
+++ b/core/src/test/java/org/elasticsearch/action/support/master/IndexingMasterFailoverIT.java
@@ -98,7 +98,7 @@ public class IndexingMasterFailoverIT extends ESIntegTestCase {
for (int i = 0; i < 10; i++) {
// index data with mapping changes
IndexResponse response = client(dataNode).prepareIndex("myindex", "mytype").setSource("field_" + i, "val").get();
- assertEquals(DocWriteResponse.Operation.CREATE, response.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, response.getResult());
}
}
});
diff --git a/core/src/test/java/org/elasticsearch/bwcompat/BasicBackwardsCompatibilityIT.java b/core/src/test/java/org/elasticsearch/bwcompat/BasicBackwardsCompatibilityIT.java
index 37d259ed1b4..a170fcd02f8 100644
--- a/core/src/test/java/org/elasticsearch/bwcompat/BasicBackwardsCompatibilityIT.java
+++ b/core/src/test/java/org/elasticsearch/bwcompat/BasicBackwardsCompatibilityIT.java
@@ -119,8 +119,8 @@ public class BasicBackwardsCompatibilityIT extends ESBackcompatTestCase {
for (int i = 0; i < numDocs; i++) {
String routingKey = routing ? randomRealisticUnicodeOfLength(10) : null;
String id = Integer.toString(i);
- assertEquals(id, DocWriteResponse.Operation.CREATE, client().prepareIndex("test", "type1", id)
- .setRouting(routingKey).setSource("field1", English.intToEnglish(i)).get().getOperation());
+ assertEquals(id, DocWriteResponse.Result.CREATED, client().prepareIndex("test", "type1", id)
+ .setRouting(routingKey).setSource("field1", English.intToEnglish(i)).get().getResult());
GetResponse get = client().prepareGet("test", "type1", id).setRouting(routingKey).setVersion(1).get();
assertThat("Document with ID " + id + " should exist but doesn't", get.isExists(), is(true));
assertThat(get.getVersion(), equalTo(1L));
@@ -478,7 +478,7 @@ public class BasicBackwardsCompatibilityIT extends ESBackcompatTestCase {
assertThat(searchResponse.getHits().totalHits(), equalTo((long) numDocs));
DeleteResponse deleteResponse = client().prepareDelete("test", "test", firstDocId).setRouting("routing").get();
- assertEquals(DocWriteResponse.Operation.DELETE, deleteResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
GetResponse getResponse = client().prepareGet("test", "test", firstDocId).setRouting("routing").get();
assertThat(getResponse.isExists(), equalTo(false));
refresh();
@@ -493,7 +493,7 @@ public class BasicBackwardsCompatibilityIT extends ESBackcompatTestCase {
int numDocs = iterations(10, 50);
for (int i = 0; i < numDocs; i++) {
IndexResponse indexResponse = client().prepareIndex(indexOrAlias(), "type", Integer.toString(i)).setSource("field", "value-" + i).get();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
assertThat(indexResponse.getIndex(), equalTo("test"));
assertThat(indexResponse.getType(), equalTo("type"));
assertThat(indexResponse.getId(), equalTo(Integer.toString(i)));
@@ -508,7 +508,7 @@ public class BasicBackwardsCompatibilityIT extends ESBackcompatTestCase {
assertThat(getResponse.getId(), equalTo(docId));
DeleteResponse deleteResponse = client().prepareDelete(indexOrAlias(), "type", docId).get();
- assertEquals(DocWriteResponse.Operation.DELETE, deleteResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
assertThat(deleteResponse.getIndex(), equalTo("test"));
assertThat(deleteResponse.getType(), equalTo("type"));
assertThat(deleteResponse.getId(), equalTo(docId));
@@ -532,7 +532,7 @@ public class BasicBackwardsCompatibilityIT extends ESBackcompatTestCase {
assertThat(updateResponse.getIndex(), equalTo("test"));
assertThat(updateResponse.getType(), equalTo("type1"));
assertThat(updateResponse.getId(), equalTo("1"));
- assertEquals(DocWriteResponse.Operation.CREATE, updateResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, updateResponse.getResult());
GetResponse getResponse = client().prepareGet("test", "type1", "1").get();
assertThat(getResponse.isExists(), equalTo(true));
@@ -543,7 +543,7 @@ public class BasicBackwardsCompatibilityIT extends ESBackcompatTestCase {
assertThat(updateResponse.getIndex(), equalTo("test"));
assertThat(updateResponse.getType(), equalTo("type1"));
assertThat(updateResponse.getId(), equalTo("1"));
- assertEquals(DocWriteResponse.Operation.INDEX, updateResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.UPDATED, updateResponse.getResult());
getResponse = client().prepareGet("test", "type1", "1").get();
assertThat(getResponse.isExists(), equalTo(true));
diff --git a/core/src/test/java/org/elasticsearch/bwcompat/RepositoryUpgradabilityIT.java b/core/src/test/java/org/elasticsearch/bwcompat/RepositoryUpgradabilityIT.java
index c29d83b4454..9bfcc554998 100644
--- a/core/src/test/java/org/elasticsearch/bwcompat/RepositoryUpgradabilityIT.java
+++ b/core/src/test/java/org/elasticsearch/bwcompat/RepositoryUpgradabilityIT.java
@@ -46,7 +46,7 @@ import static org.hamcrest.Matchers.greaterThanOrEqualTo;
* as blob names and repository blob formats have changed between the snapshot versions.
*/
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST)
-// this test sometimes fails in recovery when the recovery is reset, increasing the logging level to help debug
+// this test sometimes fails in recovery when the recovery is reset, increasing the logging level to help debug
@TestLogging("indices.recovery:DEBUG")
public class RepositoryUpgradabilityIT extends AbstractSnapshotIntegTestCase {
@@ -70,7 +70,7 @@ public class RepositoryUpgradabilityIT extends AbstractSnapshotIntegTestCase {
final Set snapshotInfos = Sets.newHashSet(getSnapshots(repoName));
assertThat(snapshotInfos.size(), equalTo(1));
SnapshotInfo originalSnapshot = snapshotInfos.iterator().next();
- assertThat(originalSnapshot.snapshotId(), equalTo(new SnapshotId("test_1", SnapshotId.UNASSIGNED_UUID)));
+ assertThat(originalSnapshot.snapshotId(), equalTo(new SnapshotId("test_1", "test_1")));
assertThat(Sets.newHashSet(originalSnapshot.indices()), equalTo(indices));
logger.info("--> restore the original snapshot");
diff --git a/core/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java b/core/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java
index 68a0f73eb34..9ffabec6fc0 100644
--- a/core/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java
+++ b/core/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java
@@ -53,7 +53,6 @@ import org.elasticsearch.index.Index;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.snapshots.Snapshot;
-import org.elasticsearch.snapshots.SnapshotId;
import org.elasticsearch.test.ESIntegTestCase;
import java.util.Collections;
@@ -659,7 +658,7 @@ public class ClusterStateDiffIT extends ESIntegTestCase {
randomBoolean(),
randomBoolean(),
SnapshotsInProgress.State.fromValue((byte) randomIntBetween(0, 6)),
- Collections.emptyList(),
+ Collections.emptyList(),
Math.abs(randomLong()),
ImmutableOpenMap.of()));
case 1:
diff --git a/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsIT.java b/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsIT.java
index 0bacac191f9..466d3b4f83d 100644
--- a/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsIT.java
+++ b/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsIT.java
@@ -491,7 +491,7 @@ public class DiscoveryWithServiceDisruptionsIT extends ESIntegTestCase {
logger.trace("[{}] indexing id [{}] through node [{}] targeting shard [{}]", name, id, node, shard);
IndexResponse response =
client.prepareIndex("test", "type", id).setSource("{}").setTimeout(timeout).get(timeout);
- assertEquals(DocWriteResponse.Operation.CREATE, response.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, response.getResult());
ackedDocs.put(id, node);
logger.trace("[{}] indexed id [{}] through node [{}]", name, id, node);
} catch (ElasticsearchException e) {
diff --git a/core/src/test/java/org/elasticsearch/get/GetActionIT.java b/core/src/test/java/org/elasticsearch/get/GetActionIT.java
index c97d99c9216..932f42eaf0f 100644
--- a/core/src/test/java/org/elasticsearch/get/GetActionIT.java
+++ b/core/src/test/java/org/elasticsearch/get/GetActionIT.java
@@ -177,7 +177,7 @@ public class GetActionIT extends ESIntegTestCase {
assertThat(response.getSourceAsMap().get("field2").toString(), equalTo("value2_2"));
DeleteResponse deleteResponse = client().prepareDelete("test", "type1", "1").get();
- assertEquals(DocWriteResponse.Operation.DELETE, deleteResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
response = client().prepareGet(indexOrAlias(), "type1", "1").get();
assertThat(response.isExists(), equalTo(false));
diff --git a/core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasIT.java b/core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasIT.java
index 2aa7b283be4..e71f42adb55 100644
--- a/core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasIT.java
+++ b/core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasIT.java
@@ -415,7 +415,7 @@ public class IndexWithShadowReplicasIT extends ESIntegTestCase {
try {
final IndexResponse indexResponse = client().prepareIndex(IDX, "doc",
Integer.toString(counter.incrementAndGet())).setSource("foo", "bar").get();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
} catch (Exception e) {
exceptions.add(e);
}
@@ -508,7 +508,7 @@ public class IndexWithShadowReplicasIT extends ESIntegTestCase {
while (counter.get() < (numPhase1Docs + numPhase2Docs + numPhase3Docs)) {
final IndexResponse indexResponse = client().prepareIndex(IDX, "doc",
Integer.toString(counter.incrementAndGet())).setSource("foo", "bar").get();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
final int docCount = counter.get();
if (docCount == numPhase1Docs) {
phase1finished.countDown();
diff --git a/core/src/test/java/org/elasticsearch/index/WaitUntilRefreshIT.java b/core/src/test/java/org/elasticsearch/index/WaitUntilRefreshIT.java
index a8eb13dc40f..378947ec345 100644
--- a/core/src/test/java/org/elasticsearch/index/WaitUntilRefreshIT.java
+++ b/core/src/test/java/org/elasticsearch/index/WaitUntilRefreshIT.java
@@ -84,7 +84,7 @@ public class WaitUntilRefreshIT extends ESIntegTestCase {
// Now delete with blockUntilRefresh
DeleteResponse delete = client().prepareDelete("test", "test", "1").setRefreshPolicy(RefreshPolicy.WAIT_UNTIL).get();
- assertEquals(DocWriteResponse.Operation.DELETE, delete.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, delete.getResult());
assertFalse("request shouldn't have forced a refresh", delete.forcedRefresh());
assertNoSearchHits(client().prepareSearch("test").setQuery(matchQuery("foo", "bar")).get());
}
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIT.java b/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIT.java
index 62569d11657..ca4f7097bfd 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIT.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIT.java
@@ -100,8 +100,8 @@ public class DynamicMappingIT extends ESIntegTestCase {
public void run() {
try {
startLatch.await();
- assertEquals(DocWriteResponse.Operation.CREATE, client().prepareIndex("index", "type", id)
- .setSource("field" + id, "bar").get().getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, client().prepareIndex("index", "type", id)
+ .setSource("field" + id, "bar").get().getResult());
} catch (Exception e) {
error.compareAndSet(null, e);
}
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/core/TokenCountFieldMapperIntegrationIT.java b/core/src/test/java/org/elasticsearch/index/mapper/core/TokenCountFieldMapperIntegrationIT.java
index aabb0f69bb4..2bce69f6ecf 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/core/TokenCountFieldMapperIntegrationIT.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/core/TokenCountFieldMapperIntegrationIT.java
@@ -137,13 +137,13 @@ public class TokenCountFieldMapperIntegrationIT extends ESIntegTestCase {
.endObject().endObject()).get();
ensureGreen();
- assertEquals(DocWriteResponse.Operation.CREATE, prepareIndex("single", "I have four terms").get().getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, prepareIndex("single", "I have four terms").get().getResult());
BulkResponse bulk = client().prepareBulk()
.add(prepareIndex("bulk1", "bulk three terms"))
.add(prepareIndex("bulk2", "this has five bulk terms")).get();
assertFalse(bulk.buildFailureMessage(), bulk.hasFailures());
- assertEquals(DocWriteResponse.Operation.CREATE,
- prepareIndex("multi", "two terms", "wow now I have seven lucky terms").get().getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED,
+ prepareIndex("multi", "two terms", "wow now I have seven lucky terms").get().getResult());
bulk = client().prepareBulk()
.add(prepareIndex("multibulk1", "one", "oh wow now I have eight unlucky terms"))
.add(prepareIndex("multibulk2", "six is a bunch of terms", "ten! ten terms is just crazy! too many too count!")).get();
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/date/LegacyDateMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/date/LegacyDateMappingTests.java
index f35958c761b..92f9a9958fb 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/date/LegacyDateMappingTests.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/date/LegacyDateMappingTests.java
@@ -449,7 +449,7 @@ public class LegacyDateMappingTests extends ESSingleNodeTestCase {
ParsedDocument doc = defaultMapper.parse("test", "type", "1", document.bytes());
assertThat(getDateAsMillis(doc.rootDoc(), "date_field"), equalTo(1433239200000L));
IndexResponse indexResponse = client().prepareIndex("test2", "test").setSource(document).get();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
// integers should always be parsed as well... cannot be sure it is a unix timestamp only
doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder()
@@ -459,7 +459,7 @@ public class LegacyDateMappingTests extends ESSingleNodeTestCase {
.bytes());
assertThat(getDateAsMillis(doc.rootDoc(), "date_field"), equalTo(1433239200000L));
indexResponse = client().prepareIndex("test", "test").setSource(document).get();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
}
public void testThatNewIndicesOnlyAllowStrictDates() throws Exception {
diff --git a/core/src/test/java/org/elasticsearch/index/query/ScriptQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/ScriptQueryBuilderTests.java
index fdf7049aced..920d2537935 100644
--- a/core/src/test/java/org/elasticsearch/index/query/ScriptQueryBuilderTests.java
+++ b/core/src/test/java/org/elasticsearch/index/query/ScriptQueryBuilderTests.java
@@ -34,7 +34,7 @@ import static org.hamcrest.Matchers.instanceOf;
public class ScriptQueryBuilderTests extends AbstractQueryTestCase {
@Override
protected ScriptQueryBuilder doCreateTestQueryBuilder() {
- String script = "5";
+ String script = "1";
Map params = Collections.emptyMap();
return new ScriptQueryBuilder(new Script(script, ScriptType.INLINE, MockScriptEngine.NAME, params));
}
diff --git a/core/src/test/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilderTests.java
index 6950a98631f..bd841a05ca1 100644
--- a/core/src/test/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilderTests.java
+++ b/core/src/test/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilderTests.java
@@ -155,7 +155,7 @@ public class FunctionScoreQueryBuilderTests extends AbstractQueryTestCase params = Collections.emptyMap();
functionBuilder = new ScriptScoreFunctionBuilder(
new Script(script, ScriptService.ScriptType.INLINE, MockScriptEngine.NAME, params));
diff --git a/core/src/test/java/org/elasticsearch/index/replication/ESIndexLevelReplicationTestCase.java b/core/src/test/java/org/elasticsearch/index/replication/ESIndexLevelReplicationTestCase.java
index 85b4d54e4f9..d561536d2b9 100644
--- a/core/src/test/java/org/elasticsearch/index/replication/ESIndexLevelReplicationTestCase.java
+++ b/core/src/test/java/org/elasticsearch/index/replication/ESIndexLevelReplicationTestCase.java
@@ -30,8 +30,6 @@ import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
-import org.elasticsearch.action.admin.indices.recovery.RecoveryRequest;
-import org.elasticsearch.action.admin.indices.stats.IndexShardStats;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.index.TransportIndexAction;
@@ -82,8 +80,6 @@ import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.threadpool.TestThreadPool;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportResponse;
-import org.junit.After;
-import org.junit.Before;
import java.io.IOException;
import java.nio.file.Files;
@@ -257,7 +253,7 @@ public abstract class ESIndexLevelReplicationTestCase extends ESTestCase {
final IndexRequest indexRequest = new IndexRequest(index.getName(), "type", Integer.toString(docId.incrementAndGet()))
.source("{}");
final IndexResponse response = index(indexRequest);
- assertEquals(DocWriteResponse.Operation.CREATE, response.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, response.getResult());
}
return numOfDoc;
}
diff --git a/core/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java b/core/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java
index 95a705f8e27..a412d37c111 100644
--- a/core/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java
+++ b/core/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java
@@ -100,7 +100,9 @@ import org.elasticsearch.index.translog.Translog;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.indices.recovery.RecoveryState;
import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.repositories.IndexId;
import org.elasticsearch.repositories.Repository;
+import org.elasticsearch.repositories.RepositoryData;
import org.elasticsearch.snapshots.Snapshot;
import org.elasticsearch.snapshots.SnapshotId;
import org.elasticsearch.snapshots.SnapshotInfo;
@@ -121,8 +123,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
@@ -1184,9 +1188,9 @@ public class IndexShardTests extends ESSingleNodeTestCase {
test_target_shard.updateRoutingEntry(routing);
DiscoveryNode localNode = new DiscoveryNode("foo", LocalTransportAddress.buildUnique(), emptyMap(), emptySet(), Version.CURRENT);
test_target_shard.markAsRecovering("store", new RecoveryState(routing.shardId(), routing.primary(), RecoveryState.Type.SNAPSHOT, routing.restoreSource(), localNode));
- assertTrue(test_target_shard.restoreFromRepository(new RestoreOnlyRepository() {
+ assertTrue(test_target_shard.restoreFromRepository(new RestoreOnlyRepository("test") {
@Override
- public void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, ShardId snapshotShardId, RecoveryState recoveryState) {
+ public void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, IndexId indexId, ShardId snapshotShardId, RecoveryState recoveryState) {
try {
cleanLuceneIndex(targetStore.directory());
for (String file : sourceStore.directory().listAll()) {
@@ -1645,8 +1649,10 @@ public class IndexShardTests extends ESSingleNodeTestCase {
/** A dummy repository for testing which just needs restore overridden */
private abstract static class RestoreOnlyRepository extends AbstractLifecycleComponent implements Repository {
- public RestoreOnlyRepository() {
+ private final String indexName;
+ public RestoreOnlyRepository(String indexName) {
super(Settings.EMPTY);
+ this.indexName = indexName;
}
@Override
protected void doStart() {}
@@ -1663,17 +1669,19 @@ public class IndexShardTests extends ESSingleNodeTestCase {
return null;
}
@Override
- public MetaData getSnapshotMetaData(SnapshotInfo snapshot, List indices) throws IOException {
+ public MetaData getSnapshotMetaData(SnapshotInfo snapshot, List indices) throws IOException {
return null;
}
@Override
- public List getSnapshots() {
- return null;
+ public RepositoryData getRepositoryData() {
+ Map> map = new HashMap<>();
+ map.put(new IndexId(indexName, "blah"), Collections.emptySet());
+ return new RepositoryData(Collections.emptyList(), map);
}
@Override
- public void initializeSnapshot(SnapshotId snapshotId, List indices, MetaData metaData) {}
+ public void initializeSnapshot(SnapshotId snapshotId, List indices, MetaData metaData) {}
@Override
- public SnapshotInfo finalizeSnapshot(SnapshotId snapshotId, List indices, long startTime, String failure, int totalShards, List shardFailures) {
+ public SnapshotInfo finalizeSnapshot(SnapshotId snapshotId, List indices, long startTime, String failure, int totalShards, List shardFailures) {
return null;
}
@Override
@@ -1697,9 +1705,9 @@ public class IndexShardTests extends ESSingleNodeTestCase {
return false;
}
@Override
- public void snapshotShard(IndexShard shard, SnapshotId snapshotId, IndexCommit snapshotIndexCommit, IndexShardSnapshotStatus snapshotStatus) {}
+ public void snapshotShard(IndexShard shard, SnapshotId snapshotId, IndexId indexId, IndexCommit snapshotIndexCommit, IndexShardSnapshotStatus snapshotStatus) {}
@Override
- public IndexShardSnapshotStatus getShardSnapshotStatus(SnapshotId snapshotId, Version version, ShardId shardId) {
+ public IndexShardSnapshotStatus getShardSnapshotStatus(SnapshotId snapshotId, Version version, IndexId indexId, ShardId shardId) {
return null;
}
@Override
diff --git a/core/src/test/java/org/elasticsearch/indexing/IndexActionIT.java b/core/src/test/java/org/elasticsearch/indexing/IndexActionIT.java
index c3678fc63d2..ad540556664 100644
--- a/core/src/test/java/org/elasticsearch/indexing/IndexActionIT.java
+++ b/core/src/test/java/org/elasticsearch/indexing/IndexActionIT.java
@@ -94,15 +94,15 @@ public class IndexActionIT extends ESIntegTestCase {
ensureGreen();
IndexResponse indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_1").execute().actionGet();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_2").execute().actionGet();
- assertEquals(DocWriteResponse.Operation.INDEX, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.UPDATED, indexResponse.getResult());
client().prepareDelete("test", "type", "1").execute().actionGet();
indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_2").execute().actionGet();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
}
@@ -111,14 +111,14 @@ public class IndexActionIT extends ESIntegTestCase {
ensureGreen();
IndexResponse indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_1").execute().actionGet();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
client().prepareDelete("test", "type", "1").execute().actionGet();
flush();
indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_2").execute().actionGet();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
}
public void testCreatedFlagParallelExecution() throws Exception {
@@ -139,7 +139,7 @@ public class IndexActionIT extends ESIntegTestCase {
public Void call() throws Exception {
int docId = random.nextInt(docCount);
IndexResponse indexResponse = index("test", "type", Integer.toString(docId), "field1", "value");
- if (indexResponse.getOperation() == DocWriteResponse.Operation.CREATE) {
+ if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
createdCounts.incrementAndGet(docId);
}
return null;
@@ -161,7 +161,7 @@ public class IndexActionIT extends ESIntegTestCase {
IndexResponse indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_1").setVersion(123)
.setVersionType(VersionType.EXTERNAL).execute().actionGet();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
}
public void testCreateFlagWithBulk() {
@@ -172,7 +172,7 @@ public class IndexActionIT extends ESIntegTestCase {
assertThat(bulkResponse.hasFailures(), equalTo(false));
assertThat(bulkResponse.getItems().length, equalTo(1));
IndexResponse indexResponse = bulkResponse.getItems()[0].getResponse();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
}
public void testCreateIndexWithLongName() {
diff --git a/core/src/test/java/org/elasticsearch/indices/DateMathIndexExpressionsIntegrationIT.java b/core/src/test/java/org/elasticsearch/indices/DateMathIndexExpressionsIntegrationIT.java
index 25be024bf14..e91ed066cc6 100644
--- a/core/src/test/java/org/elasticsearch/indices/DateMathIndexExpressionsIntegrationIT.java
+++ b/core/src/test/java/org/elasticsearch/indices/DateMathIndexExpressionsIntegrationIT.java
@@ -24,7 +24,6 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.action.update.UpdateHelper;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.test.ESIntegTestCase;
import org.joda.time.DateTime;
@@ -76,15 +75,15 @@ public class DateMathIndexExpressionsIntegrationIT extends ESIntegTestCase {
assertThat(indicesStatsResponse.getIndex(index3), notNullValue());
DeleteResponse deleteResponse = client().prepareDelete(dateMathExp1, "type", "1").get();
- assertEquals(DocWriteResponse.Operation.DELETE, deleteResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
assertThat(deleteResponse.getId(), equalTo("1"));
deleteResponse = client().prepareDelete(dateMathExp2, "type", "2").get();
- assertEquals(DocWriteResponse.Operation.DELETE, deleteResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
assertThat(deleteResponse.getId(), equalTo("2"));
deleteResponse = client().prepareDelete(dateMathExp3, "type", "3").get();
- assertEquals(DocWriteResponse.Operation.DELETE, deleteResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
assertThat(deleteResponse.getId(), equalTo("3"));
}
diff --git a/core/src/test/java/org/elasticsearch/indices/recovery/IndexPrimaryRelocationIT.java b/core/src/test/java/org/elasticsearch/indices/recovery/IndexPrimaryRelocationIT.java
index 3341700d5a3..ad4ea6567c2 100644
--- a/core/src/test/java/org/elasticsearch/indices/recovery/IndexPrimaryRelocationIT.java
+++ b/core/src/test/java/org/elasticsearch/indices/recovery/IndexPrimaryRelocationIT.java
@@ -56,9 +56,9 @@ public class IndexPrimaryRelocationIT extends ESIntegTestCase {
public void run() {
while (finished.get() == false) {
IndexResponse indexResponse = client().prepareIndex("test", "type", "id").setSource("field", "value").get();
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
DeleteResponse deleteResponse = client().prepareDelete("test", "type", "id").get();
- assertEquals(DocWriteResponse.Operation.DELETE, deleteResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
}
}
};
diff --git a/core/src/test/java/org/elasticsearch/indices/stats/IndexStatsIT.java b/core/src/test/java/org/elasticsearch/indices/stats/IndexStatsIT.java
index 5328bddf56f..aee3dd227e8 100644
--- a/core/src/test/java/org/elasticsearch/indices/stats/IndexStatsIT.java
+++ b/core/src/test/java/org/elasticsearch/indices/stats/IndexStatsIT.java
@@ -35,7 +35,6 @@ import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
-import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexModule;
import org.elasticsearch.index.IndexSettings;
@@ -1037,8 +1036,8 @@ public class IndexStatsIT extends ESIntegTestCase {
assertThat(stats.getTotal().queryCache.getCacheSize(), greaterThan(0L));
});
- assertEquals(DocWriteResponse.Operation.DELETE, client().prepareDelete("index", "type", "1").get().getOperation());
- assertEquals(DocWriteResponse.Operation.DELETE, client().prepareDelete("index", "type", "2").get().getOperation());
+ assertEquals(DocWriteResponse.Result.DELETED, client().prepareDelete("index", "type", "1").get().getResult());
+ assertEquals(DocWriteResponse.Result.DELETED, client().prepareDelete("index", "type", "2").get().getResult());
refresh();
response = client().admin().indices().prepareStats("index").setQueryCache(true).get();
assertCumulativeQueryCacheStats(response);
diff --git a/core/src/test/java/org/elasticsearch/ingest/IngestClientIT.java b/core/src/test/java/org/elasticsearch/ingest/IngestClientIT.java
index 6f4534a415e..fbe41e70263 100644
--- a/core/src/test/java/org/elasticsearch/ingest/IngestClientIT.java
+++ b/core/src/test/java/org/elasticsearch/ingest/IngestClientIT.java
@@ -162,7 +162,7 @@ public class IngestClientIT extends ESIntegTestCase {
itemResponse.isFailed(), is(false));
assertThat(indexResponse, notNullValue());
assertThat(indexResponse.getId(), equalTo(Integer.toString(i)));
- assertEquals(DocWriteResponse.Operation.CREATE, indexResponse.getOperation());
+ assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult());
}
}
}
diff --git a/core/src/test/java/org/elasticsearch/repositories/IndexIdTests.java b/core/src/test/java/org/elasticsearch/repositories/IndexIdTests.java
new file mode 100644
index 00000000000..30002d54a6b
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/repositories/IndexIdTests.java
@@ -0,0 +1,89 @@
+/*
+ * 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.repositories;
+
+import org.elasticsearch.common.UUIDs;
+import org.elasticsearch.common.io.stream.BytesStreamOutput;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.IOException;
+
+/**
+ * Tests for the {@link IndexId} class.
+ */
+public class IndexIdTests extends ESTestCase {
+
+ public void testEqualsAndHashCode() {
+ // assert equals and hashcode
+ String name = randomAsciiOfLength(8);
+ String id = UUIDs.randomBase64UUID();
+ IndexId indexId1 = new IndexId(name, id);
+ IndexId indexId2 = new IndexId(name, id);
+ assertEquals(indexId1, indexId2);
+ assertEquals(indexId1.hashCode(), indexId2.hashCode());
+ // assert equals when using index name for id
+ id = name;
+ indexId1 = new IndexId(name, id);
+ indexId2 = new IndexId(name, id);
+ assertEquals(indexId1, indexId2);
+ assertEquals(indexId1.hashCode(), indexId2.hashCode());
+ //assert not equals when name or id differ
+ indexId2 = new IndexId(randomAsciiOfLength(8), id);
+ assertNotEquals(indexId1, indexId2);
+ assertNotEquals(indexId1.hashCode(), indexId2.hashCode());
+ indexId2 = new IndexId(name, UUIDs.randomBase64UUID());
+ assertNotEquals(indexId1, indexId2);
+ assertNotEquals(indexId1.hashCode(), indexId2.hashCode());
+ }
+
+ public void testSerialization() throws IOException {
+ IndexId indexId = new IndexId(randomAsciiOfLength(8), UUIDs.randomBase64UUID());
+ BytesStreamOutput out = new BytesStreamOutput();
+ indexId.writeTo(out);
+ assertEquals(indexId, new IndexId(out.bytes().streamInput()));
+ }
+
+ public void testXContent() throws IOException {
+ IndexId indexId = new IndexId(randomAsciiOfLength(8), UUIDs.randomBase64UUID());
+ XContentBuilder builder = JsonXContent.contentBuilder();
+ indexId.toXContent(builder, ToXContent.EMPTY_PARAMS);
+ XContentParser parser = XContentType.JSON.xContent().createParser(builder.bytes());
+ assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
+ String name = null;
+ String id = null;
+ while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
+ final String currentFieldName = parser.currentName();
+ parser.nextToken();
+ if (currentFieldName.equals(IndexId.NAME)) {
+ name = parser.text();
+ } else if (currentFieldName.equals(IndexId.ID)) {
+ id = parser.text();
+ }
+ }
+ assertNotNull(name);
+ assertNotNull(id);
+ assertEquals(indexId, new IndexId(name, id));
+ }
+}
diff --git a/core/src/test/java/org/elasticsearch/repositories/RepositoryDataTests.java b/core/src/test/java/org/elasticsearch/repositories/RepositoryDataTests.java
new file mode 100644
index 00000000000..1fb34249fd2
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/repositories/RepositoryDataTests.java
@@ -0,0 +1,171 @@
+/*
+ * 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.repositories;
+
+import org.elasticsearch.common.UUIDs;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
+import org.elasticsearch.snapshots.SnapshotId;
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.greaterThan;
+
+/**
+ * Tests for the {@link RepositoryData} class.
+ */
+public class RepositoryDataTests extends ESTestCase {
+
+ public void testEqualsAndHashCode() {
+ RepositoryData repositoryData1 = generateRandomRepoData();
+ RepositoryData repositoryData2 = repositoryData1.copy();
+ assertEquals(repositoryData1, repositoryData2);
+ assertEquals(repositoryData1.hashCode(), repositoryData2.hashCode());
+ }
+
+ public void testXContent() throws IOException {
+ RepositoryData repositoryData = generateRandomRepoData();
+ XContentBuilder builder = JsonXContent.contentBuilder();
+ repositoryData.toXContent(builder, ToXContent.EMPTY_PARAMS);
+ XContentParser parser = XContentType.JSON.xContent().createParser(builder.bytes());
+ assertEquals(repositoryData, RepositoryData.fromXContent(parser));
+ }
+
+ public void testAddSnapshots() {
+ RepositoryData repositoryData = generateRandomRepoData();
+ // test that adding the same snapshot id to the repository data throws an exception
+ final SnapshotId snapshotId = repositoryData.getSnapshotIds().get(0);
+ Map indexIdMap = repositoryData.getIndices();
+ expectThrows(IllegalArgumentException.class,
+ () -> repositoryData.addSnapshot(new SnapshotId(snapshotId.getName(), snapshotId.getUUID()), Collections.emptyList()));
+ // test that adding a snapshot and its indices works
+ SnapshotId newSnapshot = new SnapshotId(randomAsciiOfLength(7), UUIDs.randomBase64UUID());
+ List indices = new ArrayList<>();
+ Set newIndices = new HashSet<>();
+ int numNew = randomIntBetween(1, 10);
+ for (int i = 0; i < numNew; i++) {
+ IndexId indexId = new IndexId(randomAsciiOfLength(7), UUIDs.randomBase64UUID());
+ newIndices.add(indexId);
+ indices.add(indexId);
+ }
+ int numOld = randomIntBetween(1, indexIdMap.size());
+ List indexNames = new ArrayList<>(indexIdMap.keySet());
+ for (int i = 0; i < numOld; i++) {
+ indices.add(indexIdMap.get(indexNames.get(i)));
+ }
+ RepositoryData newRepoData = repositoryData.addSnapshot(newSnapshot, indices);
+ // verify that the new repository data has the new snapshot and its indices
+ assertTrue(newRepoData.getSnapshotIds().contains(newSnapshot));
+ for (IndexId indexId : indices) {
+ Set snapshotIds = newRepoData.getSnapshots(indexId);
+ assertTrue(snapshotIds.contains(newSnapshot));
+ if (newIndices.contains(indexId)) {
+ assertEquals(snapshotIds.size(), 1); // if it was a new index, only the new snapshot should be in its set
+ }
+ }
+ }
+
+ public void testInitIndices() {
+ final int numSnapshots = randomIntBetween(1, 30);
+ final List snapshotIds = new ArrayList<>(numSnapshots);
+ for (int i = 0; i < numSnapshots; i++) {
+ snapshotIds.add(new SnapshotId(randomAsciiOfLength(8), UUIDs.randomBase64UUID()));
+ }
+ RepositoryData repositoryData = new RepositoryData(snapshotIds, Collections.emptyMap());
+ // test that initializing indices works
+ Map> indices = randomIndices(snapshotIds);
+ RepositoryData newRepoData = repositoryData.initIndices(indices);
+ assertEquals(repositoryData.getSnapshotIds(), newRepoData.getSnapshotIds());
+ for (IndexId indexId : indices.keySet()) {
+ assertEquals(indices.get(indexId), newRepoData.getSnapshots(indexId));
+ }
+ }
+
+ public void testRemoveSnapshot() {
+ RepositoryData repositoryData = generateRandomRepoData();
+ List snapshotIds = new ArrayList<>(repositoryData.getSnapshotIds());
+ assertThat(snapshotIds.size(), greaterThan(0));
+ SnapshotId removedSnapshotId = snapshotIds.remove(randomIntBetween(0, snapshotIds.size() - 1));
+ RepositoryData newRepositoryData = repositoryData.removeSnapshot(removedSnapshotId);
+ // make sure the repository data's indices no longer contain the removed snapshot
+ for (final IndexId indexId : newRepositoryData.getIndices().values()) {
+ assertFalse(newRepositoryData.getSnapshots(indexId).contains(removedSnapshotId));
+ }
+ }
+
+ public void testResolveIndexId() {
+ RepositoryData repositoryData = generateRandomRepoData();
+ Map indices = repositoryData.getIndices();
+ Set indexNames = indices.keySet();
+ assertThat(indexNames.size(), greaterThan(0));
+ String indexName = indexNames.iterator().next();
+ IndexId indexId = indices.get(indexName);
+ assertEquals(indexId, repositoryData.resolveIndexId(indexName));
+ String notInRepoData = randomAsciiOfLength(5);
+ assertFalse(indexName.contains(notInRepoData));
+ assertEquals(new IndexId(notInRepoData, notInRepoData), repositoryData.resolveIndexId(notInRepoData));
+ }
+
+ public static RepositoryData generateRandomRepoData() {
+ return generateRandomRepoData(new ArrayList<>());
+ }
+
+ public static RepositoryData generateRandomRepoData(final List origSnapshotIds) {
+ List snapshotIds = randomSnapshots(origSnapshotIds);
+ return new RepositoryData(snapshotIds, randomIndices(snapshotIds));
+ }
+
+ private static List randomSnapshots(final List origSnapshotIds) {
+ final int numSnapshots = randomIntBetween(1, 30);
+ final List snapshotIds = new ArrayList<>(origSnapshotIds);
+ for (int i = 0; i < numSnapshots; i++) {
+ snapshotIds.add(new SnapshotId(randomAsciiOfLength(8), UUIDs.randomBase64UUID()));
+ }
+ return snapshotIds;
+ }
+
+ private static Map> randomIndices(final List snapshotIds) {
+ final int totalSnapshots = snapshotIds.size();
+ final int numIndices = randomIntBetween(1, 30);
+ final Map> indices = new HashMap<>(numIndices);
+ for (int i = 0; i < numIndices; i++) {
+ final IndexId indexId = new IndexId(randomAsciiOfLength(8), UUIDs.randomBase64UUID());
+ final Set indexSnapshots = new LinkedHashSet<>();
+ final int numIndicesForSnapshot = randomIntBetween(1, numIndices);
+ for (int j = 0; j < numIndicesForSnapshot; j++) {
+ indexSnapshots.add(snapshotIds.get(randomIntBetween(0, totalSnapshots - 1)));
+ }
+ indices.put(indexId, indexSnapshots);
+ }
+ return indices;
+ }
+}
diff --git a/core/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java b/core/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java
index c9d8ff81aa2..6c4af1f7737 100644
--- a/core/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java
+++ b/core/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java
@@ -28,11 +28,11 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.OutputStreamStreamOutput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.repositories.RepositoriesService;
+import org.elasticsearch.repositories.RepositoryData;
import org.elasticsearch.snapshots.SnapshotId;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESSingleNodeTestCase;
@@ -44,7 +44,7 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
-import static org.elasticsearch.repositories.blobstore.BlobStoreRepository.blobId;
+import static org.elasticsearch.repositories.RepositoryDataTests.generateRandomRepoData;
import static org.hamcrest.Matchers.equalTo;
/**
@@ -109,86 +109,56 @@ public class BlobStoreRepositoryTests extends ESSingleNodeTestCase {
public void testReadAndWriteSnapshotsThroughIndexFile() throws Exception {
final BlobStoreRepository repository = setupRepo();
- // write to and read from a snapshot file with no entries
- assertThat(repository.getSnapshots().size(), equalTo(0));
- repository.writeSnapshotsToIndexGen(Collections.emptyList());
+ // write to and read from a index file with no entries
assertThat(repository.getSnapshots().size(), equalTo(0));
+ final RepositoryData emptyData = RepositoryData.EMPTY;
+ repository.writeIndexGen(emptyData);
+ final RepositoryData readData = repository.getRepositoryData();
+ assertEquals(readData, emptyData);
+ assertEquals(readData.getIndices().size(), 0);
+ assertEquals(readData.getSnapshotIds().size(), 0);
- // write to and read from a snapshot file with a random number of entries
- final int numSnapshots = randomIntBetween(1, 1000);
+ // write to and read from an index file with snapshots but no indices
+ final int numSnapshots = randomIntBetween(1, 20);
final List snapshotIds = new ArrayList<>(numSnapshots);
for (int i = 0; i < numSnapshots; i++) {
snapshotIds.add(new SnapshotId(randomAsciiOfLength(8), UUIDs.randomBase64UUID()));
}
- repository.writeSnapshotsToIndexGen(snapshotIds);
- assertThat(repository.getSnapshots(), equalTo(snapshotIds));
+ RepositoryData repositoryData = new RepositoryData(snapshotIds, Collections.emptyMap());
+ repository.writeIndexGen(repositoryData);
+ assertEquals(repository.getRepositoryData(), repositoryData);
+
+ // write to and read from a index file with random repository data
+ repositoryData = generateRandomRepoData();
+ repository.writeIndexGen(repositoryData);
+ assertThat(repository.getRepositoryData(), equalTo(repositoryData));
}
public void testIndexGenerationalFiles() throws Exception {
final BlobStoreRepository repository = setupRepo();
// write to index generational file
- final int numSnapshots = randomIntBetween(1, 1000);
- final List snapshotIds = new ArrayList<>(numSnapshots);
- for (int i = 0; i < numSnapshots; i++) {
- snapshotIds.add(new SnapshotId(randomAsciiOfLength(8), UUIDs.randomBase64UUID()));
- }
- repository.writeSnapshotsToIndexGen(snapshotIds);
- assertThat(Sets.newHashSet(repository.readSnapshotsFromIndex()), equalTo(Sets.newHashSet(snapshotIds)));
+ RepositoryData repositoryData = generateRandomRepoData();
+ repository.writeIndexGen(repositoryData);
+ assertThat(repository.getRepositoryData(), equalTo(repositoryData));
assertThat(repository.latestIndexBlobId(), equalTo(0L));
assertThat(repository.readSnapshotIndexLatestBlob(), equalTo(0L));
// adding more and writing to a new index generational file
- for (int i = 0; i < 10; i++) {
- snapshotIds.add(new SnapshotId(randomAsciiOfLength(8), UUIDs.randomBase64UUID()));
- }
- repository.writeSnapshotsToIndexGen(snapshotIds);
- assertThat(Sets.newHashSet(repository.readSnapshotsFromIndex()), equalTo(Sets.newHashSet(snapshotIds)));
+ repositoryData = generateRandomRepoData();
+ repository.writeIndexGen(repositoryData);
+ assertEquals(repository.getRepositoryData(), repositoryData);
assertThat(repository.latestIndexBlobId(), equalTo(1L));
assertThat(repository.readSnapshotIndexLatestBlob(), equalTo(1L));
- // removing a snapshot adn writing to a new index generational file
- snapshotIds.remove(0);
- repository.writeSnapshotsToIndexGen(snapshotIds);
- assertThat(Sets.newHashSet(repository.readSnapshotsFromIndex()), equalTo(Sets.newHashSet(snapshotIds)));
+ // removing a snapshot and writing to a new index generational file
+ repositoryData = repositoryData.removeSnapshot(repositoryData.getSnapshotIds().get(0));
+ repository.writeIndexGen(repositoryData);
+ assertEquals(repository.getRepositoryData(), repositoryData);
assertThat(repository.latestIndexBlobId(), equalTo(2L));
assertThat(repository.readSnapshotIndexLatestBlob(), equalTo(2L));
}
- public void testOldIndexFileFormat() throws Exception {
- final BlobStoreRepository repository = setupRepo();
-
- // write old index file format
- final int numOldSnapshots = randomIntBetween(1, 50);
- final List snapshotIds = new ArrayList<>();
- for (int i = 0; i < numOldSnapshots; i++) {
- snapshotIds.add(new SnapshotId(randomAsciiOfLength(8), SnapshotId.UNASSIGNED_UUID));
- }
- writeOldFormat(repository, snapshotIds.stream().map(SnapshotId::getName).collect(Collectors.toList()));
- assertThat(Sets.newHashSet(repository.getSnapshots()), equalTo(Sets.newHashSet(snapshotIds)));
-
- // write to and read from a snapshot file with a random number of new entries added
- final int numSnapshots = randomIntBetween(1, 1000);
- for (int i = 0; i < numSnapshots; i++) {
- snapshotIds.add(new SnapshotId(randomAsciiOfLength(8), UUIDs.randomBase64UUID()));
- }
- repository.writeSnapshotsToIndexGen(snapshotIds);
- assertThat(Sets.newHashSet(repository.getSnapshots()), equalTo(Sets.newHashSet(snapshotIds)));
- }
-
- public void testBlobId() {
- SnapshotId snapshotId = new SnapshotId("abc123", SnapshotId.UNASSIGNED_UUID);
- assertThat(blobId(snapshotId), equalTo("abc123")); // just the snapshot name
- snapshotId = new SnapshotId("abc-123", SnapshotId.UNASSIGNED_UUID);
- assertThat(blobId(snapshotId), equalTo("abc-123")); // just the snapshot name
- String uuid = UUIDs.randomBase64UUID();
- snapshotId = new SnapshotId("abc123", uuid);
- assertThat(blobId(snapshotId), equalTo("abc123-" + uuid)); // snapshot name + '-' + uuid
- uuid = UUIDs.randomBase64UUID();
- snapshotId = new SnapshotId("abc-123", uuid);
- assertThat(blobId(snapshotId), equalTo("abc-123-" + uuid)); // snapshot name + '-' + uuid
- }
-
private BlobStoreRepository setupRepo() {
final Client client = client();
final Path location = ESIntegTestCase.randomRepoPath(node().settings());
diff --git a/core/src/test/java/org/elasticsearch/script/FileScriptTests.java b/core/src/test/java/org/elasticsearch/script/FileScriptTests.java
index f932317085b..954de105a4f 100644
--- a/core/src/test/java/org/elasticsearch/script/FileScriptTests.java
+++ b/core/src/test/java/org/elasticsearch/script/FileScriptTests.java
@@ -37,14 +37,16 @@ public class FileScriptTests extends ESTestCase {
Path scriptsDir = homeDir.resolve("config").resolve("scripts");
Files.createDirectories(scriptsDir);
Path mockscript = scriptsDir.resolve("script1.mockscript");
- Files.write(mockscript, "1".getBytes("UTF-8"));
+ String scriptSource = "1";
+ Files.write(mockscript, scriptSource.getBytes("UTF-8"));
settings = Settings.builder()
.put(Environment.PATH_HOME_SETTING.getKey(), homeDir)
// no file watching, so we don't need a ResourceWatcherService
.put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), false)
.put(settings)
.build();
- ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singleton(new MockScriptEngine()));
+ MockScriptEngine scriptEngine = new MockScriptEngine(MockScriptEngine.NAME, Collections.singletonMap(scriptSource, script -> "1"));
+ ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singleton(scriptEngine));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
return new ScriptService(settings, new Environment(settings), null, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
diff --git a/core/src/test/java/org/elasticsearch/script/IndexLookupIT.java b/core/src/test/java/org/elasticsearch/script/IndexLookupIT.java
new file mode 100644
index 00000000000..7e57d41acea
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/script/IndexLookupIT.java
@@ -0,0 +1,1025 @@
+/*
+ * 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.script;
+
+import org.elasticsearch.action.search.SearchPhaseExecutionException;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.search.ShardSearchFailure;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.lookup.IndexField;
+import org.elasticsearch.search.lookup.IndexFieldTerm;
+import org.elasticsearch.search.lookup.IndexLookup;
+import org.elasticsearch.search.lookup.LeafIndexLookup;
+import org.elasticsearch.search.lookup.TermPosition;
+import org.elasticsearch.test.ESIntegTestCase;
+import org.hamcrest.Matchers;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Function;
+
+import static java.util.Collections.emptyList;
+import static org.elasticsearch.script.ScriptService.ScriptType;
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+
+public class IndexLookupIT extends ESIntegTestCase {
+
+ private static final String INCLUDE_ALL = "_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS|_CACHE";
+ private static final int ALL_FLAGS = IndexLookup.FLAG_FREQUENCIES
+ | IndexLookup.FLAG_OFFSETS
+ | IndexLookup.FLAG_PAYLOADS
+ | IndexLookup.FLAG_POSITIONS
+ | IndexLookup.FLAG_CACHE;
+
+ private static final String INCLUDE_ALL_BUT_CACHE = "_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS";
+ private static final int ALL_FLAGS_WITHOUT_CACHE = IndexLookup.FLAG_FREQUENCIES
+ | IndexLookup.FLAG_OFFSETS
+ | IndexLookup.FLAG_PAYLOADS
+ | IndexLookup.FLAG_POSITIONS;
+
+ private HashMap> expectedEndOffsetsArray;
+ private HashMap> expectedPayloadsArray;
+ private HashMap> expectedPositionsArray;
+ private HashMap> expectedStartOffsetsArray;
+
+ @Override
+ protected Collection> nodePlugins() {
+ return Collections.singleton(CustomScriptPlugin.class);
+ }
+
+ public static class CustomScriptPlugin extends MockScriptPlugin {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected Map, Object>> pluginScripts() {
+ Map, Object>> scripts = new HashMap<>();
+
+ scripts.put("term = _index['int_payload_field']['c']; term.tf()", vars -> tf(vars, "int_payload_field", "c"));
+ scripts.put("term = _index['int_payload_field']['b']; term.tf()", vars -> tf(vars, "int_payload_field", "b"));
+
+ scripts.put("Sum the payloads of [float_payload_field][b]", vars -> payloadSum(vars, "float_payload_field", "b"));
+ scripts.put("Sum the payloads of [int_payload_field][b]", vars -> payloadSum(vars, "int_payload_field", "b"));
+
+ scripts.put("createPositionsArrayScriptIterateTwice[b," + INCLUDE_ALL + ",position]",
+ vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS, p -> p.position));
+ scripts.put("createPositionsArrayScriptIterateTwice[b," + INCLUDE_ALL + ",startOffset]",
+ vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS, p -> p.startOffset));
+ scripts.put("createPositionsArrayScriptIterateTwice[b," + INCLUDE_ALL + ",endOffset]",
+ vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS, p -> p.endOffset));
+ scripts.put("createPositionsArrayScriptIterateTwice[b," + INCLUDE_ALL + ",payloadAsInt(-1)]",
+ vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS, p -> p.payloadAsInt(-1)));
+
+ scripts.put("createPositionsArrayScriptIterateTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,position]",
+ vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.position));
+ scripts.put("createPositionsArrayScriptIterateTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,startOffset]",
+ vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.startOffset));
+ scripts.put("createPositionsArrayScriptIterateTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,endOffset]",
+ vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.endOffset));
+ scripts.put("createPositionsArrayScriptIterateTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,payloadAsInt(-1)]",
+ vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.payloadAsInt(-1)));
+
+ scripts.put("createPositionsArrayScriptGetInfoObjectTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,position]",
+ vars -> createPositionsArrayScriptGetInfoObjectTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.position));
+ scripts.put("createPositionsArrayScriptGetInfoObjectTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,startOffset]",
+ vars -> createPositionsArrayScriptGetInfoObjectTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.startOffset));
+ scripts.put("createPositionsArrayScriptGetInfoObjectTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,endOffset]",
+ vars -> createPositionsArrayScriptGetInfoObjectTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.endOffset));
+ scripts.put("createPositionsArrayScriptGetInfoObjectTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,payloadAsInt(-1)]",
+ vars -> createPositionsArrayScriptGetInfoObjectTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.payloadAsInt(-1)));
+
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS,position]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_POSITIONS, p -> p.position));
+
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_OFFSETS,position]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_OFFSETS, p -> p.position));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_OFFSETS,startOffset]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_OFFSETS, p -> p.startOffset));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_OFFSETS,endOffset]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_OFFSETS, p -> p.endOffset));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_OFFSETS,payloadAsInt(-1)]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_OFFSETS, p -> p.payloadAsInt(-1)));
+
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_PAYLOADS,position]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_PAYLOADS, p -> p.position));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_PAYLOADS,startOffset]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_PAYLOADS, p -> p.startOffset));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_PAYLOADS,endOffset]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_PAYLOADS, p -> p.endOffset));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_PAYLOADS,payloadAsInt(-1)]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_PAYLOADS, p -> p.payloadAsInt(-1)));
+
+ int posoffpay = IndexLookup.FLAG_POSITIONS|IndexLookup.FLAG_OFFSETS|IndexLookup.FLAG_PAYLOADS;
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS|_OFFSETS|_PAYLOADS,position]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", posoffpay, p -> p.position));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS|_OFFSETS|_PAYLOADS,startOffset]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", posoffpay, p -> p.startOffset));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS|_OFFSETS|_PAYLOADS,endOffset]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", posoffpay, p -> p.endOffset));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS|_OFFSETS|_PAYLOADS,payloadAsInt(-1)]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", posoffpay, p -> p.payloadAsInt(-1)));
+
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,position]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.position));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,startOffset]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.startOffset));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,endOffset]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.endOffset));
+ scripts.put("createPositionsArrayScript[int_payload_field,b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,payloadAsInt(-1)]",
+ vars -> createPositionsArrayScript(vars, "int_payload_field", "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.payloadAsInt(-1)));
+
+ scripts.put("createPositionsArrayScript" +
+ "[float_payload_field,b," + INCLUDE_ALL + ",payloadAsFloat(-1)]",
+ vars -> createPositionsArrayScript(vars,"float_payload_field", "b", ALL_FLAGS, p -> p.payloadAsFloat(-1)));
+ scripts.put("createPositionsArrayScript" +
+ "[string_payload_field,b," + INCLUDE_ALL + ",payloadAsString()]",
+ vars -> createPositionsArrayScript(vars,"string_payload_field", "b", ALL_FLAGS, TermPosition::payloadAsString));
+ scripts.put("createPositionsArrayScript" +
+ "[int_payload_field,c," + INCLUDE_ALL + ",payloadAsInt(-1)]",
+ vars -> createPositionsArrayScript(vars,"int_payload_field", "c", ALL_FLAGS, p -> p.payloadAsInt(-1)));
+
+ // Call with different flags twice, equivalent to:
+ // term = _index['int_payload_field']['b']; return _index['int_payload_field'].get('b', _POSITIONS).tf();
+ scripts.put("Call with different flags twice", vars -> {
+ LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
+ IndexField indexField = leafIndexLookup.get("int_payload_field");
+
+ // 1st call
+ indexField.get("b");
+ try {
+ // 2nd call, must throws an exception
+ return indexField.get("b", IndexLookup.FLAG_POSITIONS).tf();
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "Call with different flags twice", CustomScriptPlugin.NAME);
+ }
+ });
+
+ // Call with same flags twice: equivalent to:
+ // term = _index['int_payload_field'].get('b', _POSITIONS | _FREQUENCIES);return _index['int_payload_field']['b'].tf();
+ scripts.put("Call with same flags twice", vars -> {
+ LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
+ IndexField indexField = leafIndexLookup.get("int_payload_field");
+
+ // 1st call
+ indexField.get("b", IndexLookup.FLAG_POSITIONS | IndexLookup.FLAG_FREQUENCIES);
+ try {
+ // 2nd call, must throws an exception
+ return indexField.get("b").tf();
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "Call with same flags twice", CustomScriptPlugin.NAME);
+ }
+ });
+
+ // get the number of all docs
+ scripts.put("_index.numDocs()",
+ vars -> ((LeafIndexLookup) vars.get("_index")).numDocs());
+
+ // get the number of docs with field float_payload_field
+ scripts.put("_index['float_payload_field'].docCount()",
+ vars -> indexFieldScript(vars, "float_payload_field", indexField -> {
+ try {
+ return indexField.docCount();
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "docCount()", CustomScriptPlugin.NAME);
+ }
+ }));
+
+ // corner case: what if the field does not exist?
+ scripts.put("_index['non_existent_field'].docCount()",
+ vars -> indexFieldScript(vars, "non_existent_field", indexField -> {
+ try {
+ return indexField.docCount();
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "docCount()", CustomScriptPlugin.NAME);
+ }
+ }));
+
+ // get the number of all tokens in all docs
+ scripts.put("_index['float_payload_field'].sumttf()",
+ vars -> indexFieldScript(vars, "float_payload_field", indexField -> {
+ try {
+ return indexField.sumttf();
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "sumttf()", CustomScriptPlugin.NAME);
+ }
+ }));
+
+ // corner case get the number of all tokens in all docs for non existent
+ // field
+ scripts.put("_index['non_existent_field'].sumttf()",
+ vars -> indexFieldScript(vars, "non_existent_field", indexField -> {
+ try {
+ return indexField.sumttf();
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "sumttf()", CustomScriptPlugin.NAME);
+ }
+ }));
+
+ // get the sum of doc freqs in all docs
+ scripts.put("_index['float_payload_field'].sumdf()",
+ vars -> indexFieldScript(vars, "float_payload_field", indexField -> {
+ try {
+ return indexField.sumdf();
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "sumdf()", CustomScriptPlugin.NAME);
+ }
+ }));
+
+ // get the sum of doc freqs in all docs for non existent field
+ scripts.put("_index['non_existent_field'].sumdf()",
+ vars -> indexFieldScript(vars, "non_existent_field", indexField -> {
+ try {
+ return indexField.sumdf();
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "sumdf()", CustomScriptPlugin.NAME);
+ }
+ }));
+
+ // check term frequencies for 'a'
+ scripts.put("term = _index['float_payload_field']['a']; if (term != null) {term.tf()}",
+ vars -> indexFieldTermScript(vars, "float_payload_field", "a", indexFieldTerm -> {
+ try {
+ if (indexFieldTerm != null) {
+ return indexFieldTerm.tf();
+ }
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "term.tf()", CustomScriptPlugin.NAME);
+ }
+ return null;
+ }));
+
+ // check doc frequencies for 'c'
+ scripts.put("term = _index['float_payload_field']['c']; if (term != null) {term.df()}",
+ vars -> indexFieldTermScript(vars, "float_payload_field", "c", indexFieldTerm -> {
+ try {
+ if (indexFieldTerm != null) {
+ return indexFieldTerm.df();
+ }
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "term.df()", CustomScriptPlugin.NAME);
+ }
+ return null;
+ }));
+
+ // check doc frequencies for term that does not exist
+ scripts.put("term = _index['float_payload_field']['non_existent_term']; if (term != null) {term.df()}",
+ vars -> indexFieldTermScript(vars, "float_payload_field", "non_existent_term", indexFieldTerm -> {
+ try {
+ if (indexFieldTerm != null) {
+ return indexFieldTerm.df();
+ }
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "term.df()", CustomScriptPlugin.NAME);
+ }
+ return null;
+ }));
+
+ // check doc frequencies for term that does not exist
+ scripts.put("term = _index['non_existent_field']['non_existent_term']; if (term != null) {term.tf()}",
+ vars -> indexFieldTermScript(vars, "non_existent_field", "non_existent_term", indexFieldTerm -> {
+ try {
+ if (indexFieldTerm != null) {
+ return indexFieldTerm.tf();
+ }
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "term.tf()", CustomScriptPlugin.NAME);
+ }
+ return null;
+ }));
+
+ // check total term frequencies for 'a'
+ scripts.put("term = _index['float_payload_field']['a']; if (term != null) {term.ttf()}",
+ vars -> indexFieldTermScript(vars, "float_payload_field", "a", indexFieldTerm -> {
+ try {
+ if (indexFieldTerm != null) {
+ return indexFieldTerm.ttf();
+ }
+ } catch (IOException e) {
+ throw new ScriptException(e.getMessage(), e, emptyList(), "term.ttf()", CustomScriptPlugin.NAME);
+ }
+ return null;
+ }));
+
+ return scripts;
+ }
+
+ @SuppressWarnings("unchecked")
+ static Object indexFieldScript(Map vars, String fieldName, Function fn) {
+ LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
+ return fn.apply(leafIndexLookup.get(fieldName));
+ }
+
+ @SuppressWarnings("unchecked")
+ static Object indexFieldTermScript(Map vars, String fieldName, String term, Function fn) {
+ return indexFieldScript(vars, fieldName, indexField -> fn.apply(indexField.get(term)));
+ }
+
+ @SuppressWarnings("unchecked")
+ static Object tf(Map vars, String fieldName, String term) {
+ return indexFieldTermScript(vars, fieldName, term, indexFieldTerm -> {
+ try {
+ return indexFieldTerm.tf();
+ } catch (IOException e) {
+ throw new RuntimeException("Mocked script error when retrieving TF for [" + fieldName + "][" + term + "]");
+ }
+ });
+ }
+
+ // Sum the payloads for a given field term, equivalent to:
+ // term = _index['float_payload_field'].get('b', _FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS|_CACHE);
+ // payloadSum=0;
+ // for (pos in term) {
+ // payloadSum += pos.payloadAsInt(0)
+ // };
+ // return payloadSum;
+ @SuppressWarnings("unchecked")
+ static Object payloadSum(Map vars, String fieldName, String term) {
+ return indexFieldScript(vars, fieldName, indexField -> {
+ IndexFieldTerm indexFieldTerm = indexField.get(term, IndexLookup.FLAG_FREQUENCIES
+ | IndexLookup.FLAG_OFFSETS
+ | IndexLookup.FLAG_PAYLOADS
+ | IndexLookup.FLAG_POSITIONS
+ | IndexLookup.FLAG_CACHE);
+ int payloadSum = 0;
+ for (TermPosition position : indexFieldTerm) {
+ payloadSum += position.payloadAsInt(0);
+ }
+ return payloadSum;
+ });
+ }
+
+ @SuppressWarnings("unchecked")
+ static List