Search in sources :

Example 1 with TransferBackgroundActionState

use of ch.cyberduck.core.threading.TransferBackgroundActionState in project cyberduck by iterate-ch.

the class AbstractTransferWorker method transfer.

/**
 * @param item   File to transfer
 * @param action Transfer action for existing files
 */
public Future<TransferStatus> transfer(final TransferItem item, final TransferAction action) throws BackgroundException {
    if (this.isCanceled()) {
        throw new TransferCanceledException();
    }
    // Only transfer if accepted by filter and stored in table with transfer status
    if (table.containsKey(item)) {
        // Overall transfer status
        final TransferStatus status = table.get(item);
        // Handle submit of one or more segments
        final List<TransferStatus> segments = status.getSegments();
        for (final TransferStatus segment : segments) {
            if (segment.isComplete()) {
                continue;
            }
            this.submit(new RetryTransferCallable(transfer.getSource()) {

                @Override
                public TransferStatus call() throws BackgroundException {
                    status.validate();
                    // Transfer
                    // Do transfer with retry
                    this.transferSegment(segment);
                    final Session<?> source = borrow(Connection.source);
                    final Session<?> destination = borrow(Connection.destination);
                    try {
                        // Determine transfer filter implementation from selected overwrite action
                        final TransferPathFilter filter = transfer.filter(source, destination, action, progress);
                        // Post process of file.
                        filter.complete(segment.getRename().remote != null ? segment.getRename().remote : item.remote, segment.getRename().local != null ? segment.getRename().local : item.local, options, segment, progress);
                    } finally {
                        release(source, Connection.source, null);
                        release(destination, Connection.destination, null);
                    }
                    // Recursive
                    if (item.remote.isDirectory()) {
                        if (!cache.isCached(item)) {
                            log.warn(String.format("Missing entry for %s in cache", item));
                        }
                        for (TransferItem f : cache.get(item)) {
                            // Recursive
                            transfer(f, action);
                        }
                        cache.remove(item);
                    }
                    return segment;
                }

                private void transferSegment(final TransferStatus segment) throws BackgroundException {
                    if (log.isDebugEnabled()) {
                        log.debug(String.format("Transfer item %s with status %s", item, segment));
                    }
                    final Session<?> s = borrow(Connection.source);
                    final Session<?> d = borrow(Connection.destination);
                    final BytecountStreamListener counter = new BytecountStreamListener(stream);
                    try {
                        transfer.transfer(s, d, segment.getRename().remote != null ? segment.getRename().remote : item.remote, segment.getRename().local != null ? segment.getRename().local : item.local, options, status, segment, connect, progress, counter);
                    } catch (BackgroundException e) {
                        release(s, Connection.source, e);
                        release(d, Connection.destination, e);
                        log.warn(String.format("Failure %s transferring %s", item, e));
                        // Determine if we should retry depending on failure type
                        if (this.retry(e, progress, new TransferBackgroundActionState(status))) {
                            final Session<?> source = borrow(Connection.source);
                            final Session<?> destination = borrow(Connection.destination);
                            try {
                                final TransferPathFilter filter = transfer.filter(source, destination, TransferAction.resume, progress);
                                if (filter.accept(item.remote, item.local, new TransferStatus().exists(true))) {
                                    if (log.isDebugEnabled()) {
                                        log.debug(String.format("Retry transfer of %s", item));
                                    }
                                    final TransferStatus retry = filter.prepare(item.remote, item.local, new TransferStatus().exists(true), progress);
                                    // Add bytes retrieved but not yet counted
                                    stream.recv(retry.getOffset() - counter.getRecv());
                                    stream.sent(retry.getOffset() - counter.getSent());
                                    transfer.addTransferred(retry.getOffset() - counter.getSent());
                                    // Retry immediately
                                    log.info(String.format("Retry %s with transfer status %s", item, retry));
                                    this.transferSegment(segment.withLength(retry.getLength()).withOffset(retry.getOffset()).append(retry.isAppend()));
                                    return;
                                }
                            } finally {
                                release(source, Connection.source, null);
                                release(destination, Connection.destination, null);
                            }
                        }
                        if (log.isDebugEnabled()) {
                            log.debug(String.format("Cancel retry for %s", item));
                        }
                        segment.setFailure();
                        // Prompt to continue or abort for application errors
                        if (error.prompt(item, segment, e, table.size())) {
                            // Continue
                            log.warn(String.format("Ignore transfer failure %s", e));
                        } else {
                            throw new TransferCanceledException(e);
                        }
                    } finally {
                        release(s, Connection.source, null);
                        release(d, Connection.destination, null);
                    }
                }

                @Override
                public String toString() {
                    final StringBuilder sb = new StringBuilder("RetryTransferCallable{");
                    sb.append("item=").append(item);
                    sb.append(", status=").append(segment);
                    sb.append('}');
                    return sb.toString();
                }
            });
        }
        return this.submit(new TransferCallable() {

            @Override
            public TransferStatus call() throws BackgroundException {
                status.validate();
                if (status.isSegmented()) {
                    // Await completion of all segments
                    boolean complete = true;
                    for (TransferStatus segment : segments) {
                        if (!segment.await()) {
                            log.warn(String.format("Failure to complete segment %s.", segment));
                            complete = false;
                        }
                    }
                    if (complete) {
                        final Session<?> source = borrow(Connection.source);
                        final Session<?> destination = borrow(Connection.destination);
                        try {
                            // Determine transfer filter implementation from selected overwrite action
                            final TransferPathFilter filter = transfer.filter(source, destination, action, progress);
                            // Concatenate segments with completed status set
                            filter.complete(status.getRename().remote != null ? status.getRename().remote : item.remote, status.getRename().local != null ? status.getRename().local : item.local, options, status.complete(), progress);
                        } finally {
                            release(source, Connection.source, null);
                            release(destination, Connection.destination, null);
                        }
                    } else {
                        log.warn(String.format("Skip concatenating segments for failed transfer %s", status));
                        status.setFailure();
                    }
                }
                return status;
            }

            @Override
            public String toString() {
                final StringBuilder sb = new StringBuilder("TransferCallable{");
                sb.append("item=").append(item);
                sb.append(", status=").append(status);
                sb.append('}');
                return sb.toString();
            }
        });
    } else {
        log.warn(String.format("Skip file %s with unknown transfer status", item));
    }
    return ConcurrentUtils.constantFuture(null);
}
Also used : TransferCanceledException(ch.cyberduck.core.exception.TransferCanceledException) BytecountStreamListener(ch.cyberduck.core.BytecountStreamListener) TransferStatus(ch.cyberduck.core.transfer.TransferStatus) TransferPathFilter(ch.cyberduck.core.transfer.TransferPathFilter) TransferBackgroundActionState(ch.cyberduck.core.threading.TransferBackgroundActionState) TransferItem(ch.cyberduck.core.transfer.TransferItem) BackgroundException(ch.cyberduck.core.exception.BackgroundException) Session(ch.cyberduck.core.Session)

Aggregations

BytecountStreamListener (ch.cyberduck.core.BytecountStreamListener)1 Session (ch.cyberduck.core.Session)1 BackgroundException (ch.cyberduck.core.exception.BackgroundException)1 TransferCanceledException (ch.cyberduck.core.exception.TransferCanceledException)1 TransferBackgroundActionState (ch.cyberduck.core.threading.TransferBackgroundActionState)1 TransferItem (ch.cyberduck.core.transfer.TransferItem)1 TransferPathFilter (ch.cyberduck.core.transfer.TransferPathFilter)1 TransferStatus (ch.cyberduck.core.transfer.TransferStatus)1