Skip to content

[fix](be) Harden JNI reader split lifecycle#65503

Open
Gabriel39 wants to merge 4 commits into
apache:masterfrom
Gabriel39:agent/fix-jni-reader-contracts
Open

[fix](be) Harden JNI reader split lifecycle#65503
Gabriel39 wants to merge 4 commits into
apache:masterfrom
Gabriel39:agent/fix-jni-reader-contracts

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

JNI-backed file scans had several lifecycle, compatibility, and adaptive-batching gaps:

  • FileScannerV2 could select Paimon C++ JNI splits that it cannot dispatch. This also affected rolling upgrades where Paimon metadata and the reader type exist only at split level.
  • A cancelled query could continue requesting Java batches when every row in the current batches was filtered out.
  • JNI open or close failures could discard cleanup state or mark the outer scanner closed too early, preventing retained Java resources from being cleaned up on a retry.
  • Adaptive batch-size changes did not consistently reach already-open JNI scanners and Paimon/Hudi hybrid readers. For Paimon, the initial probe could arrive after Java open, so the first physical read still used the full runtime batch size.
  • End-of-split state could be lost after the JNI scanner closed, making repeated reads after EOF non-idempotent.
  • Paimon options and Hadoop configuration supplied at split level were not retained as mixed-version fallback values.

This PR hardens those paths by:

  • conservatively keeping JNI scans on the legacy scanner while the Paimon C++ reader option is enabled, and rejecting unsupported Paimon C++ ranges in FileScannerV2;
  • checking cancellation before fetching another Java batch;
  • preserving JNI cleanup state after failures and allowing scanner-level close to retry table-reader cleanup;
  • seeding the adaptive probe before eager JNI open and forwarding later batch-size updates to open JNI and hybrid readers;
  • preserving EOF state across scanner cleanup; and
  • applying explicit precedence between current scan-level Paimon settings and split-level rolling-upgrade fallbacks.

Release note

Harden JNI table-reader lifecycle handling, adaptive batching, and rolling-upgrade compatibility for Paimon and Hudi scans.

Check List

  • Added comments for scanner-selection, lifecycle, adaptive-batch, and compatibility invariants.
  • Added focused unit tests covering cancellation, EOF idempotence, cleanup failure and retry, adaptive batching, scanner selection, and Paimon fallback precedence.
  • Passed the original 45 focused ASAN BE unit tests from 7 suites.
  • Passed an additional 20 ASAN BE unit tests for FileScannerV2Test.* and JniTableReaderTest.* after addressing review feedback.
  • Passed build-support/check-format.sh and git diff --check.
  • Ran changed-file clang-tidy; analysis is blocked by the existing toolchain missing stddef.h and pre-existing repository diagnostics.

### What problem does this PR solve?

JNI-backed table readers could violate scanner selection, cancellation, cleanup, EOF, adaptive batching, and rolling-upgrade contracts.

Issue Number: N/A

Related PR: N/A

### Release note

Harden JNI table-reader lifecycle handling and compatibility for Paimon and Hudi scans.

### Check List

