Skip to content

Commit

Permalink
Enable Reverse Iterator for LongART
Browse files Browse the repository at this point in the history
- Bug fixes for LongART
- Bug fix for register Allocation classes
  • Loading branch information
asonje committed Oct 26, 2021
1 parent 795b3fb commit c9073b2
Show file tree
Hide file tree
Showing 4 changed files with 514 additions and 36 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
<exec executable="make" dir="${project.build.directory}/cppbuild" failonerror="true">
<arg line="VERBOSE=1"/>
</exec>
<copy file="${project.build.directory}/cppbuild/libllpl.so" tofile="${project.build.directory}/classes/com/intel/pmem/llpl/linux/amd64/libllpl.so"/>
<copy file="${project.build.directory}/cppbuild/libllpl.so" tofile="${project.build.directory}/classes/com/intel/pmem/llpl/linux/${os.arch}/libllpl.so"/>
</tasks>
</configuration>
<goals>
Expand Down
16 changes: 9 additions & 7 deletions src/main/java/com/intel/pmem/llpl/AnyHeap.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.Arrays;
import java.util.MissingResourceException;
import java.io.File;
Expand Down Expand Up @@ -97,7 +97,7 @@ public abstract class AnyHeap {

AnyHeap(String path, long requestedSize) {
this.path = path;
userSizes = new TreeMap<Long, Integer>();
userSizes = new ConcurrentSkipListMap<Long, Integer>();
allocationClasses = new long[TOTAL_ALLOCATION_CLASSES];
poolHandle = nativeCreateHeap(path, requestedSize, allocationClasses, this.getHeapLayoutID());
if (poolHandle == 0) throw new HeapException("Failed to create heap.");
Expand All @@ -109,7 +109,7 @@ public abstract class AnyHeap {

AnyHeap(String path) {
this.path = path;
userSizes = new TreeMap<Long, Integer>();
userSizes = new ConcurrentSkipListMap<Long, Integer>();
allocationClasses = new long[TOTAL_ALLOCATION_CLASSES];
poolHandle = nativeOpenHeap(path, allocationClasses, this.getHeapLayoutID());
if (poolHandle == 0) throw new HeapException("Failed to open heap.");
Expand Down Expand Up @@ -191,17 +191,19 @@ void close() {
* @return true if size was successfully registered
* @throws HeapException if the allocation size could not be registered
*/
public synchronized boolean registerAllocationSize(long size, boolean compact) {
public boolean registerAllocationSize(long size, boolean compact) {
if (userSizes.size() == MAX_USER_CLASSES) throw new HeapException("Max number of allocation sizes reached.");
if (size <= 0) throw new IllegalArgumentException();
long effectiveSize;
if (!userSizes.containsKey(effectiveSize = (size + (compact ? 0L : Long.BYTES)))) {
int id = nativeRegisterAllocationClass(poolHandle, effectiveSize);
if (id != -1) {
int i = USER_CLASS_INDEX + (userSizes.size() * 2);
userSizes.put(effectiveSize, id);
allocationClasses[i++] = effectiveSize;
allocationClasses[i] = id;
return true;
}
int index = (int)((effectiveSize / 8) - 1);
if (effectiveSize % 8 == 0 && effectiveSize < 128 && allocationClasses[index] > 0) {
userSizes.put(effectiveSize, (int)allocationClasses[index]);
return true;
}
return false;
Expand Down
97 changes: 72 additions & 25 deletions src/main/java/com/intel/pmem/llpl/util/LongART.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ private void setMaxKeyLength(int length) {
public byte[] firstKey() {
Node n = root.getChild();
if (n == null) throw new NoSuchElementException();
if (n.isLeaf()) return n.getPrefix();
ByteBuffer firstKey = ByteBuffer.allocate(maxKeyLen);
SearchHelper h = (Node parent, Node child, Byte radix, Consumer<Long> cleanerFunction) -> {
byte[] ba = parent.getPrefix();
Expand All @@ -177,6 +178,7 @@ public byte[] firstKey() {
public byte[] lastKey() {
Node n = root.getChild();
if (n == null) throw new NoSuchElementException();
if (n.isLeaf()) return n.getPrefix();
ByteBuffer lastKey = ByteBuffer.allocate(maxKeyLen);
SearchHelper h = (Node parent, Node child, Byte radix, Consumer<Long> cleanerFunction) -> {
byte[] ba = parent.getPrefix();
Expand Down Expand Up @@ -467,7 +469,6 @@ void mergeTree(LongART tree) {
}
}
}

}

@SuppressWarnings("unchecked")
Expand All @@ -477,7 +478,7 @@ private long search2(Node node, byte[] key, int depth, SearchHelper helper, Cons
}
Node next;
int matchedLength = (key.length == 0) ? node.getPrefixLength() : node.checkPrefix(key, depth);
if (matchedLength != node.getPrefixLength()) {
if (matchedLength != node.getPrefixLength() && !node.isLeaf()) {
return -1;
}
if (node.isLeaf())
Expand Down Expand Up @@ -569,6 +570,7 @@ public void clear(Consumer<Long> cleanerFunction) {
if (cleanerFunction == null) throw new IllegalArgumentException("cleaner function cannot be null");
heap.execute(() -> {
root.destroy(cleanerFunction);
root.setCount(0);
count = 0;
});
}
Expand Down Expand Up @@ -607,7 +609,20 @@ else if (((InternalNode)child).getChildrenCount() == 0) {
public long remove(byte[] key, Consumer<Long> cleanerFunction) {
if (cleanerFunction == null) throw new NullPointerException("cleaner function cannot be null");
if (key.length == 0) throw new IllegalArgumentException("Invalid key");
return search(root.getChild(), key, 0, this::deleteNodes , cleanerFunction);
Node n = root.getChild();
if (n != null && n.isLeaf() && Arrays.equals(key, n.getPrefix())) {
heap.execute(() -> {
root.destroy(cleanerFunction);
root.setCount(0);
count = 0;
});
return ((SimpleLeaf)n).getValue();
}
else {
long ret = search(n, key, 0, this::deleteNodes , cleanerFunction);
if (n != null && !n.isLeaf() && ((InternalNode)n).getChildrenCount() == 0) root.deleteChild();
return ret;
}
}

/**
Expand Down Expand Up @@ -660,7 +675,21 @@ public Iterator<LongART.Entry> getReverseEntryIterator(byte[] firstKey, boolean
*/
public Iterator<Entry> getHeadEntryIterator(byte[] lastKey, boolean lastInclusive) {
if (lastKey == null || lastKey.length == 0) throw new IllegalArgumentException();
return new EntryIterator(lastKey, lastInclusive);
return new EntryIterator(lastKey, lastInclusive, false);
}

/**
* Returns a descending-order iterator over entries in this radix tree;
* the iterator will include entries whose keys are lower than (or equal to,
* if {@code firstInclusive} is true) {@code firstKey}.
* @param firstKey high endpoint of the keys in the returned iterator
* @param firstInclusive true if the highest key is to be included in the returned iterator
* @return the iterator
* @throws IllegalArgumentException if lastKey has zero length
*/
public Iterator<Entry> getReverseHeadEntryIterator(byte[] firstKey, boolean firstInclusive) {
if (firstKey == null || firstKey.length == 0) throw new IllegalArgumentException();
return new EntryIterator(firstKey, firstInclusive, null, false, true);
}

/**
Expand All @@ -670,13 +699,27 @@ public Iterator<Entry> getHeadEntryIterator(byte[] lastKey, boolean lastInclusiv
* @param firstKey low endpoint of the keys in the returned iterator
* @param firstInclusive true if the lowest key is to be included in the returned iterator
* @return the iterator
* @throws IllegalArgumentException if lastKey has zero length
* @throws IllegalArgumentException if firstKey has zero length
*/
public Iterator<Entry> getTailEntryIterator(byte[] firstKey, boolean firstInclusive) {
if (firstKey == null || firstKey.length == 0) throw new IllegalArgumentException();
return new EntryIterator(firstKey, firstInclusive, null, false, false);
}

/**
* Returns a descending-order iterator over entries in this radix tree;
* the iterator will include entries whose keys are higher than (or equal to,
* if {@code lastInclusive} is true) {@code lastKey}.
* @param lastKey low endpoint of the keys in the returned iterator
* @param lastInclusive true if the lowest key is to be included in the returned iterator
* @return the iterator
* @throws IllegalArgumentException if lastKey has zero length
*/
public Iterator<Entry> getReverseTailEntryIterator(byte[] lastKey, boolean lastInclusive) {
if (lastKey == null || lastKey.length == 0) throw new IllegalArgumentException();
return new EntryIterator(lastKey, lastInclusive, true);
}

/**
* Returns an ascending-order iterator over entries in this radix tree;
* the iterator will include entries whose keys range from {@code firstKey} to {@code lastKey}.
Expand Down Expand Up @@ -713,7 +756,7 @@ public StackItem(NodeEntry[] entries, int prefixLen, Byte radix, boolean hasBlan
this.hasBlank=hasBlank;
this.reversed = reversed;
if (radix != entries[0].radix) this.index = calcIndex(radix);
if (reversed && index == entries.length) index = entries.length - 1;
if (index == entries.length) index = entries.length - 1;
}

int calcIndex(byte radix) {
Expand Down Expand Up @@ -812,7 +855,6 @@ public EntryIterator(boolean reversed) {

void buildCache(Node parent, Node child, Byte radix, Consumer<Long> cleanerFunction) {
StackItem item;
if (reversed && child == null) return;
NodeEntry[] entries = ((InternalNode)parent).getEntries();
if (radix == null && child != null) item = new StackItem(entries, parent.getPrefixLength(), reversed);
else if (child == null) {
Expand All @@ -827,37 +869,39 @@ else if (child == null) {
if (radix != null && child != null && !child.isLeaf()) keyBuf.put(radix);
}

public EntryIterator(byte[] lastKey, boolean lastInclusive) {
this();
public EntryIterator(byte[] lastKey, boolean lastInclusive, boolean reversed) {
this(reversed);
this.lastKey = lastKey;
this.lastInclusive = lastInclusive;
}

public EntryIterator(byte[] firstKey, boolean firstInclusive, byte[] lastKey, boolean lastInclusive, boolean reversed) {
cache = new ArrayDeque<>();
this.reversed = reversed;
Node first = root.getChild();
// lastKey can be null, firstkey is never null as it is checked before calling this
if (lastKey != null) {
int comp = keyCompare(firstKey, lastKey);
if (comp == 0) {
long val = get(firstKey);
next = (val == 0) ? null : new Entry(firstKey, val);
if (firstInclusive && lastInclusive) {
long val = get(firstKey);
next = (val == 0) ? null : new Entry(firstKey, val);
}
return;
}
if (!reversed && comp > 0) throw new IllegalArgumentException();
if (reversed && comp < 0) throw new IllegalArgumentException();
}
if (reversed) {
this.lastKey = firstKey;
firstKey = lastKey;
this.lastInclusive = firstInclusive;
firstInclusive = lastInclusive;
}
else {
this.lastKey = lastKey;
this.lastInclusive = lastInclusive;
if (comp > 0) throw new IllegalArgumentException();
if (reversed) {
this.lastKey = firstKey;
firstKey = lastKey;
this.lastInclusive = firstInclusive;
firstInclusive = lastInclusive;
}
else {
this.lastKey = lastKey;
this.lastInclusive = lastInclusive;
}
}
this.reversed = reversed;

if (first != null) {
if (first.isLeaf()) {
SimpleLeaf leaf = (SimpleLeaf)first;
Expand Down Expand Up @@ -947,7 +991,10 @@ void advanceTo(byte[] firstKey, boolean inclusive) {
if ((inclusive && x == 0) || x < 0) break;
while (cursor.isDone() && cache.size() > 0) {
pop();
if (cursor == null) break;
if (cursor == null) {
if (keyBuf.position() == 0) next = null;
break;
}
}
}
}
Expand Down
Loading

0 comments on commit c9073b2

Please sign in to comment.