xiangfu0 commented on code in PR #19238:
URL: https://github.com/apache/pinot/pull/19238#discussion_r3787087097


##########
pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotIngestionRestletResource.java:
##########
@@ -197,14 +200,12 @@ public void ingestFromURI(
     tableNameWithType = DatabaseUtils.translateTableName(tableNameWithType, 
headers);
     try {
       asyncResponse.resume(ingestData(tableNameWithType, batchConfigMapStr, 
new DataPayload(new URI(sourceURIStr))));
-    } catch (IllegalArgumentException e) {
-      asyncResponse.resume(new ControllerApplicationException(LOGGER, String
-          .format("Got illegal argument when ingesting file into table: %s. 
%s", tableNameWithType, e.getMessage()),
-          Response.Status.BAD_REQUEST, e));
-    } catch (Exception e) {
-      asyncResponse.resume(new ControllerApplicationException(LOGGER,
-          String.format("Caught exception when ingesting file into table: %s. 
%s", tableNameWithType, e.getMessage()),
-          Response.Status.INTERNAL_SERVER_ERROR, e));
+    } catch (IllegalArgumentException | URISyntaxException e) {
+      asyncResponse.resume(
+          new ControllerApplicationException(LOGGER, "Invalid ingestFromURI 
request", Response.Status.BAD_REQUEST));
+    } catch (Exception | LinkageError e) {
+      asyncResponse.resume(new ControllerApplicationException(LOGGER, "Failed 
to ingest from URI",
+          Response.Status.INTERNAL_SERVER_ERROR));

Review Comment:
   Thanks—agreed that the failure type should reach the server log. Passing the 
original exception to the existing four-argument constructor would log its 
message for 4xx or the full throwable for 5xx, and those values can include the 
submitted path or URI query parameters. I added a TYPE_ONLY mode and use it in 
both branches, so the response remains generic while the log records only the 
exception class. Tests cover both status families with sentinel URI data.



##########
pinot-controller/src/main/java/org/apache/pinot/controller/util/FileIngestionHelper.java:
##########
@@ -158,12 +171,17 @@ public SuccessResponse buildSegmentAndPush(DataPayload 
payload)
       SegmentUploader segmentUploader = 
PluginManager.get().createInstance(SEGMENT_UPLOADER_CLASS);
       segmentUploader.init(tableConfigOverride);
       segmentUploader.uploadSegment(segmentTarFile.toURI(), _authProvider);
-      LOGGER.info("Uploaded tar: {} to table: {}", 
segmentTarFile.getAbsolutePath(), tableNameWithType);
+      LOGGER.info("Uploaded generated segment to table: {}", 
tableNameWithType);
 
       return new SuccessResponse(
           "Successfully ingested file into table: " + tableNameWithType + " as 
segment: " + segmentName);
     } catch (Exception e) {
-      LOGGER.error("Caught exception when ingesting file to table: {}", 
tableNameWithType, e);
+      if (payload._payloadType == PayloadType.URI) {
+        LOGGER.error("Failed URI ingestion for table: {}, exception type: {}", 
tableNameWithType,
+            e.getClass().getName());
+      } else {
+        LOGGER.error("Caught exception when ingesting file to table: {}", 
tableNameWithType, e);
+      }

Review Comment:
   Good catch on the resolution scope. I moved URI logging around the full 
resolve/use lifecycle, so resolution, initialization, copy/build/upload, and 
linkage failures are covered. URI logging remains type-only because filesystem 
exception messages and causes can contain source paths or signed URI 
parameters. The old inner URI log was removed; multipart logging is unchanged.



##########
pinot-controller/src/main/java/org/apache/pinot/controller/util/FileIngestionHelper.java:
##########
@@ -179,40 +197,104 @@ public static void copyURIToLocal(Map<String, String> 
batchConfigMap, URI source
   public static void copyURIToLocal(Map<String, String> batchConfigMap, URI 
sourceFileURI, File destFile,
       boolean allowLocalFileSystem)
       throws Exception {
+    try (ResolvedFileSystem sourceFileSystem =

Review Comment:
   Removed the unused three-argument overload. The remaining overload requires 
every caller to state the local-filesystem policy explicitly.



##########
pinot-plugins/pinot-file-system/pinot-hdfs/src/main/java/org/apache/pinot/plugin/filesystem/HadoopPinotFS.java:
##########
@@ -77,7 +77,9 @@ public void init(PinotConfiguration config) {
         UserGroupInformation.setLoginUser(ugi);
         LOGGER.info("Setting HDFS login user to: {}", globalHadoopUser);
       }
-      _hadoopFS = org.apache.hadoop.fs.FileSystem.get(_hadoopConf);
+      // Hadoop's FileSystem.get() returns a process-cached instance. 
HadoopPinotFS closes its filesystem, so it must
+      // own a distinct instance to avoid one PinotFS closing a client that is 
still in use elsewhere.
+      _hadoopFS = org.apache.hadoop.fs.FileSystem.newInstance(_hadoopConf);

Review Comment:
   Closing a replaced mapping is unsafe because callers can retain the 
non-closing wrapper returned by create() and may still be using the old Hadoop 
or S3 client. Instead, I added atomic, configuration-aware registerIfNeeded() 
for the repeated Spark and Hadoop executor setup paths. Equivalent 
registrations reuse one initialized client; a differing explicit class or 
configuration still replaces the mapping without closing retained wrappers. 
Tests cover equivalent reuse, differing mappings, nullable compatibility, and 
concurrent initialization.



##########
pinot-plugins/pinot-file-system/pinot-hdfs/src/test/java/org/apache/pinot/plugin/filesystem/HadoopPinotFSTest.java:
##########
@@ -479,4 +480,17 @@ public void testInitWithUnauthenticatedUser()
       Assert.assertEquals(currentUser, testUser, "The Hadoop login user was 
not set correctly!");
     }
   }
+
+  @Test
+  public void testInstancesOwnDistinctHadoopFileSystems()
+      throws Exception {
+    try (HadoopPinotFS first = new HadoopPinotFS(); HadoopPinotFS second = new 
HadoopPinotFS()) {
+      first.init(new PinotConfiguration());
+      second.init(new PinotConfiguration());
+
+      Field hadoopFileSystemField = 
HadoopPinotFS.class.getDeclaredField("_hadoopFS");
+      hadoopFileSystemField.setAccessible(true);
+      Assert.assertNotSame(hadoopFileSystemField.get(first), 
hadoopFileSystemField.get(second));
+    }

Review Comment:
   Replaced the reflection assertion with a behavioral close-aware filesystem 
test. It initializes two adapters with the same Hadoop configuration, closes 
the first, and verifies the second remains usable. The old shared 
FileSystem.get() behavior fails this test, while independently owned clients 
pass.



-- 
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