001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hbase.util; 020 021import org.apache.yetus.audience.InterfaceAudience; 022 023/** 024 * Lightweight, reusable class for specifying ranges of byte[]'s. 025 * <p> 026 * {@code ByteRange} maintains an underlying byte[] and a viewport into that 027 * byte[] as a range of bytes. The {@code ByteRange} is a mutable, reusable 028 * object, so the underlying byte[] can be modified after instantiation. This 029 * is done using the {@link #set(byte[])} and {@link #unset()} methods. Direct 030 * access to the byte[] is also available via {@link #getBytes()}. The viewport 031 * is defined by an {@code offset} into the byte[] and a {@code length}. The 032 * range of bytes is 0-indexed, and is accessed by index via the 033 * {@link #get(int)} and {@link #put(int, byte)} methods. 034 * </p> 035 * <p> 036 * This interface differs from ByteBuffer: 037 * </p> 038 * <ul> 039 * <li>On-heap bytes only</li> 040 * <li>Raw {@code byte} access only; does not encode other primitives.</li> 041 * <li>Implements {@code equals(Object)}, {@code #hashCode()}, and 042 * {@code #compareTo(ByteRange)} so that it can be used in standard java 043 * Collections. Comparison operations are lexicographic, which is native to 044 * HBase.</li> 045 * <li>Allows the addition of simple core methods like the deep and shallow 046 * copy methods.</li> 047 * <li>Can be reused in tight loops like a major compaction which can save 048 * significant amounts of garbage. (Without reuse, we throw off garbage like 049 * <a href="http://www.youtube.com/watch?v=lkmBH-MjZF4">this thing</a>.)</li> 050 * </ul> 051 * <p> 052 * Mutable, and always evaluates {@code #equals(Object)}, {@code #hashCode()}, 053 * and {@code #compareTo(ByteRange)} based on the current contents. 054 * </p> 055 * <p> 056 * Can contain convenience methods for comparing, printing, cloning, spawning 057 * new arrays, copying to other arrays, etc. Please place non-core methods into 058 * {@link ByteRangeUtils}. 059 * </p> 060 */ 061@InterfaceAudience.Public 062public interface ByteRange extends Comparable<ByteRange> { 063 064 /** 065 * The underlying byte[]. 066 */ 067 public byte[] getBytes(); 068 069 /** 070 * Nullifies this ByteRange. That is, it becomes a husk, being a range over 071 * no byte[] whatsoever. 072 * @return this 073 */ 074 public ByteRange unset(); 075 076 /** 077 * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to 078 * 0 and {@code length} is set to {@code capacity}. 079 * @param capacity the size of a new byte[]. 080 * @return this 081 */ 082 public ByteRange set(int capacity); 083 084 /** 085 * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to 086 * 0 and {@code length} is set to {@code bytes.length}. A null {@code bytes} 087 * IS supported, in which case this method will behave equivalently to 088 * {@link #unset()}. 089 * @param bytes the array to wrap. 090 * @return this 091 */ 092 public ByteRange set(byte[] bytes); 093 094 /** 095 * Reuse this {@code ByteRange} over a new byte[]. A null {@code bytes} IS 096 * supported, in which case this method will behave equivalently to 097 * {@link #unset()}, regardless of the values of {@code offset} and 098 * {@code length}. 099 * @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}