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 */ 018package org.apache.hadoop.hbase.util; 019 020import org.apache.yetus.audience.InterfaceAudience; 021 022/** 023 * Lightweight, reusable class for specifying ranges of byte[]'s. 024 * <p> 025 * {@code ByteRange} maintains an underlying byte[] and a viewport into that byte[] as a range of 026 * bytes. The {@code ByteRange} is a mutable, reusable object, so the underlying byte[] can be 027 * modified after instantiation. This is done using the {@link #set(byte[])} and {@link #unset()} 028 * methods. Direct access to the byte[] is also available via {@link #getBytes()}. The viewport is 029 * defined by an {@code offset} into the byte[] and a {@code length}. The range of bytes is 030 * 0-indexed, and is accessed by index via the {@link #get(int)} and {@link #put(int, byte)} 031 * methods. 032 * </p> 033 * <p> 034 * This interface differs from ByteBuffer: 035 * </p> 036 * <ul> 037 * <li>On-heap bytes only</li> 038 * <li>Raw {@code byte} access only; does not encode other primitives.</li> 039 * <li>Implements {@code equals(Object)}, {@code #hashCode()}, and {@code #compareTo(ByteRange)} so 040 * that it can be used in standard java Collections. Comparison operations are lexicographic, which 041 * is native to HBase.</li> 042 * <li>Allows the addition of simple core methods like the deep and shallow copy methods.</li> 043 * <li>Can be reused in tight loops like a major compaction which can save significant amounts of 044 * garbage. (Without reuse, we throw off garbage like 045 * <a href="http://www.youtube.com/watch?v=lkmBH-MjZF4">this thing</a>.)</li> 046 * </ul> 047 * <p> 048 * Mutable, and always evaluates {@code #equals(Object)}, {@code #hashCode()}, and 049 * {@code #compareTo(ByteRange)} based on the current contents. 050 * </p> 051 * <p> 052 * Can contain convenience methods for comparing, printing, cloning, spawning new arrays, copying to 053 * other arrays, etc. Please place non-core methods into {@link ByteRangeUtils}. 054 * </p> 055 */ 056@InterfaceAudience.Public 057public interface ByteRange extends Comparable<ByteRange> { 058 059 /** 060 * The underlying byte[]. 061 */ 062 public byte[] getBytes(); 063 064 /** 065 * Nullifies this ByteRange. That is, it becomes a husk, being a range over no byte[] whatsoever. 066 * n 067 */ 068 public ByteRange unset(); 069 070 /** 071 * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to 0 and {@code length} 072 * is set to {@code capacity}. 073 * @param capacity the size of a new byte[]. n 074 */ 075 public ByteRange set(int capacity); 076 077 /** 078 * Reuse this {@code ByteRange} over a new byte[]. {@code offset} is set to 0 and {@code length} 079 * is set to {@code bytes.length}. A null {@code bytes} IS supported, in which case this method 080 * will behave equivalently to {@link #unset()}. 081 * @param bytes the array to wrap. n 082 */ 083 public ByteRange set(byte[] bytes); 084 085 /** 086 * Reuse this {@code ByteRange} over a new byte[]. A null {@code bytes} IS supported, in which 087 * case this method will behave equivalently to {@link #unset()}, regardless of the values of 088 * {@code offset} and {@code length}. 089 * @param bytes The array to wrap. 090 * @param offset The offset into {@code bytes} considered the beginning of this range. 091 * @param length The length of this range. 092 * @return this. 093 */ 094 public ByteRange set(byte[] bytes, int offset, int length); 095 096 /** 097 * The offset, the index into the underlying byte[] at which this range begins. 098 * @see #getBytes() 099 */ 100 public int getOffset(); 101 102 /** 103 * Update the beginning of this range. {@code offset + length} may not be greater than 104 * {@code bytes.length}. 105 * @param offset the new start of this range. 106 * @return this. 107 */ 108 public ByteRange setOffset(int offset); 109 110 /** 111 * The length of the range. 112 */ 113 public int getLength(); 114 115 /** 116 * Update the length of this range. {@code offset + length} should not be greater than 117 * {@code bytes.length}. 118 * @param length The new length of this range. 119 * @return this. 120 */ 121 public ByteRange setLength(int length); 122 123 /** 124 * @return true when this range is of zero length, false otherwise. 125 */ 126 public boolean isEmpty(); 127 128 /** 129 * Retrieve the byte at {@code index}. 130 * @param index zero-based index into this range. 131 * @return single byte at index. 132 */ 133 public byte get(int index); 134 135 /** 136 * Retrieve the short value at {@code index} 137 * @param index zero-based index into this range 138 * @return the short value at {@code index} 139 */ 140 public short getShort(int index); 141 142 /** 143 * Retrieve the int value at {@code index} 144 * @param index zero-based index into this range 145 * @return the int value at {@code index} 146 */ 147 public int getInt(int index); 148 149 /** 150 * Retrieve the long value at {@code index} 151 * @param index zero-based index into this range 152 * @return the long value at {@code index} 153 */ 154 public long getLong(int index); 155 156 /** 157 * Retrieve the long value at {@code index} which is stored as VLong 158 * @param index zero-based index into this range 159 * @return the long value at {@code index} which is stored as VLong 160 */ 161 public long getVLong(int index); 162 163 /** 164 * Fill {@code dst} with bytes from the range, starting from {@code index}. 165 * @param index zero-based index into this range. 166 * @param dst the destination of the copy. 167 * @return this. 168 */ 169 public ByteRange get(int index, byte[] dst); 170 171 /** 172 * Fill {@code dst} with bytes from the range, starting from {@code index}. {@code length} bytes 173 * are copied into {@code dst}, starting at {@code offset}. 174 * @param index zero-based index into this range. 175 * @param dst the destination of the copy. 176 * @param offset the offset into {@code dst} to start the copy. 177 * @param length the number of bytes to copy into {@code dst}. 178 * @return this. 179 */ 180 public ByteRange get(int index, byte[] dst, int offset, int length); 181 182 /** 183 * Store {@code val} at {@code index}. 184 * @param index the index in the range where {@code val} is stored. 185 * @param val the value to store. 186 * @return this. 187 */ 188 public ByteRange put(int index, byte val); 189 190 /** 191 * Store the short value at {@code index} 192 * @param index the index in the range where {@code val} is stored 193 * @param val the value to store n 194 */ 195 public ByteRange putShort(int index, short val); 196 197 /** 198 * Store the int value at {@code index} 199 * @param index the index in the range where {@code val} is stored 200 * @param val the value to store n 201 */ 202 public ByteRange putInt(int index, int val); 203 204 /** 205 * Store the long value at {@code index} 206 * @param index the index in the range where {@code val} is stored 207 * @param val the value to store n 208 */ 209 public ByteRange putLong(int index, long val); 210 211 /** 212 * Store the long value at {@code index} as a VLong 213 * @param index the index in the range where {@code val} is stored 214 * @param val the value to store 215 * @return number of bytes written 216 */ 217 public int putVLong(int index, long val); 218 219 /** 220 * Store {@code val} at {@code index}. 221 * @param index the index in the range where {@code val} is stored. 222 * @param val the value to store. 223 * @return this. 224 */ 225 public ByteRange put(int index, byte[] val); 226 227 /** 228 * Store {@code length} bytes from {@code val} into this range, starting at {@code index}. Bytes 229 * from {@code val} are copied starting at {@code offset} into the range. 230 * @param index position in this range to start the copy. 231 * @param val the value to store. 232 * @param offset the offset in {@code val} from which to start copying. 233 * @param length the number of bytes to copy from {@code val}. 234 * @return this. 235 */ 236 public ByteRange put(int index, byte[] val, int offset, int length); 237 238 /** 239 * Instantiate a new byte[] with exact length, which is at least 24 bytes + length. Copy the 240 * contents of this range into it. 241 * @return The newly cloned byte[]. 242 */ 243 public byte[] deepCopyToNewArray(); 244 245 /** 246 * Create a new {@code ByteRange} with new backing byte[] containing a copy of the content from 247 * {@code this} range's window. 248 * @return Deep copy 249 */ 250 public ByteRange deepCopy(); 251 252 /** 253 * Wrapper for System.arraycopy. Copy the contents of this range into the provided array. 254 * @param destination Copy to this array 255 * @param destinationOffset First index in the destination array. 256 */ 257 public void deepCopyTo(byte[] destination, int destinationOffset); 258 259 /** 260 * Wrapper for System.arraycopy. Copy the contents of this range into the provided array. 261 * @param innerOffset Start copying from this index in this source ByteRange. First byte 262 * copied is bytes[offset + innerOffset] 263 * @param copyLength Copy this many bytes 264 * @param destination Copy to this array 265 * @param destinationOffset First index in the destination array. 266 */ 267 public void deepCopySubRangeTo(int innerOffset, int copyLength, byte[] destination, 268 int destinationOffset); 269 270 /** 271 * Create a new {@code ByteRange} that points at this range's byte[]. Modifying the shallowCopy 272 * will modify the bytes in this range's array. Pass over the hash code if it is already cached. 273 * @return new {@code ByteRange} object referencing this range's byte[]. 274 */ 275 public ByteRange shallowCopy(); 276 277 /** 278 * Create a new {@code ByteRange} that points at this range's byte[]. The new range can have 279 * different values for offset and length, but modifying the shallowCopy will modify the bytes in 280 * this range's array. Pass over the hash code if it is already cached. 281 * @param innerOffset First byte of clone will be this.offset + copyOffset. 282 * @param copyLength Number of bytes in the clone. 283 * @return new {@code ByteRange} object referencing this range's byte[]. 284 */ 285 public ByteRange shallowCopySubRange(int innerOffset, int copyLength); 286 287}