Skip to content

[feature](azure) Support native SAS and OAuth2 access with a typed FE-to-BE config - #69082

Open
xylaaaaa wants to merge 75 commits into
apache:masterfrom
xylaaaaa:refactor/be-obj-storage-client
Open

xylaaaaa wants to merge 75 commits into
apache:masterfrom
xylaaaaa:refactor/be-obj-storage-client

Conversation

@xylaaaaa

@xylaaaaa xylaaaaa commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Related PR: #67470, #69605 (BE refactor subset)

Problem Summary:

Doris reads Azure Blob natively from BE, but only with SharedKey, and the whole path is shaped around S3:

  • FE sends Azure access to BE as an S3-style property map: provider=azure, the account in AWS_ACCESS_KEY and the key in AWS_SECRET_KEY. BE uses those keys to build a SharedKey client. The legacy map has no native BE representation for a SAS token or Entra ID client credentials.
  • FE offers no SAS option. OAuth2 storage access only works for OneLake through the Hadoop path; for a normal Azure Blob location the OAuth2 map is a Hadoop configuration that the BE FILE_S3 reader cannot use.
  • In BE, S3 and Azure share one flat S3ClientConf (Azure reuses ak/sk/bucket as account/key/container, next to S3-only fields such as region and role), one S3ClientFactory that builds both SDK clients and owns one shared cache, and an ObjClientHolder that merges a new conf field by field and reads its conf without the lock.

This PR adds native SAS and OAuth2 (client credentials) access for Azure end to end, together with the BE refactor it builds on. It is the integration PR for end-to-end testing. The BE refactor is under review in #69605.

1. BE object storage refactor

  • Typed configuration end to end; S3Conf and S3ClientConf are gone. io::ObjClientConfig holds shared connection options, a client usage (internal storage / external access) and exactly one backend, std::variant<S3ClientConfig, AzureClientConfig>; the Azure authentication is a variant as well (SharedKey, SAS, client secret). io::ObjStorageConfig replaces S3Conf and carries the bucket, prefix, client configuration and the vault metadata flag sse_enabled. BE reports the flag in storage diagnostics, as on master.
  • ObjStorageConfigResolver converts legacy FE properties, resource parameters and vault metadata. An Azure client built from a flat input preserves the fields used for refresh, cache identity and validation, including the effective region. FE properties check the endpoint before the region. Resource and vault refreshes validate the merged target. The new from_azure_client_config() reads the native Thrift input, which expresses SharedKey, SAS or OAuth2 without a region.
  • ObjClientFactory validates every request with the rules of its backend, then dispatches through std::visit (a new backend without a branch fails to compile). S3ClientProvider and AzureClientProvider look up and publish entries under the cache lock. They build the SDK client outside the lock on a miss. Both providers use the same BE rate-limit policy (obj_client_rate_limit) and the same CA bundle cache (obj_client_ca). The cache reuses clients by full config and has no capacity limit. S3ClientFactory is renamed to AwsSdkManager: it no longer builds clients and keeps only the AWS SDK lifetime and AWS helpers (client configuration, credentials), which Kinesis also uses. The Azure SDK log setup that its constructor carried moves unchanged to init_azure_sdk_logging() next to AzureClientProvider; ObjClientFactory runs both SDK setups on construction, and BE startup constructs it in place of S3ClientFactory.
  • Deferred completion (Hive writes stage files and the FE completes them at commit) is a client capability: FileWriterOptions::used_by_s3_committer is renamed to deferred_completion, and ObjStorageCapabilities::deferred_completion says what the coordinator must support (ANY_COORDINATOR for S3 multipart, NAMESPACED_BLOCK_IDS for Azure blocks). VHivePartitionWriter checks it against the coordinator's supports_deferred_azure_multipart instead of comparing providers.
  • ObjClientHolder owns an immutable snapshot of the config, client and generation. Legacy resource and vault refreshes update the same file system and holder, including across S3/Azure changes. The merged client keeps the original endpoint, region and endpoint-override flag. The file system keeps its original bucket and prefix. A failed build leaves the current client in place. Of two successful overlapping resets, the last publication wins.
  • ObjStorageUri replaces S3URI: parse_s3() keeps the S3 rules (and takes container and key from native Azure locations), parse_azure() adds the Azure rules (below).
  • The common IO classes are renamed: ObjStorageFileSystem, ObjStorageFileReader, ObjStorageFileWriter (obj_storage_file_*.{h,cpp}), obj_storage_file_buffer_pool, display_path(), FileSystemType::OBJECT_STORAGE (same value). The renamed classes keep the debug and sync point names used by regression tests. The reader handles HTTP 429 without AWS types. Internal metric variables are renamed to obj_storage_*; exposed metric names and config keys are kept for compatibility.

BE client behavior

  • The S3 client cache includes the bucket in its key. Two buckets on one endpoint with the same credentials get distinct clients. Prefixes within a bucket share the client. Legacy Azure inputs retain the full flat identity. Native Azure keys include container and authentication, so two distinct SAS tokens get distinct clients. S3 cache test · SAS rotation test
  • A BE writer that finishes a multipart upload sends Complete with the client it acquired before waiting for the outstanding parts. This also applies when the holder changes backend during the wait. Hive can defer completion to its coordinator. Multipart refresh test
  • For a public URL on an endpoint ending in -internal.aliyuncs.com, BE removes -internal from a copy of the endpoint and signs with the configured backend. Presigning test

2. FE-to-BE protocol (gensrc)

TAzureClientConfig { endpoint, account_name, container, credential } with union TAzureCredential { shared_key, sas, client_secret }, carried by the new optional field TFileScanRangeParams.azure_client_config (id 43). In the merge base, id 42 is external_search_request. Id 43 was also free on branch-4.2, branch-4.1, branch-4.0 and branch-3.1 when checked. container is optional: BE takes it from each file location and rejects a configured container that differs.

The write sinks carry the same struct as a new optional azure_client_config: TIcebergTableSink (21), TIcebergDeleteSink (16), TIcebergMergeSink (26), THiveTableSink (15). Each id is one past the last id on master, and unused on branch-4.2/4.1/4.0/3.1.

The other entries that reach object storage carry it too: TParquetMetadataParams (7, parquet_meta), TResultFileSinkOptions (24, OUTFILE / EXPORT data and success files) and TTVFTableSink (17, TVF insert); TVF schema inference already received it and BE now copies it in fetch_file_schema. These ids are unused on every branch as well. Without the typed config BE falls back to the S3-style keys, which can express only SharedKey.

