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 * <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
307 }