Skip to content

Commit

Permalink
improved binary search
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob Austin committed Apr 3, 2017
1 parent 19b021e commit f543742
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 104 deletions.
229 changes: 165 additions & 64 deletions src/test/java/net/openhft/chronicle/queue/BinarySearch.java
@@ -1,13 +1,15 @@
package net.openhft.chronicle.queue;

import net.openhft.chronicle.queue.impl.single.SingleChronicleQueue;
import net.openhft.chronicle.queue.service.TestSearch;
import net.openhft.chronicle.wire.DocumentContext;
import net.openhft.chronicle.wire.Wire;
import org.jetbrains.annotations.NotNull;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.NavigableSet;

/**
Expand All @@ -19,103 +21,202 @@ public enum BinarySearch {
public <T> long search(@NotNull SingleChronicleQueue q,
@NotNull Wire key,
@NotNull Comparator<Wire> c) throws ParseException {
final long readPosition = key.bytes().readPosition();
try {
final ExcerptTailer tailer = q.createTailer();
final long start = tailer.toStart().index();
final long end = tailer.toEnd().index();

final ExcerptTailer tailer = q.createTailer();
final long start = tailer.toStart().index();
final long end = tailer.toEnd().index();

final int startCycle = q.rollCycle().toCycle(start);
final int endCycle = q.rollCycle().toCycle(end);

if (startCycle == endCycle) {
return findWithinCycle(key, c, start, end, tailer, q.rollCycle());
}

final NavigableSet<Long> cycles = q.listCyclesBetween(startCycle, endCycle);

final int cycle = (int) findCycle(q.rollCycle(), cycles, key, c, tailer);
if (cycle == -1)
return -1;
final int startCycle = q.rollCycle().toCycle(start);
final int endCycle = q.rollCycle().toCycle(end);

final long count = q.exceptsPerCycle(cycle);
if (startCycle == endCycle)
return findWithinCycle(key, c, startCycle, tailer, q);

final long startIndex = q.rollCycle().toIndex(cycle, 0);
final long endIndex = q.rollCycle().toIndex(cycle, count - 1);
final NavigableSet<Long> cycles = q.listCyclesBetween(startCycle, endCycle);


System.out.print(q.rollCycle().toCycle(endIndex));
final int cycle = (int) findCycle(q.rollCycle(), cycles, key, c, tailer);
if (cycle == -1)
return -1;

tailer.direction(TailerDirection.FORWARD);

return findWithinCycle(key, c, startIndex, endIndex, tailer, q.rollCycle());
tailer.direction(TailerDirection.FORWARD);

return findWithinCycle(key, c, cycle, tailer, q);
} finally {
key.bytes().readPosition(readPosition);
}
}


/**
* @param rollCycle
* @param cycles
* @param key
* @param c
* @param tailer
* @return -1 value if not found, otherwise the cycle number
*/
private long findCycle(RollCycle rollCycle, NavigableSet cycles, Wire key, Comparator<Wire> c, ExcerptTailer tailer) {
int low = 0;
int high = cycles.size() - 1;
final ArrayList<Long> arrayList = new ArrayList<>(cycles);

final long readPosition = key.bytes().readPosition();
while (low <= high) {
int mid = (low + high) >>> 1;
final Long midCycle = arrayList.get(mid);
final int midCycle1 = (int) (long) midCycle;
final long index = rollCycle.toIndex(midCycle1, 0);
try (DocumentContext midVal = get(index, tailer)) {

int cmp = c.compare(midVal.wire(), key);
if (cmp == 0 && mid == high)
try {
final SingleChronicleQueue q = ((SingleChronicleQueue) tailer.queue());
int low = 0;
int high = cycles.size() - 1;
final List<Long> arrayList = new ArrayList<>(cycles);

int mid = -1;
Long midCycle = 1L;
while (low <= high) {
mid = (low + high) >>> 1;
midCycle = arrayList.get(mid);
final long index = rollCycle.toIndex((int) (long) midCycle, 0);


tailer.moveToIndex(rollCycle.toIndex((int) (long) arrayList.get(low), 0));
try (final DocumentContext dc = tailer.readingDocument()) {
final TestSearch.MyData myData = new TestSearch.MyData();
dc.wire().getValueIn().marshallable(myData);
System.out.println("findCycle - low=" + myData.toString());
}


tailer.moveToIndex(rollCycle.toIndex((int) (long) arrayList.get(high), 0));
try (final DocumentContext dc = tailer.readingDocument()) {
if (!dc.isPresent())
System.out.println("");
else {
final TestSearch.MyData myData = new TestSearch.MyData();
dc.wire().getValueIn().marshallable(myData);
System.out.println("findCycle - high=" + myData.toString());
}

}


tailer.moveToIndex(index);
try (final DocumentContext dc = tailer.readingDocument()) {
if (!dc.isPresent())
System.out.println("");
else {
final TestSearch.MyData myData = new TestSearch.MyData();
dc.wire().getValueIn().marshallable(myData);
System.out.println("findCycle - mid=" + myData.toString());
}

}

if (low == high) {
return arrayList.get(high);
}

if (low + 1 == high) {

try (DocumentContext dc = moveTo(rollCycle.toIndex((int) (long) arrayList.get(high), 0), tailer)) {
int cmp = c.compare(dc.wire(), key);
if (cmp == 0 || cmp == -1)
return arrayList.get(high);

return arrayList.get(low);
}
}

try (DocumentContext dc = moveTo(index, tailer)) {

key.bytes().readPosition(readPosition);
int cmp = c.compare(dc.wire(), key);

if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else if (low == high - 1)
return arrayList.get(low);
if (cmp < 0) {
low = mid + 1;
} else if (cmp > 0)
high = mid - 1;
else
return midCycle;

} finally {
key.bytes().readPosition(readPosition);
if (low == high)
return arrayList.get(low); // key not found

}
}
if (mid == -1 || low > high)
return -1;

return midCycle;
} finally {
key.bytes().readPosition(readPosition);
}
return -1; // key not found
}


private <T> long findWithinCycle(Wire key, Comparator<Wire> c, long low, long high, ExcerptTailer tailer, final RollCycle rollCycle) {

private long findWithinCycle(Wire key, Comparator<Wire> c, int cycle, ExcerptTailer tailer, SingleChronicleQueue q) {
final long readPosition = key.bytes().readPosition();
while (low <= high) {
long mid = (low + high) >>> 1L;
System.out.println("low" + rollCycle.toSequenceNumber(low) + ",high" + rollCycle.toSequenceNumber(high) + ",mid" + rollCycle.toSequenceNumber(mid));
try (DocumentContext dc = get(mid, tailer)) {
try {
long lowSeqNum = 0;

long highSeqNum = q.exceptsPerCycle(cycle) - 1;
if (highSeqNum == 0)
return q.rollCycle().toIndex(cycle, 0);

tailer.moveToIndex(q.rollCycle().toIndex(cycle, 0));
try (final DocumentContext dc = tailer.readingDocument()) {
final TestSearch.MyData myData = new TestSearch.MyData();
dc.wire().getValueIn().marshallable(myData);
System.out.println("findWithinCycle - low=" + myData.toString());
}


tailer.moveToIndex(q.rollCycle().toIndex(cycle, highSeqNum));
try (final DocumentContext dc = tailer.readingDocument()) {
if (!dc.isPresent())
return -1;
int cmp = c.compare(dc.wire(), key);


if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
} finally {
key.bytes().readPosition(readPosition);
System.out.println("");
else {
final TestSearch.MyData myData = new TestSearch.MyData();
dc.wire().getValueIn().marshallable(myData);
System.out.println("findWithinCycle - hig=" + myData.toString());
}

}


final RollCycle rollCycle = q.rollCycle();

while (lowSeqNum <= highSeqNum) {
long midSeqNumber = (lowSeqNum + highSeqNum) >>> 1L;
System.out.println("lowSeqNum" + lowSeqNum + ",highSeqNum=" + highSeqNum + ",midSeqNum=" + midSeqNumber);

final long midIndex = rollCycle.toIndex(cycle, midSeqNumber);
try (DocumentContext dc = moveTo(midIndex, tailer)) {
if (!dc.isPresent())
return -1;
key.bytes().readPosition(readPosition);
int cmp = c.compare(dc.wire(), key);

if (cmp < 0)
lowSeqNum = midSeqNumber + 1;
else if (cmp > 0)
highSeqNum = midSeqNumber - 1;
else
return midIndex; // key found
}

}
return -1; // key not found
} finally {
key.bytes().readPosition(readPosition);
}
return -1; // key not found
}


/**
* Gets the ith element from the given list by repositioning the specified
* list listIterator.
*/
private DocumentContext get(long index, final ExcerptTailer tailer) {
tailer.moveToIndex(index);

private DocumentContext moveTo(long index, final ExcerptTailer tailer) {
final boolean b = tailer.moveToIndex(index);
assert b;
return tailer.readingDocument();
}

Expand Down
Expand Up @@ -15,8 +15,11 @@
*/
package net.openhft.chronicle.queue;

import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.queue.impl.single.Utils;
import net.openhft.chronicle.wire.WireKey;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Rule;
import org.junit.rules.*;
import org.junit.runner.Description;
Expand Down Expand Up @@ -59,11 +62,41 @@ protected void starting(Description description) {
//
// *************************************************************************

static void deleteDir(@NotNull String... dirs) {
for (String dir : dirs) {
try {
deleteDir(new File(dir));
} catch (Exception e) {
Jvm.warn().on(ChronicleQueueTestBase.class, e);
}
}

}

public static void deleteDir(@NotNull File dir) {
if (dir.isDirectory()) {
@Nullable File[] files = dir.listFiles();
if (files != null) {
for (@NotNull File file : files) {
if (file.isDirectory()) {
deleteDir(file);
} else
//noinspection ResultOfMethodCallIgnored
file.delete();
}
}
}

dir.delete();
}

protected File getTmpDir() {
return Utils.tempDir(testName.getMethodName());
}


public enum TestKey implements WireKey {
test, test2
}

}

0 comments on commit f543742

Please sign in to comment.