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