Skip to content

Commit 4162437

Browse files
committed
fixes
1 parent e7aa496 commit 4162437

7 files changed

Lines changed: 117 additions & 7 deletions

File tree

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,9 @@ private void recoverEstimatorAfterFailure(String action, RuntimeException e) {
779779

780780
@Override
781781
public void close() {
782-
// do nothing
782+
if (nonIsolated && storeTxnStarted.get()) {
783+
clearEstimatorUpdates();
784+
}
783785
}
784786

785787
@Override

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

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,21 +484,48 @@ private SketchBasedJoinEstimator getSketchBasedJoinEstimator() {
484484
}
485485

486486
private DefaultEvaluationStrategyFactory getAutomaticDefaultEvaluationStrategyFactory() {
487+
QueryOptimizerPipeline optimizerPipeline = getAutomaticOptimizerPipeline();
487488
if (defaultEvalStratFactory == null) {
488489
defaultEvalStratFactory = new DefaultEvaluationStrategyFactory(getFederatedServiceResolver());
489-
defaultEvalStratFactory.setOptimizerPipeline(automaticOptimizerPipeline);
490+
}
491+
if (optimizerPipeline != null) {
492+
defaultEvalStratFactory.setOptimizerPipeline(optimizerPipeline);
490493
}
491494
return defaultEvalStratFactory;
492495
}
493496

494497
private LmdbEvaluationStrategyFactory getAutomaticLmdbEvaluationStrategyFactory() {
498+
QueryOptimizerPipeline optimizerPipeline = getAutomaticOptimizerPipeline();
495499
if (lmdbEvalStratFactory == null) {
496500
lmdbEvalStratFactory = new LmdbEvaluationStrategyFactory(getFederatedServiceResolver());
497-
lmdbEvalStratFactory.setOptimizerPipeline(automaticOptimizerPipeline);
501+
}
502+
if (optimizerPipeline != null) {
503+
lmdbEvalStratFactory.setOptimizerPipeline(optimizerPipeline);
498504
}
499505
return lmdbEvalStratFactory;
500506
}
501507

508+
private QueryOptimizerPipeline getAutomaticOptimizerPipeline() {
509+
if (automaticOptimizerPipeline != null) {
510+
return automaticOptimizerPipeline;
511+
}
512+
if (defaultEvalStratFactory != null) {
513+
Optional<QueryOptimizerPipeline> optimizerPipeline = defaultEvalStratFactory.getOptimizerPipeline();
514+
if (optimizerPipeline.isPresent()) {
515+
automaticOptimizerPipeline = optimizerPipeline.get();
516+
return automaticOptimizerPipeline;
517+
}
518+
}
519+
if (lmdbEvalStratFactory != null) {
520+
Optional<QueryOptimizerPipeline> optimizerPipeline = lmdbEvalStratFactory.getOptimizerPipeline();
521+
if (optimizerPipeline.isPresent()) {
522+
automaticOptimizerPipeline = optimizerPipeline.get();
523+
return automaticOptimizerPipeline;
524+
}
525+
}
526+
return null;
527+
}
528+
502529
private void configureEvaluationStrategyFactory(EvaluationStrategyFactory factory) {
503530
factory.setQuerySolutionCacheThreshold(getIterationCacheSyncThreshold());
504531
factory.setTrackResultSize(isTrackResultSize());

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,15 +1243,20 @@ public boolean storeTriple(long subj, long pred, long obj, long context, boolean
12431243
long[] quad = new long[] { subj, pred, obj, context };
12441244
boolean mainExplicitExists = mdb_get(writeTxn, mainIndex.getDB(true), keyVal, dataVal) == MDB_SUCCESS;
12451245
boolean mainInferredExists = mdb_get(writeTxn, mainIndex.getDB(false), keyVal, dataVal) == MDB_SUCCESS;
1246+
boolean statementAdded = !recordExistsInCacheOrMain(recordCache.getRecordState(quad, explicit),
1247+
explicit ? mainExplicitExists : mainInferredExists);
1248+
if (!statementAdded) {
1249+
return false;
1250+
}
12461251
if (explicit) {
12471252
TxnRecordCache.RecordState inferredCacheState = recordCache.getRecordState(quad, false);
1248-
if (inferredCacheState == TxnRecordCache.RecordState.ADD
1249-
|| inferredCacheState == TxnRecordCache.RecordState.ABSENT && mainInferredExists) {
1253+
if (recordExistsInCacheOrMain(inferredCacheState, mainInferredExists)) {
12501254
recordCache.removeRecord(quad, false, true);
12511255
}
12521256
}
12531257
// put record in cache and return immediately
1254-
return recordCache.storeRecord(quad, explicit, explicit ? !mainExplicitExists : !mainInferredExists);
1258+
recordCache.storeRecord(quad, explicit, explicit ? !mainExplicitExists : !mainInferredExists);
1259+
return true;
12551260
}
12561261

12571262
int rc = mdb_put(writeTxn, mainIndex.getDB(explicit), keyVal, dataVal, MDB_NOOVERWRITE);
@@ -1291,6 +1296,11 @@ public boolean storeTriple(long subj, long pred, long obj, long context, boolean
12911296
return stAdded;
12921297
}
12931298

1299+
private boolean recordExistsInCacheOrMain(TxnRecordCache.RecordState cacheState, boolean mainExists) {
1300+
return cacheState == TxnRecordCache.RecordState.ADD
1301+
|| cacheState == TxnRecordCache.RecordState.ABSENT && mainExists;
1302+
}
1303+
12941304
@Experimental
12951305
public void storeTriplesAligned(long[] subj, long[] pred, long[] obj, long[] context, int count, boolean explicit)
12961306
throws IOException {

core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/LmdbOptimizerPipelineTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import static org.junit.jupiter.api.Assertions.assertEquals;
1515
import static org.junit.jupiter.api.Assertions.assertFalse;
1616
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
17+
import static org.junit.jupiter.api.Assertions.assertSame;
1718
import static org.junit.jupiter.api.Assertions.assertTrue;
1819

1920
import java.io.File;
@@ -47,6 +48,7 @@
4748
import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy;
4849
import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategyFactory;
4950
import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer;
51+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizerPipeline;
5052
import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource;
5153
import org.eclipse.rdf4j.query.algebra.evaluation.impl.DefaultEvaluationStrategy;
5254
import org.eclipse.rdf4j.query.algebra.evaluation.impl.DefaultEvaluationStrategyFactory;
@@ -121,6 +123,25 @@ void longLivedConnectionsChooseCurrentAutomaticFactoryPerQueryCreation(@TempDir
121123
}
122124
}
123125

126+
@Test
127+
void automaticFactoryPreservesConfiguredPipelineAfterSketchesBecomeReady(@TempDir File dataDir) throws Exception {
128+
QueryOptimizerPipeline customPipeline = List::of;
129+
LmdbStore store = new LmdbStore(dataDir, new LmdbStoreConfig("spoc"));
130+
store.getEvaluationStrategyFactory().setOptimizerPipeline(customPipeline);
131+
store.init();
132+
try {
133+
addSingleStatement(store, "urn:configured-pipeline");
134+
SketchBasedJoinEstimator estimator = store.getBackingStore().getSketchBasedJoinEstimator();
135+
estimator.stop();
136+
estimator.rebuild();
137+
138+
assertTrue(estimator.isReadyNonBlocking());
139+
assertSame(customPipeline, store.getEvaluationStrategyFactory().getOptimizerPipeline().orElse(null));
140+
} finally {
141+
store.shutDown();
142+
}
143+
}
144+
124145
@Test
125146
void configuredEvaluationStrategyFactoryIsHonored() {
126147
LmdbStoreConfig config = new LmdbStoreConfig();

core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/LmdbSailStoreEstimatorPersistenceTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,52 @@ void noneIsolationAppliesEstimatorUpdatesAcrossSinkFlushes(@TempDir File dataDir
439439
}
440440
}
441441

442+
@Test
443+
void noneIsolationRollbackDiscardsEagerEstimatorUpdates(@TempDir File dataDir) throws Exception {
444+
var vf = SimpleValueFactory.getInstance();
445+
var s = vf.createIRI("urn:rollback:s");
446+
var p = vf.createIRI("urn:rollback:p");
447+
var o = vf.createIRI("urn:rollback:o");
448+
449+
LmdbStore store = new LmdbStore(dataDir, new LmdbStoreConfig("spoc"));
450+
store.init();
451+
try {
452+
LmdbSailStore backingStore = store.getBackingStore();
453+
backingStore.enableMultiThreading = false;
454+
SketchBasedJoinEstimator estimator = backingStore.getSketchBasedJoinEstimator();
455+
try (NotifyingSailConnection conn = store.getConnection()) {
456+
conn.begin(IsolationLevels.NONE);
457+
conn.addStatement(vf.createIRI("urn:rollback:seed"), p, vf.createIRI("urn:rollback:seed-o"));
458+
conn.commit();
459+
}
460+
estimator.stop();
461+
estimator.rebuild();
462+
estimator.setRebuildAllowedSupplier(() -> false);
463+
assertTrue(estimator.isReady());
464+
465+
try (NotifyingSailConnection conn = store.getConnection()) {
466+
conn.begin(IsolationLevels.NONE);
467+
conn.addStatement(s, p, o);
468+
assertEquals(2.0d, estimator.cardinalitySingle(SketchBasedJoinEstimator.Component.P, p.stringValue()),
469+
0.0d,
470+
"NONE isolation applies estimator deltas eagerly before commit");
471+
conn.rollback();
472+
}
473+
474+
assertFalse(estimator.isReadyNonBlocking(),
475+
"Rollback must discard eager non-isolated estimator state");
476+
assertEquals(0.0d, estimator.cardinalitySingle(SketchBasedJoinEstimator.Component.P, p.stringValue()),
477+
0.0d,
478+
"Rolled-back statement must not remain visible to estimator sketches");
479+
try (NotifyingSailConnection conn = store.getConnection()) {
480+
assertFalse(conn.hasStatement(s, p, o, false),
481+
"Rolled-back statement must not remain visible in the store");
482+
}
483+
} finally {
484+
store.shutDown();
485+
}
486+
}
487+
442488
@Test
443489
void commitsAndQueriesSucceedWhileEstimatorIsNotReady(@TempDir File dataDir) throws Exception {
444490
var vf = SimpleValueFactory.getInstance();

core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/SketchEstimatorThemeJoinAccuracyTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ private static LibraryJoinLoadResult loadLibraryThemeIntoDefaultContext(File dat
369369
connection.commit();
370370
}
371371
SketchBasedJoinEstimator estimator = store.getBackingStore().getSketchBasedJoinEstimator();
372+
if (!estimator.isReadyNonBlocking()) {
373+
estimator.rebuild();
374+
}
372375
double leftRows = estimator.estimateCount(SketchBasedJoinEstimator.Component.O, null,
373376
LIBRARY_LOCATED_AT.stringValue(), null, null);
374377
double rightRows = estimator.estimateCount(SketchBasedJoinEstimator.Component.S, null,

core/sail/lmdb/src/test/java/org/eclipse/rdf4j/sail/lmdb/TripleStoreAutoGrowTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ public void testCachedDuplicateExplicitAddKeepsContextCountsBalanced() throws Ex
203203

204204
forceRecordCache(cachedStore);
205205
cachedStore.startTransaction();
206-
cachedStore.storeTriple(subject, predicate, object, context, true);
206+
assertFalse(cachedStore.storeTriple(subject, predicate, object, context, true),
207+
"Cached duplicate explicit add should not report a new statement");
207208
cachedStore.commit();
208209

209210
cachedStore.startTransaction();

0 commit comments

Comments
 (0)