Exemplo n.º 1
0
        private async Task <T> DoWithRetry <T>(FileEntryItem item, Func <Task <T> > method)
        {
            item.IsRetry = false;
            Exception lastException = null;

            if (!await m_taskreader.TransferProgressAsync)
            {
                throw new OperationCanceledException();
            }

            if (m_workerSource.IsCancellationRequested)
            {
                throw new OperationCanceledException();
            }

            for (var i = 0; i < m_options.NumberOfRetries; i++)
            {
                if (m_options.RetryDelay.Ticks != 0 && i != 0)
                {
                    await Task.Delay(m_options.RetryDelay).ConfigureAwait(false);
                }

                if (!await m_taskreader.TransferProgressAsync)
                {
                    throw new OperationCanceledException();
                }

                if (m_workerSource.IsCancellationRequested)
                {
                    throw new OperationCanceledException();
                }

                try
                {
                    if (m_backend == null)
                    {
                        m_backend = DynamicLoader.BackendLoader.GetBackend(m_backendurl, m_options.RawOptions);
                    }
                    if (m_backend == null)
                    {
                        throw new Exception("Backend failed to re-load");
                    }

                    var r = await method().ConfigureAwait(false);

                    return(r);
                }
                catch (Exception ex)
                {
                    item.IsRetry  = true;
                    lastException = ex;
                    Logging.Log.WriteRetryMessage(LOGTAG, $"Retry{item.Operation}", ex, "Operation {0} with file {1} attempt {2} of {3} failed with message: {4}", item.Operation, item.RemoteFilename, i + 1, m_options.NumberOfRetries, ex.Message);
                    // If the thread is aborted, we exit here
                    if (ex is System.Threading.ThreadAbortException || ex is OperationCanceledException)
                    {
                        break;
                    }

                    await m_stats.SendEventAsync(item.Operation, i < m_options.NumberOfRetries?BackendEventType.Retrying : BackendEventType.Failed, item.RemoteFilename, item.Size);

                    bool recovered = false;
                    if (!m_uploadSuccess && ex is Duplicati.Library.Interface.FolderMissingException && m_options.AutocreateFolders)
                    {
                        try
                        {
                            // If we successfully create the folder, we can re-use the connection
                            m_backend.CreateFolder();
                            recovered = true;
                        }
                        catch (Exception dex)
                        {
                            Logging.Log.WriteWarningMessage(LOGTAG, "FolderCreateError", dex, "Failed to create folder: {0}", ex.Message);
                        }
                    }

                    if (!recovered)
                    {
                        ResetBackend(ex);
                    }
                }
                finally
                {
                    if (m_options.NoConnectionReuse)
                    {
                        ResetBackend(null);
                    }
                }
            }

            throw lastException;
        }