5353
5454import software .amazon .awssdk .core .ResponseInputStream ;
5555import software .amazon .awssdk .core .exception .SdkException ;
56+ import software .amazon .awssdk .services .s3 .S3AsyncClient ;
5657import software .amazon .awssdk .services .s3 .S3Client ;
58+ import software .amazon .awssdk .services .s3 .internal .crt .S3CrtAsyncClient ;
5759import software .amazon .awssdk .services .s3 .model .CompleteMultipartUploadRequest ;
5860import software .amazon .awssdk .services .s3 .model .CompleteMultipartUploadResponse ;
5961import software .amazon .awssdk .services .s3 .model .GetBucketLocationRequest ;
8688import software .amazon .awssdk .transfer .s3 .model .Copy ;
8789import software .amazon .awssdk .transfer .s3 .model .CopyRequest ;
8890
91+ import software .amazon .s3 .analyticsaccelerator .S3SdkObjectClient ;
92+ import software .amazon .s3 .analyticsaccelerator .S3SeekableInputStreamConfiguration ;
93+ import software .amazon .s3 .analyticsaccelerator .S3SeekableInputStreamFactory ;
94+ import software .amazon .s3 .analyticsaccelerator .common .ConnectorConfiguration ;
95+
8996import org .apache .hadoop .fs .impl .prefetch .ExecutorServiceFuturePool ;
9097import org .slf4j .Logger ;
9198import org .slf4j .LoggerFactory ;
@@ -313,6 +320,13 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
313320 */
314321 private S3Client s3Client ;
315322
323+ /**
324+ * CRT-Based S3Client created of analytics accelerator library is enabled
325+ * and managed by the S3AStoreImpl. Analytics accelerator library can be
326+ * enabled with {@link Constants#ANALYTICS_ACCELERATOR_ENABLED_KEY}
327+ */
328+ private S3AsyncClient s3AsyncClient ;
329+
316330 // initial callback policy is fail-once; it's there just to assist
317331 // some mock tests and other codepaths trying to call the low level
318332 // APIs on an uninitialized filesystem.
@@ -340,6 +354,11 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
340354 // If true, the prefetching input stream is used for reads.
341355 private boolean prefetchEnabled ;
342356
357+ // If true, S3SeekableInputStream from Analytics Accelerator for Amazon S3 will be used.
358+ private boolean analyticsAcceleratorEnabled ;
359+
360+ private boolean analyticsAcceleratorCRTEnabled ;
361+
343362 // Size in bytes of a single prefetch block.
344363 private int prefetchBlockSize ;
345364
@@ -515,6 +534,11 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
515534 */
516535 private boolean s3AccessGrantsEnabled ;
517536
537+ /**
538+ * Factory to create S3SeekableInputStream if {@link this#analyticsAcceleratorEnabled} is true.
539+ */
540+ private S3SeekableInputStreamFactory s3SeekableInputStreamFactory ;
541+
518542 /** Add any deprecated keys. */
519543 @ SuppressWarnings ("deprecation" )
520544 private static void addDeprecatedKeys () {
@@ -670,8 +694,21 @@ public void initialize(URI name, Configuration originalConf)
670694 this .prefetchBlockSize = (int ) prefetchBlockSizeLong ;
671695 this .prefetchBlockCount =
672696 intOption (conf , PREFETCH_BLOCK_COUNT_KEY , PREFETCH_BLOCK_DEFAULT_COUNT , 1 );
697+
698+ this .analyticsAcceleratorEnabled =
699+ conf .getBoolean (ANALYTICS_ACCELERATOR_ENABLED_KEY , ANALYTICS_ACCELERATOR_ENABLED_DEFAULT );
700+ this .analyticsAcceleratorCRTEnabled =
701+ conf .getBoolean (ANALYTICS_ACCELERATOR_CRT_ENABLED ,
702+ ANALYTICS_ACCELERATOR_CRT_ENABLED_DEFAULT );
703+
673704 this .isMultipartUploadEnabled = conf .getBoolean (MULTIPART_UPLOADS_ENABLED ,
674- DEFAULT_MULTIPART_UPLOAD_ENABLED );
705+ DEFAULT_MULTIPART_UPLOAD_ENABLED );
706+
707+ if (this .analyticsAcceleratorEnabled && !analyticsAcceleratorCRTEnabled ) {
708+ // Temp change: Analytics Accelerator with S3AsyncClient do not support Multi-part upload.
709+ this .isMultipartUploadEnabled = false ;
710+ }
711+
675712 // multipart copy and upload are the same; this just makes it explicit
676713 this .isMultipartCopyEnabled = isMultipartUploadEnabled ;
677714
@@ -794,6 +831,27 @@ public void initialize(URI name, Configuration originalConf)
794831 // directly through the client manager.
795832 // this is to aid mocking.
796833 s3Client = store .getOrCreateS3Client ();
834+
835+ if (this .analyticsAcceleratorEnabled ) {
836+ LOG .info ("Using S3SeekableInputStream" );
837+ if (this .analyticsAcceleratorCRTEnabled ) {
838+ LOG .info ("Using S3 CRT client for analytics accelerator S3" );
839+ this .s3AsyncClient = S3CrtAsyncClient .builder ().maxConcurrency (600 ).build ();
840+ } else {
841+ LOG .info ("Using S3 async client for analytics accelerator S3" );
842+ this .s3AsyncClient = store .getOrCreateAsyncClient ();
843+ }
844+
845+ ConnectorConfiguration configuration = new ConnectorConfiguration (conf ,
846+ ANALYTICS_ACCELERATOR_CONFIGURATION_PREFIX );
847+ S3SeekableInputStreamConfiguration seekableInputStreamConfiguration =
848+ S3SeekableInputStreamConfiguration .fromConfiguration (configuration );
849+ this .s3SeekableInputStreamFactory =
850+ new S3SeekableInputStreamFactory (
851+ new S3SdkObjectClient (this .s3AsyncClient ),
852+ seekableInputStreamConfiguration );
853+ }
854+
797855 // The filesystem is now ready to perform operations against
798856 // S3
799857 // This initiates a probe against S3 for the bucket existing.
@@ -1861,6 +1919,8 @@ private FSDataInputStream executeOpen(
18611919 final Path path ,
18621920 final OpenFileSupport .OpenFileInformation fileInformation )
18631921 throws IOException {
1922+
1923+
18641924 // create the input stream statistics before opening
18651925 // the file so that the time to prepare to open the file is included.
18661926 S3AInputStreamStatistics inputStreamStats =
@@ -1877,6 +1937,14 @@ private FSDataInputStream executeOpen(
18771937 fileInformation .applyOptions (readContext );
18781938 LOG .debug ("Opening '{}'" , readContext );
18791939
1940+ if (this .analyticsAcceleratorEnabled ) {
1941+ return new FSDataInputStream (
1942+ new S3ASeekableStream (
1943+ this .bucket ,
1944+ pathToKey (path ),
1945+ s3SeekableInputStreamFactory ));
1946+ }
1947+
18801948 if (this .prefetchEnabled ) {
18811949 Configuration configuration = getConf ();
18821950 initLocalDirAllocatorIfNotInitialized (configuration );
@@ -4354,9 +4422,11 @@ public void close() throws IOException {
43544422 protected synchronized void stopAllServices () {
43554423 try {
43564424 trackDuration (getDurationTrackerFactory (), FILESYSTEM_CLOSE .getSymbol (), () -> {
4357- closeAutocloseables (LOG , store );
4425+ closeAutocloseables (LOG , store , s3SeekableInputStreamFactory );
43584426 store = null ;
43594427 s3Client = null ;
4428+ s3AsyncClient = null ;
4429+ s3SeekableInputStreamFactory = null ;
43604430
43614431 // At this point the S3A client is shut down,
43624432 // now the executor pools are closed
0 commit comments