File tree Expand file tree Collapse file tree
main/java/org/eclipse/rdf4j/sail/lmdb
test/java/org/eclipse/rdf4j/sail/lmdb Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -45,6 +45,9 @@ class TxnManager {
4545 private static final long READERS_FULL_WAIT_MILLIS = 10L ;
4646
4747 private final Mode mode ;
48+ /**
49+ * Live transactions keyed by reference. The value controls whether {@link #reset()} should renew the transaction.
50+ */
4851 private final IdentityHashMap <Txn , Boolean > active = new IdentityHashMap <>();
4952 private final long [] pool ;
5053 private final StampedLongAdderLockManager lockManager = new StampedLongAdderLockManager ();
@@ -228,7 +231,7 @@ void deactivate() throws IOException {
228231 }
229232
230233 void reset () throws IOException {
231- for (Txn txn : activeTransactions ()) {
234+ for (Txn txn : resettableActiveTransactions ()) {
232235 txn .reset ();
233236 }
234237 }
@@ -239,12 +242,21 @@ private List<Txn> activeTransactions() {
239242 }
240243 }
241244
245+ private List <Txn > resettableActiveTransactions () {
246+ synchronized (active ) {
247+ List <Txn > transactions = new ArrayList <>();
248+ active .forEach ((txn , resetOnWrite ) -> {
249+ if (Boolean .TRUE .equals (resetOnWrite )) {
250+ transactions .add (txn );
251+ }
252+ });
253+ return transactions ;
254+ }
255+ }
256+
242257 private void updateActiveState (Txn txn , boolean isActive ) {
243258 synchronized (active ) {
244- if (active .containsKey (txn )) {
245- active .put (txn , isActive );
246- }
247- if (!isActive ) {
259+ if (active .containsKey (txn ) && !isActive ) {
248260 active .notifyAll ();
249261 }
250262 }
Original file line number Diff line number Diff line change @@ -96,6 +96,36 @@ public void resetDoesNotAbortTrackedInactiveTxn(@TempDir Path dataDir) throws Ex
9696 }
9797 }
9898
99+ @ Test
100+ public void resetSkipsUntrackedReadTxn (@ TempDir Path dataDir ) throws Exception {
101+ long env = openEnv (dataDir , 2 );
102+ TxnManager .Txn trackedTxn = null ;
103+ TxnManager .Txn untrackedTxn = null ;
104+
105+ try {
106+ TxnManager txnManager = new TxnManager (env , TxnManager .Mode .RESET );
107+ trackedTxn = txnManager .createReadTxn ();
108+ untrackedTxn = txnManager .createReadTxnUntracked ();
109+ long trackedVersion = trackedTxn .version ();
110+ long version = untrackedTxn .version ();
111+
112+ txnManager .reset ();
113+
114+ assertEquals (trackedVersion + 1 , trackedTxn .version (),
115+ "Reset must still renew regular tracked transactions" );
116+ assertEquals (version , untrackedTxn .version (),
117+ "Reset must not renew untracked transactions owned by long-running refresh readers" );
118+ } finally {
119+ if (trackedTxn != null ) {
120+ trackedTxn .close ();
121+ }
122+ if (untrackedTxn != null ) {
123+ untrackedTxn .close ();
124+ }
125+ mdb_env_close (env );
126+ }
127+ }
128+
99129 private static long openEnv (Path dataDir , int maxReaders ) throws IOException {
100130 try (MemoryStack stack = stackPush ()) {
101131 PointerBuffer pp = stack .mallocPointer (1 );
You can’t perform that action at this time.
0 commit comments