@@ -70,6 +70,8 @@ class LmdbTxnContext {
7070 private boolean overlayChanges ;
7171 private boolean snapshotReadMode ;
7272 private boolean snapshotWriteMode ;
73+ private boolean pinnedSnapshotTransactionScoped ;
74+ private int pinnedSnapshotRefCount ;
7375 private long ownerThreadId = -1 ;
7476
7577 private Txn pinnedTripleReadTxn ;
@@ -92,10 +94,13 @@ void init(IsolationLevel level) throws SailException {
9294 this .level = level ;
9395 initialized = true ;
9496 snapshotWriteMode = IsolationLevels .SNAPSHOT .equals (level );
95- snapshotReadMode = snapshotWriteMode || IsolationLevels .SNAPSHOT_READ .equals (level )
96- || IsolationLevels .SERIALIZABLE .equals (level );
97- if (snapshotReadMode ) {
97+ boolean serializable = IsolationLevels .SERIALIZABLE .equals (level );
98+ snapshotReadMode = snapshotWriteMode || IsolationLevels .SNAPSHOT_READ .equals (level ) || serializable ;
99+ if (snapshotWriteMode || serializable ) {
98100 ensurePinnedReadSnapshot ();
101+ pinnedSnapshotTransactionScoped = true ;
102+ }
103+ if (snapshotReadMode ) {
99104 deferWrites = true ;
100105 overlayChanges = true ;
101106 }
@@ -157,6 +162,10 @@ Txn acquireReadTxn(IsolationLevel level) throws SailException {
157162 init (level );
158163 verifyThread ();
159164 try {
165+ if (snapshotReadMode && !pinnedSnapshotTransactionScoped ) {
166+ ensurePinnedReadSnapshot ();
167+ pinnedSnapshotRefCount ++;
168+ }
160169 if (pinnedTripleReadTxn != null ) {
161170 return store .getTripleStore ().getTxnManager ().createTxn (pinnedTripleReadTxn .get ());
162171 }
@@ -321,6 +330,18 @@ private void checkSerializableConflicts() throws SailException {
321330 }
322331 }
323332
333+ void releaseReadSnapshot () {
334+ if (!snapshotReadMode || pinnedSnapshotTransactionScoped ) {
335+ return ;
336+ }
337+ if (pinnedSnapshotRefCount > 0 ) {
338+ pinnedSnapshotRefCount --;
339+ }
340+ if (pinnedSnapshotRefCount == 0 ) {
341+ closePinnedReadSnapshot ();
342+ }
343+ }
344+
324345 void rollback () throws SailException {
325346 if (finished ) {
326347 return ;
@@ -519,14 +540,9 @@ private void cleanup() {
519540 overlayChanges = false ;
520541 snapshotReadMode = false ;
521542 snapshotWriteMode = false ;
522- if (pinnedTripleReadTxn != null ) {
523- pinnedTripleReadTxn .close ();
524- pinnedTripleReadTxn = null ;
525- }
526- if (pinnedValueReadTxn != null ) {
527- store .getValueStore ().clearPinnedReadTxn (pinnedValueReadTxn );
528- pinnedValueReadTxn = null ;
529- }
543+ pinnedSnapshotTransactionScoped = false ;
544+ pinnedSnapshotRefCount = 0 ;
545+ closePinnedReadSnapshot ();
530546 releaseWriteLock ();
531547 }
532548
@@ -540,18 +556,13 @@ private void resetStateForNewTransaction() {
540556 overlayChanges = false ;
541557 snapshotReadMode = false ;
542558 snapshotWriteMode = false ;
559+ pinnedSnapshotTransactionScoped = false ;
560+ pinnedSnapshotRefCount = 0 ;
543561 observedExplicit = null ;
544562 observedInferred = null ;
545563 ownerThreadId = -1 ;
546564 clearStatementChanges ();
547- if (pinnedTripleReadTxn != null ) {
548- pinnedTripleReadTxn .close ();
549- pinnedTripleReadTxn = null ;
550- }
551- if (pinnedValueReadTxn != null ) {
552- store .getValueStore ().clearPinnedReadTxn (pinnedValueReadTxn );
553- pinnedValueReadTxn = null ;
554- }
565+ closePinnedReadSnapshot ();
555566 }
556567
557568 private void releaseWriteLock () {
@@ -574,6 +585,17 @@ private void rollbackSilently() {
574585 }
575586 }
576587
588+ private void closePinnedReadSnapshot () {
589+ if (pinnedTripleReadTxn != null ) {
590+ pinnedTripleReadTxn .close ();
591+ pinnedTripleReadTxn = null ;
592+ }
593+ if (pinnedValueReadTxn != null ) {
594+ store .getValueStore ().clearPinnedReadTxn (pinnedValueReadTxn );
595+ pinnedValueReadTxn = null ;
596+ }
597+ }
598+
577599 private void clearStatementChanges () {
578600 addedExplicit .clear ();
579601 removedExplicit .clear ();
@@ -665,8 +687,10 @@ private void applyPendingDeprecatedTo(Set<Quad> deprecated, boolean explicit) {
665687 private boolean existsInStore (Quad quad , boolean explicit ) {
666688 store .acquireCommitReadLock ();
667689 Txn txn = null ;
690+ boolean releaseSnapshot = false ;
668691 try {
669692 txn = acquireReadTxn (level );
693+ releaseSnapshot = snapshotReadMode && !pinnedSnapshotTransactionScoped ;
670694 ValueStore valueStore = store .getValueStore ();
671695 long subjId = valueStore .getId (quad .subj , false );
672696 if (subjId == LmdbValue .UNKNOWN_ID ) {
@@ -702,6 +726,9 @@ private boolean existsInStore(Quad quad, boolean explicit) {
702726 if (txn != null ) {
703727 txn .close ();
704728 }
729+ if (releaseSnapshot ) {
730+ releaseReadSnapshot ();
731+ }
705732 store .releaseCommitReadLock ();
706733 }
707734 }
0 commit comments