/// <summary>
        /// Downloads content from the file image store to local destination.
        /// </summary>
        /// <param name="storeSource">The relative path of source file image store to be downloaded from.</param>
        /// <param name="localDestination">The local destination path to download the content.</param>
        /// <param name="handler">The image store progress handler which is not supported at the file image store.</param>
        /// <param name="timeout">The timeout for performing the downloading operation.</param>
        /// <param name="copyFlag">The copying control information to specify how file can be overwritten.</param>
        public void DownloadContent(string storeSource, string localDestination, IImageStoreProgressHandler handler, TimeSpan timeout, CopyFlag copyFlag)
        {
            TimeoutHelper helper = timeout == TimeSpan.MaxValue ? null : new TimeoutHelper(timeout);

            localDestination = this.GetLocalPath(localDestination);
            string         tempDirectory = null;
            FileReaderLock readerLock    = null;

            try
            {
                string smbTag = this.ConvertTagToSMBPath(storeSource);
                if ((!FabricFile.Exists(smbTag)) &&
                    (!FabricDirectory.Exists(smbTag)))
                {
                    throw new IOException(string.Format(CultureInfo.CurrentCulture, StringResources.ImageStoreError_DoesNotExistError, smbTag));
                }

                readerLock = new FileReaderLock(smbTag);
                if (!readerLock.Acquire())
                {
                    throw new FabricTransientException(StringResources.Error_ImageStoreAcquireFileLockFailed, FabricErrorCode.ImageStoreAcquireFileLockFailed);
                }

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

                if (accessDescription != null && !accessDescription.HasWriteAccess)
                {
                    // Copy the content from the remote Store to a temp location using the ImpersonationContext
                    string tempLocalResource = null;
#if !DotNetCoreClr
                    using (WindowsImpersonationContext impersonationContext = accessDescription.WindowsIdentity.Impersonate())
#endif
                    {
                        tempDirectory     = CreateAndAclDirectory();
                        tempLocalResource = Path.Combine(tempDirectory, Path.GetRandomFileName());
                        CopyCallerHoldsReaderLock(smbTag, tempLocalResource, CopyFlag.AtomicCopy, helper);
                    }

                    readerLock.Release();

                    // Copy the content from the temp location to the local destination outside the ImpersonationContext
                    CopyCallerHoldsReaderLock(tempLocalResource, localDestination, copyFlag, helper);
                }

#if !DotNetCoreClr
                using (WindowsImpersonationContext impersonationContext = this.GetImpersonationContext())
#endif
                {
                    CopyCallerHoldsReaderLock(smbTag, localDestination, copyFlag, helper);
                }
            }
            catch (IOException exception)
            {
                if (exception.GetType() == typeof(IOException))
                {
                    throw new FabricImageStoreException(StringResources.Error_ImageStoreIOException, exception);
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (readerLock != null)
                {
                    readerLock.Dispose();
                }

                if (tempDirectory != null && FabricDirectory.Exists(tempDirectory))
                {
                    FabricDirectory.Delete(tempDirectory, recursive: true, deleteReadOnlyFiles: true);
                }
            }
        }
        /// <summary>
        /// Uploads the local source content to the image store at the remote destination.
        /// </summary>
        /// <param name="storeSource"> Location (relative to RootUri) from where to download the content. </param>
        /// <param name="storeDestination"> Location relative to RootUri where the content needs to be uploaded. </param>
        /// <param name="timeout">The timeout for copy content operation.</param>
        /// <param name="skipFiles">Files that do not need to be copied.</param>
        /// <param name="copyFlag">The copying control information to specify how file can be overwritten</param>
        /// <param name="checkMarkFile">Flag the specified the checkmark file.</param>
        public void CopyContent(string storeSource, string storeDestination, TimeSpan timeout, string[] skipFiles, CopyFlag copyFlag, bool checkMarkFile)
        {
            TimeoutHelper  helper     = timeout == TimeSpan.MaxValue ? null : new TimeoutHelper(timeout);
            FileReaderLock readerLock = null;

            try
            {
                string smbSourcePath      = this.ConvertTagToSMBPath(storeSource);
                string smbDestinationPath = this.ConvertTagToSMBPath(storeDestination);

                readerLock = new FileReaderLock(smbSourcePath);
                if (!readerLock.Acquire())
                {
                    throw new FabricTransientException(StringResources.Error_ImageStoreAcquireFileLockFailed, FabricErrorCode.ImageStoreAcquireFileLockFailed);
                }

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

#if !DotNetCoreClr
                using (WindowsImpersonationContext impersonationContext = this.GetImpersonationContext())
#endif
                {
                    bool fabricDirectoryExists = FabricDirectory.Exists(smbSourcePath);
                    if (fabricDirectoryExists && skipFiles.Any())
                    {
                        string[] fileNames = FabricDirectory.GetFiles(smbSourcePath, "*", false, SearchOption.TopDirectoryOnly);
                        string[] filtered  = fileNames.Where(file => !skipFiles.Contains <string>(file)).ToArray <string>();

                        if (filtered.Count() < fileNames.Count())
                        {
                            foreach (string file in filtered)
                            {
                                CopyCallerHoldsReaderLock(Path.Combine(smbSourcePath, file), Path.Combine(smbDestinationPath, file), copyFlag, helper);
                            }
                        }
                        else
                        {
                            CopyCallerHoldsReaderLock(smbSourcePath, smbDestinationPath, copyFlag, helper);
                        }
                    }
                    else
                    {
                        bool fabricFileExist = FabricFile.Exists(smbSourcePath);
                        if ((!FabricFile.Exists(smbSourcePath)) &&
                            (!FabricDirectory.Exists(smbSourcePath)))
                        {
                            throw new IOException(string.Format(CultureInfo.CurrentCulture, StringResources.ImageStoreError_DoesNotExistError, smbSourcePath));
                        }

                        CopyCallerHoldsReaderLock(smbSourcePath, smbDestinationPath, copyFlag, helper);
                    }
                }
            }
            catch (IOException exception)
            {
                if (exception.GetType() == typeof(IOException))
                {
                    throw new FabricImageStoreIOException(exception);
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (readerLock != null)
                {
                    readerLock.Dispose();
                }
            }
        }