/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.accumulo.tserver.logger;
import static org.apache.accumulo.tserver.logger.LogEvents.DEFINE_TABLET;
import static org.apache.accumulo.tserver.logger.LogEvents.MANY_MUTATIONS;
import static org.apache.accumulo.tserver.logger.LogEvents.MUTATION;
import static org.apache.accumulo.tserver.logger.LogEvents.OPEN;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.accumulo.core.data.impl.KeyExtent;
import org.apache.hadoop.io.WritableComparable;
public class LogFileKey implements WritableComparable<LogFileKey> {
public LogEvents event;
public String filename = null;
public KeyExtent tablet = null;
public long seq = -1;
public int tid = -1;
public static final int VERSION = 2;
public String tserverSession;
@Override
public void readFields(DataInput in) throws IOException {
int value = in.readByte();
if (value >= LogEvents.values().length) {
throw new IOException("Invalid LogEvent type, got ordinal " + value + ", but only know about " + LogEvents.values().length + " possible types.");
}
event = LogEvents.values()[value];
switch (event) {
case OPEN:
tid = in.readInt();
tserverSession = in.readUTF();
if (tid != VERSION) {
throw new RuntimeException(String.format("Bad version number for log file: expected %d, but saw %d", VERSION, tid));
}
break;
case COMPACTION_FINISH:
seq = in.readLong();
tid = in.readInt();
break;
case COMPACTION_START:
seq = in.readLong();
tid = in.readInt();
filename = in.readUTF();
break;
case DEFINE_TABLET:
seq = in.readLong();
tid = in.readInt();
tablet = new KeyExtent();
tablet.readFields(in);
break;
case MANY_MUTATIONS:
seq = in.readLong();
tid = in.readInt();
break;
case MUTATION:
seq = in.readLong();
tid = in.readInt();
break;
default:
throw new RuntimeException("Unknown log event type: " + event);
}
}
@Override
public void write(DataOutput out) throws IOException {
out.writeByte(event.ordinal());
switch (event) {
case OPEN:
seq = -1;
tid = -1;
out.writeInt(VERSION);
out.writeUTF(tserverSession);
// out.writeUTF(Accumulo.getInstanceID());
break;
case COMPACTION_FINISH:
out.writeLong(seq);
out.writeInt(tid);
break;
case COMPACTION_START:
out.writeLong(seq);
out.writeInt(tid);
out.writeUTF(filename);
break;
case DEFINE_TABLET:
out.writeLong(seq);
out.writeInt(tid);
tablet.write(out);
break;
case MANY_MUTATIONS:
out.writeLong(seq);
out.writeInt(tid);
break;
case MUTATION:
out.writeLong(seq);
out.writeInt(tid);
break;
default:
throw new IllegalArgumentException("Bad value for LogFileEntry type");
}
}
static int eventType(LogEvents event) {
// Order logs by START, TABLET_DEFINITIONS, COMPACTIONS and then MUTATIONS
if (event == MUTATION || event == MANY_MUTATIONS) {
return 3;
}
if (event == DEFINE_TABLET) {
return 1;
}
if (event == OPEN) {
return 0;
}
return 2;
}
private static int sign(long l) {
if (l < 0)
return -1;
if (l > 0)
return 1;
return 0;
}
@Override
public int compareTo(LogFileKey o) {
if (eventType(this.event) != eventType(o.event)) {
return eventType(this.event) - eventType(o.event);
}
if (this.event == OPEN)
return 0;
if (this.tid != o.tid) {
return this.tid - o.tid;
}
return sign(this.seq - o.seq);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof LogFileKey) {
return this.compareTo((LogFileKey) obj) == 0;
}
return false;
}
@Override
public int hashCode() {
return (int) seq;
}
@Override
public String toString() {
switch (event) {
case OPEN:
return String.format("OPEN %s", tserverSession);
case COMPACTION_FINISH:
return String.format("COMPACTION_FINISH %d %d", tid, seq);
case COMPACTION_START:
return String.format("COMPACTION_START %d %d %s", tid, seq, filename);
case MUTATION:
return String.format("MUTATION %d %d", tid, seq);
case MANY_MUTATIONS:
return String.format("MANY_MUTATIONS %d %d", tid, seq);
case DEFINE_TABLET:
return String.format("DEFINE_TABLET %d %d %s", tid, seq, tablet);
}
throw new RuntimeException("Unknown type of entry: " + event);
}
}