org.apache.hadoop.hbase.util.ByteRange Maven / Gradle / Ivy
/*
* 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.hadoop.hbase.util;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
/**
* Lightweight, reusable class for specifying ranges of byte[]'s.
*
* {@code ByteRange} maintains an underlying byte[] and a viewport into that
* byte[] as a range of bytes. The {@code ByteRange} is a mutable, reusable
* object, so the underlying byte[] can be modified after instantiation. This
* is done using the {@link #set(byte[])} and {@link #unset()} methods. Direct
* access to the byte[] is also available via {@link #getBytes()}. The viewport
* is defined by an {@code offset} into the byte[] and a {@code length}. The
* range of bytes is 0-indexed, and is accessed by index via the
* {@link #get(int)} and {@link #put(int, byte)} methods.
*
*
* This interface differs from ByteBuffer:
*
*
* - On-heap bytes only
* - Raw {@code byte} access only; does not encode other primitives.
* - Implements {@code equals(Object)}, {@code #hashCode()}, and
* {@code #compareTo(ByteRange)} so that it can be used in standard java
* Collections. Comparison operations are lexicographic, which is native to
* HBase.
* - Allows the addition of simple core methods like the deep and shallow
* copy methods.
* - Can be reused in tight loops like a major compaction which can save
* significant amounts of garbage. (Without reuse, we throw off garbage like
* this thing.)
*
*
* Mutable, and always evaluates {@code #equals(Object)}, {@code #hashCode()},
* and {@code #compareTo(ByteRange)} based on the current contents.
*
*
* Can contain convenience methods for comparing, printing, cloning, spawning
* new arrays, copying to other arrays, etc. Please place non-core methods into
* {@link ByteRangeUtils}.
*
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
public interface ByteRange extends Comparable {
/**
* The underlying byte[].
*/
public byte[] getBytes();
/**
* Nullifies this ByteRange. That is, it becomes a husk, being a range over
* no byte[] whatsoever.
* @return this
*/
public ByteRange unset();
/**
* Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to
* 0 and {@code length} is set to {@code capacity}.
* @param capacity the size of a new byte[].
* @return this
*/
public ByteRange set(int capacity);
/**
* Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to
* 0 and {@code length} is set to {@code bytes.length}. A null {@code bytes}
* IS supported, in which case this method will behave equivalently to
* {@link #unset()}.
* @param bytes the array to wrap.
* @return this
*/
public ByteRange set(byte[] bytes);
/**
* Reuse this {@code ByteRange} over a new byte[]. A null {@code bytes} IS
* supported, in which case this method will behave equivalently to
* {@link #unset()}, regardless of the values of {@code offset} and
* {@code length}.
* @param bytes The array to wrap.
* @param offset The offset into {@code bytes} considered the beginning of
* this range.
* @param length The length of this range.
* @return this.
*/
public ByteRange set(byte[] bytes, int offset, int length);
/**
* The offset, the index into the underlying byte[] at which this range
* begins.
* @see #getBytes()
*/
public int getOffset();
/**
* Update the beginning of this range. {@code offset + length} may not be
* greater than {@code bytes.length}.
* @param offset the new start of this range.
* @return this.
*/
public ByteRange setOffset(int offset);
/**
* The length of the range.
*/
public int getLength();
/**
* Update the length of this range. {@code offset + length} should not be
* greater than {@code bytes.length}.
* @param length The new length of this range.
* @return this.
*/
public ByteRange setLength(int length);
/**
* @return true when this range is of zero length, false otherwise.
*/
public boolean isEmpty();
/**
* Retrieve the byte at {@code index}.
* @param index zero-based index into this range.
* @return single byte at index.
*/
public byte get(int index);
/**
* Retrieve the short value at {@code index}
* @param index zero-based index into this range
* @return the short value at {@code index}
*/
public short getShort(int index);
/**
* Retrieve the int value at {@code index}
* @param index zero-based index into this range
* @return the int value at {@code index}
*/
public int getInt(int index);
/**
* Retrieve the long value at {@code index}
* @param index zero-based index into this range
* @return the long value at {@code index}
*/
public long getLong(int index);
/**
* Retrieve the long value at {@code index} which is stored as VLong
* @param index zero-based index into this range
* @return the long value at {@code index} which is stored as VLong
*/
public long getVLong(int index);
/**
* Fill {@code dst} with bytes from the range, starting from {@code index}.
* @param index zero-based index into this range.
* @param dst the destination of the copy.
* @return this.
*/
public ByteRange get(int index, byte[] dst);
/**
* Fill {@code dst} with bytes from the range, starting from {@code index}.
* {@code length} bytes are copied into {@code dst}, starting at {@code offset}.
* @param index zero-based index into this range.
* @param dst the destination of the copy.
* @param offset the offset into {@code dst} to start the copy.
* @param length the number of bytes to copy into {@code dst}.
* @return this.
*/
public ByteRange get(int index, byte[] dst, int offset, int length);
/**
* Store {@code val} at {@code index}.
* @param index the index in the range where {@code val} is stored.
* @param val the value to store.
* @return this.
*/
public ByteRange put(int index, byte val);
/**
* Store the short value at {@code index}
* @param index the index in the range where {@code val} is stored
* @param val the value to store
* @return this
*/
public ByteRange putShort(int index, short val);
/**
* Store the int value at {@code index}
* @param index the index in the range where {@code val} is stored
* @param val the value to store
* @return this
*/
public ByteRange putInt(int index, int val);
/**
* Store the long value at {@code index}
* @param index the index in the range where {@code val} is stored
* @param val the value to store
* @return this
*/
public ByteRange putLong(int index, long val);
/**
* Store the long value at {@code index} as a VLong
* @param index the index in the range where {@code val} is stored
* @param val the value to store
* @return number of bytes written
*/
public int putVLong(int index, long val);
/**
* Store {@code val} at {@code index}.
* @param index the index in the range where {@code val} is stored.
* @param val the value to store.
* @return this.
*/
public ByteRange put(int index, byte[] val);
/**
* Store {@code length} bytes from {@code val} into this range, starting at
* {@code index}. Bytes from {@code val} are copied starting at {@code offset}
* into the range.
* @param index position in this range to start the copy.
* @param val the value to store.
* @param offset the offset in {@code val} from which to start copying.
* @param length the number of bytes to copy from {@code val}.
* @return this.
*/
public ByteRange put(int index, byte[] val, int offset, int length);
/**
* Instantiate a new byte[] with exact length, which is at least 24 bytes +
* length. Copy the contents of this range into it.
* @return The newly cloned byte[].
*/
public byte[] deepCopyToNewArray();
/**
* Create a new {@code ByteRange} with new backing byte[] containing a copy
* of the content from {@code this} range's window.
* @return Deep copy
*/
public ByteRange deepCopy();
/**
* Wrapper for System.arraycopy. Copy the contents of this range into the
* provided array.
* @param destination Copy to this array
* @param destinationOffset First index in the destination array.
*/
public void deepCopyTo(byte[] destination, int destinationOffset);
/**
* Wrapper for System.arraycopy. Copy the contents of this range into the
* provided array.
* @param innerOffset Start copying from this index in this source
* ByteRange. First byte copied is bytes[offset + innerOffset]
* @param copyLength Copy this many bytes
* @param destination Copy to this array
* @param destinationOffset First index in the destination array.
*/
public void deepCopySubRangeTo(int innerOffset, int copyLength, byte[] destination,
int destinationOffset);
/**
* Create a new {@code ByteRange} that points at this range's byte[].
* Modifying the shallowCopy will modify the bytes in this range's array.
* Pass over the hash code if it is already cached.
* @return new {@code ByteRange} object referencing this range's byte[].
*/
public ByteRange shallowCopy();
/**
* Create a new {@code ByteRange} that points at this range's byte[]. The new
* range can have different values for offset and length, but modifying the
* shallowCopy will modify the bytes in this range's array. Pass over the
* hash code if it is already cached.
* @param innerOffset First byte of clone will be this.offset + copyOffset.
* @param copyLength Number of bytes in the clone.
* @return new {@code ByteRange} object referencing this range's byte[].
*/
public ByteRange shallowCopySubRange(int innerOffset, int copyLength);
}