- [x] Added unit tests for the fixes
- [x] Added comments for compatibility and lifecycle invariants
- [x] Passed 45 focused ASAN BE unit tests
- [x] Passed repository format and diff checks
@Gabriel39 Gabriel39 requested a review from yiguolei as a code owner July 12, 2026 14:15
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at 5:19 PM.
Workflow run: https://github.com/apache/doris/actions/runs/29195932553

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at 5:19 PM.
Workflow run: https://github.com/apache/doris/actions/runs/29196846018

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 30004 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit f4dd46c9839e89e245846a4a58308e8de5482540, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17707	4099	4333	4099
q2	2026	341	209	209
q3	10274	1417	850	850
q4	4686	471	339	339
q5	7499	879	564	564
q6	179	172	139	139
q7	771	905	625	625
q8	9317	1557	1569	1557
q9	5652	4438	4430	4430
q10	6757	1796	1564	1564
q11	511	349	317	317
q12	699	566	439	439
q13	18086	3399	2767	2767
q14	263	259	240	240
q15	q16	791	783	711	711
q17	1000	999	1054	999
q18	7483	5624	5630	5624
q19	1306	1214	1069	1069
q20	768	613	554	554
q21	6383	2896	2581	2581
q22	460	367	327	327
Total cold run time: 102618 ms
Total hot run time: 30004 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5080	4753	4897	4753
q2	318	320	213	213
q3	5084	5272	4566	4566
q4	2076	2133	1396	1396
q5	5016	4662	4765	4662
q6	224	187	136	136
q7	1863	1698	1580	1580
q8	2519	2354	2206	2206
q9	7751	7339	7255	7255
q10	4627	4585	4145	4145
q11	539	402	356	356
q12	736	740	530	530
q13	2953	3396	2712	2712
q14	274	284	249	249
q15	q16	685	695	600	600
q17	1297	1272	1274	1272
q18	7347	7040	6870	6870
q19	1117	1086	1041	1041
q20	2228	2186	1960	1960
q21	5313	4604	4489	4489
q22	531	473	415	415
Total cold run time: 57578 ms
Total hot run time: 51406 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 180273 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit f4dd46c9839e89e245846a4a58308e8de5482540, data reload: false

query5	4310	646	481	481
query6	452	226	201	201
query7	4831	594	336	336
query8	350	195	175	175
query9	8762	4102	4078	4078
query10	457	356	310	310
query11	5960	2394	2135	2135
query12	160	103	99	99
query13	1252	602	409	409
query14	6205	5282	4970	4970
query14_1	4254	4261	4269	4261
query15	207	206	179	179
query16	1034	464	435	435
query17	923	742	560	560
query18	2469	458	344	344
query19	200	184	142	142
query20	115	106	103	103
query21	228	154	131	131
query22	13631	13530	13380	13380
query23	17379	16516	16159	16159
query23_1	16319	16353	16306	16306
query24	7572	1797	1300	1300
query24_1	1332	1311	1309	1309
query25	588	466	398	398
query26	1330	351	217	217
query27	2636	587	387	387
query28	4436	2035	2064	2035
query29	1092	645	503	503
query30	338	267	231	231
query31	1131	1093	984	984
query32	111	66	61	61
query33	536	331	268	268
query34	1179	1201	665	665
query35	787	789	659	659
query36	1411	1386	1205	1205
query37	152	111	95	95
query38	1899	1693	1650	1650
query39	929	935	876	876
query39_1	902	875	881	875
query40	254	165	141	141
query41	71	71	70	70
query42	95	95	93	93
query43	326	342	295	295
query44	1502	802	782	782
query45	205	188	181	181
query46	1092	1226	791	791
query47	2364	2365	2180	2180
query48	419	411	306	306
query49	601	434	323	323
query50	1130	415	331	331
query51	10978	10940	10902	10902
query52	89	90	77	77
query53	276	284	205	205
query54	309	261	228	228
query55	77	74	70	70
query56	313	316	291	291
query57	1414	1402	1314	1314
query58	297	278	255	255
query59	1594	1640	1464	1464
query60	326	282	269	269
query61	192	147	138	138
query62	702	640	581	581
query63	242	202	204	202
query64	2826	1056	866	866
query65	4880	4729	4775	4729
query66	1795	508	389	389
query67	29771	29409	29312	29312
query68	3105	1545	1035	1035
query69	398	306	260	260
query70	1033	960	954	954
query71	372	335	320	320
query72	3103	2771	2384	2384
query73	806	805	433	433
query74	5100	4980	4740	4740
query75	2621	2595	2233	2233
query76	2313	1190	764	764
query77	360	383	283	283
query78	12298	12432	11704	11704
query79	1380	1201	780	780
query80	1298	541	450	450
query81	527	315	274	274
query82	594	161	125	125
query83	403	323	295	295
query84	322	157	127	127
query85	976	641	509	509
query86	422	298	280	280
query87	1832	1821	1727	1727
query88	3727	2837	2790	2790
query89	454	405	359	359
query90	1932	203	201	201
query91	211	193	165	165
query92	65	69	55	55
query93	1572	1521	976	976
query94	721	363	324	324
query95	769	578	465	465
query96	1048	834	364	364
query97	2670	2676	2541	2541
query98	219	202	197	197
query99	1139	1185	1026	1026
Total cold run time: 266138 ms
Total hot run time: 180273 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.99 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit f4dd46c9839e89e245846a4a58308e8de5482540, data reload: false

