Cyberduck Mountain Duck CLI

Changeset 42890


Ignore:
Timestamp:
Oct 11, 2017 6:56:41 PM (2 years ago)
Author:
dkocher
Message:

Review zero byte writes with memory segmenting wrapped stream..

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/backblaze/src/main/java/ch/cyberduck/core/b2/B2LargeUploadWriteFeature.java

    r42584 r42890  
    7272
    7373    private final PathContainerService containerService
    74             = new B2PathContainerService();
     74        = new B2PathContainerService();
    7575
    7676    private final B2Session session;
     
    9292        final LargeUploadOutputStream proxy = new LargeUploadOutputStream(file, status);
    9393        return new HttpResponseOutputStream<VersionId>(new MemorySegementingOutputStream(proxy,
    94                 PreferencesFactory.get().getInteger("b2.upload.largeobject.size.minimum"))) {
     94            PreferencesFactory.get().getInteger("b2.upload.largeobject.size.minimum"))) {
    9595            @Override
    9696            public VersionId getStatus() throws BackgroundException {
     
    145145        @Override
    146146        public void write(final byte[] content, final int off, final int len) throws IOException {
    147             if(0 == len) {
    148                 // Skip empty segment
    149                 return;
    150             }
    151147            try {
    152148                if(0 == partNumber && len < PreferencesFactory.get().getInteger("b2.upload.largeobject.size.minimum")) {
     
    155151                    final Checksum checksum = overall.getChecksum();
    156152                    final B2FileResponse response = session.getClient().uploadFile(uploadUrl,
    157                             containerService.getKey(file),
    158                             new ByteArrayEntity(content, off, len), Checksum.NONE == checksum ? "do_not_verify" : checksum.hash,
    159                             overall.getMime(), overall.getMetadata());
     153                        containerService.getKey(file),
     154                        new ByteArrayEntity(content, off, len), Checksum.NONE == checksum ? "do_not_verify" : checksum.hash,
     155                        overall.getMime(), overall.getMetadata());
    160156                    if(log.isDebugEnabled()) {
    161157                        log.debug(String.format("Upload finished for %s with response %s", file, response));
     
    170166                        }
    171167                        final B2StartLargeFileResponse response = session.getClient().startLargeFileUpload(new B2FileidProvider(session).getFileid(containerService.getContainer(file), new DisabledListProgressListener()),
    172                                 containerService.getKey(file), overall.getMime(), fileinfo);
     168                            containerService.getKey(file), overall.getMime(), fileinfo);
    173169                        version = new VersionId(response.getFileId());
    174170                        if(log.isDebugEnabled()) {
     
    186182                            final ByteArrayEntity entity = new ByteArrayEntity(content, off, len);
    187183                            final Checksum checksum = ChecksumComputeFactory.get(HashAlgorithm.sha1)
    188                                     .compute(new ByteArrayInputStream(content, off, len), status);
     184                                .compute(new ByteArrayInputStream(content, off, len), status);
    189185                            try {
    190186                                return session.getClient().uploadLargeFilePart(version.id, segment, entity, checksum.hash);
     
    218214                    if(null == version) {
    219215                        // No single file upload and zero parts
    220                         try {
    221                             version = new VersionId(new B2TouchFeature(session).touch(file, overall.length(0L)).attributes().getVersionId());
    222                         }
    223                         catch(BackgroundException e) {
    224                             throw new IOException(e);
    225                         }
     216                        version = new VersionId(new B2TouchFeature(session).touch(file, overall.length(0L)).attributes().getVersionId());
    226217                    }
    227218                }
     
    243234                }
    244235            }
     236            catch(BackgroundException e) {
     237                throw new IOException(e);
     238            }
    245239            catch(B2ApiException e) {
    246240                throw new IOException(new B2ExceptionMappingService().map("Upload {0} failed", e, file));
  • trunk/core/src/main/java/ch/cyberduck/core/io/MemorySegementingOutputStream.java

    r42250 r42890  
    7171        }
    7272        try {
    73             proxy.write(buffer.toByteArray());
     73            if(buffer.size() > 0) {
     74                proxy.write(buffer.toByteArray());
     75            }
    7476            // Re-use buffer
    7577            buffer.reset();
  • trunk/onedrive/src/main/java/ch/cyberduck/core/onedrive/OneDriveWriteFeature.java

    r42876 r42890  
    4444import java.io.OutputStream;
    4545import java.util.Arrays;
     46import java.util.concurrent.atomic.AtomicBoolean;
    4647
    4748public class OneDriveWriteFeature implements Write<Void> {
     
    4950
    5051    private final Preferences preferences
    51             = PreferencesFactory.get();
     52        = PreferencesFactory.get();
    5253
    5354    private final OneDriveSession session;
     
    7172            final ChunkedOutputStream proxy = new ChunkedOutputStream(upload, file, new TransferStatus(status));
    7273            return new HttpResponseOutputStream<Void>(new MemorySegementingOutputStream(proxy,
    73                     preferences.getInteger("onedrive.upload.multipart.partsize.minimum"))) {
     74                preferences.getInteger("onedrive.upload.multipart.partsize.minimum"))) {
    7475                @Override
    7576                public Void getStatus() throws BackgroundException {
     
    114115        private final Path file;
    115116        private final TransferStatus status;
     117        private final AtomicBoolean close = new AtomicBoolean();
    116118
    117119        private Long offset = 0L;
     
    131133        public void write(final byte[] b, final int off, final int len) throws IOException {
    132134            final byte[] content = Arrays.copyOfRange(b, off, len);
    133             if(content.length == 0) {
     135            final HttpRange range = HttpRange.byLength(offset, content.length);
     136            final String header;
     137            if(status.getLength() == -1L) {
     138                header = String.format("%d-%d/*", range.getStart(), range.getEnd());
     139            }
     140            else {
     141                header = String.format("%d-%d/%d", range.getStart(), range.getEnd(), status.getOffset() + status.getLength());
     142            }
     143            if(upload.uploadFragment(header, content) instanceof OneDriveFile.Metadata) {
     144                log.info(String.format("Completed upload for %s", file));
     145            }
     146            else {
     147                log.debug(String.format("Uploaded fragment %s for file %s", header, file));
     148            }
     149            offset += content.length;
     150        }
     151
     152        @Override
     153        public void close() throws IOException {
     154            try {
     155                if(close.get()) {
     156                    log.warn(String.format("Skip double close of stream %s", this));
     157                    return;
     158                }
    134159                if(0L == offset) {
     160                    log.warn(String.format("Abort upload session %s with no completed parts", upload));
    135161                    // Use touch feature for empty file upload
    136162                    upload.cancelUpload();
    137                     try {
    138                         new OneDriveTouchFeature(session).touch(file, status);
    139                     }
    140                     catch(BackgroundException e) {
    141                         throw new IOException(e);
    142                     }
     163                    new OneDriveTouchFeature(session).touch(file, status);
    143164                }
    144                 // Ignore empty content
    145165            }
    146             else {
    147                 final HttpRange range = HttpRange.byLength(offset, content.length);
    148                 final String header;
    149                 if(status.getLength() == -1L) {
    150                     header = String.format("%d-%d/*", range.getStart(), range.getEnd());
    151                 }
    152                 else {
    153                     header = String.format("%d-%d/%d", range.getStart(), range.getEnd(), status.getOffset() + status.getLength());
    154                 }
    155                 if(upload.uploadFragment(header, content) instanceof OneDriveFile.Metadata) {
    156                     log.info(String.format("Completed upload for %s", file));
    157                 }
    158                 else {
    159                     log.debug(String.format("Uploaded fragment %s for file %s", header, file));
    160                 }
    161                 offset += content.length;
     166            catch(BackgroundException e) {
     167                throw new IOException(e);
     168            }
     169            finally {
     170                close.set(true);
    162171            }
    163172        }
  • trunk/openstack/src/main/java/ch/cyberduck/core/openstack/SwiftLargeUploadWriteFeature.java

    r41833 r42890  
    145145        @Override
    146146        public void write(final byte[] content, final int off, final int len) throws IOException {
    147             if(0 == len) {
    148                 // Skip empty segment
    149                 return;
    150             }
    151147            try {
    152148                completed.add(new DefaultRetryCallable<StorageObject>(new BackgroundExceptionCallable<StorageObject>() {
  • trunk/s3/src/main/java/ch/cyberduck/core/s3/S3MultipartWriteFeature.java

    r42585 r42890  
    5252
    5353    private final Preferences preferences
    54             = PreferencesFactory.get();
     54        = PreferencesFactory.get();
    5555
    5656    private final PathContainerService containerService
    57             = new S3PathContainerService();
     57        = new S3PathContainerService();
    5858
    5959    private final S3Session session;
     
    7474    public HttpResponseOutputStream<List<MultipartPart>> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
    7575        final S3Object object = new S3WriteFeature(session, new S3DisabledMultipartService())
    76                 .getDetails(containerService.getKey(file), status);
     76            .getDetails(containerService.getKey(file), status);
    7777        // ID for the initiated multipart upload.
    7878        final MultipartUpload multipart;
    7979        try {
    8080            multipart = session.getClient().multipartStartUpload(
    81                     containerService.getContainer(file).getName(), object);
     81                containerService.getContainer(file).getName(), object);
    8282            if(log.isDebugEnabled()) {
    8383                log.debug(String.format("Multipart upload started for %s with ID %s",
    84                         multipart.getObjectKey(), multipart.getUploadId()));
     84                    multipart.getObjectKey(), multipart.getUploadId()));
    8585            }
    8686        }
     
    9090        final MultipartOutputStream proxy = new MultipartOutputStream(multipart, file, status);
    9191        return new HttpResponseOutputStream<List<MultipartPart>>(new MemorySegementingOutputStream(proxy,
    92                 preferences.getInteger("s3.upload.multipart.partsize.minimum"))) {
     92            preferences.getInteger("s3.upload.multipart.partsize.minimum"))) {
    9393            @Override
    9494            public List<MultipartPart> getStatus() throws BackgroundException {
     
    122122         */
    123123        private final List<MultipartPart> completed
    124                 = new ArrayList<MultipartPart>();
     124            = new ArrayList<MultipartPart>();
    125125
    126126        private final MultipartUpload multipart;
     
    147147        @Override
    148148        public void write(final byte[] content, final int off, final int len) throws IOException {
    149             if(0 == len) {
    150                 // Skip empty segment
    151                 return;
    152             }
    153149            try {
    154150                completed.add(new DefaultRetryCallable<MultipartPart>(new BackgroundExceptionCallable<MultipartPart>() {
     
    162158                            case AWS4HMACSHA256:
    163159                                status.setChecksum(ChecksumComputeFactory.get(HashAlgorithm.sha256)
    164                                         .compute(new ByteArrayInputStream(content, off, len), status)
     160                                    .compute(new ByteArrayInputStream(content, off, len), status)
    165161                                );
    166162                                break;
     
    168164                        status.setSegment(true);
    169165                        final S3Object part = new S3WriteFeature(session, new S3DisabledMultipartService())
    170                                 .getDetails(containerService.getKey(file), status);
     166                            .getDetails(containerService.getKey(file), status);
    171167                        try {
    172168                            session.getClient().putObjectWithRequestEntityImpl(
    173                                     containerService.getContainer(file).getName(), part,
    174                                     new ByteArrayEntity(content, off, len), parameters);
     169                                containerService.getContainer(file).getName(), part,
     170                                new ByteArrayEntity(content, off, len), parameters);
    175171                        }
    176172                        catch(ServiceException e) {
     
    181177                        }
    182178                        return new MultipartPart(partNumber,
    183                                 null == part.getLastModifiedDate() ? new Date(System.currentTimeMillis()) : part.getLastModifiedDate(),
    184                                 null == part.getETag() ? StringUtils.EMPTY : part.getETag(),
    185                                 part.getContentLength());
     179                            null == part.getLastModifiedDate() ? new Date(System.currentTimeMillis()) : part.getLastModifiedDate(),
     180                            null == part.getETag() ? StringUtils.EMPTY : part.getETag(),
     181                            part.getContentLength());
    186182                    }
    187183                }, overall).call());
     
    202198                    log.warn(String.format("Abort multipart upload %s with no completed parts", multipart));
    203199                    session.getClient().multipartAbortUpload(multipart);
    204                     try {
    205                         new S3TouchFeature(session).touch(file, overall.length(0L));
    206                     }
    207                     catch(BackgroundException e) {
    208                         throw new IOException(e);
    209                     }
     200                    new S3TouchFeature(session).touch(file, overall.length(0L));
    210201                }
    211202                else {
     
    213204                    if(log.isDebugEnabled()) {
    214205                        log.debug(String.format("Completed multipart upload for %s with checksum %s",
    215                                 complete.getObjectKey(), complete.getEtag()));
     206                            complete.getObjectKey(), complete.getEtag()));
    216207                    }
    217208                    if(file.getType().contains(Path.Type.encrypted)) {
     
    224215                        }
    225216                        final String expected = String.format("%s-%d",
    226                                 new MD5ChecksumCompute().compute(concat.toString(), overall), completed.size());
     217                            new MD5ChecksumCompute().compute(concat.toString(), overall), completed.size());
    227218                        final String reference;
    228219                        if(complete.getEtag().startsWith("\"") && complete.getEtag().endsWith("\"")) {
     
    235226                            if(session.getHost().getHostname().endsWith(preferences.getProperty("s3.hostname.default"))) {
    236227                                throw new ChecksumException(MessageFormat.format(LocaleFactory.localizedString("Upload {0} failed", "Error"), file.getName()),
    237                                         MessageFormat.format("Mismatch between MD5 hash {0} of uploaded data and ETag {1} returned by the server",
    238                                                 expected, reference));
     228                                    MessageFormat.format("Mismatch between MD5 hash {0} of uploaded data and ETag {1} returned by the server",
     229                                        expected, reference));
    239230                            }
    240231                            else {
     
    245236                }
    246237            }
    247             catch(ChecksumException e) {
    248                 throw new IOException(e.getMessage(), e);
     238            catch(BackgroundException e) {
     239                throw new IOException(e);
    249240            }
    250241            catch(ServiceException e) {
Note: See TracChangeset for help on using the changeset viewer.
swiss made software