|
|
|
@ -5,121 +5,133 @@ |
|
|
|
|
|
|
|
|
|
package org.rocksdb; |
|
|
|
|
|
|
|
|
|
public class WBWIRocksIterator extends RocksObject implements RocksIteratorInterface { |
|
|
|
|
|
|
|
|
|
//TODO(AR) abstract common code from WBWIRocksIterator and RocksIterator into AbstractRocksIterator
|
|
|
|
|
|
|
|
|
|
final WriteBatchWithIndex wbwi_; |
|
|
|
|
public class WBWIRocksIterator extends AbstractRocksIterator<WriteBatchWithIndex> { |
|
|
|
|
private final WriteEntry entry = new WriteEntry(); |
|
|
|
|
|
|
|
|
|
protected WBWIRocksIterator(WriteBatchWithIndex wbwi, long nativeHandle) { |
|
|
|
|
super(); |
|
|
|
|
nativeHandle_ = nativeHandle; |
|
|
|
|
// rocksDB must point to a valid RocksDB instance.
|
|
|
|
|
assert (wbwi != null); |
|
|
|
|
// WBWIRocksIterator must hold a reference to the related WriteBatchWithIndex instance
|
|
|
|
|
// to guarantee that while a GC cycle starts WBWIRocksIterator instances
|
|
|
|
|
// are freed prior to WriteBatchWithIndex instances.
|
|
|
|
|
wbwi_ = wbwi; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public boolean isValid() { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void seekToFirst() { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void seekToLast() { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void seek(byte[] target) { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void next() { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void prev() { |
|
|
|
|
|
|
|
|
|
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! |
|
|
|
|
* |
|
|
|
|
* @return The WriteEntry of the current entry |
|
|
|
|
*/ |
|
|
|
|
public WriteEntry entry() { |
|
|
|
|
throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); //TODO(AR) implement
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void status() throws RocksDBException { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* <p>Deletes underlying C++ iterator pointer.</p> |
|
|
|
|
* <p/> |
|
|
|
|
* <p>Note: the underlying handle can only be safely deleted if the WriteBatchWithIndex |
|
|
|
|
* instance related to a certain WBWIRocksIterator is still valid and initialized. |
|
|
|
|
* Therefore {@code disposeInternal()} checks if the WriteBatchWithIndex is initialized |
|
|
|
|
* before freeing the native handle.</p> |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
protected void disposeInternal() { |
|
|
|
|
synchronized (wbwi_) { |
|
|
|
|
assert(isInitialized()); |
|
|
|
|
if (wbwi_.isInitialized()) { |
|
|
|
|
disposeInternal(nativeHandle_); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
assert(entry != null); |
|
|
|
|
entry1(nativeHandle_, entry); |
|
|
|
|
return entry; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private native void disposeInternal(long handle); |
|
|
|
|
@Override final native void disposeInternal(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 void entry1(long handle, WriteEntry entry); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Enumeration of the Write operation |
|
|
|
|
* that created the record in the Write Batch |
|
|
|
|
*/ |
|
|
|
|
public enum WriteType { |
|
|
|
|
PutRecord, |
|
|
|
|
MergeRecord, |
|
|
|
|
DeleteRecord, |
|
|
|
|
LogDataRecord |
|
|
|
|
PUT, |
|
|
|
|
MERGE, |
|
|
|
|
DELETE, |
|
|
|
|
LOG |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Represents the entry returned by a |
|
|
|
|
* WBWIRocksIterator |
|
|
|
|
* 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 { |
|
|
|
|
final WriteType type; |
|
|
|
|
final Slice key; |
|
|
|
|
final Slice value; |
|
|
|
|
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 Slice key, final Slice value) { |
|
|
|
|
public WriteEntry(WriteType type, DirectSlice key, 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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Slice getKey() { |
|
|
|
|
/** |
|
|
|
|
* Returns the key of the Write Entry |
|
|
|
|
* |
|
|
|
|
* @return The slice containing the key |
|
|
|
|
* of the WriteEntry |
|
|
|
|
*/ |
|
|
|
|
public DirectSlice getKey() { |
|
|
|
|
return key; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Slice getValue() { |
|
|
|
|
/** |
|
|
|
|
* 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.isInitialized()) { |
|
|
|
|
return null; //TODO(AR) migrate to JDK8 java.util.Optional#empty()
|
|
|
|
|
} else { |
|
|
|
|
return value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public boolean equals(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.isInitialized() ? value.equals(otherWriteEntry.value) |
|
|
|
|
: !otherWriteEntry.value.isInitialized()); |
|
|
|
|
} else { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|