View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.util;
20  
21  import org.apache.hadoop.classification.InterfaceAudience;
22  import org.apache.hadoop.classification.InterfaceStability;
23  
24  /**
25   * Lightweight, reusable class for specifying ranges of byte[]'s.
26   * <p>
27   * {@code ByteRange} maintains an underlying byte[] and a viewport into that
28   * byte[] as a range of bytes. The {@code ByteRange} is a mutable, reusable
29   * object, so the underlying byte[] can be modified after instantiation. This
30   * is done using the {@link #set(byte[])} and {@link #unset()} methods. Direct
31   * access to the byte[] is also available via {@link #getBytes()}. The viewport
32   * is defined by an {@code offset} into the byte[] and a {@code length}. The
33   * range of bytes is 0-indexed, and is accessed by index via the
34   * {@link #get(int)} and {@link #put(int, byte)} methods.
35   * </p>
36   * <p>
37   * This interface differs from ByteBuffer:
38   * <li>On-heap bytes only</li>
39   * <li>Raw {@code byte} access only; does not encode other primitives.</li>
40   * <li>Implements {@code equals(Object)}, {@code #hashCode()}, and
41   * {@code #compareTo(ByteRange)} so that it can be used in standard java
42   * Collections. Comparison operations are lexicographic, which is native to
43   * HBase.</li>
44   * <li>Allows the addition of simple core methods like the deep and shallow
45   * copy methods.</li>
46   * <li>Can be reused in tight loops like a major compaction which can save
47   * significant amounts of garbage. (Without reuse, we throw off garbage like
48   * <a href="http://www.youtube.com/watch?v=lkmBH-MjZF4">this thing</a>.)</li>
49   * </p>
50   * <p>
51   * Mutable, and always evaluates {@code #equals(Object)}, {@code #hashCode()},
52   * and {@code #compareTo(ByteRange)} based on the current contents.
53   * </p>
54   * <p>
55   * Can contain convenience methods for comparing, printing, cloning, spawning
56   * new arrays, copying to other arrays, etc. Please place non-core methods into
57   * {@link ByteRangeUtils}.
58   * </p>
59   */
60  @InterfaceAudience.Public
61  @InterfaceStability.Evolving
62  public interface ByteRange extends Comparable<ByteRange> {
63  
64    /**
65     * The underlying byte[].
66     */
67    public byte[] getBytes();
68  
69    /**
70     * Nullifies this ByteRange. That is, it becomes a husk, being a range over
71     * no byte[] whatsoever.
72     * @return this
73     */
74    public ByteRange unset();
75  
76    /**
77     * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to
78     * 0 and {@code length} is set to {@code capacity}.
79     * @param capacity the size of a new byte[].
80     * @return this
81     */
82    public ByteRange set(int capacity);
83  
84    /**
85     * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to
86     * 0 and {@code length} is set to {@code bytes.length}. A null {@code bytes}
87     * IS supported, in which case this method will behave equivalently to
88     * {@link #unset()}.
89     * @param bytes the array to wrap.
90     * @return this
91     */
92    public ByteRange set(byte[] bytes);
93  
94    /**
95     * Reuse this {@code ByteRange} over a new byte[]. A null {@code bytes} IS
96     * supported, in which case this method will behave equivalently to
97     * {@link #unset()}, regardless of the values of {@code offset} and
98     * {@code length}.
99     * @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 }