query1	0.01	0.00	0.01
query2	0.10	0.05	0.05
query3	0.26	0.14	0.14
query4	1.61	0.14	0.14
query5	0.24	0.24	0.23
query6	1.34	1.06	1.09
query7	0.04	0.01	0.01
query8	0.06	0.03	0.04
query9	0.39	0.32	0.31
query10	0.60	0.56	0.56
query11	0.21	0.14	0.14
query12	0.19	0.15	0.14
query13	0.48	0.47	0.48
query14	1.02	1.00	1.00
query15	0.61	0.58	0.59
query16	0.32	0.33	0.31
query17	1.13	1.16	1.10
query18	0.23	0.22	0.21
query19	1.99	1.96	1.95
query20	0.02	0.01	0.02
query21	15.48	0.20	0.14
query22	4.96	0.05	0.05
query23	16.13	0.32	0.12
query24	2.95	0.44	0.35
query25	0.13	0.05	0.05
query26	0.73	0.21	0.14
query27	0.05	0.04	0.05
query28	3.58	0.92	0.51
query29	12.47	4.12	3.22
query30	0.28	0.16	0.18
query31	2.77	0.62	0.31
query32	3.23	0.59	0.49
query33	3.18	3.15	3.20
query34	15.46	4.27	3.51
query35	3.56	3.54	3.55
query36	0.55	0.46	0.42
query37	0.09	0.07	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.04
query40	0.18	0.16	0.15
query41	0.08	0.03	0.02
query42	0.04	0.02	0.03
query43	0.04	0.04	0.04
Total cold run time: 96.88 s
Total hot run time: 24.99 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 77.78% (84/108) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 74.72% (30167/40372)
Line Coverage 58.70% (331032/563963)
Region Coverage 55.44% (277594/500719)
Branch Coverage 56.73% (122775/216407)

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review found three blocking issues that should be fixed before merge:

  1. The PAIMON_CPP FileScannerV2 exclusion does not match real FE Paimon scan params, so PAIMON_CPP JNI splits can still be routed into V2.
  2. Failed JNI Java cleanup is made non-retryable even though JniTableReader::close() leaves _closed false after failure.
  3. Adaptive batch sizing reaches Paimon JNI after Java open, too late to cap Paimon's first physical readBatch() size.

Checkpoint conclusions: the PR goal is only partially met because the lifecycle hardening and routing fixes still miss real execution paths. The change is focused, but the tests use simplified shapes that miss the FE-generated Paimon params, the real close-reset state transition, and Paimon's open-time batch option. No new lock-order or transaction/persistence issue was found. Mixed-version Paimon option fallback looks correct. Observability changes are not required, but M2 is a memory/performance correctness issue for the adaptive batch feature. Validation was static only, as the review prompt forbids builds and test execution.

Comment thread be/src/exec/operator/file_scan_operator.cpp Outdated
Comment thread be/src/format_v2/jni/jni_table_reader.cpp Outdated
Comment thread be/src/format_v2/jni/jni_table_reader.cpp
### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#65503

Problem Summary: Paimon C++ splits could still enter FileScannerV2 because scanner selection inspected a scan-level table-format descriptor that FE only sends per split. Failed JNI cleanup also discarded the Java object before a retry, and adaptive JNI sizing was applied after Paimon had already opened its physical reader. Use the scan-level Paimon predicate marker for routing, retain JNI state until cleanup succeeds, and seed adaptive batch sizing before split preparation opens JNI readers.

