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 }