Skip to content

Commit 6f953d9

Browse files
committed
First sketch of MDB_DUPSORT.
1 parent d61fb7a commit 6f953d9

File tree

11 files changed

+897
-1098
lines changed

11 files changed

+897
-1098
lines changed

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbRecordIterator.java

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
package org.eclipse.rdf4j.sail.lmdb;
1212

1313
import static org.eclipse.rdf4j.sail.lmdb.LmdbUtil.E;
14+
import static org.lwjgl.util.lmdb.LMDB.MDB_GET_BOTH_RANGE;
1415
import static org.lwjgl.util.lmdb.LMDB.MDB_NEXT;
1516
import static org.lwjgl.util.lmdb.LMDB.MDB_NOTFOUND;
1617
import static org.lwjgl.util.lmdb.LMDB.MDB_SET;
@@ -21,6 +22,7 @@
2122
import static org.lwjgl.util.lmdb.LMDB.mdb_cursor_get;
2223
import static org.lwjgl.util.lmdb.LMDB.mdb_cursor_open;
2324
import static org.lwjgl.util.lmdb.LMDB.mdb_cursor_renew;
25+
import static org.lwjgl.util.lmdb.LMDB.mdb_dcmp;
2426

2527
import java.io.IOException;
2628
import java.nio.ByteBuffer;
@@ -53,6 +55,7 @@ class LmdbRecordIterator implements RecordIterator {
5355
private final long cursor;
5456

5557
private final MDBVal maxKey;
58+
private final MDBVal maxValue;
5659

5760
private final boolean matchValues;
5861
private GroupMatcher groupMatcher;
@@ -73,44 +76,60 @@ class LmdbRecordIterator implements RecordIterator {
7376

7477
private ByteBuffer minKeyBuf;
7578

79+
private ByteBuffer minValueBuf;
80+
7681
private ByteBuffer maxKeyBuf;
7782

83+
private ByteBuffer maxValueBuf;
84+
7885
private int lastResult;
7986

8087
private final long[] quad;
81-
private final long[] originalQuad;
88+
private final long[] patternQuad;
8289

8390
private boolean fetchNext = false;
8491

8592
private final StampedLongAdderLockManager txnLockManager;
8693

8794
private final Thread ownerThread = Thread.currentThread();
8895

89-
LmdbRecordIterator(TripleIndex index, boolean rangeSearch, long subj, long pred, long obj,
96+
private final int indexScore;
97+
98+
LmdbRecordIterator(TripleIndex index, int indexScore, long subj, long pred, long obj,
9099
long context, boolean explicit, Txn txnRef) throws IOException {
91100
this.subj = subj;
92101
this.pred = pred;
93102
this.obj = obj;
94103
this.context = context;
95-
this.originalQuad = new long[] { subj, pred, obj, context };
104+
this.patternQuad = new long[] { subj, pred, obj, context };
96105
this.quad = new long[] { subj, pred, obj, context };
97106
this.pool = Pool.get();
98107
this.keyData = pool.getVal();
99108
this.valueData = pool.getVal();
100109
this.index = index;
101-
if (rangeSearch) {
110+
this.indexScore = indexScore;
111+
// prepare min and max keys if index can be used
112+
// otherwise, leave as null to indicate full scan
113+
if (indexScore > 0) {
102114
minKeyBuf = pool.getKeyBuffer();
103-
index.getMinKey(minKeyBuf, subj, pred, obj, context);
115+
minValueBuf = pool.getKeyBuffer();
116+
index.getMinEntry(minKeyBuf, minValueBuf, subj, pred, obj, context);
104117
minKeyBuf.flip();
118+
minValueBuf.flip();
105119

106120
this.maxKey = pool.getVal();
121+
this.maxValue = pool.getVal();
107122
this.maxKeyBuf = pool.getKeyBuffer();
108-
index.getMaxKey(maxKeyBuf, subj, pred, obj, context);
123+
this.maxValueBuf = pool.getKeyBuffer();
124+
index.getMaxEntry(maxKeyBuf, maxValueBuf, subj, pred, obj, context);
109125
maxKeyBuf.flip();
126+
maxValueBuf.flip();
110127
this.maxKey.mv_data(maxKeyBuf);
128+
this.maxValue.mv_data(maxValueBuf);
111129
} else {
112130
minKeyBuf = null;
113131
this.maxKey = null;
132+
this.maxValue = null;
114133
}
115134

116135
this.matchValues = subj > 0 || pred > 0 || obj > 0 || context >= 0;
@@ -163,13 +182,15 @@ public long[] next() {
163182
minKeyBuf = pool.getKeyBuffer();
164183
}
165184
minKeyBuf.clear();
166-
index.toKey(minKeyBuf, quad[0], quad[1], quad[2], quad[3]);
185+
index.toEntry(minKeyBuf, minValueBuf, quad[0], quad[1], quad[2], quad[3]);
167186
minKeyBuf.flip();
187+
minValueBuf.flip();
168188
keyData.mv_data(minKeyBuf);
169-
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_SET);
170-
if (lastResult != MDB_SUCCESS) {
171-
// use MDB_SET_RANGE if key was deleted
172-
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_SET_RANGE);
189+
// use set range if entry was deleted
190+
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_SET_RANGE);
191+
if (lastResult == MDB_SUCCESS) {
192+
valueData.mv_data(minValueBuf);
193+
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_GET_BOTH_RANGE);
173194
}
174195
if (lastResult != MDB_SUCCESS) {
175196
closeInternal(false);
@@ -187,7 +208,12 @@ public long[] next() {
187208
if (minKeyBuf != null) {
188209
// set cursor to min key
189210
keyData.mv_data(minKeyBuf);
190-
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_SET_RANGE);
211+
lastResult = indexScore >= 2 ? MDB_SUCCESS
212+
: mdb_cursor_get(cursor, keyData, valueData, MDB_SET_RANGE);
213+
if (lastResult == MDB_SUCCESS) {
214+
valueData.mv_data(minValueBuf);
215+
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_GET_BOTH_RANGE);
216+
}
191217
} else {
192218
// set cursor to first item
193219
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_NEXT);
@@ -196,14 +222,17 @@ public long[] next() {
196222

197223
while (lastResult == MDB_SUCCESS) {
198224
// if (maxKey != null && TripleStore.COMPARATOR.compare(keyData.mv_data(), maxKey.mv_data()) > 0) {
199-
if (maxKey != null && mdb_cmp(txn, dbi, keyData, maxKey) > 0) {
225+
int keyDiff;
226+
if (maxKey != null &&
227+
(keyDiff = mdb_cmp(txn, dbi, keyData, maxKey)) >= 0
228+
&& (keyDiff > 0 || mdb_dcmp(txn, dbi, valueData, maxValue) > 0)) {
200229
lastResult = MDB_NOTFOUND;
201-
} else if (matches()) {
230+
} else if (notMatches()) {
202231
// value doesn't match search key/mask, fetch next value
203232
lastResult = mdb_cursor_get(cursor, keyData, valueData, MDB_NEXT);
204233
} else {
205234
// Matching value found
206-
index.keyToQuad(keyData.mv_data(), originalQuad, quad);
235+
index.entryToQuad(keyData.mv_data(), valueData.mv_data(), patternQuad, quad);
207236
// fetch next value
208237
fetchNext = true;
209238
return quad;
@@ -216,13 +245,13 @@ public long[] next() {
216245
}
217246
}
218247

219-
private boolean matches() {
220-
248+
private boolean notMatches() {
221249
if (groupMatcher != null) {
222-
return !this.groupMatcher.matches(keyData.mv_data());
250+
return !this.groupMatcher.matches(keyData.mv_data(), valueData.mv_data());
223251
} else if (matchValues) {
252+
// lazy init of group matcher
224253
this.groupMatcher = index.createMatcher(subj, pred, obj, context);
225-
return !this.groupMatcher.matches(keyData.mv_data());
254+
return !this.groupMatcher.matches(keyData.mv_data(), valueData.mv_data());
226255
} else {
227256
return false;
228257
}
@@ -247,10 +276,13 @@ private void closeInternal(boolean maybeCalledAsync) {
247276
pool.free(valueData);
248277
if (minKeyBuf != null) {
249278
pool.free(minKeyBuf);
279+
pool.free(minValueBuf);
250280
}
251281
if (maxKey != null) {
252282
pool.free(maxKeyBuf);
253283
pool.free(maxKey);
284+
pool.free(maxValueBuf);
285+
pool.free(maxValue);
254286
}
255287
}
256288
} finally {

0 commit comments

Comments
 (0)