### Release note

Ensure Paimon C++ scans use the supported scanner path, JNI cleanup remains retryable, and the first Paimon JNI batch honors adaptive sizing.

### Check List (For Author)

- Test: Unit Test
    - Remote ASAN BE unit tests: FileScannerV2Test.PaimonCppReaderForcesLegacyScanner and JniTableReaderTest.* (6 tests passed)
    - Remote build-support/check-format.sh passed with clang-format 16
    - Remote ASAN_UT changed objects compiled successfully
    - Remote clang-tidy analyzers completed for changed production files; final wrapper summary was not captured after the SSH output channel ended
- Behavior changed: Yes, scanner routing, JNI cleanup retry state, and first-batch sizing are corrected
- Does this need documentation: No
@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed after 2 rounds. All five subagents converged on this final M1/M2 comment set with NO_NEW_VALUABLE_FINDINGS.

I found two blocking issues: one compatibility gap in the Paimon CPP V1/V2 selection, and one lifecycle gap where the new JNI close retry state cannot be reached through the scanner close path. I did not duplicate existing review threads for the prior first-Paimon-JNI-batch timing concern or the inner JNI close-state retryability thread.

Critical checkpoint conclusions:

  • Goal: the PR addresses current-FE Paimon selection, JNI cleanup, cancellation, and adaptive batch feedback, but still misses rolling-upgrade Paimon CPP split-level metadata and scanner-level close retry.
  • Scope: mostly focused, but the close retry fix crosses the JniTableReader/FileScannerV2 lifecycle boundary.
  • Concurrency: no new shared-thread synchronization was added; the issue is lifecycle state ordering during close.
  • Lifecycle: not complete; FileScannerV2 marks itself closed before retained JNI cleanup state can be retried.
  • Configuration: no new config.
  • Compatibility: not complete for old FE/new BE Paimon CPP shapes that keep Paimon metadata only at split level.
  • Parallel paths: Paimon/Hudi hybrid batch forwarding was reviewed; no additional adaptive-batch issue found after the current seeding change.
  • Tests: new BE tests are discovered by the existing CMake glob, but coverage is still missing for the accepted Paimon CPP rolling-upgrade selector and scanner-level failing-then-succeeding close path.
  • Observability/performance: warning/profile changes and adaptive-batch seeding look reasonable; no separate metrics issue found.
  • Transactions/persistence/data writes: not directly involved.
  • User focus: no additional user-provided review focus.

Validation: static review only per the review prompt; no builds or unit tests were run. git diff --check is clean in this checkout.

// FE stores Paimon's table-format descriptor per split, but paimon_predicate is a scan-level
// Paimon marker. PAIMON_CPP is also selected per split, and FileScannerV2 cannot dispatch that
// reader type, so retain the V1 path until the V2 hybrid reader supports it.
const bool uses_paimon_cpp_reader = scan_params.__isset.paimon_predicate &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exclusion still misses the rolling-upgrade shape where Paimon metadata is only on each split. This selector only sees TFileScanRangeParams, so an old FE that has enable_paimon_cpp_reader=true but still sends Paimon predicate/reader metadata only in TFileRangeDesc.table_format_params.paimon_params will leave scan_params.__isset.paimon_predicate false and V2 remains selected. The first FORMAT_JNI range with TPaimonReaderType::PAIMON_CPP is not supported by V2: FileScannerV2::is_supported() accepts Paimon JNI only for PAIMON_JNI, and PaimonHybridReader dispatches only PAIMON_JNI to the JNI child. Please either use a marker that is guaranteed for both current and rolling-upgrade Paimon CPP scans, or conservatively keep JNI Paimon CPP on V1 until the split-level reader type can be inspected, and add a test for scan params without scan-level paimon_predicate plus a split-level PAIMON_CPP range.

