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 public class WBWIRocksIterator 11 extends AbstractRocksIterator<WriteBatchWithIndex> { 12 private final WriteEntry entry = new WriteEntry(); 13 WBWIRocksIterator(final WriteBatchWithIndex wbwi, final long nativeHandle)14 protected WBWIRocksIterator(final WriteBatchWithIndex wbwi, 15 final long nativeHandle) { 16 super(wbwi, nativeHandle); 17 } 18 19 /** 20 * Get the current entry 21 * 22 * The WriteEntry is only valid 23 * until the iterator is repositioned. 24 * If you want to keep the WriteEntry across iterator 25 * movements, you must make a copy of its data! 26 * 27 * Note - This method is not thread-safe with respect to the WriteEntry 28 * as it performs a non-atomic update across the fields of the WriteEntry 29 * 30 * @return The WriteEntry of the current entry 31 */ entry()32 public WriteEntry entry() { 33 assert(isOwningHandle()); 34 final long ptrs[] = entry1(nativeHandle_); 35 36 entry.type = WriteType.fromId((byte)ptrs[0]); 37 entry.key.resetNativeHandle(ptrs[1], ptrs[1] != 0); 38 entry.value.resetNativeHandle(ptrs[2], ptrs[2] != 0); 39 40 return entry; 41 } 42 disposeInternal(final long handle)43 @Override protected final native void disposeInternal(final long handle); isValid0(long handle)44 @Override final native boolean isValid0(long handle); seekToFirst0(long handle)45 @Override final native void seekToFirst0(long handle); seekToLast0(long handle)46 @Override final native void seekToLast0(long handle); next0(long handle)47 @Override final native void next0(long handle); prev0(long handle)48 @Override final native void prev0(long handle); seek0(long handle, byte[] target, int targetLen)49 @Override final native void seek0(long handle, byte[] target, int targetLen); seekForPrev0(long handle, byte[] target, int targetLen)50 @Override final native void seekForPrev0(long handle, byte[] target, int targetLen); status0(long handle)51 @Override final native void status0(long handle) throws RocksDBException; 52 @Override seekDirect0(long handle, ByteBuffer target, int targetOffset, int targetLen)53 final native void seekDirect0(long handle, ByteBuffer target, int targetOffset, int targetLen); 54 entry1(final long handle)55 private native long[] entry1(final long handle); 56 57 /** 58 * Enumeration of the Write operation 59 * that created the record in the Write Batch 60 */ 61 public enum WriteType { 62 PUT((byte)0x0), 63 MERGE((byte)0x1), 64 DELETE((byte)0x2), 65 SINGLE_DELETE((byte)0x3), 66 DELETE_RANGE((byte)0x4), 67 LOG((byte)0x5), 68 XID((byte)0x6); 69 70 final byte id; WriteType(final byte id)71 WriteType(final byte id) { 72 this.id = id; 73 } 74 fromId(final byte id)75 public static WriteType fromId(final byte id) { 76 for(final WriteType wt : WriteType.values()) { 77 if(id == wt.id) { 78 return wt; 79 } 80 } 81 throw new IllegalArgumentException("No WriteType with id=" + id); 82 } 83 } 84 85 @Override close()86 public void close() { 87 entry.close(); 88 super.close(); 89 } 90 91 /** 92 * Represents an entry returned by 93 * {@link org.rocksdb.WBWIRocksIterator#entry()} 94 * 95 * It is worth noting that a WriteEntry with 96 * the type {@link org.rocksdb.WBWIRocksIterator.WriteType#DELETE} 97 * or {@link org.rocksdb.WBWIRocksIterator.WriteType#LOG} 98 * will not have a value. 99 */ 100 public static class WriteEntry implements AutoCloseable { 101 WriteType type = null; 102 final DirectSlice key; 103 final DirectSlice value; 104 105 /** 106 * Intentionally private as this 107 * should only be instantiated in 108 * this manner by the outer WBWIRocksIterator 109 * class; The class members are then modified 110 * by calling {@link org.rocksdb.WBWIRocksIterator#entry()} 111 */ WriteEntry()112 private WriteEntry() { 113 key = new DirectSlice(); 114 value = new DirectSlice(); 115 } 116 WriteEntry(final WriteType type, final DirectSlice key, final DirectSlice value)117 public WriteEntry(final WriteType type, final DirectSlice key, 118 final DirectSlice value) { 119 this.type = type; 120 this.key = key; 121 this.value = value; 122 } 123 124 /** 125 * Returns the type of the Write Entry 126 * 127 * @return the WriteType of the WriteEntry 128 */ getType()129 public WriteType getType() { 130 return type; 131 } 132 133 /** 134 * Returns the key of the Write Entry 135 * 136 * @return The slice containing the key 137 * of the WriteEntry 138 */ getKey()139 public DirectSlice getKey() { 140 return key; 141 } 142 143 /** 144 * Returns the value of the Write Entry 145 * 146 * @return The slice containing the value of 147 * the WriteEntry or null if the WriteEntry has 148 * no value 149 */ getValue()150 public DirectSlice getValue() { 151 if(!value.isOwningHandle()) { 152 return null; //TODO(AR) migrate to JDK8 java.util.Optional#empty() 153 } else { 154 return value; 155 } 156 } 157 158 /** 159 * Generates a hash code for the Write Entry. NOTE: The hash code is based 160 * on the string representation of the key, so it may not work correctly 161 * with exotic custom comparators. 162 * 163 * @return The hash code for the Write Entry 164 */ 165 @Override hashCode()166 public int hashCode() { 167 return (key == null) ? 0 : key.hashCode(); 168 } 169 170 @Override equals(final Object other)171 public boolean equals(final Object other) { 172 if(other == null) { 173 return false; 174 } else if (this == other) { 175 return true; 176 } else if(other instanceof WriteEntry) { 177 final WriteEntry otherWriteEntry = (WriteEntry)other; 178 return type.equals(otherWriteEntry.type) 179 && key.equals(otherWriteEntry.key) 180 && value.equals(otherWriteEntry.value); 181 } else { 182 return false; 183 } 184 } 185 186 @Override close()187 public void close() { 188 value.close(); 189 key.close(); 190 } 191 } 192 193 @Override seekForPrevDirect0(long handle, ByteBuffer target, int targetOffset, int targetLen)194 void seekForPrevDirect0(long handle, ByteBuffer target, int targetOffset, int targetLen) { 195 throw new IllegalAccessError("Not implemented"); 196 } 197 } 198