703 lines
20 KiB
Java
Raw Normal View History

2010-02-08 15:30:06 +02:00
/*
* 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
2010-02-08 15:30:06 +02:00
*
* 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.index.translog;
import org.apache.lucene.index.Term;
import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Streamable;
import org.elasticsearch.common.lease.Releasable;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.index.CloseableIndexComponent;
import org.elasticsearch.index.VersionType;
2010-02-08 15:30:06 +02:00
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.shard.IndexShardComponent;
import java.io.IOException;
import java.io.InputStream;
2010-02-08 15:30:06 +02:00
/**
2011-12-06 02:42:25 +02:00
*
2010-02-08 15:30:06 +02:00
*/
public interface Translog extends IndexShardComponent, CloseableIndexComponent {
2010-02-08 15:30:06 +02:00
static ByteSizeValue INACTIVE_SHARD_TRANSLOG_BUFFER = ByteSizeValue.parseBytesSizeValue("1kb");
public static final String TRANSLOG_ID_KEY = "translog_id";
void updateBuffer(ByteSizeValue bufferSize);
void closeWithDelete();
2010-02-08 15:30:06 +02:00
/**
* Returns the id of the current transaction log.
*/
long currentId();
/**
* Returns the number of operations in the transaction log.
*/
int estimatedNumberOfOperations();
2010-02-08 15:30:06 +02:00
/**
* The estimated memory size this translog is taking.
*/
2011-01-29 04:04:58 +02:00
long memorySizeInBytes();
/**
* Returns the size in bytes of the translog.
*/
2011-01-29 04:04:58 +02:00
long translogSizeInBytes();
2010-02-08 15:30:06 +02:00
/**
* Creates a new transaction log internally.
2011-12-06 02:42:25 +02:00
* <p/>
* <p>Can only be called by one thread.
*/
void newTranslog(long id) throws TranslogException;
/**
* Creates a new transient translog, where added ops will be added to the current one, and to
* it.
2011-12-06 02:42:25 +02:00
* <p/>
* <p>Can only be called by one thread.
*/
void newTransientTranslog(long id) throws TranslogException;
/**
* Swaps the transient translog to be the current one.
2011-12-06 02:42:25 +02:00
* <p/>
* <p>Can only be called by one thread.
*/
void makeTransientCurrent();
/**
* Reverts back to not have a transient translog.
*/
void revertTransient();
2010-02-08 15:30:06 +02:00
/**
* Adds a create operation to the transaction log.
*/
2011-06-24 09:39:37 +03:00
Location add(Operation operation) throws TranslogException;
byte[] read(Location location);
2010-02-08 15:30:06 +02:00
/**
* Snapshots the current transaction log allowing to safely iterate over the snapshot.
*/
Snapshot snapshot() throws TranslogException;
/**
* Snapshots the delta between the current state of the translog, and the state defined
* by the provided snapshot. If a new translog has been created after the provided snapshot
* has been take, will return a snapshot on the current trasnlog.
*/
Snapshot snapshot(Snapshot snapshot);
/**
* Clears unreferenced transaclogs.
*/
void clearUnreferenced();
2010-09-24 12:29:52 +02:00
/**
* Sync's the translog.
2010-09-24 12:29:52 +02:00
*/
void sync() throws IOException;
boolean syncNeeded();
void syncOnEachOperation(boolean syncOnEachOperation);
2010-09-24 12:29:52 +02:00
/**
* return stats
*/
TranslogStats stats();
2011-06-24 09:39:37 +03:00
static class Location {
public final long translogId;
public final long translogLocation;
public final int size;
public Location(long translogId, long translogLocation, int size) {
this.translogId = translogId;
this.translogLocation = translogLocation;
this.size = size;
}
}
2010-02-08 15:30:06 +02:00
/**
* A snapshot of the transaction log, allows to iterate over all the transaction log operations.
*/
static interface Snapshot extends Releasable {
2010-02-08 15:30:06 +02:00
/**
* The id of the translog the snapshot was taken with.
*/
long translogId();
long position();
2010-02-08 15:30:06 +02:00
/**
* Returns the internal length (*not* number of operations) of this snapshot.
2010-02-08 15:30:06 +02:00
*/
long length();
/**
* The total number of operations in the translog.
*/
int estimatedTotalOperations();
boolean hasNext();
Operation next();
2010-02-08 15:30:06 +02:00
void seekForward(long length);
/**
* Returns a stream of this snapshot.
*/
InputStream stream() throws IOException;
/**
* The length in bytes of this stream.
*/
long lengthInBytes();
2010-02-08 15:30:06 +02:00
}
/**
* A generic interface representing an operation performed on the transaction log.
2010-02-08 15:30:06 +02:00
* Each is associated with a type.
*/
static interface Operation extends Streamable {
static enum Type {
CREATE((byte) 1),
SAVE((byte) 2),
DELETE((byte) 3),
DELETE_BY_QUERY((byte) 4);
private final byte id;
private Type(byte id) {
this.id = id;
}
public byte id() {
return this.id;
}
public static Type fromId(byte id) {
switch (id) {
case 1:
return CREATE;
case 2:
return SAVE;
case 3:
return DELETE;
case 4:
return DELETE_BY_QUERY;
default:
throw new IllegalArgumentException("No type mapped for [" + id + "]");
}
}
}
Type opType();
long estimateSize();
2011-06-24 09:39:37 +03:00
Source readSource(StreamInput in) throws IOException;
}
static class Source {
public final BytesReference source;
public final String routing;
public final String parent;
public final long timestamp;
2011-08-30 17:48:06 +02:00
public final long ttl;
public Source(BytesReference source, String routing, String parent, long timestamp, long ttl) {
this.source = source;
this.routing = routing;
this.parent = parent;
this.timestamp = timestamp;
2011-08-30 17:48:06 +02:00
this.ttl = ttl;
}
2010-02-08 15:30:06 +02:00
}
static class Create implements Operation {
public static final int SERIALIZATION_FORMAT = 6;
2010-02-08 15:30:06 +02:00
private String id;
private String type;
private BytesReference source;
private String routing;
2010-12-08 00:16:05 +02:00
private String parent;
2011-08-26 11:06:10 +02:00
private long timestamp;
2011-08-30 17:48:06 +02:00
private long ttl;
private long version = Versions.MATCH_ANY;
private VersionType versionType = VersionType.INTERNAL;
2010-02-08 15:30:06 +02:00
public Create() {
}
public Create(Engine.Create create) {
this.id = create.id();
this.type = create.type();
this.source = create.source();
this.routing = create.routing();
2010-12-08 00:16:05 +02:00
this.parent = create.parent();
2011-08-26 11:06:10 +02:00
this.timestamp = create.timestamp();
2011-08-30 17:48:06 +02:00
this.ttl = create.ttl();
2011-01-04 04:04:30 +02:00
this.version = create.version();
this.versionType = create.versionType();
2010-02-08 15:30:06 +02:00
}
public Create(String type, String id, byte[] source) {
2010-02-08 15:30:06 +02:00
this.id = id;
this.type = type;
this.source = new BytesArray(source);
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public Type opType() {
2010-02-08 15:30:06 +02:00
return Type.CREATE;
}
2011-12-06 02:42:25 +02:00
@Override
public long estimateSize() {
return ((id.length() + type.length()) * 2) + source.length() + 12;
2010-02-08 15:30:06 +02:00
}
public String id() {
return this.id;
}
public BytesReference source() {
2010-02-08 15:30:06 +02:00
return this.source;
}
public String type() {
return this.type;
}
public String routing() {
return this.routing;
2010-02-08 15:30:06 +02:00
}
2010-12-08 00:16:05 +02:00
public String parent() {
return this.parent;
}
2011-08-26 11:06:10 +02:00
public long timestamp() {
return this.timestamp;
}
2011-08-30 17:48:06 +02:00
public long ttl() {
return this.ttl;
}
2011-01-04 04:04:30 +02:00
public long version() {
return this.version;
}
public VersionType versionType() {
return versionType;
}
2011-12-06 02:42:25 +02:00
@Override
public Source readSource(StreamInput in) throws IOException {
readFrom(in);
2011-08-30 17:48:06 +02:00
return new Source(source, routing, parent, timestamp, ttl);
2011-06-24 09:39:37 +03:00
}
2011-12-06 02:42:25 +02:00
@Override
public void readFrom(StreamInput in) throws IOException {
int version = in.readVInt(); // version
id = in.readString();
type = in.readString();
source = in.readBytesReference();
2010-12-08 00:16:05 +02:00
if (version >= 1) {
if (in.readBoolean()) {
routing = in.readString();
}
}
2010-12-08 00:16:05 +02:00
if (version >= 2) {
if (in.readBoolean()) {
parent = in.readString();
2010-12-08 00:16:05 +02:00
}
}
2011-01-04 04:04:30 +02:00
if (version >= 3) {
this.version = in.readLong();
}
2011-08-26 11:06:10 +02:00
if (version >= 4) {
this.timestamp = in.readLong();
}
2011-08-30 17:48:06 +02:00
if (version >= 5) {
this.ttl = in.readLong();
}
if (version >= 6) {
this.versionType = VersionType.fromValue(in.readByte());
}
assert versionType.validateVersionForWrites(version);
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(SERIALIZATION_FORMAT);
out.writeString(id);
out.writeString(type);
out.writeBytesReference(source);
if (routing == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeString(routing);
}
2010-12-08 00:16:05 +02:00
if (parent == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeString(parent);
2010-12-08 00:16:05 +02:00
}
2011-01-04 04:04:30 +02:00
out.writeLong(version);
2011-08-26 11:06:10 +02:00
out.writeLong(timestamp);
2011-08-30 17:48:06 +02:00
out.writeLong(ttl);
out.writeByte(versionType.getValue());
2010-02-08 15:30:06 +02:00
}
}
static class Index implements Operation {
public static final int SERIALIZATION_FORMAT = 6;
2010-02-08 15:30:06 +02:00
private String id;
private String type;
private long version = Versions.MATCH_ANY;
private VersionType versionType = VersionType.INTERNAL;
private BytesReference source;
private String routing;
2010-12-08 00:16:05 +02:00
private String parent;
2011-08-26 11:06:10 +02:00
private long timestamp;
2011-08-30 17:48:06 +02:00
private long ttl;
2010-02-08 15:30:06 +02:00
public Index() {
}
public Index(Engine.Index index) {
this.id = index.id();
this.type = index.type();
this.source = index.source();
this.routing = index.routing();
2010-12-08 00:16:05 +02:00
this.parent = index.parent();
2011-01-04 04:04:30 +02:00
this.version = index.version();
2011-08-26 11:06:10 +02:00
this.timestamp = index.timestamp();
2011-08-30 17:48:06 +02:00
this.ttl = index.ttl();
this.versionType = index.versionType();
2010-02-08 15:30:06 +02:00
}
public Index(String type, String id, byte[] source) {
2010-02-08 15:30:06 +02:00
this.type = type;
this.id = id;
this.source = new BytesArray(source);
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public Type opType() {
2010-02-08 15:30:06 +02:00
return Type.SAVE;
}
2011-12-06 02:42:25 +02:00
@Override
public long estimateSize() {
return ((id.length() + type.length()) * 2) + source.length() + 12;
2010-02-08 15:30:06 +02:00
}
public String type() {
return this.type;
}
public String id() {
return this.id;
}
public String routing() {
return this.routing;
2010-02-08 15:30:06 +02:00
}
2010-12-08 00:16:05 +02:00
public String parent() {
return this.parent;
}
2011-08-26 11:06:10 +02:00
public long timestamp() {
return this.timestamp;
}
2011-08-30 17:48:06 +02:00
public long ttl() {
return this.ttl;
}
public BytesReference source() {
return this.source;
2010-02-08 15:30:06 +02:00
}
2011-01-04 04:04:30 +02:00
public long version() {
return this.version;
}
public VersionType versionType() {
return versionType;
}
2011-12-06 02:42:25 +02:00
@Override
public Source readSource(StreamInput in) throws IOException {
readFrom(in);
2011-08-30 17:48:06 +02:00
return new Source(source, routing, parent, timestamp, ttl);
2011-06-24 09:39:37 +03:00
}
2011-12-06 02:42:25 +02:00
@Override
public void readFrom(StreamInput in) throws IOException {
int version = in.readVInt(); // version
id = in.readString();
type = in.readString();
source = in.readBytesReference();
2010-12-08 00:16:05 +02:00
if (version >= 1) {
if (in.readBoolean()) {
routing = in.readString();
}
}
2010-12-08 00:16:05 +02:00
if (version >= 2) {
if (in.readBoolean()) {
parent = in.readString();
2010-12-08 00:16:05 +02:00
}
}
2011-01-04 04:04:30 +02:00
if (version >= 3) {
this.version = in.readLong();
}
2011-08-26 11:06:10 +02:00
if (version >= 4) {
this.timestamp = in.readLong();
}
2011-08-30 17:48:06 +02:00
if (version >= 5) {
this.ttl = in.readLong();
}
if (version >= 6) {
this.versionType = VersionType.fromValue(in.readByte());
}
assert versionType.validateVersionForWrites(version);
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(SERIALIZATION_FORMAT);
out.writeString(id);
out.writeString(type);
out.writeBytesReference(source);
if (routing == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeString(routing);
}
2010-12-08 00:16:05 +02:00
if (parent == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeString(parent);
2010-12-08 00:16:05 +02:00
}
2011-01-04 04:04:30 +02:00
out.writeLong(version);
2011-08-26 11:06:10 +02:00
out.writeLong(timestamp);
2011-08-30 17:48:06 +02:00
out.writeLong(ttl);
out.writeByte(versionType.getValue());
2010-02-08 15:30:06 +02:00
}
}
static class Delete implements Operation {
public static final int SERIALIZATION_FORMAT = 2;
2010-02-08 15:30:06 +02:00
private Term uid;
private long version = Versions.MATCH_ANY;
private VersionType versionType = VersionType.INTERNAL;
2010-02-08 15:30:06 +02:00
public Delete() {
}
public Delete(Engine.Delete delete) {
this(delete.uid());
2011-01-04 04:04:30 +02:00
this.version = delete.version();
this.versionType = delete.versionType();
2010-02-08 15:30:06 +02:00
}
public Delete(Term uid) {
this.uid = uid;
}
2011-12-06 02:42:25 +02:00
@Override
public Type opType() {
2010-02-08 15:30:06 +02:00
return Type.DELETE;
}
2011-12-06 02:42:25 +02:00
@Override
public long estimateSize() {
2010-02-08 15:30:06 +02:00
return ((uid.field().length() + uid.text().length()) * 2) + 20;
}
public Term uid() {
return this.uid;
}
2011-01-04 04:04:30 +02:00
public long version() {
return this.version;
}
public VersionType versionType() {
return this.versionType;
}
2011-12-06 02:42:25 +02:00
@Override
public Source readSource(StreamInput in) throws IOException {
throw new ElasticsearchIllegalStateException("trying to read doc source from delete operation");
2011-06-24 09:39:37 +03:00
}
2011-12-06 02:42:25 +02:00
@Override
public void readFrom(StreamInput in) throws IOException {
2011-01-04 04:04:30 +02:00
int version = in.readVInt(); // version
uid = new Term(in.readString(), in.readString());
2011-01-04 04:04:30 +02:00
if (version >= 1) {
this.version = in.readLong();
}
if (version >= 2) {
this.versionType = VersionType.fromValue(in.readByte());
}
assert versionType.validateVersionForWrites(version);
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(SERIALIZATION_FORMAT);
out.writeString(uid.field());
out.writeString(uid.text());
2011-01-04 04:04:30 +02:00
out.writeLong(version);
out.writeByte(versionType.getValue());
2010-02-08 15:30:06 +02:00
}
}
static class DeleteByQuery implements Operation {
public static final int SERIALIZATION_FORMAT = 2;
private BytesReference source;
2011-12-06 02:42:25 +02:00
@Nullable
private String[] filteringAliases;
2010-02-08 15:30:06 +02:00
private String[] types = Strings.EMPTY_ARRAY;
public DeleteByQuery() {
}
public DeleteByQuery(Engine.DeleteByQuery deleteByQuery) {
this(deleteByQuery.source(), deleteByQuery.filteringAliases(), deleteByQuery.types());
2010-02-08 15:30:06 +02:00
}
public DeleteByQuery(BytesReference source, String[] filteringAliases, String... types) {
2010-02-08 15:30:06 +02:00
this.source = source;
this.types = types == null ? Strings.EMPTY_ARRAY : types;
this.filteringAliases = filteringAliases;
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public Type opType() {
2010-02-08 15:30:06 +02:00
return Type.DELETE_BY_QUERY;
}
2011-12-06 02:42:25 +02:00
@Override
public long estimateSize() {
return source.length() + 8;
2010-02-08 15:30:06 +02:00
}
public BytesReference source() {
2010-02-08 15:30:06 +02:00
return this.source;
}
public String[] filteringAliases() {
return filteringAliases;
}
2010-02-08 15:30:06 +02:00
public String[] types() {
return this.types;
}
2011-12-06 02:42:25 +02:00
@Override
public Source readSource(StreamInput in) throws IOException {
throw new ElasticsearchIllegalStateException("trying to read doc source from delete_by_query operation");
2011-06-24 09:39:37 +03:00
}
2011-12-06 02:42:25 +02:00
@Override
public void readFrom(StreamInput in) throws IOException {
int version = in.readVInt(); // version
source = in.readBytesReference();
if (version < 2) {
// for query_parser_name, which was removed
if (in.readBoolean()) {
in.readString();
}
2010-02-08 15:30:06 +02:00
}
int typesSize = in.readVInt();
2010-02-08 15:30:06 +02:00
if (typesSize > 0) {
types = new String[typesSize];
for (int i = 0; i < typesSize; i++) {
types[i] = in.readString();
2010-02-08 15:30:06 +02:00
}
}
if (version >= 1) {
int aliasesSize = in.readVInt();
if (aliasesSize > 0) {
filteringAliases = new String[aliasesSize];
for (int i = 0; i < aliasesSize; i++) {
filteringAliases[i] = in.readString();
}
}
}
2010-02-08 15:30:06 +02:00
}
2011-12-06 02:42:25 +02:00
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(SERIALIZATION_FORMAT);
out.writeBytesReference(source);
out.writeVInt(types.length);
2010-02-08 15:30:06 +02:00
for (String type : types) {
out.writeString(type);
2010-02-08 15:30:06 +02:00
}
if (filteringAliases != null) {
out.writeVInt(filteringAliases.length);
for (String alias : filteringAliases) {
out.writeString(alias);
}
} else {
out.writeVInt(0);
}
2010-02-08 15:30:06 +02:00
}
}
}