001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.hbase.util;
020
021import org.apache.yetus.audience.InterfaceAudience;
022
023/**
024 * Lightweight, reusable class for specifying ranges of byte[]'s.
025 * <p>
026 * {@code ByteRange} maintains an underlying byte[] and a viewport into that
027 * byte[] as a range of bytes. The {@code ByteRange} is a mutable, reusable
028 * object, so the underlying byte[] can be modified after instantiation. This
029 * is done using the {@link #set(byte[])} and {@link #unset()} methods. Direct
030 * access to the byte[] is also available via {@link #getBytes()}. The viewport
031 * is defined by an {@code offset} into the byte[] and a {@code length}. The
032 * range of bytes is 0-indexed, and is accessed by index via the
033 * {@link #get(int)} and {@link #put(int, byte)} methods.
034 * </p>
035 * <p>
036 * This interface differs from ByteBuffer:
037 * </p>
038 * <ul>
039 * <li>On-heap bytes only</li>
040 * <li>Raw {@code byte} access only; does not encode other primitives.</li>
041 * <li>Implements {@code equals(Object)}, {@code #hashCode()}, and
042 * {@code #compareTo(ByteRange)} so that it can be used in standard java
043 * Collections. Comparison operations are lexicographic, which is native to
044 * HBase.</li>
045 * <li>Allows the addition of simple core methods like the deep and shallow
046 * copy methods.</li>
047 * <li>Can be reused in tight loops like a major compaction which can save
048 * significant amounts of garbage. (Without reuse, we throw off garbage like
049 * <a href="http://www.youtube.com/watch?v=lkmBH-MjZF4">this thing</a>.)</li>
050 * </ul>
051 * <p>
052 * Mutable, and always evaluates {@code #equals(Object)}, {@code #hashCode()},
053 * and {@code #compareTo(ByteRange)} based on the current contents.
054 * </p>
055 * <p>
056 * Can contain convenience methods for comparing, printing, cloning, spawning
057 * new arrays, copying to other arrays, etc. Please place non-core methods into
058 * {@link ByteRangeUtils}.
059 * </p>
060 */
061@InterfaceAudience.Public
062public interface ByteRange extends Comparable<ByteRange> {
063
064  /**
065   * The underlying byte[].
066   */
067  public byte[] getBytes();
068
069  /**
070   * Nullifies this ByteRange. That is, it becomes a husk, being a range over
071   * no byte[] whatsoever.
072   * @return this
073   */
074  public ByteRange unset();
075
076  /**
077   * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to
078   * 0 and {@code length} is set to {@code capacity}.
079   * @param capacity the size of a new byte[].
080   * @return this
081   */
082  public ByteRange set(int capacity);
083
084  /**
085   * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to
086   * 0 and {@code length} is set to {@code bytes.length}. A null {@code bytes}
087   * IS supported, in which case this method will behave equivalently to
088   * {@link #unset()}.
089   * @param bytes the array to wrap.
090   * @return this
091   */
092  public ByteRange set(byte[] bytes);
093
094  /**
095   * Reuse this {@code ByteRange} over a new byte[]. A null {@code bytes} IS
096   * supported, in which case this method will behave equivalently to
097   * {@link #unset()}, regardless of the values of {@code offset} and
098   * {@code length}.
099   * @param bytes The array to wrap.
100   * @param offset The offset into {@code bytes} considered the beginning of
101   *            this range.
102   * @param length The length of this range.
103   * @return this.
104   */
105  public ByteRange set(byte[] bytes, int offset, int length);
106
107  /**
108   * The offset, the index into the underlying byte[] at which this range
109   * begins.
110   * @see #getBytes()
111   */
112  public int getOffset();
113
114  /**
115   * Update the beginning of this range. {@code offset + length} may not be
116   * greater than {@code bytes.length}.
117   * @param offset the new start of this range.
118   * @return this.
119   */
120  public ByteRange setOffset(int offset);
121
122  /**
123   * The length of the range.
124   */
125  public int getLength();
126
127  /**
128   * Update the length of this range. {@code offset + length} should not be
129   * greater than {@code bytes.length}.
130   * @param length The new length of this range.
131   * @return this.
132   */
133  public ByteRange setLength(int length);
134
135  /**
136   * @return true when this range is of zero length, false otherwise.
137   */
138  public boolean isEmpty();
139
140  /**
141   * Retrieve the byte at {@code index}.
142   * @param index zero-based index into this range.
143   * @return single byte at index.
144   */
145  public byte get(int index);
146
147  /**
148   * Retrieve the short value at {@code index}
149   * @param index zero-based index into this range
150   * @return the short value at {@code index}
151   */
152  public short getShort(int index);
153
154  /**
155   * Retrieve the int value at {@code index}
156   * @param index zero-based index into this range
157   * @return the int value at {@code index}
158   */
159  public int getInt(int index);
160
161  /**
162   * Retrieve the long value at {@code index}
163   * @param index zero-based index into this range
164   * @return the long value at {@code index}
165   */
166  public long getLong(int index);
167
168  /**
169   * Retrieve the long value at {@code index} which is stored as VLong
170   * @param index zero-based index into this range
171   * @return the long value at {@code index} which is stored as VLong
172   */
173  public long getVLong(int index);
174
175  /**
176   * Fill {@code dst} with bytes from the range, starting from {@code index}.
177   * @param index zero-based index into this range.
178   * @param dst the destination of the copy.
179   * @return this.
180   */
181  public ByteRange get(int index, byte[] dst);
182
183  /**
184   * Fill {@code dst} with bytes from the range, starting from {@code index}.
185   * {@code length} bytes are copied into {@code dst}, starting at {@code offset}.
186   * @param index zero-based index into this range.
187   * @param dst the destination of the copy.
188   * @param offset the offset into {@code dst} to start the copy.
189   * @param length the number of bytes to copy into {@code dst}.
190   * @return this.
191   */
192  public ByteRange get(int index, byte[] dst, int offset, int length);
193
194  /**
195   * Store {@code val} at {@code index}.
196   * @param index the index in the range where {@code val} is stored.
197   * @param val the value to store.
198   * @return this.
199   */
200  public ByteRange put(int index, byte val);
201
202  /**
203   * Store the short value at {@code index}
204   * @param index the index in the range where {@code val} is stored
205   * @param val the value to store
206   * @return this
207   */
208  public ByteRange putShort(int index, short val);
209
210  /**
211   * Store the int value at {@code index}
212   * @param index the index in the range where {@code val} is stored
213   * @param val the value to store
214   * @return this
215   */
216  public ByteRange putInt(int index, int val);
217
218  /**
219   * Store the long value at {@code index}
220   * @param index the index in the range where {@code val} is stored
221   * @param val the value to store
222   * @return this
223   */
224  public ByteRange putLong(int index, long val);
225
226  /**
227   * Store the long value at {@code index} as a VLong
228   * @param index the index in the range where {@code val} is stored
229   * @param val the value to store
230   * @return number of bytes written
231   */
232  public int putVLong(int index, long val);
233
234  /**
235   * Store {@code val} at {@code index}.
236   * @param index the index in the range where {@code val} is stored.
237   * @param val the value to store.
238   * @return this.
239   */
240  public ByteRange put(int index, byte[] val);
241
242  /**
243   * Store {@code length} bytes from {@code val} into this range, starting at
244   * {@code index}. Bytes from {@code val} are copied starting at {@code offset}
245   * into the range.
246   * @param index position in this range to start the copy.
247   * @param val the value to store.
248   * @param offset the offset in {@code val} from which to start copying.
249   * @param length the number of bytes to copy from {@code val}.
250   * @return this.
251   */
252  public ByteRange put(int index, byte[] val, int offset, int length);
253
254  /**
255   * Instantiate a new byte[] with exact length, which is at least 24 bytes +
256   * length. Copy the contents of this range into it.
257   * @return The newly cloned byte[].
258   */
259  public byte[] deepCopyToNewArray();
260
261  /**
262   * Create a new {@code ByteRange} with new backing byte[] containing a copy
263   * of the content from {@code this} range's window.
264   * @return Deep copy
265   */
266  public ByteRange deepCopy();
267
268  /**
269   * Wrapper for System.arraycopy. Copy the contents of this range into the
270   * provided array.
271   * @param destination Copy to this array
272   * @param destinationOffset First index in the destination array.
273   */
274  public void deepCopyTo(byte[] destination, int destinationOffset);
275
276  /**
277   * Wrapper for System.arraycopy. Copy the contents of this range into the
278   * provided array.
279   * @param innerOffset Start copying from this index in this source
280   *          ByteRange. First byte copied is bytes[offset + innerOffset]
281   * @param copyLength Copy this many bytes
282   * @param destination Copy to this array
283   * @param destinationOffset First index in the destination array.
284   */
285  public void deepCopySubRangeTo(int innerOffset, int copyLength, byte[] destination,
286      int destinationOffset);
287
288  /**
289   * Create a new {@code ByteRange} that points at this range's byte[].
290   * Modifying the shallowCopy will modify the bytes in this range's array.
291   * Pass over the hash code if it is already cached.
292   * @return new {@code ByteRange} object referencing this range's byte[].
293   */
294  public ByteRange shallowCopy();
295
296  /**
297   * Create a new {@code ByteRange} that points at this range's byte[]. The new
298   * range can have different values for offset and length, but modifying the
299   * shallowCopy will modify the bytes in this range's array. Pass over the
300   * hash code if it is already cached.
301   * @param innerOffset First byte of clone will be this.offset + copyOffset.
302   * @param copyLength Number of bytes in the clone.
303   * @return new {@code ByteRange} object referencing this range's byte[].
304   */
305  public ByteRange shallowCopySubRange(int innerOffset, int copyLength);
306
307}