5454
5555import software .amazon .awssdk .core .ResponseInputStream ;
5656import software .amazon .awssdk .core .exception .SdkException ;
57+ import software .amazon .awssdk .services .s3 .S3AsyncClient ;
5758import software .amazon .awssdk .services .s3 .S3Client ;
59+ import software .amazon .awssdk .services .s3 .internal .crt .S3CrtAsyncClient ;
5860import software .amazon .awssdk .services .s3 .model .CompleteMultipartUploadRequest ;
5961import software .amazon .awssdk .services .s3 .model .CompleteMultipartUploadResponse ;
6062import software .amazon .awssdk .services .s3 .model .GetBucketLocationRequest ;
8789import software .amazon .awssdk .transfer .s3 .model .Copy ;
8890import software .amazon .awssdk .transfer .s3 .model .CopyRequest ;
8991
92+ import software .amazon .s3 .analyticsaccelerator .S3SdkObjectClient ;
93+ import software .amazon .s3 .analyticsaccelerator .S3SeekableInputStreamConfiguration ;
94+ import software .amazon .s3 .analyticsaccelerator .S3SeekableInputStreamFactory ;
95+ import software .amazon .s3 .analyticsaccelerator .common .ConnectorConfiguration ;
96+
9097import org .apache .hadoop .fs .impl .prefetch .ExecutorServiceFuturePool ;
9198import org .slf4j .Logger ;
9299import org .slf4j .LoggerFactory ;
@@ -317,6 +324,13 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
317324 */
318325 private S3Client s3Client ;
319326
327+ /**
328+ * CRT-Based S3Client created of analytics accelerator library is enabled
329+ * and managed by the S3AStoreImpl. Analytics accelerator library can be
330+ * enabled with {@link Constants#ANALYTICS_ACCELERATOR_ENABLED_KEY}
331+ */
332+ private S3AsyncClient s3AsyncClient ;
333+
320334 // initial callback policy is fail-once; it's there just to assist
321335 // some mock tests and other codepaths trying to call the low level
322336 // APIs on an uninitialized filesystem.
@@ -344,6 +358,11 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
344358 // If true, the prefetching input stream is used for reads.
345359 private boolean prefetchEnabled ;
346360
361+ // If true, S3SeekableInputStream from Analytics Accelerator for Amazon S3 will be used.
362+ private boolean analyticsAcceleratorEnabled ;
363+
364+ private boolean analyticsAcceleratorCRTEnabled ;
365+
347366 // Size in bytes of a single prefetch block.
348367 private int prefetchBlockSize ;
349368
@@ -525,6 +544,11 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
525544 */
526545 private boolean s3AccessGrantsEnabled ;
527546
547+ /**
548+ * Factory to create S3SeekableInputStream if {@link this#analyticsAcceleratorEnabled} is true.
549+ */
550+ private S3SeekableInputStreamFactory s3SeekableInputStreamFactory ;
551+
528552 /** Add any deprecated keys. */
529553 @ SuppressWarnings ("deprecation" )
530554 private static void addDeprecatedKeys () {
@@ -680,8 +704,21 @@ public void initialize(URI name, Configuration originalConf)
680704 this .prefetchBlockSize = (int ) prefetchBlockSizeLong ;
681705 this .prefetchBlockCount =
682706 intOption (conf , PREFETCH_BLOCK_COUNT_KEY , PREFETCH_BLOCK_DEFAULT_COUNT , 1 );
707+
708+ this .analyticsAcceleratorEnabled =
709+ conf .getBoolean (ANALYTICS_ACCELERATOR_ENABLED_KEY , ANALYTICS_ACCELERATOR_ENABLED_DEFAULT );
710+ this .analyticsAcceleratorCRTEnabled =
711+ conf .getBoolean (ANALYTICS_ACCELERATOR_CRT_ENABLED ,
712+ ANALYTICS_ACCELERATOR_CRT_ENABLED_DEFAULT );
713+
683714 this .isMultipartUploadEnabled = conf .getBoolean (MULTIPART_UPLOADS_ENABLED ,
684- DEFAULT_MULTIPART_UPLOAD_ENABLED );
715+ DEFAULT_MULTIPART_UPLOAD_ENABLED );
716+
717+ if (this .analyticsAcceleratorEnabled && !analyticsAcceleratorCRTEnabled ) {
718+ // Temp change: Analytics Accelerator with S3AsyncClient do not support Multi-part upload.
719+ this .isMultipartUploadEnabled = false ;
720+ }
721+
685722 // multipart copy and upload are the same; this just makes it explicit
686723 this .isMultipartCopyEnabled = isMultipartUploadEnabled ;
687724
@@ -809,6 +846,27 @@ public void initialize(URI name, Configuration originalConf)
809846 // directly through the client manager.
810847 // this is to aid mocking.
811848 s3Client = store .getOrCreateS3Client ();
849+
850+ if (this .analyticsAcceleratorEnabled ) {
851+ LOG .info ("Using S3SeekableInputStream" );
852+ if (this .analyticsAcceleratorCRTEnabled ) {
853+ LOG .info ("Using S3 CRT client for analytics accelerator S3" );
854+ this .s3AsyncClient = S3CrtAsyncClient .builder ().maxConcurrency (600 ).build ();
855+ } else {
856+ LOG .info ("Using S3 async client for analytics accelerator S3" );
857+ this .s3AsyncClient = store .getOrCreateAsyncClient ();
858+ }
859+
860+ ConnectorConfiguration configuration = new ConnectorConfiguration (conf ,
861+ ANALYTICS_ACCELERATOR_CONFIGURATION_PREFIX );
862+ S3SeekableInputStreamConfiguration seekableInputStreamConfiguration =
863+ S3SeekableInputStreamConfiguration .fromConfiguration (configuration );
864+ this .s3SeekableInputStreamFactory =
865+ new S3SeekableInputStreamFactory (
866+ new S3SdkObjectClient (this .s3AsyncClient ),
867+ seekableInputStreamConfiguration );
868+ }
869+
812870 // The filesystem is now ready to perform operations against
813871 // S3
814872 // This initiates a probe against S3 for the bucket existing.
@@ -1876,6 +1934,8 @@ private FSDataInputStream executeOpen(
18761934 final Path path ,
18771935 final OpenFileSupport .OpenFileInformation fileInformation )
18781936 throws IOException {
1937+
1938+
18791939 // create the input stream statistics before opening
18801940 // the file so that the time to prepare to open the file is included.
18811941 S3AInputStreamStatistics inputStreamStats =
@@ -1892,6 +1952,14 @@ private FSDataInputStream executeOpen(
18921952 fileInformation .applyOptions (readContext );
18931953 LOG .debug ("Opening '{}'" , readContext );
18941954
1955+ if (this .analyticsAcceleratorEnabled ) {
1956+ return new FSDataInputStream (
1957+ new S3ASeekableStream (
1958+ this .bucket ,
1959+ pathToKey (path ),
1960+ s3SeekableInputStreamFactory ));
1961+ }
1962+
18951963 if (this .prefetchEnabled ) {
18961964 Configuration configuration = getConf ();
18971965 initLocalDirAllocatorIfNotInitialized (configuration );
@@ -4421,9 +4489,11 @@ public void close() throws IOException {
44214489 protected synchronized void stopAllServices () {
44224490 try {
44234491 trackDuration (getDurationTrackerFactory (), FILESYSTEM_CLOSE .getSymbol (), () -> {
4424- closeAutocloseables (LOG , store );
4492+ closeAutocloseables (LOG , store , s3SeekableInputStreamFactory );
44254493 store = null ;
44264494 s3Client = null ;
4495+ s3AsyncClient = null ;
4496+ s3SeekableInputStreamFactory = null ;
44274497
44284498 // At this point the S3A client is shut down,
44294499 // now the executor pools are closed
0 commit comments