com.datasalt.pangool.io.BytesWritable.java Source code

Java tutorial

Introduction

Here is the source code for com.datasalt.pangool.io.BytesWritable.java

Source

/**
 * Copyright [2012] [Datasalt Systems S.L.]
 *
 * 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.
 */

/**
 * This file is modification of Hadoop {@link org.apache.hadoop.io.BytesWritable},
 * that was developed under the following license:
 *
 * 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 com.datasalt.pangool.io;

import org.apache.hadoop.io.*;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

/**
 * A byte sequence that is usable as a key or value.
 * It is resizable and distinguishes between the size of the seqeunce and
 * the current capacity. The hash function is the front of the md5 of the
 * buffer. The sort order is the same as memcmp. Uses a
 * variable length integer for serializing the size.
 */
public class BytesWritable extends BinaryComparable implements WritableComparable<BinaryComparable> {
    private static final byte[] EMPTY_BYTES = {};

    private int size;
    private byte[] bytes;

    /**
     * Create a zero-size sequence.
     */
    public BytesWritable() {
        this(EMPTY_BYTES);
    }

    /**
     * Create a BytesWritable using the byte array as the initial value.
     * @param bytes This array becomes the backing storage for the object.
     */
    public BytesWritable(byte[] bytes) {
        this.bytes = bytes;
        this.size = bytes.length;
    }

    /**
     * Get the data from the BytesWritable.
     * @return The data is only valid between 0 and getLength() - 1.
     */
    public byte[] getBytes() {
        return bytes;
    }

    /**
     * Get the current size of the buffer.
     */
    public int getLength() {
        return size;
    }

    /**
     * Change the size of the buffer. The values in the old range are preserved
     * and any new values are undefined. The capacity is changed if it is
     * necessary.
     * @param size The new number of bytes
     */
    public void setSize(int size) {
        if (size > getCapacity()) {
            setCapacity(size * 3 / 2);
        }
        this.size = size;
    }

    /**
     * Get the capacity, which is the maximum size that could handled without
     * resizing the backing storage.
     * @return The number of bytes
     */
    public int getCapacity() {
        return bytes.length;
    }

    /**
     * Change the capacity of the backing storage.
     * The data is preserved.
     * @param new_cap The new capacity in bytes.
     */
    public void setCapacity(int new_cap) {
        if (new_cap != getCapacity()) {
            byte[] new_data = new byte[new_cap];
            if (new_cap < size) {
                size = new_cap;
            }
            if (size != 0) {
                System.arraycopy(bytes, 0, new_data, 0, size);
            }
            bytes = new_data;
        }
    }

    /**
     * Set the BytesWritable to the contents of the given newData.
     * @param newData the value to set this BytesWritable to.
     */
    public void set(BytesWritable newData) {
        set(newData.bytes, 0, newData.size);
    }

    /**
     * Replaces the internal byte array by the given one.
     * The byte array can be bigger than the given size.
     */
    public void replace(byte[] newArray, int size) {
        bytes = newArray;
        this.size = size;
    }

    /**
     * Set the value to a copy of the given byte range
     * @param newData the new values to copy in
     * @param offset the offset in newData to start at
     * @param length the number of bytes to copy
     */
    public void set(byte[] newData, int offset, int length) {
        setSize(0);
        setSize(length);
        System.arraycopy(newData, offset, bytes, 0, size);
    }

    // inherit javadoc
    public void readFields(DataInput in) throws IOException {
        setSize(0); // clear the old data
        setSize(WritableUtils.readVInt(in));
        in.readFully(bytes, 0, size);
    }

    // inherit javadoc
    public void write(DataOutput out) throws IOException {
        WritableUtils.writeVInt(out, size);
        out.write(bytes, 0, size);
    }

    public int hashCode() {
        return super.hashCode();
    }

    /**
     * Are the two byte sequences equal?
     */
    public boolean equals(Object right_obj) {
        if (right_obj instanceof BytesWritable)
            return super.equals(right_obj);
        return false;
    }

    /**
     * Generate the stream of bytes as hex pairs separated by ' '.
     */
    public String toString() {
        StringBuffer sb = new StringBuffer(3 * size);
        for (int idx = 0; idx < size; idx++) {
            // if not the first, put a blank separator in
            if (idx != 0) {
                sb.append(' ');
            }
            String num = Integer.toHexString(0xff & bytes[idx]);
            // if it is only one digit, add a leading 0.
            if (num.length() < 2) {
                sb.append('0');
            }
            sb.append(num);
        }
        return sb.toString();
    }

    /** A Comparator optimized for BytesWritable. */
    public static class Comparator extends WritableComparator {
        public Comparator() {
            super(BytesWritable.class);
        }

        /**
         * Compare the buffers in serialized form.
         */
        public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
            int skip1 = WritableUtils.decodeVIntSize(b1[s1]);
            int skip2 = WritableUtils.decodeVIntSize(b1[s2]);
            return compareBytes(b1, s1 + skip1, l1 - skip1, b2, s2 + skip2, l2 - skip2);
        }
    }

    static { // register this comparator
        WritableComparator.define(BytesWritable.class, new Comparator());
    }

}