Exemplo n.º 1
0
        async Task <bool> MakeSureLibraryIsInPlace(XamarinBuildDownload xbd, CancellationToken token)
        {
            // Skip extraction if the file is already in place
            var flagFile = xbd.DestinationDir + ".unpacked";

            if (File.Exists(flagFile))
            {
                return(true);
            }

            try {
                Directory.CreateDirectory(xbd.DestinationDir);
            } catch (Exception ex) {
                LogCodedError(ThisOrThat(xbd.CustomErrorCode, ErrorCodes.DirectoryCreateFailed), ThisOrThat(xbd.CustomErrorMessage, () => string.Format("Failed to create directory '{0}'.", xbd.DestinationDir)));
                LogMessage("Directory creation failure reason: " + ex.ToString(), MessageImportance.High);
                return(false);
            }

            var lockFile = xbd.DestinationDir + ".locked";

            using (var lockStream = DownloadUtils.ObtainExclusiveFileLock(lockFile, Token, TimeSpan.FromSeconds(xbd.ExclusiveLockTimeout), this)) {
                if (lockStream == null)
                {
                    LogCodedError(ErrorCodes.ExclusiveLockTimeout, "Timed out waiting for exclusive file lock on: {0}", lockFile);
                    LogMessage("Timed out waiting for an exclusive file lock on: " + lockFile, MessageImportance.High);
                    return(false);
                }

                if (!File.Exists(xbd.CacheFile) || !IsValidDownload(xbd.DestinationDir + ".sha1", xbd.CacheFile, xbd.Sha1))
                {
                    try {
                        int progress = -1;
                        DownloadProgressChangedEventHandler downloadHandler = (o, e) => {
                            if (e.ProgressPercentage % 10 != 0 || progress == e.ProgressPercentage)
                            {
                                return;
                            }
                            progress = e.ProgressPercentage;
                            LogMessage(
                                "\t({0}/{1}b), total {2:F1}%", e.BytesReceived, e.TotalBytesToReceive, e.ProgressPercentage
                                );
                        };
                        using (var client = new WebClient()) {
                            client.DownloadProgressChanged += downloadHandler;
                            LogMessage("  Downloading {0} to {1}", xbd.Url, xbd.CacheFile);
                            client.DownloadFileTaskAsync(xbd.Url, xbd.CacheFile).Wait(token);
                            LogMessage("  Downloading Complete");
                            client.DownloadProgressChanged -= downloadHandler;
                        }
                    } catch (Exception e) {
                        LogCodedError(ThisOrThat(xbd.CustomErrorCode, ErrorCodes.DownloadFailed), ThisOrThat(xbd.CustomErrorMessage, () => string.Format("Download failed. Please download {0} to a file called {1}.", xbd.Url, xbd.CacheFile)));
                        LogMessage("Download failure reason: " + e.GetBaseException().Message, MessageImportance.High);
                        File.Delete(xbd.CacheFile);
                        return(false);
                    }
                }

                if (!File.Exists(xbd.CacheFile))
                {
                    LogCodedError(ThisOrThat(xbd.CustomErrorCode, ErrorCodes.DownloadedFileMissing), ThisOrThat(xbd.CustomErrorMessage, () => string.Format("Downloaded file '{0}' is missing.", xbd.CacheFile)));
                    return(false);
                }

                if (xbd.Kind == ArchiveKind.Uncompressed)
                {
                    var uncompressedCacheFile = xbd.CacheFile;
                    if (!string.IsNullOrEmpty(xbd.ToFile))
                    {
                        uncompressedCacheFile = xbd.ToFile;
                    }

                    File.Move(xbd.CacheFile, Path.Combine(xbd.DestinationDir, Path.GetFileName(uncompressedCacheFile)));
                    File.WriteAllText(flagFile, "This marks that the extraction completed successfully");
                    return(true);
                }
                else
                {
                    if (await ExtractArchive(xbd, flagFile, token))
                    {
                        File.WriteAllText(flagFile, "This marks that the extraction completed successfully");
                        return(true);
                    }
                }
            }

            // We will attempt to delete the lock file when we're done
            try {
                if (File.Exists(lockFile))
                {
                    File.Delete(lockFile);
                }
            } catch { }

            return(false);
        }
Exemplo n.º 2
0
        async Task DownloadAll(string cacheDirectory, List <PartialZipDownload> parts)
        {
            // Get the parts all grouped by their URL so we can batch requests with multiple ranges
            // instead of making a request to the same url for each part
            // also only grab the parts that don't already locally exist
            var uniqueUrls = parts
                             .Where(p => !File.Exists(Path.Combine(cacheDirectory, p.Id, p.ToFile)))
                             .GroupBy(p => p.Url);

            // For each unique url...
            foreach (var partsByUrl in uniqueUrls)
            {
                var downloadUrl = partsByUrl.Key;

                LogMessage("Downloading Partial Zip parts from: " + downloadUrl);

                try {
                    // Create a lock file based on the hash of the URL we are downloading from
                    // Since we could download a multipart request, we are locking on the url from any other process downloading from it
                    var lockFile = Path.Combine(cacheDirectory, DownloadUtils.Crc64(downloadUrl) + ".locked");

                    using (var lockStream = DownloadUtils.ObtainExclusiveFileLock(lockFile, base.Token, TimeSpan.FromSeconds(30))) {
                        if (lockStream == null)
                        {
                            LogCodedError(ErrorCodes.ExclusiveLockTimeout, "Timed out waiting for exclusive file lock on: {0}", lockFile);
                            LogMessage("Timed out waiting for an exclusive file lock on: " + lockFile, MessageImportance.High);

                            // Log Custom error if one was specified in the partial download info
                            var firstPart = partsByUrl.FirstOrDefault();
                            if (!string.IsNullOrEmpty(firstPart?.CustomErrorCode) && !string.IsNullOrEmpty(firstPart?.CustomErrorMessage))
                            {
                                LogCodedError(firstPart.CustomErrorCode, firstPart.CustomErrorMessage);
                            }

                            return;
                        }

                        try {
                            await Download(cacheDirectory, partsByUrl.Key, partsByUrl.ToList()).ConfigureAwait(false);
                        } catch (Exception ex) {
                            LogCodedError(ErrorCodes.PartialDownloadFailed, "Partial Download Failed for one or more parts");
                            LogErrorFromException(ex);

                            // Log Custom error if one was specified in the partial download info
                            var firstPart = partsByUrl.FirstOrDefault();
                            if (!string.IsNullOrEmpty(firstPart?.CustomErrorCode) && !string.IsNullOrEmpty(firstPart?.CustomErrorMessage))
                            {
                                LogCodedError(firstPart.CustomErrorCode, firstPart.CustomErrorMessage);
                            }
                        }
                    }

                    try {
                        if (File.Exists(lockFile))
                        {
                            File.Delete(lockFile);
                        }
                    } catch { }
                } catch (Exception ex) {
                    LogCodedError(ErrorCodes.PartialDownloadFailed, "Partial Download Failed for one or more parts");
                    LogErrorFromException(ex);

                    // Log Custom error if one was specified in the partial download info
                    var firstPart = partsByUrl.FirstOrDefault();
                    if (!string.IsNullOrEmpty(firstPart?.CustomErrorCode) && !string.IsNullOrEmpty(firstPart?.CustomErrorMessage))
                    {
                        LogCodedError(firstPart.CustomErrorCode, firstPart.CustomErrorMessage);
                    }
                }
            }
        }