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