mixermt commented on code in PR #5898:
URL: https://github.com/apache/datafusion-comet/pull/5898#discussion_r4366281622


##########
native/Cargo.toml:
##########
@@ -85,8 +85,8 @@ aws-sdk-sts = { version = "1.114.0", default-features = false 
}
 # Pinned to a revision rather than a release because no published iceberg-rust
 # version is on our arrow: 0.10.1 requires arrow/parquet ^58. Move to a plain
 # version requirement once a release ships on arrow 59. Bump policy: #5645.
-iceberg = { git = "https://github.com/apache/iceberg-rust";, rev = 
"1f3bc34058e3f3e45336bc5428f37b92649a608b" }
-iceberg-storage-opendal = { git = "https://github.com/apache/iceberg-rust";, 
rev = "1f3bc34058e3f3e45336bc5428f37b92649a608b", features = ["opendal-memory", 
"opendal-fs", "opendal-s3", "opendal-gcs", "opendal-oss", "opendal-azdls"] }
+iceberg = { git = "https://github.com/apache/iceberg-rust";, rev = 
"ca21f1587c6caaeb88dd3a9e1cc245747e1aba08" }

Review Comment:
   Pushing back on this one, under these assumptions: (a) files written by 
Iceberg writers carry field ids, so this only concerns tables imported from 
pre-existing Parquet without a name mapping (`migrate`/`snapshot`/`add_files` 
set one; only the low-level `importSparkTable` does not); (b) Spark returns 
NULL for every id-less nested field (#6794), so the base read of `s.b` that 
returned the file's values was not parity either — the repro agrees only 
because `b` is all-NULL; (c) the pin has to pass apache/iceberg-rust#3255 to 
reach the HDFS backend, and nothing at planning time tells id-less files apart. 
Parity (NULL, pruned or not) lands with apache/iceberg-rust#3437; once the pin 
passes it, this test becomes a `checkSparkAnswer` assertion. Until then the 
documented knob applies.
   



##########
native/core/src/execution/operators/iceberg_common.rs:
##########
@@ -302,9 +306,10 @@ fn cached_file_io(
 /// mode; the JVM read and write gates load these lists over JNI. `memory` is 
write-only: an OpenDAL
 /// memory backend is a fresh empty in-process store the write path assembles 
manifests in, so a
 /// read finds nothing. `oss` is read-only: no `oss.*` property is forwarded 
and no test covers it.
+/// `hdfs` is read-only: the write path has not been tested against it.
 pub(crate) fn builtin_storage_schemes(access_mode: AccessMode) -> &'static 
[&'static str] {
     match access_mode {
-        AccessMode::Read => &["file", "gs", "oss", "s3", "s3a"],
+        AccessMode::Read => &["file", "gs", "hdfs", "oss", "s3", "s3a"],

Review Comment:
   Agreed: one `FileIO` is built from the metadata location, so a data/delete 
file on another backend fails at open. The same holds today for local or REST 
metadata with `s3://`/`gs://` data, so the gate is general: the planner 
declines a scan whose data/delete files are not all in the metadata location's 
storage family (`file`, `s3`/`s3a`, aliases, `gs`, `oss`, `hdfs`). The 
nameservice planner tests moved their warehouse onto the fake `hdfs://` 
filesystem; decline tests cover local+hdfs, hdfs+local and local+s3; 
`CometIcebergHdfsSuite` covers all-hdfs end to end.
   



##########
spark/src/main/scala/org/apache/comet/rules/CometScanRule.scala:
##########
@@ -898,6 +905,52 @@ case class CometScanRule(session: SparkSession)
           case None => true
         }
 
+        // iceberg-rust's HDFS client cannot use an executor's delegation 
tokens: opendal builds
+        // every client for a synthetic nameservice, and the client looks 
tokens up by that name.
+        // A portless authority must be a declared nameservice (see 
hadoopToIcebergHdfsProperties).
+        val hdfsSupported = taskValidation.hdfsAuthorities.isEmpty || {
+          val authentication = 
hadoopConf.getTrimmed("hadoop.security.authentication", "simple")
+          val secure = !authentication.equalsIgnoreCase("simple")
+          if (secure) {
+            fallbackReasons += "Iceberg scan reads HDFS with " +
+              s"hadoop.security.authentication=$authentication, but Comet's 
native Iceberg " +
+              "reader cannot authenticate to HDFS with delegation tokens"
+          }
+          val undeclared = CometIcebergNativeScan.undeclaredHdfsNameservice(
+            taskValidation.hdfsAuthorities,
+            metadata.catalogProperties)
+          undeclared.foreach { ns =>
+            fallbackReasons += s"Iceberg scan reads HDFS authority '$ns', 
which has no port and " +
+              "which the Hadoop configuration does not declare as a 
nameservice " +
+              s"(dfs.ha.namenodes.$ns, and a host:port 
dfs.namenode.rpc-address.$ns.<id> for " +
+              "each NameNode)"
+          }
+          !secure && undeclared.isEmpty

Review Comment:
   Agreed. The planner now declines instead: when the NameNode's server 
defaults or the session conf name a key provider, each distinct data/delete 
directory is checked with `FileStatus.isEncrypted()` (set for directories 
inside a zone; works through viewfs/HA); clusters without a key provider pay 
one cached `getServerDefaults` call. Not enabling `kms` here: hdfs-native reads 
the KMS URI only from `hadoop.security.key.provider.path` and rejects any 
non-`kms://` provider at client construction, which would break unencrypted 
reads on `jceks://` clusters; MiniKMS is also absent from the minicluster jar. 
`CometIcebergHdfsSuite` gains an encryption-zone case (jceks provider; the 
table inside the zone falls back and matches Spark, a sibling outside stays 
native); the docs entry moves to the fallback list.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to