|
@@ -464,6 +464,12 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
|
|
|
*/
|
|
|
private String scheme = FS_S3A;
|
|
|
|
|
|
+ /**
|
|
|
+ * Flag to indicate that the higher performance copyFromLocalFile implementation
|
|
|
+ * should be used.
|
|
|
+ */
|
|
|
+ private boolean optimizedCopyFromLocal;
|
|
|
+
|
|
|
/** Add any deprecated keys. */
|
|
|
@SuppressWarnings("deprecation")
|
|
|
private static void addDeprecatedKeys() {
|
|
@@ -700,6 +706,9 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
|
|
|
AWS_S3_VECTOR_ACTIVE_RANGE_READS, DEFAULT_AWS_S3_VECTOR_ACTIVE_RANGE_READS, 1);
|
|
|
vectoredIOContext = populateVectoredIOContext(conf);
|
|
|
scheme = (this.uri != null && this.uri.getScheme() != null) ? this.uri.getScheme() : FS_S3A;
|
|
|
+ optimizedCopyFromLocal = conf.getBoolean(OPTIMIZED_COPY_FROM_LOCAL,
|
|
|
+ OPTIMIZED_COPY_FROM_LOCAL_DEFAULT);
|
|
|
+ LOG.debug("Using optimized copyFromLocal implementation: {}", optimizedCopyFromLocal);
|
|
|
} catch (SdkException e) {
|
|
|
// amazon client exception: stop all services then throw the translation
|
|
|
cleanupWithLogger(LOG, span);
|
|
@@ -4028,9 +4037,9 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
|
|
|
* the given dst name.
|
|
|
*
|
|
|
* This version doesn't need to create a temporary file to calculate the md5.
|
|
|
- * Sadly this doesn't seem to be used by the shell cp :(
|
|
|
+ * If {@link Constants#OPTIMIZED_COPY_FROM_LOCAL} is set to false,
|
|
|
+ * the superclass implementation is used.
|
|
|
*
|
|
|
- * delSrc indicates if the source should be removed
|
|
|
* @param delSrc whether to delete the src
|
|
|
* @param overwrite whether to overwrite an existing file
|
|
|
* @param src path
|
|
@@ -4038,35 +4047,59 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
|
|
|
* @throws IOException IO problem
|
|
|
* @throws FileAlreadyExistsException the destination file exists and
|
|
|
* overwrite==false
|
|
|
- * @throws SdkException failure in the AWS SDK
|
|
|
*/
|
|
|
@Override
|
|
|
@AuditEntryPoint
|
|
|
public void copyFromLocalFile(boolean delSrc, boolean overwrite, Path src,
|
|
|
Path dst) throws IOException {
|
|
|
checkNotClosed();
|
|
|
- LOG.debug("Copying local file from {} to {}", src, dst);
|
|
|
- trackDurationAndSpan(INVOCATION_COPY_FROM_LOCAL_FILE, dst,
|
|
|
- () -> new CopyFromLocalOperation(
|
|
|
- createStoreContext(),
|
|
|
- src,
|
|
|
- dst,
|
|
|
- delSrc,
|
|
|
- overwrite,
|
|
|
- createCopyFromLocalCallbacks()).execute());
|
|
|
+ LOG.debug("Copying local file from {} to {} (delSrc={} overwrite={}",
|
|
|
+ src, dst, delSrc, overwrite);
|
|
|
+ if (optimizedCopyFromLocal) {
|
|
|
+ trackDurationAndSpan(INVOCATION_COPY_FROM_LOCAL_FILE, dst, () ->
|
|
|
+ new CopyFromLocalOperation(
|
|
|
+ createStoreContext(),
|
|
|
+ src,
|
|
|
+ dst,
|
|
|
+ delSrc,
|
|
|
+ overwrite,
|
|
|
+ createCopyFromLocalCallbacks(getActiveAuditSpan()))
|
|
|
+ .execute());
|
|
|
+ } else {
|
|
|
+ // call the superclass, but still count statistics.
|
|
|
+ // there is no overall span here, as each FS API call will
|
|
|
+ // be in its own span.
|
|
|
+ LOG.debug("Using base copyFromLocalFile implementation");
|
|
|
+ trackDurationAndSpan(INVOCATION_COPY_FROM_LOCAL_FILE, dst, () -> {
|
|
|
+ super.copyFromLocalFile(delSrc, overwrite, src, dst);
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Create the CopyFromLocalCallbacks;
|
|
|
+ * protected to assist in mocking.
|
|
|
+ * @param span audit span.
|
|
|
+ * @return the callbacks
|
|
|
+ * @throws IOException failure to get the local fs.
|
|
|
+ */
|
|
|
protected CopyFromLocalOperation.CopyFromLocalOperationCallbacks
|
|
|
- createCopyFromLocalCallbacks() throws IOException {
|
|
|
+ createCopyFromLocalCallbacks(final AuditSpanS3A span) throws IOException {
|
|
|
LocalFileSystem local = getLocal(getConf());
|
|
|
- return new CopyFromLocalCallbacksImpl(local);
|
|
|
+ return new CopyFromLocalCallbacksImpl(span, local);
|
|
|
}
|
|
|
|
|
|
protected final class CopyFromLocalCallbacksImpl implements
|
|
|
CopyFromLocalOperation.CopyFromLocalOperationCallbacks {
|
|
|
+
|
|
|
+ /** Span to use for all operations. */
|
|
|
+ private final AuditSpanS3A span;
|
|
|
private final LocalFileSystem local;
|
|
|
|
|
|
- private CopyFromLocalCallbacksImpl(LocalFileSystem local) {
|
|
|
+ private CopyFromLocalCallbacksImpl(final AuditSpanS3A span,
|
|
|
+ LocalFileSystem local) {
|
|
|
+ this.span = span;
|
|
|
this.local = local;
|
|
|
}
|
|
|
|
|
@@ -4088,20 +4121,18 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
|
|
|
|
|
|
@Override
|
|
|
public void copyLocalFileFromTo(File file, Path from, Path to) throws IOException {
|
|
|
- trackDurationAndSpan(
|
|
|
- OBJECT_PUT_REQUESTS,
|
|
|
- to,
|
|
|
- () -> {
|
|
|
- final String key = pathToKey(to);
|
|
|
- Progressable progress = null;
|
|
|
- PutObjectRequest.Builder putObjectRequestBuilder =
|
|
|
- newPutObjectRequestBuilder(key, file.length(), false);
|
|
|
- S3AFileSystem.this.invoker.retry("putObject(" + "" + ")", to.toString(), true,
|
|
|
- () -> executePut(putObjectRequestBuilder.build(), progress, putOptionsForPath(to),
|
|
|
- file));
|
|
|
-
|
|
|
- return null;
|
|
|
- });
|
|
|
+ // the duration of the put is measured, but the active span is the
|
|
|
+ // constructor-supplied one -this ensures all audit log events are grouped correctly
|
|
|
+ span.activate();
|
|
|
+ trackDuration(getDurationTrackerFactory(), OBJECT_PUT_REQUESTS.getSymbol(), () -> {
|
|
|
+ final String key = pathToKey(to);
|
|
|
+ PutObjectRequest.Builder putObjectRequestBuilder =
|
|
|
+ newPutObjectRequestBuilder(key, file.length(), false);
|
|
|
+ final String dest = to.toString();
|
|
|
+ S3AFileSystem.this.invoker.retry("putObject(" + dest + ")", dest, true, () ->
|
|
|
+ executePut(putObjectRequestBuilder.build(), null, putOptionsForPath(to), file));
|
|
|
+ return null;
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -5403,6 +5434,10 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
|
|
|
case FS_S3A_CREATE_PERFORMANCE_ENABLED:
|
|
|
return performanceCreation;
|
|
|
|
|
|
+ // is the optimized copy from local enabled.
|
|
|
+ case OPTIMIZED_COPY_FROM_LOCAL:
|
|
|
+ return optimizedCopyFromLocal;
|
|
|
+
|
|
|
default:
|
|
|
return super.hasPathCapability(p, cap);
|
|
|
}
|