Comment thread be/src/format_v2/jni/jni_table_reader.cpp
@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29530 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 52bda3f2c241f23986c5350bfbf636b9afa9687c, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17675	4054	4025	4025
q2	2037	329	211	211
q3	10253	1466	874	874
q4	4689	518	335	335
q5	7563	943	581	581
q6	202	171	138	138
q7	782	825	635	635
q8	9920	1612	1554	1554
q9	6034	4380	4372	4372
q10	6812	1833	1540	1540
q11	509	341	316	316
q12	743	549	431	431
q13	18114	3357	2791	2791
q14	268	262	248	248
q15	q16	788	784	720	720
q17	1362	1120	822	822
q18	6818	5783	5608	5608
q19	1743	1321	1063	1063
q20	751	662	557	557
q21	6051	2597	2405	2405
q22	437	364	304	304
Total cold run time: 103551 ms
Total hot run time: 29530 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4419	4301	4350	4301
q2	295	320	224	224
q3	4543	4939	4376	4376
q4	2067	2141	1369	1369
q5	4431	4369	4293	4293
q6	234	182	131	131
q7	2282	1947	1716	1716
q8	2530	2308	2225	2225
q9	8276	7826	7767	7767
q10	4729	4671	4231	4231
q11	577	436	399	399
q12	810	817	589	589
q13	3244	3618	2989	2989
q14	281	310	281	281
q15	q16	739	764	626	626
q17	1376	1471	1309	1309
q18	7910	7272	7263	7263
q19	1102	1055	1067	1055
q20	2219	2230	1947	1947
q21	5243	4608	4510	4510
q22	542	462	388	388
Total cold run time: 57849 ms
Total hot run time: 51989 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 181365 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 52bda3f2c241f23986c5350bfbf636b9afa9687c, data reload: false

query5	4318	637	486	486
query6	457	219	203	203
query7	4839	593	348	348
query8	335	196	174	174
query9	8773	4151	4114	4114
query10	452	390	278	278
query11	5903	2372	2208	2208
query12	162	102	101	101
query13	1271	625	431	431
query14	6295	5366	5013	5013
query14_1	4359	4337	4358	4337
query15	227	218	180	180
query16	1032	489	454	454
query17	1144	764	597	597
query18	2458	491	358	358
query19	214	196	153	153
query20	114	107	108	107
query21	226	165	143	143
query22	13766	13749	13542	13542
query23	17305	16519	16293	16293
query23_1	16339	16311	16237	16237
query24	7505	1775	1302	1302
query24_1	1332	1295	1292	1292
query25	565	474	403	403
query26	1339	373	225	225
query27	2575	568	388	388
query28	4492	2027	2032	2027
query29	1109	649	510	510
query30	347	263	226	226
query31	1131	1099	985	985
query32	108	65	67	65
query33	534	329	260	260
query34	1143	1134	661	661
query35	774	782	693	693
query36	1409	1448	1213	1213
query37	153	109	97	97
query38	1870	1697	1686	1686
query39	933	914	892	892
query39_1	875	875	892	875
query40	246	198	139	139
query41	68	67	62	62
query42	97	91	92	91
query43	336	332	286	286
query44	1474	794	774	774
query45	204	188	181	181
query46	1081	1223	784	784
query47	2326	2315	2244	2244
query48	410	433	264	264
query49	585	431	323	323
query50	1045	417	345	345
query51	11018	10685	10774	10685
query52	92	85	78	78
query53	264	277	202	202
query54	283	226	225	225
query55	79	78	66	66
query56	309	304	293	293
query57	1419	1395	1319	1319
query58	280	278	259	259
query59	1616	1677	1445	1445
query60	320	264	245	245
query61	150	148	160	148
query62	703	646	580	580
query63	246	212	214	212
query64	2818	1050	831	831
query65	4880	4842	4803	4803
query66	1819	508	388	388
query67	29547	29516	29339	29339
query68	3224	1541	923	923
query69	410	301	266	266
query70	1115	967	987	967
query71	367	340	300	300
query72	3006	2663	2402	2402
query73	828	822	447	447
query74	5147	4979	4766	4766
query75	2618	2591	2236	2236
query76	2320	1196	761	761
query77	356	394	313	313
query78	12192	12454	11865	11865
query79	1376	1164	777	777
query80	1252	547	473	473
query81	524	320	280	280
query82	635	159	124	124
query83	371	320	291	291
query84	277	163	131	131
query85	951	643	498	498
query86	432	304	296	296
query87	1826	1832	1738	1738
query88	3770	2842	2779	2779
query89	460	401	359	359
query90	1953	222	207	207
query91	198	201	161	161
query92	64	62	55	55
query93	1680	1486	970	970
query94	714	362	317	317
query95	789	609	462	462
query96	1034	831	354	354
query97	2683	2701	2571	2571
query98	214	207	198	198
query99	1169	1165	1016	1016
Total cold run time: 266372 ms
Total hot run time: 181365 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 25.09 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 52bda3f2c241f23986c5350bfbf636b9afa9687c, data reload: false

