/*
* Copyright 2012 NGDATA nv
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lilyproject.mapreduce;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.BinaryComparable;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.io.WritableUtils;
import org.lilyproject.repository.api.IdGenerator;
import org.lilyproject.repository.api.RecordId;
import org.lilyproject.repository.impl.id.IdGeneratorImpl;
/**
* A Hadoop WritableComparable for Lily RecordId's.
*
* <p>Stores the length of the record id as a vint, followed by the normal binary
* representation of the record id (= the same as used as row key in the HBase table).</p>
*/
public class RecordIdWritable extends BinaryComparable implements WritableComparable<BinaryComparable> {
private RecordId recordId;
private static final IdGenerator ID_GENERATOR = new IdGeneratorImpl();
public RecordIdWritable() {
}
public RecordIdWritable(RecordId recordId) {
this.recordId = recordId;
}
@Override
public int getLength() {
// RecordId's cache their binary representation, so this should be fast
return recordId.toBytes().length;
}
@Override
public byte[] getBytes() {
return recordId.toBytes();
}
// Disclaimer: the Comparator was copied from Hadoop's Text class.
public static class Comparator extends WritableComparator {
public Comparator() {
super(RecordIdWritable.class);
}
public int compare(byte[] b1, int s1, int l1,
byte[] b2, int s2, int l2) {
// don't include the vint length in the comparison
int n1 = WritableUtils.decodeVIntSize(b1[s1]);
int n2 = WritableUtils.decodeVIntSize(b2[s2]);
return compareBytes(b1, s1+n1, l1-n1, b2, s2+n2, l2-n2);
}
}
static {
// register this comparator
WritableComparator.define(RecordIdWritable.class, new Comparator());
}
@Override
public void write(DataOutput out) throws IOException {
byte[] bytes = recordId.toBytes();
WritableUtils.writeVInt(out, bytes.length);
out.write(bytes);
}
@Override
public void readFields(DataInput in) throws IOException {
int length = WritableUtils.readVInt(in);
byte[] bytes = new byte[length];
in.readFully(bytes, 0, length);
this.recordId = ID_GENERATOR.fromBytes(bytes);
}
public RecordId getRecordId() {
return recordId;
}
public void setRecordId(RecordId recordId) {
this.recordId = recordId;
}
}