| // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
| // This source code is licensed under both the GPLv2 (found in the |
| // COPYING file in the root directory) and Apache 2.0 License |
| // (found in the LICENSE.Apache file in the root directory). |
| |
| package org.rocksdb; |
| |
| public class WBWIRocksIterator |
| extends AbstractRocksIterator<WriteBatchWithIndex> { |
| private final WriteEntry entry = new WriteEntry(); |
| |
| protected WBWIRocksIterator(final WriteBatchWithIndex wbwi, |
| final long nativeHandle) { |
| super(wbwi, nativeHandle); |
| } |
| |
| /** |
| * Get the current entry |
| * |
| * The WriteEntry is only valid |
| * until the iterator is repositioned. |
| * If you want to keep the WriteEntry across iterator |
| * movements, you must make a copy of its data! |
| * |
| * Note - This method is not thread-safe with respect to the WriteEntry |
| * as it performs a non-atomic update across the fields of the WriteEntry |
| * |
| * @return The WriteEntry of the current entry |
| */ |
| public WriteEntry entry() { |
| assert(isOwningHandle()); |
| final long ptrs[] = entry1(nativeHandle_); |
| |
| entry.type = WriteType.fromId((byte)ptrs[0]); |
| entry.key.resetNativeHandle(ptrs[1], ptrs[1] != 0); |
| entry.value.resetNativeHandle(ptrs[2], ptrs[2] != 0); |
| |
| return entry; |
| } |
| |
| @Override protected final native void disposeInternal(final long handle); |
| @Override final native boolean isValid0(long handle); |
| @Override final native void seekToFirst0(long handle); |
| @Override final native void seekToLast0(long handle); |
| @Override final native void next0(long handle); |
| @Override final native void prev0(long handle); |
| @Override final native void seek0(long handle, byte[] target, int targetLen); |
| @Override final native void status0(long handle) throws RocksDBException; |
| |
| private native long[] entry1(final long handle); |
| |
| /** |
| * Enumeration of the Write operation |
| * that created the record in the Write Batch |
| */ |
| public enum WriteType { |
| PUT((byte)0x1), |
| MERGE((byte)0x2), |
| DELETE((byte)0x4), |
| LOG((byte)0x8); |
| |
| final byte id; |
| WriteType(final byte id) { |
| this.id = id; |
| } |
| |
| public static WriteType fromId(final byte id) { |
| for(final WriteType wt : WriteType.values()) { |
| if(id == wt.id) { |
| return wt; |
| } |
| } |
| throw new IllegalArgumentException("No WriteType with id=" + id); |
| } |
| } |
| |
| @Override |
| public void close() { |
| entry.close(); |
| super.close(); |
| } |
| |
| /** |
| * Represents an entry returned by |
| * {@link org.rocksdb.WBWIRocksIterator#entry()} |
| * |
| * It is worth noting that a WriteEntry with |
| * the type {@link org.rocksdb.WBWIRocksIterator.WriteType#DELETE} |
| * or {@link org.rocksdb.WBWIRocksIterator.WriteType#LOG} |
| * will not have a value. |
| */ |
| public static class WriteEntry implements AutoCloseable { |
| WriteType type = null; |
| final DirectSlice key; |
| final DirectSlice value; |
| |
| /** |
| * Intentionally private as this |
| * should only be instantiated in |
| * this manner by the outer WBWIRocksIterator |
| * class; The class members are then modified |
| * by calling {@link org.rocksdb.WBWIRocksIterator#entry()} |
| */ |
| private WriteEntry() { |
| key = new DirectSlice(); |
| value = new DirectSlice(); |
| } |
| |
| public WriteEntry(final WriteType type, final DirectSlice key, |
| final DirectSlice value) { |
| this.type = type; |
| this.key = key; |
| this.value = value; |
| } |
| |
| /** |
| * Returns the type of the Write Entry |
| * |
| * @return the WriteType of the WriteEntry |
| */ |
| public WriteType getType() { |
| return type; |
| } |
| |
| /** |
| * Returns the key of the Write Entry |
| * |
| * @return The slice containing the key |
| * of the WriteEntry |
| */ |
| public DirectSlice getKey() { |
| return key; |
| } |
| |
| /** |
| * Returns the value of the Write Entry |
| * |
| * @return The slice containing the value of |
| * the WriteEntry or null if the WriteEntry has |
| * no value |
| */ |
| public DirectSlice getValue() { |
| if(!value.isOwningHandle()) { |
| return null; //TODO(AR) migrate to JDK8 java.util.Optional#empty() |
| } else { |
| return value; |
| } |
| } |
| |
| /** |
| * Generates a hash code for the Write Entry. NOTE: The hash code is based |
| * on the string representation of the key, so it may not work correctly |
| * with exotic custom comparators. |
| * |
| * @return The hash code for the Write Entry |
| */ |
| @Override |
| public int hashCode() { |
| return (key == null) ? 0 : key.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(final Object other) { |
| if(other == null) { |
| return false; |
| } else if (this == other) { |
| return true; |
| } else if(other instanceof WriteEntry) { |
| final WriteEntry otherWriteEntry = (WriteEntry)other; |
| return type.equals(otherWriteEntry.type) |
| && key.equals(otherWriteEntry.key) |
| && value.equals(otherWriteEntry.value); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public void close() { |
| value.close(); |
| key.close(); |
| } |
| } |
| } |