Skip to content

Commit 68f8d49

Browse files
committed
Adapt iterator to storage layout.
1 parent 46f9a19 commit 68f8d49

2 files changed

Lines changed: 60 additions & 30 deletions

File tree

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

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ static class State {
6868

6969
private final MDBVal valueData = MDBVal.malloc();
7070

71+
private ByteBuffer valueBuf;
72+
7173
private final ByteBuffer minKeyBuf = MemoryUtil.memAlloc((Long.BYTES + 1) * 4);
7274

7375
private final ByteBuffer minValueBuf = MemoryUtil.memAlloc((Long.BYTES + 1) * 4);
@@ -203,12 +205,19 @@ public long[] next() {
203205

204206
boolean isDupValue = false;
205207
if (fetchNext) {
206-
lastResult = mdb_cursor_get(state.cursor, state.keyData, state.valueData, MDB_NEXT_DUP);
207-
if (lastResult != MDB_SUCCESS) {
208-
// no more duplicates, move to next key
209-
lastResult = mdb_cursor_get(state.cursor, state.keyData, state.valueData, MDB_NEXT_NODUP);
208+
if (!state.valueBuf.hasRemaining()) {
209+
lastResult = mdb_cursor_get(state.cursor, state.keyData, state.valueData, MDB_NEXT_DUP);
210+
if (lastResult != MDB_SUCCESS) {
211+
// no more duplicates, move to next key
212+
lastResult = mdb_cursor_get(state.cursor, state.keyData, state.valueData, MDB_NEXT_NODUP);
213+
} else {
214+
isDupValue = true;
215+
}
216+
if (lastResult == MDB_SUCCESS) {
217+
state.valueBuf = state.valueData.mv_data();
218+
}
210219
} else {
211-
isDupValue = true;
220+
lastResult = MDB_SUCCESS;
212221
}
213222
fetchNext = false;
214223
} else {
@@ -231,31 +240,56 @@ public long[] next() {
231240
// set cursor to first item
232241
lastResult = mdb_cursor_get(state.cursor, state.keyData, state.valueData, MDB_FIRST);
233242
}
243+
if (lastResult == MDB_SUCCESS) {
244+
state.valueBuf = state.valueData.mv_data();
245+
}
234246
}
235247

236248
while (lastResult == MDB_SUCCESS) {
237-
// if (maxKey != null && TripleStore.COMPARATOR.compare(keyData.mv_data(), maxKey.mv_data()) > 0) {
238-
int keyDiff;
239-
if (state.indexScore > 0 &&
240-
(keyDiff = isDupValue ? 0 : mdb_cmp(state.txn, state.dbi, state.keyData, state.maxKey)) >= 0
241-
&& (keyDiff > 0 || mdb_dcmp(state.txn, state.dbi, state.valueData, state.maxValue) > 0)) {
242-
lastResult = MDB_NOTFOUND;
243-
} else if (notMatches(isDupValue)) {
244-
// value doesn't match search key/mask, fetch next value
249+
if (state.indexScore > 0) {
250+
int keyDiff = isDupValue ? 0 : mdb_cmp(state.txn, state.dbi, state.keyData, state.maxKey);
251+
if (keyDiff > 0) {
252+
break;
253+
}
254+
int valueDiff = TripleStore.compareRegion(state.valueBuf, state.valueBuf.position(),
255+
state.maxValueBuf, 0,
256+
Math.min(state.valueBuf.remaining(), state.maxValueBuf.remaining()));
257+
if (valueDiff > 0) {
258+
break;
259+
}
260+
}
261+
262+
// value doesn't match search key/mask, fetch next value
263+
if (!state.valueBuf.hasRemaining()) {
245264
lastResult = mdb_cursor_get(state.cursor, state.keyData, state.valueData, MDB_NEXT_DUP);
246265
if (lastResult != MDB_SUCCESS) {
247266
// no more duplicates, move to next key
248267
lastResult = mdb_cursor_get(state.cursor, state.keyData, state.valueData, MDB_NEXT_NODUP);
249268
isDupValue = false;
250269
}
251-
} else {
252-
// Matching value found
253-
state.index.entryToQuad(state.keyData.mv_data(), state.valueData.mv_data(), state.patternQuad,
254-
state.quad);
255-
// fetch next value
256-
fetchNext = true;
257-
return state.quad;
270+
if (lastResult == MDB_SUCCESS) {
271+
state.valueBuf = state.valueData.mv_data();
272+
} else {
273+
break;
274+
}
258275
}
276+
277+
int valueBufPos = state.valueBuf.position();
278+
if (notMatches(isDupValue, isDupValue ? null : state.keyData.mv_data(), state.valueBuf)) {
279+
state.valueBuf.position(valueBufPos);
280+
int skip = 4 - state.index.getIndexSplitPosition();
281+
for (int i = 0; i < skip; i++) {
282+
TripleStore.skipVarint(state.valueBuf);
283+
}
284+
continue;
285+
}
286+
state.valueBuf.position(valueBufPos);
287+
288+
// Matching value found
289+
state.index.entryToQuad(state.keyData.mv_data(), state.valueBuf, state.patternQuad, state.quad);
290+
// fetch next value
291+
fetchNext = true;
292+
return state.quad;
259293
}
260294
closeInternal(false);
261295
return null;
@@ -264,18 +298,14 @@ public long[] next() {
264298
}
265299
}
266300

267-
private boolean notMatches(boolean testValueOnly) {
301+
private boolean notMatches(boolean testValueOnly, ByteBuffer keyBuf, ByteBuffer valueBuf) {
268302
if (state.matcher != null) {
269-
if (testValueOnly) {
270-
// already positioned on correct key, no need to match key again
271-
return !state.matcher.matchesValue(state.valueData.mv_data());
272-
}
273-
return !state.matcher.matches(state.keyData.mv_data(), state.valueData.mv_data());
303+
return testValueOnly ? !state.matcher.matchesValue(valueBuf) : !state.matcher.matches(keyBuf, valueBuf);
274304
} else if (state.matchValues) {
275305
// lazy init of group matcher
276306
state.matcher = state.index.createMatcher(state.patternQuad[0], state.patternQuad[1], state.patternQuad[2],
277307
state.patternQuad[3]);
278-
return !state.matcher.matches(state.keyData.mv_data(), state.valueData.mv_data());
308+
return testValueOnly ? !state.matcher.matchesValue(valueBuf) : !state.matcher.matches(keyBuf, valueBuf);
279309
} else {
280310
return false;
281311
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ private int merge(long cursor, int elements, MDBVal keyVal, MDBVal dataVal, Byte
930930
if (insertPos > 0) {
931931
// copy existing elements and insert new elements in between
932932
target.clear();
933-
target.put(existing.slice().flip());
933+
target.put(existing.duplicate().flip());
934934
target.put(newValueBuf);
935935
if (existing.hasRemaining()) {
936936
target.put(existing);
@@ -994,15 +994,15 @@ private int merge(long cursor, int elements, MDBVal keyVal, MDBVal dataVal, Byte
994994
return MDB_SUCCESS;
995995
}
996996

997-
private static int compareRegion(ByteBuffer bb1, int startIdx1, ByteBuffer bb2, int startIdx2, int length) {
997+
static int compareRegion(ByteBuffer bb1, int startIdx1, ByteBuffer bb2, int startIdx2, int length) {
998998
int result = 0;
999999
for (int i = 0; result == 0 && i < length; i++) {
10001000
result = (bb1.get(startIdx1 + i) & 0xff) - (bb2.get(startIdx2 + i) & 0xff);
10011001
}
10021002
return result;
10031003
}
10041004

1005-
private void skipVarint(ByteBuffer other) {
1005+
static void skipVarint(ByteBuffer other) {
10061006
int i = firstToLength(other.get()) - 1;
10071007
assert i >= 0;
10081008
if (i > 0) {

0 commit comments

Comments
 (0)