private async Task <ServiceManifest> GetServiceManifestAsync(
            ApplicationManifestTypeServiceManifestImport serviceManifestImport,
            StoreLayoutSpecification storeLayoutSpecification,
            TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper       = new TimeoutHelper(timeout);
            string        serviceManifestFile = storeLayoutSpecification.GetServiceManifestFile(
                this.ApplicationTypeName,
                serviceManifestImport.ServiceManifestRef.ServiceManifestName,
                serviceManifestImport.ServiceManifestRef.ServiceManifestVersion);

            string checksumFile = storeLayoutSpecification.GetServiceManifestChecksumFile(
                this.ApplicationTypeName,
                serviceManifestImport.ServiceManifestRef.ServiceManifestName,
                serviceManifestImport.ServiceManifestRef.ServiceManifestVersion);

            var getServiceManifestTask = this.ImageStoreWrapper.GetFromStoreAsync <ServiceManifestType>(serviceManifestFile, timeoutHelper.GetRemainingTime());
            var getChecksumTask        = this.ImageStoreWrapper.TryGetFromStoreAsync(checksumFile, timeoutHelper.GetRemainingTime());

            await Task.WhenAll(getServiceManifestTask, getChecksumTask);

            timeoutHelper.ThrowIfExpired();
            ServiceManifestType serviceManifestType = getServiceManifestTask.Result;
            string checksum = getChecksumTask.Result.Item1;

            ServiceManifest serviceManifest = new ServiceManifest(serviceManifestType)
            {
                Checksum = checksum
            };

            List <Task <CodePackage> > codePackageTaskList = new List <Task <CodePackage> >();
            TimeSpan remainingTime = timeoutHelper.GetRemainingTime();

            foreach (CodePackageType codePackageType in serviceManifestType.CodePackage)
            {
                codePackageTaskList.Add(this.GetCodePackageAsync(codePackageType, serviceManifest, storeLayoutSpecification, remainingTime));
            }

            List <Task <ConfigPackage> > configPackageTaskList = new List <Task <ConfigPackage> >();

            if (serviceManifestType.ConfigPackage != null)
            {
                foreach (ConfigPackageType configPackageType in serviceManifestType.ConfigPackage)
                {
                    configPackageTaskList.Add(this.GetConfigPackageAsync(configPackageType, serviceManifest, storeLayoutSpecification, remainingTime));
                }
            }

            List <Task <DataPackage> > dataPackageTaskList = new List <Task <DataPackage> >();

            if (serviceManifestType.DataPackage != null)
            {
                foreach (DataPackageType dataPackageType in serviceManifestType.DataPackage)
                {
                    dataPackageTaskList.Add(this.GetDataPackageAsync(dataPackageType, serviceManifest, storeLayoutSpecification, remainingTime));
                }
            }

            List <Task> packageTasks = new List <Task>();

            packageTasks.AddRange(codePackageTaskList);
            packageTasks.AddRange(configPackageTaskList);
            packageTasks.AddRange(dataPackageTaskList);

            await Task.WhenAll(packageTasks);

            codePackageTaskList.ForEach(task => serviceManifest.CodePackages.Add(task.Result));
            configPackageTaskList.ForEach(task => serviceManifest.ConfigPackages.Add(task.Result));
            dataPackageTaskList.ForEach(task => serviceManifest.DataPackages.Add(task.Result));

            return(serviceManifest);
        }
        private void GetImageStoreContentByAppVersionImpl(
            List <ImageStoreFile> sourceFiles,
            List <ImageStoreFolder> sourceFolders,
            List <ImageStoreFile> targetFiles,
            List <ImageStoreFolder> targetFolders,
            string version,
            IImageStore imageStore,
            StoreLayoutSpecification storeLayoutSpecification,
            IClusterConnection clusterConnection,
            TimeoutHelper helper)
        {
            Action <string, string, string, string, bool> updateStoreInfo = (string path, string serviceName, string serviceVersion, string appVersion, bool isFile) =>
            {
                if (isFile)
                {
                    var existingFile = (from file in targetFiles
                                        where string.Compare(file.StoreRelativePath, path, StringComparison.OrdinalIgnoreCase) == 0
                                        select file).FirstOrDefault();

                    if (existingFile != null)
                    {
                        existingFile.VersionInfo.ConfigVersionInfo(serviceName, serviceVersion, appVersion);
                    }
                    else
                    {
                        existingFile = (from file in sourceFiles
                                        where string.Compare(file.StoreRelativePath, path, StringComparison.OrdinalIgnoreCase) == 0
                                        select file).FirstOrDefault();

                        if (existingFile != null)
                        {
                            existingFile.VersionInfo.ConfigVersionInfo(serviceName, serviceVersion, appVersion);
                            targetFiles.Add(existingFile);
                        }
                        else
                        {
                            throw new ArgumentException(StringResources.Error_ImageStoreRelativePathNotExist);
                        }
                    }
                }
                else
                {
                    var existingFolder = (from folder in targetFolders
                                          where string.Compare(folder.StoreRelativePath, path, StringComparison.OrdinalIgnoreCase) == 0
                                          select folder).FirstOrDefault();

                    if (existingFolder != null)
                    {
                        existingFolder.VersionInfo.ConfigVersionInfo(serviceName, serviceVersion, appVersion);
                    }
                    else
                    {
                        existingFolder = (from folder in sourceFolders
                                          where string.Compare(folder.StoreRelativePath, path, StringComparison.OrdinalIgnoreCase) == 0
                                          select folder).FirstOrDefault();

                        if (existingFolder != null)
                        {
                            existingFolder.VersionInfo.ConfigVersionInfo(serviceName, serviceVersion, appVersion);
                            targetFolders.Add(existingFolder);
                        }
                        else
                        {
                            throw new ArgumentException(StringResources.Error_ImageStoreRelativePathNotExist);
                        }
                    }
                }
            };

            if (helper != null)
            {
                helper.ThrowIfExpired();
            }

            var    foldersPath             = new Dictionary <string, Tuple <string, string> >();
            string applicationManifestPath = storeLayoutSpecification.GetApplicationManifestFile(this.ApplicationTypeName, version);

            updateStoreInfo(applicationManifestPath, string.Empty, string.Empty, version, true);
            var serviceTypeList = clusterConnection.GetServiceTypeListAsync(this.ApplicationTypeName, version, null, this.GetTimeout(), this.GetCancellationToken()).Result;

            foreach (var serviceType in serviceTypeList)
            {
                if (helper != null)
                {
                    helper.ThrowIfExpired();
                }

                string serviceManifestPath = storeLayoutSpecification.GetServiceManifestFile(this.ApplicationTypeName, serviceType.ServiceManifestName, serviceType.ServiceManifestVersion);
                updateStoreInfo(serviceManifestPath, serviceType.ServiceManifestName, serviceType.ServiceManifestVersion, version, true);
                if (helper != null)
                {
                    helper.ThrowIfExpired();
                }

                string serviceManifestChecksumPath = storeLayoutSpecification.GetServiceManifestChecksumFile(this.ApplicationTypeName, serviceType.ServiceManifestName, serviceType.ServiceManifestVersion);
                updateStoreInfo(serviceManifestChecksumPath, serviceType.ServiceManifestName, serviceType.ServiceManifestVersion, version, true);
                string localPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), serviceManifestPath.Substring(serviceManifestPath.LastIndexOf(@"\") + 1));
                try
                {
                    if (helper != null)
                    {
                        helper.ThrowIfExpired();
                        imageStore.DownloadContent(serviceManifestPath, localPath, helper.GetRemainingTime(), CopyFlag.AtomicCopy);
                    }
                    else
                    {
                        imageStore.DownloadContent(serviceManifestPath, localPath, this.GetTimeout(), CopyFlag.AtomicCopy);
                    }

                    foreach (var packagePath in this.GetPackagesPath(localPath, storeLayoutSpecification))
                    {
                        updateStoreInfo(packagePath, serviceType.ServiceManifestName, serviceType.ServiceManifestVersion, version, false);
                        updateStoreInfo(string.Format("{0}.{1}", packagePath, ChecksumFileExtension), serviceType.ServiceManifestName, serviceType.ServiceManifestVersion, version, true);
                    }
                }
                catch (Exception exception)
                {
                    this.ThrowTerminatingError(exception, Constants.GetImageStoreContentErrorId, null);
                }
                finally
                {
                    File.Delete(localPath);
                }
            }
        }