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.hbase.classification.InterfaceAudience;
22  import org.apache.hadoop.hbase.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   * </p>
39   * <ul>
40   * <li>On-heap bytes only</li>
41   * <li>Raw {@code byte} access only; does not encode other primitives.</li>
42   * <li>Implements {@code equals(Object)}, {@code #hashCode()}, and
43   * {@code #compareTo(ByteRange)} so that it can be used in standard java
44   * Collections. Comparison operations are lexicographic, which is native to
45   * HBase.</li>
46   * <li>Allows the addition of simple core methods like the deep and shallow
47   * copy methods.</li>
48   * <li>Can be reused in tight loops like a major compaction which can save
49   * significant amounts of garbage. (Without reuse, we throw off garbage like
50   * <a href="http://www.youtube.com/watch?v=lkmBH-MjZF4">this thing</a>.)</li>
51   * </ul>
52   * <p>
53   * Mutable, and always evaluates {@code #equals(Object)}, {@code #hashCode()},
54   * and {@code #compareTo(ByteRange)} based on the current contents.
55   * </p>
56   * <p>
57   * Can contain convenience methods for comparing, printing, cloning, spawning
58   * new arrays, copying to other arrays, etc. Please place non-core methods into
59   * {@link ByteRangeUtils}.
60   * </p>
61   */
62  @InterfaceAudience.Public
63  @InterfaceStability.Evolving
64  public interface ByteRange extends Comparable<ByteRange> {
65  
66    /**
67     * The underlying byte[].
68     */
69    public byte[] getBytes();
70  
71    /**
72     * Nullifies this ByteRange. That is, it becomes a husk, being a range over
73     * no byte[] whatsoever.
74     * @return this
75     */
76    public ByteRange unset();
77  
78    /**
79     * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to
80     * 0 and {@code length} is set to {@code capacity}.
81     * @param capacity the size of a new byte[].
82     * @return this
83     */
84    public ByteRange set(int capacity);
85  
86    /**
87     * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to
88     * 0 and {@code length} is set to {@code bytes.length}. A null {@code bytes}
89     * IS supported, in which case this method will behave equivalently to
90     * {@link #unset()}.
91     * @param bytes the array to wrap.
92     * @return this
93     */
94    public ByteRange set(byte[] bytes);
95  
96    /**
97     * Reuse this {@code ByteRange} over a new byte[]. A null {@code bytes} IS
98     * supported, in which case this method will behave equivalently to
99     * {@link #unset()}, regardless of the values of {@code offset} and
100    * {@code length}.
101    * @param bytes The array to wrap.
102    * @param offset The offset into {@code bytes} considered the beginning of
103    *            this range.
104    * @param length The length of this range.
105    * @return this.
106    */
107   public ByteRange set(byte[] bytes, int offset, int length);
108 
109   /**
110    * The offset, the index into the underlying byte[] at which this range
111    * begins.
112    * @see #getBytes()
113    */
114   public int getOffset();
115 
116   /**
117    * Update the beginning of this range. {@code offset + length} may not be
118    * greater than {@code bytes.length}.
119    * @param offset the new start of this range.
120    * @return this.
121    */
122   public ByteRange setOffset(int offset);
123 
124   /**
125    * The length of the range.
126    */
127   public int getLength();
128 
129   /**
130    * Update the length of this range. {@code offset + length} should not be
131    * greater than {@code bytes.length}.
132    * @param length The new length of this range.
133    * @return this.
134    */
135   public ByteRange setLength(int length);
136 
137   /**
138    * @return true when this range is of zero length, false otherwise.
139    */
140   public boolean isEmpty();
141 
142   /**
143    * Retrieve the byte at {@code index}.
144    * @param index zero-based index into this range.
145    * @return single byte at index.
146    */
147   public byte get(int index);
148 
149   /**
150    * Retrieve the short value at {@code index}
151    * @param index zero-based index into this range
152    * @return the short value at {@code index}
153    */
154   public short getShort(int index);
155 
156   /**
157    * Retrieve the int value at {@code index}
158    * @param index zero-based index into this range
159    * @return the int value at {@code index}
160    */
161   public int getInt(int index);
162 
163   /**
164    * Retrieve the long value at {@code index}
165    * @param index zero-based index into this range
166    * @return the long value at {@code index}
167    */
168   public long getLong(int index);
169 
170   /**
171    * Retrieve the long value at {@code index} which is stored as VLong
172    * @param index zero-based index into this range
173    * @return the long value at {@code index} which is stored as VLong
174    */
175   public long getVLong(int index);
176 
177   /**
178    * Fill {@code dst} with bytes from the range, starting from {@code index}.
179    * @param index zero-based index into this range.
180    * @param dst the destination of the copy.
181    * @return this.
182    */
183   public ByteRange get(int index, byte[] dst);
184 
185   /**
186    * Fill {@code dst} with bytes from the range, starting from {@code index}.
187    * {@code length} bytes are copied into {@code dst}, starting at {@code offset}.
188    * @param index zero-based index into this range.
189    * @param dst the destination of the copy.
190    * @param offset the offset into {@code dst} to start the copy.
191    * @param length the number of bytes to copy into {@code dst}.
192    * @return this.
193    */
194   public ByteRange get(int index, byte[] dst, int offset, int length);
195 
196   /**
197    * Store {@code val} at {@code index}.
198    * @param index the index in the range where {@code val} is stored.
199    * @param val the value to store.
200    * @return this.
201    */
202   public ByteRange put(int index, byte val);
203 
204   /**
205    * Store the short value at {@code index}
206    * @param index the index in the range where {@code val} is stored
207    * @param val the value to store
208    * @return this
209    */
210   public ByteRange putShort(int index, short val);
211 
212   /**
213    * Store the int value at {@code index}
214    * @param index the index in the range where {@code val} is stored
215    * @param val the value to store
216    * @return this
217    */
218   public ByteRange putInt(int index, int val);
219 
220   /**
221    * Store the long value at {@code index}
222    * @param index the index in the range where {@code val} is stored
223    * @param val the value to store
224    * @return this
225    */
226   public ByteRange putLong(int index, long val);
227 
228   /**
229    * Store the long value at {@code index} as a VLong
230    * @param index the index in the range where {@code val} is stored
231    * @param val the value to store
232    * @return number of bytes written
233    */
234   public int putVLong(int index, long val);
235 
236   /**
237    * Store {@code val} at {@code index}.
238    * @param index the index in the range where {@code val} is stored.
239    * @param val the value to store.
240    * @return this.
241    */
242   public ByteRange put(int index, byte[] val);
243 
244   /**
245    * Store {@code length} bytes from {@code val} into this range, starting at
246    * {@code index}. Bytes from {@code val} are copied starting at {@code offset}
247    * into the range.
248    * @param index position in this range to start the copy.
249    * @param val the value to store.
250    * @param offset the offset in {@code val} from which to start copying.
251    * @param length the number of bytes to copy from {@code val}.
252    * @return this.
253    */
254   public ByteRange put(int index, byte[] val, int offset, int length);
255 
256   /**
257    * Instantiate a new byte[] with exact length, which is at least 24 bytes +
258    * length. Copy the contents of this range into it.
259    * @return The newly cloned byte[].
260    */
261   public byte[] deepCopyToNewArray();
262 
263   /**
264    * Create a new {@code ByteRange} with new backing byte[] containing a copy
265    * of the content from {@code this} range's window.
266    * @return Deep copy
267    */
268   public ByteRange deepCopy();
269 
270   /**
271    * Wrapper for System.arraycopy. Copy the contents of this range into the
272    * provided array.
273    * @param destination Copy to this array
274    * @param destinationOffset First index in the destination array.
275    */
276   public void deepCopyTo(byte[] destination, int destinationOffset);
277 
278   /**
279    * Wrapper for System.arraycopy. Copy the contents of this range into the
280    * provided array.
281    * @param innerOffset Start copying from this index in this source
282    *          ByteRange. First byte copied is bytes[offset + innerOffset]
283    * @param copyLength Copy this many bytes
284    * @param destination Copy to this array
285    * @param destinationOffset First index in the destination array.
286    */
287   public void deepCopySubRangeTo(int innerOffset, int copyLength, byte[] destination,
288       int destinationOffset);
289 
290   /**
291    * Create a new {@code ByteRange} that points at this range's byte[].
292    * Modifying the shallowCopy will modify the bytes in this range's array.
293    * Pass over the hash code if it is already cached.
294    * @return new {@code ByteRange} object referencing this range's byte[].
295    */
296   public ByteRange shallowCopy();
297 
298   /**
299    * Create a new {@code ByteRange} that points at this range's byte[]. The new
300    * range can have different values for offset and length, but modifying the
301    * shallowCopy will modify the bytes in this range's array. Pass over the
302    * hash code if it is already cached.
303    * @param innerOffset First byte of clone will be this.offset + copyOffset.
304    * @param copyLength Number of bytes in the clone.
305    * @return new {@code ByteRange} object referencing this range's byte[].
306    */
307   public ByteRange shallowCopySubRange(int innerOffset, int copyLength);
308 
309 }