Skip to content

Commit

Permalink
Fix #6208.
Browse files Browse the repository at this point in the history
Former-commit-id: a1d577b4abc744b650ee578044065339501b5a5f
  • Loading branch information
dkocher committed Jul 31, 2013
1 parent f362d34 commit 1bdab5c
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 22 deletions.
2 changes: 2 additions & 0 deletions Changelog.txt
Expand Up @@ -6,6 +6,7 @@ Changelog. Last modified: $Date$
4.4 [http://trac.cyberduck.ch/milestone/4.3.2]
- [Feature] Performance improvements
- [Feature] No Java installation requirement (Mac)
- [Feature] Resumable multipart uploads (S3) (#6208)
- [Feature] Bucket lifecycle configuration to archive objects in Glacier (S3) (#6830)
- [Feature] Keystone (2.0) authentication support (OpenStack) (#6330)
- [Feature] Multiple region support (OpenStack) (#6902)
Expand All @@ -22,6 +23,7 @@ Changelog. Last modified: $Date$
- [Bugfix] Authentication with none password (SFTP) (#7322)
- [Bugfix] Interoperability issues (WebDAV) (#7227)
- [Bugfix] Subsequent edit fails (#7248)
- [Bugfix] Omit absolute paths in archives (ZIP, TAR) (#6644)

4.3.1 [http://trac.cyberduck.ch/milestone/4.3.1]
- [Bugfix] Modification date shown as 01.01.1970 (Windows) (#7177)
Expand Down
27 changes: 9 additions & 18 deletions source/ch/cyberduck/core/s3/S3MultipartUploadService.java
Expand Up @@ -55,12 +55,6 @@
public class S3MultipartUploadService extends S3SingleUploadService {
private static final Logger log = Logger.getLogger(S3MultipartUploadService.class);

/**
* Default minimum part size for upload parts.
*/
private static final int DEFAULT_MINIMUM_UPLOAD_PART_SIZE =
Preferences.instance().getInteger("s3.upload.multipart.size");

/**
* The maximum allowed parts in a multipart upload.
*/
Expand All @@ -78,16 +72,23 @@ public class S3MultipartUploadService extends S3SingleUploadService {
private ThreadPool pool = new ThreadPool(
Preferences.instance().getInteger("s3.upload.multipart.concurency"));

/**
* A split smaller than 5M is not allowed
*/
private Long partsize;

public S3MultipartUploadService(final S3Session session) {
public S3MultipartUploadService(final S3Session session, final Long partsize) {
super(session);
this.session = session;
this.partsize = partsize;
}

@Override
public void upload(final Path file, final BandwidthThrottle throttle, final StreamListener listener,
final TransferStatus status) throws BackgroundException {
try {
final S3TouchFeature touch = new S3TouchFeature(session);
touch.touch(file);
MultipartUpload multipart = null;
if(status.isAppend()) {
// This operation lists in-progress multipart uploads. An in-progress multipart upload is a
Expand Down Expand Up @@ -138,13 +139,8 @@ public void upload(final Path file, final BandwidthThrottle throttle, final Stre
}
try {
final List<Future<MultipartPart>> parts = new ArrayList<Future<MultipartPart>>();

final long defaultPartSize = Math.max((status.getLength() / MAXIMUM_UPLOAD_PARTS),
DEFAULT_MINIMUM_UPLOAD_PART_SIZE);

long remaining = status.getLength();
long marker = 0;

for(int partNumber = 1; remaining > 0; partNumber++) {
boolean skip = false;
if(status.isAppend()) {
Expand All @@ -159,7 +155,7 @@ public void upload(final Path file, final BandwidthThrottle throttle, final Stre
}
}
// Last part can be less than 5 MB. Adjust part size.
final long length = Math.min(defaultPartSize, remaining);
final long length = Math.min(Math.max((status.getLength() / MAXIMUM_UPLOAD_PARTS), partsize), remaining);
if(!skip) {
// Submit to queue
parts.add(this.submitPart(file, throttle, listener, status, multipart, partNumber, marker, length));
Expand Down Expand Up @@ -191,11 +187,6 @@ public void upload(final Path file, final BandwidthThrottle throttle, final Stre
}
}
finally {
if(!status.isComplete()) {
// Cancel all previous parts
log.info(String.format("Cancel multipart upload %s", multipart.getUploadId()));
session.getClient().multipartAbortUpload(multipart);
}
// Cancel future tasks
pool.shutdown();
}
Expand Down
2 changes: 1 addition & 1 deletion source/ch/cyberduck/core/s3/S3ThresholdUploadService.java
Expand Up @@ -41,7 +41,7 @@ public S3ThresholdUploadService(final S3Session session) {
public void upload(final Path file, final BandwidthThrottle throttle, final StreamListener listener,
final TransferStatus status) throws BackgroundException {
if(status.getLength() > Preferences.instance().getLong("s3.upload.multipart.threshold")) {
new S3MultipartUploadService(session).upload(file, throttle, listener, status);
new S3MultipartUploadService(session, Preferences.instance().getLong("s3.upload.multipart.size")).upload(file, throttle, listener, status);
}
else {
new S3SingleUploadService(session).upload(file, throttle, listener, status);
Expand Down
6 changes: 3 additions & 3 deletions test/ch/cyberduck/core/s3/S3MultipartUploadServiceTest.java
Expand Up @@ -39,7 +39,7 @@ public void testUploadSinglePart() throws Exception {
)));
session.open(new DefaultHostKeyController());
session.login(new DisabledPasswordStore(), new DisabledLoginController());
final S3MultipartUploadService m = new S3MultipartUploadService(session);
final S3MultipartUploadService m = new S3MultipartUploadService(session, 5 * 1024L);
final Path container = new Path("test.cyberduck.ch", Path.VOLUME_TYPE);
final Path test = new Path(container, UUID.randomUUID().toString(), Path.FILE_TYPE);
test.setLocal(new FinderLocal(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString()));
Expand All @@ -64,7 +64,7 @@ public void testUploadInvalidContainer() throws Exception {
)));
session.open(new DefaultHostKeyController());
session.login(new DisabledPasswordStore(), new DisabledLoginController());
final S3MultipartUploadService m = new S3MultipartUploadService(session);
final S3MultipartUploadService m = new S3MultipartUploadService(session, 5 * 1024L);
final Path container = new Path("nosuchcontainer.cyberduck.ch", Path.VOLUME_TYPE);
final Path test = new Path(container, UUID.randomUUID().toString(), Path.FILE_TYPE);
final TransferStatus status = new TransferStatus();
Expand All @@ -81,7 +81,7 @@ public void testMultipleParts() throws Exception {
)));
session.open(new DefaultHostKeyController());
session.login(new DisabledPasswordStore(), new DisabledLoginController());
final S3MultipartUploadService m = new S3MultipartUploadService(session);
final S3MultipartUploadService m = new S3MultipartUploadService(session, 5 * 1024L);
final Path container = new Path("test.cyberduck.ch", Path.VOLUME_TYPE);
final Path test = new Path(container, UUID.randomUUID().toString(), Path.FILE_TYPE);
test.setLocal(new FinderLocal(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString()));
Expand Down
2 changes: 2 additions & 0 deletions www/update/changelog.html
Expand Up @@ -45,6 +45,7 @@
<ul>
<li>[Feature] Performance improvements</li>
<li>[Feature] No Java installation requirement (Mac)</li>
<li>- [Feature] Resumable multipart uploads (S3) (<a href="http://trac.cyberduck.ch/ticket/6208">#6208</a>)</li>
<li>[Feature] Bucket lifecycle configuration to archive objects in Glacier (S3) <a href="http://trac.cyberduck.ch/ticket/6830">#6830</a></li>
<li>[Feature] Keystone (2.0) authentication support (OpenStack) (<a href="http://trac.cyberduck.ch/ticket/6330">#6330</a>)</li>
<li>[Feature] Multiple region support (OpenStack) (<a href="http://trac.cyberduck.ch/ticket/6902">#6902</a>)</li>
Expand All @@ -61,6 +62,7 @@
<li>[Bugfix] Authentication with none password (SFTP) (<a href="http://trac.cyberduck.ch/ticket/7322">#7322</a>)</li>
<li>[Bugfix] Interoperability issues (WebDAV) (<a href="http://trac.cyberduck.ch/ticket/7227">#7227</a>)</li>
<li>[Bugfix] Subsequent edit fails (<a href="http://trac.cyberduck.ch/ticket/7248">#7248</a>)</li>
<li>[Bugfix] Omit absolute paths in archives (ZIP, TAR) (<a href="http://trac.cyberduck.ch/ticket/6644">#6644</a>)</li>
</ul>

<p>Release notes for previous versions can be found at <a
Expand Down
2 changes: 2 additions & 0 deletions www/update/changelog.txt
@@ -1,5 +1,6 @@
4.4 [http://trac.cyberduck.ch/milestone/4.4]
- [Feature] Performance improvements
- [Feature] Resumable multipart uploads (S3) (#6208)
- [Feature] Bucket lifecycle configuration to archive objects in Glacier (S3) (#6830)
- [Feature] Keystone (2.0) authentication support (OpenStack) (#6330)
- [Feature] Multiple region support (OpenStack) (#6902)
Expand All @@ -13,3 +14,4 @@
- [Bugfix] Authentication with none password (SFTP) (#7322)
- [Bugfix] Interoperability issues (WebDAV) (#7227)
- [Bugfix] Subsequent edit fails (#7248)
- [Bugfix] Omit absolute paths in archives (ZIP, TAR) (#6644)

0 comments on commit 1bdab5c

Please sign in to comment.