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 }