3. BE

  • AzureAuthFactory builds SAS clients (token appended to the container URL) and client secret clients (Azure::Identity::ClientSecretCredential, sharing the blob transport and CA bundle; the SDK requests and refreshes the access token).
  • AzureConfigCodec decodes the Thrift config (exactly one credential); AzureConfigValidator checks the fields of the selected method and the account name against standard Azure hosts; The common Azure auth code parses the SAS se expiry and takes the earlier of that expiry and an explicit expires_at_ms when both exist. AzureClientProvider calls validate_azure_auth_expiry before each cache lookup and again before publishing a newly built client. Range reads reuse the open client.
  • io::ObjStorageUri parses a location by the Azure rules: abfs[s]://[email protected]..., wasb[s]://[email protected]..., http(s)://acct.blob.../container/key and the legacy s3://container/key all become account, container and key, and the original location is kept untouched. The resolver rejects a location whose account differs from the one requests go to (account_name, or the account the endpoint names).
  • The FileFactory reader, create_fs and create_file_writer resolve a FILE_S3 location through one function: typed Azure access when FE sends it, the AWS_* properties otherwise. The scan readers copy the field from TFileScanRangeParams through one helper, io::azure_client_config_of(); the Iceberg table/delete/merge writers, the rewritable-delete reader and the Hive writer pass the sink's field to FileFactory.
  • Iceberg DELETE commits the original location. VIcebergDeleteSink used to report position delete and puffin files under output_path, the normalized form (s3://b/db/t/data for an oss:// or Azure table), so Iceberg metadata recorded the internal s3:// address. It now commits them under table_location, the raw data location, which every FE version sets to the same directory as output_path. Data files were already committed under original_output_path.

4. FE

  • New user property azure.sas_token (sensitive) with azure.auth_type = SAS; validation requires the token and an endpoint or account name. FE listing (AzureObjStorage) and the Hadoop ABFS map (fixed SAS token) support it too.
  • AzureFileSystemProperties.toMap() keeps its S3-style keys for old BEs and also writes neutral AZURE_* keys (AzureBackendPropertyKeys in fe-filesystem-api). SAS adds no legacy credential, so an old BE is never handed a wrong one. OAuth2 resolves the tenant as the FE SDK client already does and derives the authority host from azure.oauth2_server_uri; the FE SDK client now uses that authority host as well.
  • AzureThriftAdapter (fe-core) turns the neutral keys into TAzureClientConfig, and FileQueryScanNode sets it for FILE_S3 ranges. TVF scans and plugin-driven catalogs both build their location properties from the provider map, so both are covered. The TVF fetch-schema request, which BE serves before any scan, carries it too.
  • The old rule that azure.auth_type = OAuth2 is only accepted for an Iceberg REST catalog is removed: it existed because BE could only use OAuth2 through the Iceberg REST / OneLake Hadoop path.
  • Iceberg REST vended SAS: a catalog can vend adls.sas-token.<account host> with a table and optionally provide adls.sas-token-expires-at-ms.<account host>. These keys used to be dropped by the vended-credential filter. IcebergAdlsVendedCredentials now turns them into Azure SAS properties (account and Blob endpoint from the host, token, expiry), so Iceberg scans and writes, which already overlay the vended properties, send them to BE as TAzureClientConfig. The expiry travels as TAzureSas.expires_at_ms. One storage account per table: tokens for several accounts are rejected with a message naming them.
  • PluginDrivenTableSink binds the typed config onto Iceberg and Hive sinks (AzureThriftAdapter.bindToWriteSink), from the backend properties the connector already put in the sink, so connectors are unchanged.
  • Connector scans and writes keep native Azure locations. Every path normalized through DefaultConnectorContext (Iceberg, Hive, Paimon, Hudi scan ranges and write paths) ends up in a request that carries typed Azure access, so it now uses LocationPath.ofAdaptersForNativeAccess: Azure locations are validated and kept as abfss://[email protected]/... instead of being rewritten to s3://c/..., which dropped the account; other storages are normalized as before. BE can then check every file's account, and Hive commits record the native location in HMS. Other callers can still use s3://container/key. OUTFILE (also used by EXPORT) and FILE_S3 TVFs can carry typed Azure credentials alongside that path. Paimon and Hudi JNI readers use raw paths and are unaffected; the FE Azure filesystem accepts the native forms for Hive multipart completion.
  • FileQueryScanNode binds the typed config even when a JNI scan already set the scan properties, which fixes SAS and OAuth2 reads of Iceberg position_deletes; the Iceberg plugins package the Azure FileIO dependencies.

Azure access by entry point

FE and BE carry typed Azure access for external table and TVF reads (including parquet_meta), Iceberg and Hive writes, OUTFILE/EXPORT, and FILE_S3 TVF inserts. The result-file and TVF writers pass the optional config to FileFactory. Broker Load and backup repositories accept only SharedKey for Azure. Resources and storage vaults continue to use their existing metadata credentials.

Rolling upgrade: SharedKey reads keep working on old BEs through the S3-style keys. SAS and OAuth2 on FILE_S3 require every BE to be upgraded before they are used. Connector scans and writes send native abfss:// locations, which old BEs cannot parse, so BE must be upgraded before FE (the standard order). After the upgrade, the BE file cache keys and split affinity of Azure files change once, because their path strings change.

Outbound requests (SSRF surface): with OAuth2, BE now requests access tokens from the authority host derived from azure.oauth2_server_uri, in addition to the storage endpoint it already contacted. Both values come from catalog or TVF properties, so reaching them requires the privilege to create or alter the catalog, or to run the TVF.

Release note

Azure storage accessed through TVFs, external catalogs, Iceberg and Hive writes, and OUTFILE/EXPORT supports SAS tokens (azure.auth_type = SAS, azure.sas_token) and native BE OAuth2 client credentials, in addition to SharedKey. Iceberg REST catalogs that vend Azure SAS (such as Databricks Unity Catalog) can read and write their Azure data through the vended SAS. Iceberg position delete files are committed with the table's own location instead of the internal s3:// form. Upgrade all BEs before FE and before using SAS or OAuth2.

Check List (For Author)

  • Test

    • Built FE and the ASAN BE at f0b0c6b557 on macOS arm64 with ./build.sh --be --fe, Azure enabled and PCH disabled.
    • Ran clang-format 16, clang-tidy on changed lines and build-support/check-build-hygiene.sh.
    • Added BE and FE unit tests.
      • BE tests cover flat-source conversion and validation, full cache identity, SAS expiry and rotation, cache reuse, holder snapshots, concurrent and cross-backend refresh, multipart completion, Azure URI and credential handling, typed file access and Iceberg delete paths.
      • FE: AzureFileSystemPropertiesTest (native keys for SharedKey/SAS/OAuth2, SAS validation and Hadoop config, sensitive SAS key), IcebergAdlsVendedCredentialsTest (vended SAS translation, single-account rule), AzureThriftAdapterTest (including binding onto Iceberg/Hive sinks and SAS expiry) and StorageAdapterAzureNativeTest (OAuth2 outside Iceberg REST and SAS, through StorageAdapter)
    • The standard macOS ASAN_UT build stops before GoogleTest at the upstream std::min(size_t, ordinal_t) call in binary_column_extract_iterator_test.cpp:74. Clang deduces two distinct unsigned types. Upstream test
    • With just that one segment source excluded (1,366 of 1,367 UT sources), the three factory and URI suites passed 70/70 and the native Azure, SAS and client-cache suites passed 21/21, both with exit 0. This covers different tokens, reuse after 256 other keys, rejection of expired SAS and typed file access. The larger group including multipart refresh passed 92/92 assertions and exited 134. The multipart refresh test alone also passed and exited 134. The static writer fixture released an S3 client at process exit and the AWS component registry raised mutex lock failed: Invalid argument.
    • The default file-system/reader/writer/spill/merge filter passed 5 cases, skipped 34 gated external-storage cases (six Azure), then hit an ASAN read at 0x48 in S3FileWriterTest.multi_part_io_error. The cache-disabled fixture followed by all 14 writer tests passed 15/15 before the same process-exit exception. All 42 spill tests passed in a separate process (exit 0).
    • The default consumer filter passed 52 EMBED cases, then hit the same uninitialized file-cache factory in the first Hive writer reporting case. CSV and EMBED passed 95/95 separately. Both Hive reporting cases passed after the cache-disabled fixture (3/3, exit 0).
    • At f0b0c6b557, ran the local S3-compatible regression through FE, BE and SeaweedFS. Using one endpoint and one set of credentials, SELECT INTO OUTFILE wrote one two-part object per bucket. SQL read back 128 rows per bucket and an independent S3 client verified the complete byte content of both objects.
    • End-to-end testing against a real Azure storage account with SharedKey, SAS and OAuth2 is pending.
  • Behavior changed:

    • Yes. Native Azure access adds typed SharedKey, SAS and OAuth2 for the documented scans and sinks, including Iceberg REST vended SAS. Iceberg writes keep native Azure locations and publish delete files under table_location. FileSystemType prints OBJECT_STORAGE.
  • Does this need documentation?

    • Yes. azure.auth_type = SAS, azure.sas_token and the upgrade order; not included yet.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

### What problem does this PR solve?

Issue Number: None

Related PR: apache#67470

Problem Summary: BE creates every native object storage client from one flat
`S3ClientConf`. Azure reuses `ak/sk/bucket` as account/key/container, while
region, the AWS role and the AWS credential provider type sit in the same
struct and only mean something for S3. `S3ClientFactory` builds AWS and Azure
clients, owns one shared client cache, applies the rate-limit wrapper and
initializes the AWS SDK. `ObjClientHolder` keeps a mutable conf and client
side by side: `reset()` writes them under the lock, but `s3_client_conf()` and
`full_s3_path()` read the conf without it, and two concurrent resets that
both merged onto the same old conf silently overwrite each other.

This is the first step of the BE object storage refactor. It changes how
clients are configured and managed without changing any caller-facing input:

- Add `io::ObjStorageClientConfig` with shared connection options, a client
  usage (internal storage / external access) and exactly one backend
  alternative: `S3ClientConfig` or `AzureClientConfig`. Azure authentication is
  a variant of methods (SharedKey only today), so a new method is a new
  alternative instead of another loosely related field.
- Add `ObjStorageConfigResolver::from_client_conf()`, the single mapping from
  the legacy conf. All existing inputs (FE properties, `TS3StorageParam`,
  `ObjectStoreInfoPB`) still produce an `S3ClientConf` and reach the providers
  through it.
- Split construction into `S3ClientProvider` and `AzureClientProvider`, each
  with its own cache keyed by the full typed config, dispatched by
  `ObjStorageClientFactory`. SDK clients are still built outside the cache
  lock; a losing concurrent candidate is now released after unlocking. The
  BE rate-limit policy moves next to the factory and is applied by every
  provider in the same way.
- `S3ClientFactory` keeps its public API as a compatibility entry: it
  validates the legacy conf, keeps the test client hook, and still owns the
  AWS SDK lifetime, the CA certificate path and the AWS credential helpers.
- `ObjClientHolder` now owns an immutable `ObjClientState` (conf, client,
  generation) and replaces it as a whole. Readers take one snapshot, so the
  conf and client always come from the same generation. A reset is published
  only if no other publish happened since it read the state; otherwise it
  returns `ABORTED` and the holder keeps the newer state. Both callers
  (`update_s3_resource` and storage vault refresh) already handle a failed
  reset by logging a warning and keeping the existing file system.

Client identity now follows the selected backend: S3 clients are no longer
split by bucket (an AWS SDK client is not bound to a bucket), and Azure
clients are no longer split by region, token or AWS role fields that the
Azure client never read. The provider cache singleton is created after the
AWS SDK is initialized, so cached AWS clients are released before
`Aws::ShutdownAPI`.

Renaming `S3URI`, `S3FileSystem`, `S3FileReader` and `S3FileWriter`, and
migrating callers from `S3ClientConf` to the typed config, are left to
follow-up changes.

### Release note

None

### Check List (For Author)

- Test: Unit Test (added, not run)
    - Added `be/test/io/obj_storage/obj_storage_client_factory_test.cpp` for the
      resolver mapping, backend-specific identity, credential masking,
      provider caching, holder snapshots and the concurrent reset conflict.
    - Updated tests that assigned the holder's private client to use
      `set_client_for_test`.
    - BE was not compiled and unit tests were not run in this change;
      clang-format 16 and `build-support/check-build-hygiene.sh` passed.
- Behavior changed: Yes. S3 clients are shared across buckets with the same
  endpoint and credentials; Azure clients ignore S3-only fields for reuse; a
  reset that races with another reset on the same holder returns `ABORTED`
  instead of overwriting it.
- Does this need documentation: No
Copilot AI balanced review requested due to automatic review settings October 14, 2026 16:07

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@xylaaaaa

Copy link
Copy Markdown
Contributor Author

run buildall

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69082

Problem Summary: BE UT compilation failed with clang's
-Wmissing-designated-field-initializers (-Werror) because
ObjStorageConfigResolver::from_client_conf() built ObjStorageClientConfig
with a designated initializer that omitted `backend` and assigned it
afterwards. Build the backend alternative first and initialize all fields
in one designated initializer.

### Release note

None

### Check List (For Author)

- Test: No need to test (compile fix only; BE was not built locally,
  clang-format 16 and check-build-hygiene.sh passed)
- Behavior changed: No
- Does this need documentation: No
@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17584	5644	5581	5581
q2	2084	314	258	258
q3	10256	1413	836	836
q4	4680	471	341	341
q5	7435	823	532	532
q6	183	191	161	161
q7	767	823	621	621
q8	9239	1340	1091	1091
q9	5611	4321	4278	4278
q10	6832	1326	1031	1031
q11	448	257	244	244
q12	640	403	281	281
q13	18088	3644	3029	3029
q14	282	267	252	252
q15	q16	749	732	669	669
q17	1219	750	586	586
q18	7189	6249	6183	6183
q19	1250	958	622	622
q20	399	339	229	229
q21	5497	2279	2398	2279
q22	381	316	264	264
Total cold run time: 100813 ms
Total hot run time: 29368 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6171	6176	6169	6169
q2	716	577	566	566
q3	5226	5480	5016	5016
q4	2023	2156	1545	1545
q5	5269	5631	5986	5631
q6	251	195	150	150
q7	2410	2150	1933	1933
q8	3278	2949	2759	2759
q9	8192	8038	8141	8038
q10	3814	3678	3346	3346
q11	633	472	420	420
q12	675	711	519	519
q13	3618	3900	3402	3402
q14	311	302	290	290
q15	q16	714	742	674	674
q17	8355	7625	7399	7399
q18	13133	12273	13135	12273
q19	951	820	795	795
q20	2164	2151	1913	1913
q21	5880	4814	4850	4814
q22	507	448	400	400
Total cold run time: 74291 ms
Total hot run time: 68052 ms

@xylaaaaa

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 153478 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 ad388ff3d980eb96ea5518504f9984a9c608ebf7, data reload: false

query5	4314	583	461	461
query6	422	206	190	190
query7	4806	452	239	239
query8	322	182	156	156
query9	8741	4072	4050	4050
query10	450	312	247	247
query11	5993	3798	3531	3531
query12	143	97	88	88
query13	1267	471	330	330
query14	6063	4156	3918	3918
query14_1	3526	3510	3580	3510
query15	209	196	189	189
query16	945	438	418	418
query17	876	658	541	541
query18	2419	426	316	316
query19	195	166	138	138
query20	89	86	82	82
query21	211	144	118	118
query22	13118	13018	12880	12880
query23	13472	12948	12550	12550
query23_1	12528	12595	12636	12595
query24	7107	863	483	483
query24_1	485	483	480	480
query25	546	424	362	362
query26	1292	263	144	144
query27	2758	439	279	279
query28	4630	2002	1996	1996
query29	1558	609	458	458
query30	305	218	183	183
query31	1021	926	809	809
query32	150	96	92	92
query33	550	310	254	254
query34	946	849	512	512
query35	774	755	659	659
query36	864	807	713	713
query37	129	103	95	95
query38	1799	1747	1721	1721
query39	821	819	756	756
query39_1	746	732	747	732
query40	226	118	102	102
query41	74	68	70	68
query42	92	86	83	83
query43	381	390	335	335
query44	1383	715	714	714
query45	190	192	164	164
query46	857	966	580	580
query47	2989	2993	2937	2937
query48	301	343	214	214
query49	581	403	298	298
query50	687	294	228	228
query51	10635	10625	10682	10625
query52	79	83	76	76
query53	189	214	153	153
query54	252	216	184	184
query55	74	71	63	63
query56	238	211	209	209
query57	1616	1597	1551	1551
query58	283	269	258	258
query59	2104	2162	1982	1982
query60	274	245	231	231
query61	150	148	150	148
query62	393	336	290	290
query63	199	172	171	171
query64	2771	973	767	767
query65	3293	3282	3259	3259
query66	1781	429	323	323
query67	20144	20188	20015	20015
query68	3103	1025	622	622
query69	382	285	249	249
query70	890	801	787	787
query71	311	240	213	213
query72	2883	2531	2274	2274
query73	540	541	298	298
query74	4630	4469	4333	4333
query75	2364	2289	1989	1989
query76	2385	1044	633	633
query77	349	394	288	288
query78	9735	9645	9178	9178
query79	987	867	530	530
query80	1212	441	354	354
query81	589	312	281	281
query82	618	141	109	109
query83	309	204	181	181
query84	308	134	106	106
query85	873	418	383	383
query86	398	249	233	233
query87	2013	1965	1829	1829
query88	3687	2725	2696	2696
query89	341	300	258	258
query90	1914	191	181	181
query91	161	161	131	131
query92	96	92	83	83
query93	1060	1030	593	593
query94	626	313	282	282
query95	592	346	319	319
query96	667	541	237	237
query97	2467	2456	2338	2338
query98	166	153	146	146
query99	778	769	659	659
Total cold run time: 235965 ms
Total hot run time: 153478 ms

@hello-stephen

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

query1	0.01	0.00	0.00
query2	0.11	0.05	0.04
query3	0.27	0.12	0.12
query4	1.61	0.12	0.13
query5	0.24	0.25	0.24
query6	1.18	0.69	0.67
query7	0.04	0.01	0.00
query8	0.05	0.04	0.04
query9	0.41	0.35	0.35
query10	0.62	0.57	0.60
query11	0.21	0.15	0.14
query12	0.19	0.15	0.14
query13	0.50	0.49	0.49
query14	1.04	1.01	1.01
query15	0.63	0.60	0.61
query16	0.36	0.37	0.31
query17	1.15	1.15	1.19
query18	0.23	0.21	0.21
query19	2.11	1.97	2.05
query20	0.02	0.01	0.01
query21	15.48	0.29	0.14
query22	4.47	0.06	0.05
query23	16.27	0.33	0.11
query24	2.73	0.71	0.44
query25	0.11	0.06	0.03
query26	1.38	0.25	0.15
query27	0.05	0.04	0.03
query28	2.00	0.59	0.41
query29	12.52	4.13	3.33
query30	0.28	0.14	0.14
query31	2.77	0.57	0.34
query32	3.22	0.61	0.54
query33	3.27	3.32	3.16
query34	15.50	4.03	3.39
query35	3.38	3.35	3.37
query36	0.55	0.45	0.42
query37	0.10	0.07	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.18	0.15	0.14
query41	0.10	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 95.51 s
Total hot run time: 24.56 s

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17595	5815	5705	5705
q2	2110	330	277	277
q3	10212	1514	870	870
q4	4680	486	343	343
q5	7449	832	531	531
q6	206	202	157	157
q7	827	822	594	594
q8	9242	1517	1217	1217
q9	5665	4448	4433	4433
q10	6846	1295	1034	1034
q11	439	253	236	236
q12	644	426	280	280
q13	18068	3626	2954	2954
q14	275	273	248	248
q15	q16	739	726	670	670
q17	1327	753	586	586
q18	6989	6219	6164	6164
q19	1096	1092	641	641
q20	400	345	223	223
q21	5026	2299	2449	2299
q22	381	321	260	260
Total cold run time: 100216 ms
Total hot run time: 29722 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6352	6303	6308	6303
q2	707	586	542	542
q3	5216	5378	4918	4918
q4	2095	2214	1536	1536
q5	5270	5705	5726	5705
q6	290	216	167	167
q7	2342	2028	1879	1879
q8	3276	2806	2891	2806
q9	7984	7950	8293	7950
q10	3822	3726	3355	3355
q11	684	451	426	426
q12	724	724	544	544
q13	3624	3977	3319	3319
q14	325	334	299	299
q15	q16	746	724	657	657
q17	8616	7695	7079	7079
q18	13233	12237	13121	12237
q19	1058	858	856	856
q20	2196	2192	1934	1934
q21	6081	4945	5053	4945
q22	517	461	416	416
Total cold run time: 75158 ms
Total hot run time: 67873 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152943 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 a827621e1f08bc1dbff17bccd9e6df702031787b, data reload: false

query5	4330	592	441	441
query6	428	212	188	188
query7	4821	446	233	233
query8	342	166	154	154
query9	8753	3934	3952	3934
query10	476	311	279	279
query11	6033	3839	3544	3544
query12	141	90	87	87
query13	1240	449	343	343
query14	6112	4064	3758	3758
query14_1	3524	3560	3569	3560
query15	209	205	179	179
query16	943	437	409	409
query17	867	666	546	546
query18	2410	417	318	318
query19	208	164	134	134
query20	88	92	81	81
query21	218	132	114	114
query22	12993	13063	12815	12815
query23	13511	12872	12501	12501
query23_1	12498	12630	12789	12630
query24	7109	855	474	474
query24_1	486	487	492	487
query25	546	438	367	367
query26	1285	268	147	147
query27	2741	442	275	275
query28	4636	1974	1945	1945
query29	1540	599	449	449
query30	301	219	186	186
query31	1036	930	818	818
query32	142	105	96	96
query33	519	303	256	256
query34	920	860	496	496
query35	758	764	652	652
query36	815	815	780	780
query37	133	105	91	91
query38	1810	1720	1687	1687
query39	800	808	757	757
query39_1	742	743	754	743
query40	220	116	99	99
query41	73	69	71	69
query42	90	94	87	87
query43	363	382	334	334
query44	1288	708	733	708
query45	185	180	166	166
query46	852	966	566	566
query47	3023	3006	2941	2941
query48	306	304	215	215
query49	574	399	301	301
query50	706	279	211	211
query51	10603	10716	10609	10609
query52	82	78	70	70
query53	185	208	150	150
query54	259	194	173	173
query55	70	72	63	63
query56	225	218	213	213
query57	1627	1604	1559	1559
query58	289	261	251	251
query59	2118	2081	1905	1905
query60	297	241	226	226
query61	159	151	154	151
query62	386	338	290	290
query63	197	165	165	165
query64	2722	993	777	777
query65	3300	3247	3228	3228
query66	1787	410	309	309
query67	20131	20332	20413	20332
query68	3023	1000	618	618
query69	392	297	256	256
query70	838	816	809	809
query71	284	222	206	206
query72	2684	2575	2255	2255
query73	521	529	294	294
query74	4617	4494	4302	4302
query75	2341	2336	1928	1928
query76	2296	1024	596	596
query77	339	383	268	268
query78	9986	9666	9118	9118
query79	978	863	516	516
query80	856	413	346	346
query81	592	320	279	279
query82	578	141	116	116
query83	315	195	181	181
query84	320	120	105	105
query85	905	432	368	368
query86	355	246	233	233
query87	2014	1970	1833	1833
query88	3627	2705	2664	2664
query89	337	307	264	264
query90	1823	180	178	178
query91	161	148	126	126
query92	97	89	89	89
query93	1017	1001	578	578
query94	535	302	284	284
query95	577	365	379	365
query96	669	524	238	238
query97	2462	2425	2301	2301
query98	164	153	146	146
query99	775	766	653	653
Total cold run time: 235220 ms
Total hot run time: 152943 ms

@hello-stephen

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

query1	0.00	0.00	0.00
query2	0.10	0.04	0.05
query3	0.27	0.12	0.12
query4	1.61	0.12	0.12
query5	0.27	0.25	0.26
query6	1.16	0.68	0.68
query7	0.03	0.01	0.01
query8	0.05	0.04	0.04
query9	0.42	0.34	0.34
query10	0.58	0.56	0.57
query11	0.21	0.15	0.14
query12	0.18	0.14	0.14
query13	0.49	0.48	0.48
query14	1.04	1.02	1.00
query15	0.65	0.61	0.61
query16	0.35	0.31	0.35
query17	1.17	1.16	1.13
query18	0.23	0.21	0.21
query19	2.09	1.92	2.03
query20	0.02	0.02	0.01
query21	15.48	0.25	0.14
query22	4.42	0.05	0.06
query23	16.25	0.33	0.12
query24	3.01	0.72	0.46
query25	0.11	0.06	0.06
query26	1.83	0.24	0.14
query27	0.05	0.04	0.03
query28	2.30	0.60	0.41
query29	12.47	4.11	3.29
query30	0.28	0.15	0.14
query31	2.77	0.57	0.34
query32	3.26	0.62	0.51
query33	3.15	3.19	3.25
query34	15.55	4.02	3.37
query35	3.34	3.34	3.33
query36	0.55	0.44	0.44
query37	0.10	0.07	0.06
query38	0.05	0.04	0.04
query39	0.03	0.03	0.03
query40	0.18	0.14	0.15
query41	0.07	0.03	0.03
query42	0.04	0.02	0.02
query43	0.04	0.04	0.04
Total cold run time: 96.25 s
Total hot run time: 24.49 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 98.59% (70/71) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.05% (35646/46261)
Line Coverage 62.32% (403326/647140)
Region Coverage 58.73% (340515/579838)
Branch Coverage 59.66% (156910/263021)

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69082

Problem Summary: Align the names introduced by this PR with the agreed design
for native Azure authentication, which uses the ObjClient* family next to the
existing ObjClientHolder:

- ObjStorageClientFactory -> ObjClientFactory (obj_client_factory.{h,cpp})
- ObjStorageClientConfig / ObjStorageClientConfigHash -> ObjClientConfig /
  ObjClientConfigHash
- ObjStorageClientCache -> ObjClientCache (obj_client_cache.h)
- obj_storage_client_factory_test.cpp -> obj_client_factory_test.cpp

ObjStorageClient (the shared object operation interface in common) and the
ObjStorage* IO types are unchanged. This is a pure rename with no behavior
change.

### Release note

None

### Check List (For Author)

- Test: No need to test (pure rename; BE was not built locally, clang-format 16
  and check-build-hygiene.sh passed)
- Behavior changed: No
- Does this need documentation: No
@xylaaaaa

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17595	5619	5544	5544
q2	2140	300	245	245
q3	10249	1417	844	844
q4	4678	477	345	345
q5	7422	798	540	540
q6	186	191	158	158
q7	759	796	613	613
q8	9244	1375	1052	1052
q9	5638	4275	4266	4266
q10	6808	1314	1027	1027
q11	444	260	236	236
q12	644	402	287	287
q13	18092	3640	3037	3037
q14	282	263	249	249
q15	q16	742	734	656	656
q17	1198	743	585	585
q18	7028	6264	6204	6204
q19	1242	979	603	603
q20	380	335	219	219
q21	5483	2579	2693	2579
q22	400	377	305	305
Total cold run time: 100654 ms
Total hot run time: 29594 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6731	6595	6795	6595
q2	761	621	566	566
q3	5742	5833	5387	5387
q4	2065	2150	1557	1557
q5	5682	5615	5860	5615
q6	250	195	150	150
q7	2302	2087	1858	1858
q8	3129	2761	2760	2760
q9	8068	8152	7737	7737
q10	3644	3608	3264	3264
q11	599	400	368	368
q12	658	683	503	503
q13	3272	3560	2991	2991
q14	286	286	273	273
q15	q16	663	686	625	625
q17	7812	6975	6894	6894
q18	13107	12257	13012	12257
q19	913	783	792	783
q20	2169	2197	1931	1931
q21	5876	4787	4771	4771
q22	495	466	413	413
Total cold run time: 74224 ms
Total hot run time: 67298 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152362 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 90c15f1237bb15d3fc5475606f533145d26ed859, data reload: false

query5	4316	581	465	465
query6	435	213	195	195
query7	4811	460	233	233
query8	325	182	157	157
query9	8771	3970	3935	3935
query10	459	315	269	269
query11	5978	3845	3526	3526
query12	147	94	88	88
query13	1256	444	333	333
query14	6089	4098	3781	3781
query14_1	3654	3525	3557	3525
query15	219	201	181	181
query16	960	448	427	427
query17	866	666	544	544
query18	2431	429	311	311
query19	200	170	145	145
query20	88	85	85	85
query21	213	134	111	111
query22	12956	13015	12884	12884
query23	13430	13030	12462	12462
query23_1	12579	12582	12529	12529
query24	7115	837	472	472
query24_1	482	474	473	473
query25	540	424	363	363
query26	1344	258	145	145
query27	2757	450	275	275
query28	4622	1943	1935	1935
query29	1614	613	452	452
query30	310	232	186	186
query31	1028	934	806	806
query32	164	97	93	93
query33	528	310	248	248
query34	912	879	497	497
query35	766	762	663	663
query36	807	828	738	738
query37	135	104	95	95
query38	1812	1815	1683	1683
query39	806	820	750	750
query39_1	740	737	761	737
query40	264	113	94	94
query41	68	63	63	63
query42	86	82	81	81
query43	364	378	338	338
query44	1276	692	701	692
query45	184	177	160	160
query46	839	965	573	573
query47	3010	2874	2868	2868
query48	290	307	213	213
query49	582	397	296	296
query50	683	285	213	213
query51	10658	10481	10390	10390
query52	79	81	70	70
query53	193	214	150	150
query54	247	194	180	180
query55	72	71	63	63
query56	238	225	202	202
query57	1603	1579	1576	1576
query58	294	255	253	253
query59	2147	2172	1906	1906
query60	287	242	220	220
query61	146	138	146	138
query62	389	344	283	283
query63	196	163	174	163
query64	2741	932	812	812
query65	3299	3230	3236	3230
query66	1781	417	308	308
query67	20559	20325	20150	20150
query68	3016	997	611	611
query69	386	290	242	242
query70	834	773	804	773
query71	291	250	206	206
query72	2796	2568	2334	2334
query73	516	529	300	300
query74	4576	4478	4299	4299
query75	2339	2312	1942	1942
query76	2331	1027	615	615
query77	339	396	274	274
query78	9714	9635	9144	9144
query79	968	894	523	523
query80	720	445	351	351
query81	543	315	271	271
query82	1037	133	106	106
query83	275	203	192	192
query84	322	122	103	103
query85	918	414	378	378
query86	345	234	241	234
query87	2010	1980	1811	1811
query88	3606	2706	2676	2676
query89	348	302	265	265
query90	1747	184	182	182
query91	160	155	130	130
query92	100	84	92	84
query93	1009	1008	581	581
query94	488	315	275	275
query95	592	396	321	321
query96	664	527	239	239
query97	2464	2436	2323	2323
query98	167	153	147	147
query99	781	769	646	646
Total cold run time: 235478 ms
Total hot run time: 152362 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.12	0.05	0.05
query3	0.28	0.11	0.11
query4	1.61	0.13	0.13
query5	0.26	0.24	0.24
query6	1.16	0.68	0.68
query7	0.04	0.00	0.00
query8	0.05	0.04	0.04
query9	0.40	0.36	0.34
query10	0.58	0.54	0.60
query11	0.20	0.14	0.14
query12	0.18	0.14	0.14
query13	0.49	0.49	0.50
query14	1.03	1.01	1.00
query15	0.62	0.61	0.61
query16	0.35	0.34	0.31
query17	1.17	1.11	1.16
query18	0.23	0.22	0.20
query19	2.10	1.99	2.01
query20	0.02	0.02	0.01
query21	15.49	0.28	0.15
query22	4.48	0.06	0.06
query23	16.23	0.33	0.12
query24	2.91	1.04	0.40
query25	0.12	0.07	0.04
query26	1.56	0.24	0.14
query27	0.05	0.03	0.04
query28	2.25	0.57	0.38
query29	12.52	4.28	3.31
query30	0.28	0.14	0.13
query31	2.77	0.58	0.33
query32	3.21	0.62	0.52
query33	3.29	3.15	3.17
query34	15.39	4.04	3.42
query35	3.34	3.38	3.36
query36	0.55	0.46	0.43
query37	0.10	0.07	0.06
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.17	0.15	0.15
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 95.87 s
Total hot run time: 24.48 s

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69082

Problem Summary: ObjClientFactory::get_or_create() selected the client
provider with std::get_if<S3ClientConfig> and fell back to
std::get<AzureClientConfig>. Adding a third alternative to
ObjClientConfig::backend would still compile, and a config of the new type
would throw bad_variant_access at runtime. Dispatch through std::visit to
one private overload per backend instead, so a missing overload is a
compile error, as the hash and to_string helpers of ObjClientConfig already
do.

### Release note

None

### Check List (For Author)

- Test: No need to test (dispatch is equivalent for both existing
  alternatives and covered by obj_client_factory_test; BE was not built
  locally, clang-format 16 and check-build-hygiene.sh passed)
- Behavior changed: No
- Does this need documentation: No
@xylaaaaa

Copy link
Copy Markdown
Contributor Author

run buildall

…ntials

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69082

Problem Summary: FE passes Azure access to BE through the S3-style
properties map, reusing AWS_ACCESS_KEY / AWS_SECRET_KEY for the account and
key. That map cannot express a SAS token or Entra ID client credentials, so
the native BE Azure client only supports SharedKey, and OAuth2 storage
access only works for OneLake through the Hadoop path.

This change adds a typed FE-to-BE protocol and the BE side of it:

- gensrc: TAzureClientConfig with a TAzureCredential union (shared_key,
  sas, client_secret), carried by the new optional field
  TFileScanRangeParams.azure_client_config (id 42, unused on master and on
  branch-4.2/4.1/4.0/3.1).
- AzureAuthFactory builds SAS clients (token appended to the container
  URL) and client secret clients (Azure::Identity::ClientSecretCredential
  sharing the blob transport).
- AzureAuthConfig gains AzureSasConfig and AzureClientSecretConfig;
  hash/to_string cover them and keep secrets masked.
- AzureConfigCodec decodes TAzureClientConfig (exactly one credential;
  container from the file location unless configured, and both must
  match); AzureConfigValidator checks the fields of the selected method
  and the account against standard Azure hosts;
  AzureCredentialValidator parses the SAS "se" expiry and rejects an
  expired SAS. AzureClientProvider runs it on every client request, i.e.
  each reader open, never per range read.
- ObjStorageConfigResolver::from_azure_client_config() is the entry for
  the typed input. FileFactory uses it for FILE_S3 reads when the scan
  params carry azure_client_config, and ignores the S3-style keys then.
- ObjClientHolder now keeps the typed ObjClientConfig in its state, plus
  the legacy conf when built from one; a holder built from a typed config
  initializes through ObjClientFactory directly.
- The scan readers that build FileSystemProperties from
  TFileScanRangeParams copy azure_client_config.

### Release note

None

### Check List (For Author)

- Test: Unit Test (added, not run; BE was not built locally,
  clang-format 16 and check-build-hygiene.sh passed)
    - azure_config_test.cpp: codec, validator, SAS expiry parsing,
      expired SAS, resolver entry, masking and identity
    - obj_client_factory_test.cpp: typed holder initialization and an
      expired SAS rejected before any client is built
- Behavior changed: No for existing requests; only requests that carry
  the new field take the new path.
- Does this need documentation: No
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69082

Problem Summary: FE hands Azure access to BE as an S3-style map
(AWS_ACCESS_KEY = account, AWS_SECRET_KEY = key). That map has no way to
carry a SAS token or Entra ID client credentials, so FE offered no SAS
option at all, and OAuth2 storage access to a normal Azure Blob location
reached BE as a Hadoop configuration it cannot use on the FILE_S3 path.

This change fills the new TAzureClientConfig from FE:

- New user property azure.sas_token (sensitive) with
  azure.auth_type = SAS; validation requires the token and an endpoint
  or account name. FE listing (AzureObjStorage) uses the SAS too, and the
  Hadoop map configures hadoop-azure's fixed SAS token for ABFS access.
- AzureFileSystemProperties.toMap() keeps its S3-style keys for old BEs
  (SAS adds no legacy credential, so an old BE is never handed a wrong
  one) and also writes neutral AZURE_* keys (AzureBackendPropertyKeys in
  fe-filesystem-api). OAuth2 resolves the tenant as the FE SDK client
  already does and derives the authority host from oauth2_server_uri; the
  FE SDK client now uses that authority host as well.
- AzureThriftAdapter (fe-core) is the only place that knows the Thrift
  shape: it turns the neutral keys into TAzureClientConfig.
  FileQueryScanNode sets it on TFileScanRangeParams for FILE_S3 ranges,
  which covers TVF scans and plugin-driven catalogs, since both build
  their location properties from the provider map.

Rolling upgrade: SharedKey keeps working on old BEs through the S3-style
keys. SAS and OAuth2 on FILE_S3 need every BE upgraded first.

Outbound requests: with OAuth2, BE now requests tokens from the
authority host derived from azure.oauth2_server_uri, in addition to the
storage endpoint. Both come from catalog/TVF properties, so reaching them
requires the privilege to create or alter that catalog, or to run the
TVF.

### Release note

Azure storage accessed through TVF or external catalogs supports SAS
tokens (azure.auth_type = SAS, azure.sas_token) and native BE OAuth2
client credentials, in addition to SharedKey. Upgrade all BEs before using
SAS or OAuth2.

### Check List (For Author)

- Test: Unit Test (added, not run; FE was not built locally)
    - AzureFileSystemPropertiesTest: native keys for SharedKey, SAS and
      OAuth2, SAS validation, SAS hadoop config, sensitive SAS key
    - AzureThriftAdapterTest: each credential, no native keys, unknown
      auth type
- Behavior changed: Yes. The Azure backend map carries AZURE_* keys and
  FILE_S3 scans carry TAzureClientConfig; new SAS auth type.
- Does this need documentation: Yes (azure.auth_type = SAS and
  azure.sas_token), not included in this change
@xylaaaaa

xylaaaaa commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69605

Problem Summary: `ObjStorageFileSystem::refresh` applies a refreshed cold-storage resource and can
return a new file system, while `refresh_vault` applies a refreshed storage vault and never
replaces the file system. The bare name read like a general version that a vault could use too, so
it is now `refresh_resource`. No behavior change.

### Release note

None

### Check List (For Author)

- Test: No need to test (rename; existing unit tests cover it, BE UT in CI)
- Behavior changed: No
- Does this need documentation: No
@xylaaaaa

xylaaaaa commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

Cloud UT Coverage Report

Increment line coverage 100.00% (3/3) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.91% (2108/2777)
Line Coverage 65.78% (38833/59039)
Region Coverage 53.53% (36373/67950)
Branch Coverage 56.90% (11870/20862)

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17626	5233	5129	5129
q2	2121	320	287	287
q3	10217	1409	842	842
q4	4683	460	337	337
q5	7426	804	526	526
q6	184	183	154	154
q7	773	813	608	608
q8	9257	1327	1089	1089
q9	5712	4223	4230	4223
q10	6844	1299	1014	1014
q11	446	255	235	235
q12	643	400	289	289
q13	18109	4328	3075	3075
q14	271	274	245	245
q15	q16	746	746	695	695
q17	1217	763	576	576
q18	7066	6181	6130	6130
q19	1144	959	608	608
q20	413	341	229	229
q21	5438	2509	2600	2509
q22	400	326	273	273
Total cold run time: 100736 ms
Total hot run time: 29073 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5990	5925	6130	5925
q2	719	649	584	584
q3	5649	5869	5320	5320
q4	2226	2206	1601	1601
q5	5740	5844	5578	5578
q6	235	191	149	149
q7	2231	2048	1801	1801
q8	3131	2640	2760	2640
q9	7931	7474	7514	7474
q10	3614	3614	3177	3177
q11	589	404	385	385
q12	667	714	539	539
q13	3390	3668	3092	3092
q14	286	294	256	256
q15	q16	649	669	630	630
q17	7840	7120	6982	6982
q18	12917	12120	12992	12120
q19	929	823	832	823
q20	2145	2135	1921	1921
q21	5924	4862	5050	4862
q22	514	481	422	422
Total cold run time: 73316 ms
Total hot run time: 66281 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 151627 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 eb15c5a56ca095acf8a72d3876d61ed97ee2f726, data reload: false

query5	4307	610	454	454
query6	425	212	197	197
query7	4812	437	220	220
query8	315	160	149	149
query9	8770	3196	3193	3193
query10	465	305	259	259
query11	6029	3851	3588	3588
query12	157	94	90	90
query13	1250	458	340	340
query14	6151	3955	3603	3603
query14_1	3452	3408	3399	3399
query15	212	201	185	185
query16	950	449	441	441
query17	887	674	536	536
query18	2424	420	309	309
query19	207	169	146	146
query20	86	87	82	82
query21	219	125	104	104
query22	13132	13038	12743	12743
query23	13465	12880	12450	12450
query23_1	12534	12452	12523	12452
query24	7365	823	476	476
query24_1	487	485	500	485
query25	543	429	376	376
query26	1284	255	142	142
query27	2762	444	276	276
query28	4625	2075	2061	2061
query29	1584	643	459	459
query30	303	220	192	192
query31	1017	934	823	823
query32	153	101	92	92
query33	533	307	243	243
query34	916	853	498	498
query35	765	750	641	641
query36	840	812	719	719
query37	136	103	89	89
query38	1771	1709	1669	1669
query39	798	788	750	750
query39_1	731	735	729	729
query40	225	119	97	97
query41	72	69	72	69
query42	89	83	85	83
query43	345	357	316	316
query44	1374	734	719	719
query45	183	182	179	179
query46	902	966	585	585
query47	2923	3025	2897	2897
query48	297	310	226	226
query49	571	397	297	297
query50	690	290	217	217
query51	10522	10614	10496	10496
query52	77	82	69	69
query53	189	220	162	162
query54	263	208	191	191
query55	74	65	62	62
query56	238	215	230	215
query57	1698	1643	1532	1532
query58	283	264	254	254
query59	2163	2174	1971	1971
query60	297	245	232	232
query61	155	145	149	145
query62	393	343	287	287
query63	186	160	162	160
query64	2763	986	768	768
query65	3327	3283	3271	3271
query66	1772	417	330	330
query67	20157	20198	19922	19922
query68	3214	1025	617	617
query69	416	298	244	244
query70	857	771	778	771
query71	322	245	210	210
query72	2798	2598	2292	2292
query73	530	534	309	309
query74	4674	4598	4347	4347
query75	2347	2310	1950	1950
query76	2406	1018	604	604
query77	344	378	284	284
query78	9953	9689	9205	9205
query79	1035	861	551	551
query80	1220	440	351	351
query81	595	324	272	272
query82	615	138	104	104
query83	314	198	190	190
query84	313	124	105	105
query85	875	443	383	383
query86	416	247	225	225
query87	2003	1930	1801	1801
query88	3920	2833	2821	2821
query89	340	285	244	244
query90	1922	192	179	179
query91	163	149	129	129
query92	102	92	93	92
query93	1061	1029	582	582
query94	662	308	270	270
query95	584	394	308	308
query96	689	508	248	248
query97	2430	2429	2357	2357
query98	164	152	147	147
query99	765	762	668	668
Total cold run time: 236934 ms
Total hot run time: 151627 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.10	0.05	0.05
query3	0.26	0.08	0.09
query4	1.61	0.09	0.08
query5	0.28	0.24	0.25
query6	1.20	0.68	0.66
query7	0.04	0.00	0.00
query8	0.05	0.04	0.04
query9	0.40	0.35	0.35
query10	0.63	0.57	0.58
query11	0.20	0.15	0.14
query12	0.19	0.17	0.14
query13	0.49	0.48	0.51
query14	1.04	1.01	1.01
query15	0.64	0.62	0.61
query16	0.33	0.35	0.34
query17	1.15	1.10	1.14
query18	0.19	0.19	0.19
query19	2.05	1.96	2.01
query20	0.02	0.04	0.01
query21	15.48	0.18	0.14
query22	4.94	0.05	0.06
query23	16.28	0.32	0.13
query24	3.19	0.48	0.45
query25	0.11	0.06	0.04
query26	1.46	0.21	0.16
query27	0.05	0.05	0.05
query28	3.50	0.72	0.37
query29	12.46	4.09	3.26
query30	0.28	0.12	0.09
query31	2.77	0.55	0.32
query32	3.24	0.61	0.50
query33	3.11	3.21	3.15
query34	15.30	4.02	3.42
query35	3.33	3.35	3.32
query36	0.56	0.46	0.63
query37	0.12	0.08	0.07
query38	0.06	0.04	0.04
query39	0.04	0.02	0.03
query40	0.18	0.16	0.15
query41	0.08	0.03	0.03
query42	0.04	0.03	0.02
query43	0.04	0.04	0.03
Total cold run time: 97.5 s
Total hot run time: 24.32 s

…torage-client

# Conflicts:
#	be/src/exec/sink/writer/iceberg/viceberg_delete_file_writer.cpp
#	be/src/exec/sink/writer/iceberg/viceberg_partition_writer.cpp
#	be/src/exec/sink/writer/vhive_partition_writer.cpp
@xylaaaaa
xylaaaaa requested a review from Mryange as a code owner November 9, 2026 02:01
@xylaaaaa

xylaaaaa commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

xylaaaaa added a commit to xylaaaaa/doris that referenced this pull request Nov 9, 2026
…mment

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69605, apache#69082

Problem Summary: The bulk rename of S3ClientFactory to AwsSdkManager also
rewrote a comment in obj_storage_config.cpp that names the function the
config checks came from, so it read "the former AwsSdkManager::create".
That function was S3ClientFactory::create; AwsSdkManager never had a
create method. Restore the original name. A scan of comments that name a
method of AwsSdkManager or the ObjStorage* classes found no other method
that does not exist.

### Release note

None

### Check List (For Author)

- Test: No need to test (comment only)
- Behavior changed: No
- Does this need documentation: No
chenjunwei and others added 12 commits November 9, 2026 14:44
### What problem does this PR solve?

Related PR: apache#69082, apache#69605

Problem Summary: Keep the integration branch aligned with the split BE
refactor. Include the bucket supplied by the legacy configuration sources
in the S3 client cache key and preserve it through refresh. This keeps
separate connection pools for otherwise identical configurations that
name different buckets.

### Release note

None

### Check List (For Author)

- Test: FE and ASAN BE builds passed. A local two-bucket S3 regression
  passed with cold and warm caches. BE logs confirmed two client builds,
  and SQL and an independent S3 client verified the exported data.
  Header hygiene, formatting and clang-tidy passed.
- Behavior changed: No (preserves the pre-refactor S3 cache behavior)
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082

Problem Summary: Public URL generation assumed an S3 client whenever an
endpoint matched the OSS private endpoint suffix. A custom Azure endpoint
with that suffix would fail before signing. Rewrite the endpoint in a
copy of the configured backend so its own client signs the public URL.

### Release note

None

### Check List (For Author)

- Test: FE and ASAN BE builds passed. The file system and regression
  test compiled. The macOS BE UT target stopped at the pre-existing
  std::min type mismatch in binary_column_extract_iterator_test.cpp:74
  from apache#70212. Header hygiene, clang-format 16 and clang-tidy passed.
- Behavior changed: No (restores pre-refactor public URL generation).
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082

Problem Summary: When credentials were refreshed while a writer waited
for its parts, CompleteMultipartUpload used the replacement client.
Remember the holder state before waiting. After all upload callbacks
finish, reject an invalidated holder and keep the original client
when only authentication changed. Other configuration updates and
resource backend rebinds still use the current client.

### Release note

None

### Check List (For Author)

- Test: ASAN BE and FE builds passed. The new writer test compiled.
  The macOS BE UT target still stops in the upstream segment test
  binary_column_extract_iterator_test.cpp:74 (apache#70212), before test
  execution. Header hygiene, clang-format 16 and clang-tidy passed.
- Behavior changed: No (restores pre-refactor credential rotation).
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082

Problem Summary: A holder refresh that changed a timeout or S3
addressing during multipart close routed CompleteMultipartUpload to
the replacement client. Keep the client selected before waiting when
only credentials, request or connection timeouts, or S3 addressing
change. Check the live holder after all uploads finish and continue to
honor vault invalidation and resource backend changes.

### Release note

None

### Check List (For Author)

- Test: Production FE and ASAN BE builds, formatting, header hygiene and
  clang-tidy passed. The equivalent writer regression passed on apache#69605.
  This branch's macOS BE UT build is blocked by the existing size_t /
  ordinal_t std::min mismatch in binary_column_extract_iterator_test.cpp.
- Behavior changed: No (restores pre-refactor multipart close behavior
  for addressing and timeout updates).
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082

Problem Summary: During a multipart close, the client selector compared individual configuration fields after waiting for the parts. A change of S3 vendor or Azure container switched the pending Complete to the refreshed client, even though the backend type stayed the same. Use the client captured before the wait for same-type refreshes, as on master. Recheck the live holder after draining callbacks so invalidation still blocks Complete, and use the current client after a cross-backend resource rebind. The test clients keep separate parts to check both selection and storage error propagation.

### Release note

None

### Check List (For Author)

- Test: FE and ASAN BE build, clang-format 16, clang-tidy and build hygiene. The macOS arm64 BE UT build stops in the upstream binary_column_extract_iterator_test.cpp:74 at std::min(size_t, ordinal_t), before any UT runs.
- Behavior changed: Yes. Same-backend multipart completion preserves master's choice of client.
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082

Problem Summary: With both AWS_ENDPOINT and AWS_REGION missing, flat FE property resolution reported the region first for S3 and Azure. Restore master's endpoint-first diagnostic at the properties entry point and cover both providers. Move the stateless key parser back into the source file's anonymous namespace, remove three unused headers and correct comments left behind by the holder migration.

### Release note

When BE receives flat object storage properties without an endpoint or a region, it again reports the missing endpoint first.

### Check List (For Author)

- Test: Built FE and ASAN BE with Azure enabled, and passed build hygiene, clang-format 16 and clang-tidy on the changed BE files. The macOS arm64 BE unit test build stopped before execution in binary_column_extract_iterator_test.cpp:74 at std::min(size_t, ordinal_t), from the master base.
- Behavior changed: Yes. The diagnostic order for incomplete FE properties matches master.
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082

Problem Summary: Migrating the BE storage binding from S3Conf dropped the sse_enabled value carried by ObjectStoreInfoPB. The previous BE included that value in vault creation and error diagnostics. Carry it on ObjStorageConfig, keep the original false default and print it in the storage and flat-source diagnostics. Client construction, caching and the upload path continue to use their existing inputs.

### Release note

BE vault diagnostics retain the sse_enabled value from storage metadata.

### Check List (For Author)

- Test: Built FE and the ASAN BE with Azure enabled. Build hygiene, clang-format 16 and clang-tidy passed. The macOS arm64 BE UT build stopped before execution in the upstream binary_column_extract_iterator_test.cpp:74 at std::min(size_t, ordinal_t).
- Behavior changed: No relative to master. The refactored BE reports the vault SSE value again.
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082, apache#69605

Problem Summary: The benchmark writer sets a 3000 ms S3 connection timeout. The reader at the merge base passed a property that the resolver ignored and inherited the SDK setting. Omit the reader override when converting the benchmark to typed client configuration so its read workload uses the same settings as before.

### Release note

None

### Check List (For Author)

- Test: clang-format 16, BE header hygiene and changed-file clang-tidy passed on this branch. The identical change on apache#69605 passed the default FE and ASAN BE build and 72 related BE tests. The optional tool on macOS still encounters the existing RapidJSON overload ambiguity when serializing released_elements.
- Behavior changed: No relative to the merge base.
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082

Problem Summary: The typed Azure file system test called the removed _get_key member and could not compile with Azure enabled. Open a reader through the file system for each supported location and assert its resolved path. A supplied file size avoids a metadata request.

### Release note

None

### Check List (For Author)

- Test: On macOS arm64 with Azure enabled, ASAN_UT compiled the updated Azure test. The normal test build then stopped at the independent std::min(size_t, ordinal_t) error in binary_column_extract_iterator_test.cpp before running tests. clang-format 16, clang-tidy and BE header hygiene passed.
- Behavior changed: No
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69082, apache#69605

Problem Summary: Keep the behavior of the merge base when migrating object storage clients. Leave the file cache benchmark's read-side connection timeout property spelling and the vault sync warning's status argument as they were. Enable RFC 3986 encoding in the reader and writer constructors and remove the test for eager SDK encoding.

### Release note

None

### Check List (For Author)

- Test: Built FE and the Azure-enabled ASAN BE on macOS arm64 with PCH disabled. The standard BE UT build stops at the pre-existing std::min(size_t, ordinal_t) error in binary_column_extract_iterator_test.cpp before running tests. clang-format 16, clang-tidy and BE build hygiene passed. On apache#69605, separate fresh test processes called the encoding setter with false at SDK initialization and true from the respective reader and writer constructors.
- Behavior changed: No relative to the master merge base for these three paths.
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#69605, apache#69082

Problem Summary: The integration branch differed from the reviewed child PR in three places. The file cache benchmark reader passed an unrecognized connection timeout key. The vault sync warning used the status of fetching the vault list after a create or refresh failed. Requests sent before the first reader or writer could use a different path encoding. Pass the recognized benchmark key, log the failing operation status and enable RFC 3986 encoding through the AWS SDK initialization options. Restore the SDK initialization regression test.

### Release note

The BE uses strict RFC 3986 path encoding from AWS SDK startup and reports the failing operation in vault sync warnings. The file cache benchmark applies its configured S3 connection timeout to reads.

### Check List (For Author)

- Test: Compared all three code paths and the encoding regression test with apache#69605 at b6ac43e. The six changed C++ files passed clang-format 16, the changed-line clang-tidy check and BE build hygiene.
- Behavior changed: Yes, as described in the release note.
- Does this need documentation: No
…obench key as on master

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69605

Problem Summary: Review asked to keep this refactor free of behavior changes and bug fixes. Three places still differed from master and are returned to it:

- A failed vault create or refresh in `CloudStorageEngine::sync_storage_vault` logs the status of `get_storage_vault_info` again, as on master.
- The object storage reader and writer constructors set `Aws::Http::SetCompliantRfc3986Encoding(true)` again, instead of `SDKOptions` before `InitAPI`. The test that asserted the flag after SDK initialization is removed with it.
- The file cache microbench reader passes `AWS_CONNECT_TIMEOUT_MS` again, the key master uses.

The fixes themselves will be sent separately. The six files are identical to the parent of `96f3b7ee9e3`.

### Release note

None

### Check List (For Author)

- Test: No need to test; the six files are identical to the parent of 96f3b7e. Build hygiene and clang-format 16 passed. Not compiled locally; CI compiles and runs the unit tests.
- Behavior changed: No (returns these three places to master behavior)
- Does this need documentation: No
@xylaaaaa

Copy link
Copy Markdown
Contributor Author

run buildall

### What problem does this PR solve?

Related PR: apache#69605

Problem Summary: ObjClientHolder published a new state only when no other reset had published since the caller took its snapshot, and otherwise returned Aborted. Before the refactor the holder built the client outside the lock and the last reset to publish won, with both calls succeeding. The generation check did not add correctness: the merge keeps only the storage target, which no reset changes, so the published configuration is the same whichever state it was merged with, and the holder cannot tell which caller carries the newer configuration either way. Its only effect was a different arbitrary winner and a failed refresh for the other caller.

Restore the previous behavior: _publish no longer takes the expected state, and it assigns the next generation under the lock. The check for an invalidated holder stays, so a client that was being built during invalidate() still cannot bring the holder back. A reset cannot overlap a rebind: resource updates run on a single worker thread, and vault syncs only reset or invalidate.

### Release note

None

### Check List (For Author)

- Test: Cherry-picked from apache#69605 (e0caadd); the change is identical apart from the ObjStorageFileSystem name in one comment. The unit test for overlapping resets expects both resets to succeed and the last one to stay. Not compiled locally; CI compiles and runs it. Build hygiene and clang-format 16 passed.
- Behavior changed: No relative to master. Overlapping resets both succeed and the last one wins again.
- Does this need documentation: No
@xylaaaaa

Copy link
Copy Markdown
Contributor Author

run buildall

…f AwsSdkManager

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69605

Problem Summary: `AwsSdkManager` owns the AWS SDK lifetime, yet it still carried two Azure parts: its constructor set up the Azure SDK log, and `AzureClientProvider` called `AwsSdkManager::instance().ca_cert_file_path()` for its CA bundle. Review on apache#69605 pointed this out; this applies the same change here, where the class is already named `AwsSdkManager`.

- `AwsSdkManager` keeps only the AWS SDK lifetime (`InitAPI` / `ShutdownAPI`), `getClientConfiguration` and `create_aws_credentials_provider`, which the S3 provider and Kinesis use.
- The Azure SDK log setup moves unchanged into `init_azure_sdk_logging()` in `azure_client_provider`. `ObjClientFactory` calls it on construction, right after initializing the AWS SDK, and BE startup now constructs `ObjClientFactory` instead of `AwsSdkManager`, so both SDKs are still set up at startup in the same thread, and the AWS SDK is still shut down after the providers release their clients.
- The CA bundle cache moves unchanged into `io/obj_storage/obj_client_ca.{h,cpp}` (`obj_client_ca_cert_file_path()`): the first valid path of `ca_cert_file_paths`, cached, looked up again while empty. Both providers and the AWS credentials provider use it, so the Azure provider no longer depends on an AWS class. `AwsSdkManager` still resolves it once on construction. The CA test uses a test hook instead of the removed private members.

### Release note

None

### Check List (For Author)

- Test: Unit Test (`S3ClientFactoryTest.RefreshCaCertForCredentialsProvider` now goes through the new hook). Ported from apache#69605 (61f6dec); apart from the class rename, which this branch already has, the change is identical. Not compiled locally; CI compiles and runs the unit tests. Build hygiene and clang-format 16 passed.
- Behavior changed: No
- Does this need documentation: No
@xylaaaaa

Copy link
Copy Markdown
Contributor Author

run buildall

### What problem does this PR solve?

Issue Number: None
Related PR: apache#69082, apache#69605

Problem Summary: Keep resource and vault updates on the original file
system. Preserve the flat input fields that determine the effective
storage target, credential validation, and cache identity across S3 and
Azure. Keep the client captured before waiting for multipart completion.
Defer the Azure client cache limit and eviction policy to a separate
change. Native Azure access still checks SAS expiry before looking up a
client and before publishing a newly built one.

### Release note

None

### Check List (For Author)

- Test: Built the Azure-enabled ASAN BE and FE locally on macOS arm64
  with PCH disabled. Ran clang-format 16, clang-tidy and build hygiene.
  The standard ASAN_UT build stops at the upstream size_t/ordinal_t
  std::min call in binary_column_extract_iterator_test.cpp:74. The PR
  checklist records the separate object storage runs and S3 regression.
- Behavior changed: Restore the legacy refresh, validation and cache
  behavior. Native Azure access keeps the integration PR's credential
  and expiry rules.
- 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.

4 participants