query1	0.01	0.01	0.01
query2	0.09	0.06	0.05
query3	0.27	0.14	0.14
query4	1.60	0.13	0.14
query5	0.24	0.23	0.23
query6	1.28	1.04	1.09
query7	0.04	0.01	0.01
query8	0.06	0.03	0.04
query9	0.39	0.32	0.35
query10	0.58	0.61	0.55
query11	0.19	0.14	0.14
query12	0.19	0.15	0.14
query13	0.48	0.48	0.48
query14	1.02	1.02	1.02
query15	0.62	0.59	0.59
query16	0.32	0.35	0.32
query17	1.13	1.12	1.11
query18	0.24	0.23	0.22
query19	2.02	1.98	1.89
query20	0.01	0.02	0.01
query21	15.44	0.22	0.13
query22	4.80	0.05	0.05
query23	16.12	0.30	0.12
query24	2.98	0.41	0.33
query25	0.11	0.06	0.04
query26	0.71	0.21	0.14
query27	0.04	0.04	0.04
query28	3.57	0.93	0.55
query29	12.53	4.07	3.24
query30	0.29	0.17	0.15
query31	2.77	0.59	0.31
query32	3.23	0.60	0.48
query33	3.16	3.23	3.24
query34	15.57	4.26	3.51
query35	3.52	3.55	3.54
query36	0.56	0.44	0.44
query37	0.10	0.07	0.06
query38	0.05	0.04	0.04
query39	0.04	0.03	0.02
query40	0.18	0.17	0.15
query41	0.08	0.03	0.03
query42	0.03	0.03	0.03
query43	0.05	0.03	0.04
Total cold run time: 96.71 s
Total hot run time: 25.09 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 59.56% (81/136) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 56.92% (23558/41386)
Line Coverage 40.58% (230285/567551)
Region Coverage 36.46% (181893/498834)
Branch Coverage 37.56% (81244/216331)

### What problem does this PR solve?

Issue Number: None

Related PR: apache#65503

Problem Summary: FileScannerV2 selection could still route rolling-upgrade Paimon CPP JNI splits into an unsupported V2 reader, and a failed table-reader close left the scanner marked closed so retained JNI cleanup state could not be retried. Conservatively keep JNI scans on V1 while the Paimon C++ reader option is enabled, and roll back the scanner close guard when table-reader cleanup fails.

### Release note

Harden Paimon CPP scanner selection and retry JNI cleanup after close failures.

### Check List (For Author)

- Test: Unit Test

    - FileScannerV2Test.* and JniTableReaderTest.*: 20 tests passed under ASAN BE UT

- Behavior changed: Yes. Unsupported Paimon CPP JNI splits stay on V1, and failed V2 table-reader cleanup can be retried.

- Does this need documentation: No
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes based on static review.

