1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 package org.rocksdb; 7 8 import java.nio.ByteBuffer; 9 10 /** 11 * Similar to {@link org.rocksdb.WriteBatch} but with a binary searchable 12 * index built for all the keys inserted. 13 * 14 * Calling put, merge, remove or putLogData calls the same function 15 * as with {@link org.rocksdb.WriteBatch} whilst also building an index. 16 * 17 * A user can call {@link org.rocksdb.WriteBatchWithIndex#newIterator()} to 18 * create an iterator over the write batch or 19 * {@link org.rocksdb.WriteBatchWithIndex#newIteratorWithBase(org.rocksdb.RocksIterator)} 20 * to get an iterator for the database with Read-Your-Own-Writes like capability 21 */ 22 public class WriteBatchWithIndex extends AbstractWriteBatch { 23 /** 24 * Creates a WriteBatchWithIndex where no bytes 25 * are reserved up-front, bytewise comparison is 26 * used for fallback key comparisons, 27 * and duplicate keys operations are retained 28 */ WriteBatchWithIndex()29 public WriteBatchWithIndex() { 30 super(newWriteBatchWithIndex()); 31 } 32 33 34 /** 35 * Creates a WriteBatchWithIndex where no bytes 36 * are reserved up-front, bytewise comparison is 37 * used for fallback key comparisons, and duplicate key 38 * assignment is determined by the constructor argument 39 * 40 * @param overwriteKey if true, overwrite the key in the index when 41 * inserting a duplicate key, in this way an iterator will never 42 * show two entries with the same key. 43 */ WriteBatchWithIndex(final boolean overwriteKey)44 public WriteBatchWithIndex(final boolean overwriteKey) { 45 super(newWriteBatchWithIndex(overwriteKey)); 46 } 47 48 /** 49 * Creates a WriteBatchWithIndex 50 * 51 * @param fallbackIndexComparator We fallback to this comparator 52 * to compare keys within a column family if we cannot determine 53 * the column family and so look up it's comparator. 54 * 55 * @param reservedBytes reserved bytes in underlying WriteBatch 56 * 57 * @param overwriteKey if true, overwrite the key in the index when 58 * inserting a duplicate key, in this way an iterator will never 59 * show two entries with the same key. 60 */ WriteBatchWithIndex( final AbstractComparator fallbackIndexComparator, final int reservedBytes, final boolean overwriteKey)61 public WriteBatchWithIndex( 62 final AbstractComparator 63 fallbackIndexComparator, final int reservedBytes, 64 final boolean overwriteKey) { 65 super(newWriteBatchWithIndex(fallbackIndexComparator.nativeHandle_, 66 fallbackIndexComparator.getComparatorType().getValue(), reservedBytes, 67 overwriteKey)); 68 } 69 70 /** 71 * <p>Private WriteBatchWithIndex constructor which is used to construct 72 * WriteBatchWithIndex instances from C++ side. As the reference to this 73 * object is also managed from C++ side the handle will be disowned.</p> 74 * 75 * @param nativeHandle address of native instance. 76 */ WriteBatchWithIndex(final long nativeHandle)77 WriteBatchWithIndex(final long nativeHandle) { 78 super(nativeHandle); 79 disOwnNativeHandle(); 80 } 81 82 /** 83 * Create an iterator of a column family. User can call 84 * {@link org.rocksdb.RocksIteratorInterface#seek(byte[])} to 85 * search to the next entry of or after a key. Keys will be iterated in the 86 * order given by index_comparator. For multiple updates on the same key, 87 * each update will be returned as a separate entry, in the order of update 88 * time. 89 * 90 * @param columnFamilyHandle The column family to iterate over 91 * @return An iterator for the Write Batch contents, restricted to the column 92 * family 93 */ newIterator( final ColumnFamilyHandle columnFamilyHandle)94 public WBWIRocksIterator newIterator( 95 final ColumnFamilyHandle columnFamilyHandle) { 96 return new WBWIRocksIterator(this, iterator1(nativeHandle_, 97 columnFamilyHandle.nativeHandle_)); 98 } 99 100 /** 101 * Create an iterator of the default column family. User can call 102 * {@link org.rocksdb.RocksIteratorInterface#seek(byte[])} to 103 * search to the next entry of or after a key. Keys will be iterated in the 104 * order given by index_comparator. For multiple updates on the same key, 105 * each update will be returned as a separate entry, in the order of update 106 * time. 107 * 108 * @return An iterator for the Write Batch contents 109 */ newIterator()110 public WBWIRocksIterator newIterator() { 111 return new WBWIRocksIterator(this, iterator0(nativeHandle_)); 112 } 113 114 /** 115 * Provides Read-Your-Own-Writes like functionality by 116 * creating a new Iterator that will use {@link org.rocksdb.WBWIRocksIterator} 117 * as a delta and baseIterator as a base 118 * 119 * Updating write batch with the current key of the iterator is not safe. 120 * We strongly recommand users not to do it. It will invalidate the current 121 * key() and value() of the iterator. This invalidation happens even before 122 * the write batch update finishes. The state may recover after Next() is 123 * called. 124 * 125 * @param columnFamilyHandle The column family to iterate over 126 * @param baseIterator The base iterator, 127 * e.g. {@link org.rocksdb.RocksDB#newIterator()} 128 * @return An iterator which shows a view comprised of both the database 129 * point-in-time from baseIterator and modifications made in this write batch. 130 */ newIteratorWithBase( final ColumnFamilyHandle columnFamilyHandle, final RocksIterator baseIterator)131 public RocksIterator newIteratorWithBase( 132 final ColumnFamilyHandle columnFamilyHandle, 133 final RocksIterator baseIterator) { 134 RocksIterator iterator = new RocksIterator(baseIterator.parent_, 135 iteratorWithBase( 136 nativeHandle_, columnFamilyHandle.nativeHandle_, baseIterator.nativeHandle_)); 137 // when the iterator is deleted it will also delete the baseIterator 138 baseIterator.disOwnNativeHandle(); 139 return iterator; 140 } 141 142 /** 143 * Provides Read-Your-Own-Writes like functionality by 144 * creating a new Iterator that will use {@link org.rocksdb.WBWIRocksIterator} 145 * as a delta and baseIterator as a base. Operates on the default column 146 * family. 147 * 148 * @param baseIterator The base iterator, 149 * e.g. {@link org.rocksdb.RocksDB#newIterator()} 150 * @return An iterator which shows a view comprised of both the database 151 * point-in-timefrom baseIterator and modifications made in this write batch. 152 */ newIteratorWithBase(final RocksIterator baseIterator)153 public RocksIterator newIteratorWithBase(final RocksIterator baseIterator) { 154 return newIteratorWithBase(baseIterator.parent_.getDefaultColumnFamily(), baseIterator); 155 } 156 157 /** 158 * Similar to {@link RocksDB#get(ColumnFamilyHandle, byte[])} but will only 159 * read the key from this batch. 160 * 161 * @param columnFamilyHandle The column family to retrieve the value from 162 * @param options The database options to use 163 * @param key The key to read the value for 164 * 165 * @return a byte array storing the value associated with the input key if 166 * any. null if it does not find the specified key. 167 * 168 * @throws RocksDBException if the batch does not have enough data to resolve 169 * Merge operations, MergeInProgress status may be returned. 170 */ getFromBatch(final ColumnFamilyHandle columnFamilyHandle, final DBOptions options, final byte[] key)171 public byte[] getFromBatch(final ColumnFamilyHandle columnFamilyHandle, 172 final DBOptions options, final byte[] key) throws RocksDBException { 173 return getFromBatch(nativeHandle_, options.nativeHandle_, 174 key, key.length, columnFamilyHandle.nativeHandle_); 175 } 176 177 /** 178 * Similar to {@link RocksDB#get(byte[])} but will only 179 * read the key from this batch. 180 * 181 * @param options The database options to use 182 * @param key The key to read the value for 183 * 184 * @return a byte array storing the value associated with the input key if 185 * any. null if it does not find the specified key. 186 * 187 * @throws RocksDBException if the batch does not have enough data to resolve 188 * Merge operations, MergeInProgress status may be returned. 189 */ getFromBatch(final DBOptions options, final byte[] key)190 public byte[] getFromBatch(final DBOptions options, final byte[] key) 191 throws RocksDBException { 192 return getFromBatch(nativeHandle_, options.nativeHandle_, key, key.length); 193 } 194 195 /** 196 * Similar to {@link RocksDB#get(ColumnFamilyHandle, byte[])} but will also 197 * read writes from this batch. 198 * 199 * This function will query both this batch and the DB and then merge 200 * the results using the DB's merge operator (if the batch contains any 201 * merge requests). 202 * 203 * Setting {@link ReadOptions#setSnapshot(long, long)} will affect what is 204 * read from the DB but will NOT change which keys are read from the batch 205 * (the keys in this batch do not yet belong to any snapshot and will be 206 * fetched regardless). 207 * 208 * @param db The Rocks database 209 * @param columnFamilyHandle The column family to retrieve the value from 210 * @param options The read options to use 211 * @param key The key to read the value for 212 * 213 * @return a byte array storing the value associated with the input key if 214 * any. null if it does not find the specified key. 215 * 216 * @throws RocksDBException if the value for the key cannot be read 217 */ getFromBatchAndDB(final RocksDB db, final ColumnFamilyHandle columnFamilyHandle, final ReadOptions options, final byte[] key)218 public byte[] getFromBatchAndDB(final RocksDB db, final ColumnFamilyHandle columnFamilyHandle, 219 final ReadOptions options, final byte[] key) throws RocksDBException { 220 return getFromBatchAndDB(nativeHandle_, db.nativeHandle_, 221 options.nativeHandle_, key, key.length, 222 columnFamilyHandle.nativeHandle_); 223 } 224 225 /** 226 * Similar to {@link RocksDB#get(byte[])} but will also 227 * read writes from this batch. 228 * 229 * This function will query both this batch and the DB and then merge 230 * the results using the DB's merge operator (if the batch contains any 231 * merge requests). 232 * 233 * Setting {@link ReadOptions#setSnapshot(long, long)} will affect what is 234 * read from the DB but will NOT change which keys are read from the batch 235 * (the keys in this batch do not yet belong to any snapshot and will be 236 * fetched regardless). 237 * 238 * @param db The Rocks database 239 * @param options The read options to use 240 * @param key The key to read the value for 241 * 242 * @return a byte array storing the value associated with the input key if 243 * any. null if it does not find the specified key. 244 * 245 * @throws RocksDBException if the value for the key cannot be read 246 */ getFromBatchAndDB(final RocksDB db, final ReadOptions options, final byte[] key)247 public byte[] getFromBatchAndDB(final RocksDB db, final ReadOptions options, 248 final byte[] key) throws RocksDBException { 249 return getFromBatchAndDB(nativeHandle_, db.nativeHandle_, 250 options.nativeHandle_, key, key.length); 251 } 252 disposeInternal(final long handle)253 @Override protected final native void disposeInternal(final long handle); count0(final long handle)254 @Override final native int count0(final long handle); put(final long handle, final byte[] key, final int keyLen, final byte[] value, final int valueLen)255 @Override final native void put(final long handle, final byte[] key, 256 final int keyLen, final byte[] value, final int valueLen); put(final long handle, final byte[] key, final int keyLen, final byte[] value, final int valueLen, final long cfHandle)257 @Override final native void put(final long handle, final byte[] key, 258 final int keyLen, final byte[] value, final int valueLen, 259 final long cfHandle); 260 @Override putDirect(final long handle, final ByteBuffer key, final int keyOffset, final int keyLength, final ByteBuffer value, final int valueOffset, final int valueLength, final long cfHandle)261 final native void putDirect(final long handle, final ByteBuffer key, final int keyOffset, 262 final int keyLength, final ByteBuffer value, final int valueOffset, final int valueLength, 263 final long cfHandle); merge(final long handle, final byte[] key, final int keyLen, final byte[] value, final int valueLen)264 @Override final native void merge(final long handle, final byte[] key, 265 final int keyLen, final byte[] value, final int valueLen); merge(final long handle, final byte[] key, final int keyLen, final byte[] value, final int valueLen, final long cfHandle)266 @Override final native void merge(final long handle, final byte[] key, 267 final int keyLen, final byte[] value, final int valueLen, 268 final long cfHandle); delete(final long handle, final byte[] key, final int keyLen)269 @Override final native void delete(final long handle, final byte[] key, 270 final int keyLen) throws RocksDBException; delete(final long handle, final byte[] key, final int keyLen, final long cfHandle)271 @Override final native void delete(final long handle, final byte[] key, 272 final int keyLen, final long cfHandle) throws RocksDBException; singleDelete(final long handle, final byte[] key, final int keyLen)273 @Override final native void singleDelete(final long handle, final byte[] key, 274 final int keyLen) throws RocksDBException; singleDelete(final long handle, final byte[] key, final int keyLen, final long cfHandle)275 @Override final native void singleDelete(final long handle, final byte[] key, 276 final int keyLen, final long cfHandle) throws RocksDBException; 277 @Override removeDirect(final long handle, final ByteBuffer key, final int keyOffset, final int keyLength, final long cfHandle)278 final native void removeDirect(final long handle, final ByteBuffer key, final int keyOffset, 279 final int keyLength, final long cfHandle) throws RocksDBException; 280 // DO NOT USE - `WriteBatchWithIndex::deleteRange` is not yet supported 281 @Override deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, final byte[] endKey, final int endKeyLen)282 final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, 283 final byte[] endKey, final int endKeyLen); 284 // DO NOT USE - `WriteBatchWithIndex::deleteRange` is not yet supported 285 @Override deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, final byte[] endKey, final int endKeyLen, final long cfHandle)286 final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, 287 final byte[] endKey, final int endKeyLen, final long cfHandle); putLogData(final long handle, final byte[] blob, final int blobLen)288 @Override final native void putLogData(final long handle, final byte[] blob, 289 final int blobLen) throws RocksDBException; clear0(final long handle)290 @Override final native void clear0(final long handle); setSavePoint0(final long handle)291 @Override final native void setSavePoint0(final long handle); rollbackToSavePoint0(final long handle)292 @Override final native void rollbackToSavePoint0(final long handle); popSavePoint(final long handle)293 @Override final native void popSavePoint(final long handle) throws RocksDBException; setMaxBytes(final long nativeHandle, final long maxBytes)294 @Override final native void setMaxBytes(final long nativeHandle, 295 final long maxBytes); getWriteBatch(final long handle)296 @Override final native WriteBatch getWriteBatch(final long handle); 297 newWriteBatchWithIndex()298 private native static long newWriteBatchWithIndex(); newWriteBatchWithIndex(final boolean overwriteKey)299 private native static long newWriteBatchWithIndex(final boolean overwriteKey); newWriteBatchWithIndex( final long fallbackIndexComparatorHandle, final byte comparatorType, final int reservedBytes, final boolean overwriteKey)300 private native static long newWriteBatchWithIndex( 301 final long fallbackIndexComparatorHandle, 302 final byte comparatorType, final int reservedBytes, 303 final boolean overwriteKey); iterator0(final long handle)304 private native long iterator0(final long handle); iterator1(final long handle, final long cfHandle)305 private native long iterator1(final long handle, final long cfHandle); iteratorWithBase( final long handle, final long baseIteratorHandle, final long cfHandle)306 private native long iteratorWithBase( 307 final long handle, final long baseIteratorHandle, final long cfHandle); getFromBatch(final long handle, final long optHandle, final byte[] key, final int keyLen)308 private native byte[] getFromBatch(final long handle, final long optHandle, 309 final byte[] key, final int keyLen); getFromBatch(final long handle, final long optHandle, final byte[] key, final int keyLen, final long cfHandle)310 private native byte[] getFromBatch(final long handle, final long optHandle, 311 final byte[] key, final int keyLen, final long cfHandle); getFromBatchAndDB(final long handle, final long dbHandle, final long readOptHandle, final byte[] key, final int keyLen)312 private native byte[] getFromBatchAndDB(final long handle, 313 final long dbHandle, final long readOptHandle, final byte[] key, 314 final int keyLen); getFromBatchAndDB(final long handle, final long dbHandle, final long readOptHandle, final byte[] key, final int keyLen, final long cfHandle)315 private native byte[] getFromBatchAndDB(final long handle, 316 final long dbHandle, final long readOptHandle, final byte[] key, 317 final int keyLen, final long cfHandle); 318 } 319