-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Test Python
-
None
-
Storage Engines - Transactions
-
255.644
-
SE Transactions - 2026-08-28
-
2
Symptom
FAIL: test_layered_cursor19.test_layered_cursor19.test_follower_insert_overwrite_does_not_open_stable(palite) AssertionError: 0 != 1 : overwrite=true insert on a follower opened 0 cursors, expected 1 (ingest only); delta > 1 means the stable cursor was opened unnecessarily
Cause
This is a test bug, not a product bug.
stat.conn.cursor_open_count is not a monotonic counter. conn_stat.c:88 reports the live gauge conn->open_cursor_count:
cursor_open_count, __wt_atomic_load_uint32_relaxed(&conn->open_cursor_count)
The test's measure_cursor_opens() differences that gauge across the operation, so it measures the net change in all cursors open on the follower connection, not the opens performed by the operation. Any other thread that holds a cursor open at the before sample and closes it before the after sample contributes -1 and cancels the +1 from the ingest open, giving the observed 0.
The test configures the interfering thread itself: conn_base_config sets statistics_log=(wait=1,json=true,on_close=true) on both connections, and the statlog server opens and closes a statistics cursor once a second (_wt_curstat_open in _statlog_dump, conn_stat.c:353). The follower's checkpoint-pickup and layered-table-manager work is a second, less frequent source.
The write path itself is correct. The ingest cursor is opened lazily on the first write in _clayered_update_ingest() -> clayered_open_ingest() (cur_layered.c:1142), and a cursor-cache hit still bumps the gauge (_wti_cursor_reopen(), cur_std.c:790), so there is no path on which a correct run legitimately opens zero cursors.
Fix
Measure the property the test is actually about instead of a global gauge. layered_curs_open_stable is incremented only where a layered cursor first opens its stable constituent (cur_layered.c:1218), which is exactly the "did we touch stable" question; the overwrite=true cases assert the counter does not move and the overwrite=false cases assert it does. It is a monotonic counter, so a concurrent open cannot cancel it out. This is the idiom already used by test_layered_follower16/17/18 and test_layered_stepup09.
Also drop statistics_log from the test's connection config - it removes the once-a-second background cursor churn on both connections and the test never reads the log.