Critical checkpoint conclusions:

  • Goal: the PR addresses several prior JNI/FileScannerV2 review issues, but three compatibility/lifecycle/resource issues remain.
  • Scope: the changes are focused on scanner selection, JNI cleanup, adaptive batch sizing, hybrid readers, and BE tests.
  • Concurrency/lifecycle: scanner close retry and JNI resource lifecycle were reviewed; Paimon Java cleanup still invalidates retry state.
  • Compatibility: rolling-upgrade Paimon JNI without reader_type is still not preserved on the V2 path.
  • Parallel paths: FileScannerV1, FileScannerV2, Paimon/Hudi hybrid readers, and representative Java JNI scanners were checked.
  • Testing: new BE tests cover useful cases, but they miss the three accepted edge cases below.
  • Configuration/storage/transactions/observability: no new config, storage format, transaction, or observability requirement was found.

User focus: no additional user-provided focus was supplied.

Validation: static review only. I did not run builds or tests because the review prompt forbids build/test operations in this runner; the checkout also lacks .worktree_initialized and thirdparty/installed.

Comment thread be/src/exec/operator/file_scan_operator.cpp Outdated
return;
}
const auto status = _set_open_scanner_batch_size(_batch_size);
if (!status.ok()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forwarding the later adaptive prediction to JniScanner.setBatchSize() still does not change Paimon's physical read batch after Java open(). FileScannerV2 updates the predictor after the first materialized block and calls set_batch_size() before the next get_block(), but this method only invokes Java setBatchSize, whose base implementation assigns batchSize. Paimon copied the constructor batch into CoreOptions.READ_BATCH_SIZE in buildTableOptions() while creating the reader during open(), and later reader.readBatch() calls keep using that existing RecordReader. The output loop stops appending after the new batchSize, but the connector can still read/materialize stale probe-sized batches, for example 32 very wide rows, on subsequent physical reads. Please make PaimonJniScanner.setBatchSize() update the physical reader batch, or keep Paimon JNI out of mid-split adaptive resizing, and add a test that observes the next physical readBatch() size after the predictor lowers the batch.

}
if (cleanup_status.ok()) {
// Keep the Java object and opened state on failure so close() can retry the cleanup.
_reset_split_state(env);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping the Java object on a failed close is not sufficient for Paimon, because PaimonJniScanner.close() clears the resources that would need the retry. releaseRecordIterator() nulls recordIterator in finally even if releaseBatch() throws; reader.close() and ioManager.close() also set their fields to null in finally before rethrowing. If any of those operations fails, C++ preserves _scanner_opened and will call close again, but the same Java object has already forgotten the iterator/reader/ioManager that may still be unclosed, so the retry is a no-op for that resource. Please only clear those Java fields after cleanup succeeds, or make such failures terminal rather than exposing them as retryable, and cover a Paimon-like close-fails-then-succeeds case.

### What problem does this PR solve?

Issue Number: None

Related PR: apache#65503

Problem Summary: Legacy Paimon JNI splits without reader_type could still enter FileScannerV2, adaptive batch-size updates after open did not resize Paimon physical readers, and failed Java cleanup cleared resource references before a retry. Keep JNI compatibility shapes on the legacy scanner, preserve the initial Paimon physical batch size after open, and retain each Java resource until its cleanup succeeds.

### Release note

Harden legacy JNI selection, Paimon batch-size handling, and retryable Java cleanup.

### Check List (For Author)

- Test: Unit Test

    - FileScannerV2Test.*, JniTableReaderTest.*, and PaimonJniReaderTest.*: 30 tests passed under ASAN BE UT
    - PaimonJniScannerTest: 10 tests passed; checkstyle reported 0 violations
    - clang-format and git diff checks passed

- Behavior changed: Yes. Legacy JNI compatibility splits stay on V1, Paimon ignores unsupported post-open physical batch resizing, and failed Java cleanup remains retryable.

- Does this need documentation: No
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants