예제 #1
0
        private void CopyCallerHoldsReaderLock(string source, string destination, CopyFlag copyFlag, TimeoutHelper helper)
        {
            string destinationDirectory = FabricPath.GetDirectoryName(destination);

            if (!string.IsNullOrEmpty(destinationDirectory) && !FabricDirectory.Exists(destinationDirectory))
            {
                FabricDirectory.CreateDirectory(destinationDirectory);
            }

            using (FileWriterLock writerLock = new FileWriterLock(destination))
            {
                if (!writerLock.Acquire())
                {
                    throw new FabricTransientException(StringResources.Error_ImageStoreAcquireFileLockFailed, FabricErrorCode.ImageStoreAcquireFileLockFailed);
                }

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

                if (FabricFile.Exists(source))
                {
                    // This is a file copy
                    if (FabricFile.Exists(destination))
                    {
                        FabricFile.Delete(destination, deleteReadonly: true);
                    }

                    int retryCount = 0;
                    while (helper == null || !TimeoutHelper.HasExpired(helper))
                    {
                        try
                        {
                            bool shouldOverwrite = (copyFlag != CopyFlag.AtomicCopySkipIfExists);
                            FabricFile.Copy(source, destination, shouldOverwrite);
                            break;
                        }
                        catch (UnauthorizedAccessException)
                        {
                            TraceSource.WriteInfo(
                                TraceType,
                                "Uploading {0} to {1} caused UnauthorizedAccessException. RetryCount: {2}.",
                                source,
                                destination,
                                retryCount);

                            if (retryCount++ > 3)
                            {
                                throw;
                            }

                            // This could happen when a file is marked for delete and we try to delete
                            // it again or try to open the file. Retrying after sometime should fix the issue.
                            Thread.Sleep(TimeSpan.FromSeconds(retryCount));
                        }

                        if (helper != null)
                        {
                            helper.ThrowIfExpired();
                        }
                    }
                }
                else
                {
                    // This is a folder copy
                    using (FolderCopy fc = new FolderCopy(copyFlag, null))
                    {
                        fc.Copy(source, destination);
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Remove tag from store and clear the data associated with tag.
        /// </summary>
        /// <param name="tag">Location (relative to RootUri) from where to delete the content.</param>
        /// <param name="timeout">The timeout for performing the delete operation.</param>
        public void DeleteContent(string tag, TimeSpan timeout)
        {
            TimeoutHelper helper = (timeout == TimeSpan.MaxValue) ? null : new TimeoutHelper(timeout);

#if !DotNetCoreClr
            using (WindowsImpersonationContext impersonationContext = this.GetImpersonationContext())
#endif
            {
                try
                {
                    string smbTag = this.ConvertTagToSMBPath(tag);
                    if ((!FabricFile.Exists(smbTag)) &&
                        (!FabricDirectory.Exists(smbTag)))
                    {
                        return;
                    }

                    using (FileWriterLock fileWriterLock = new FileWriterLock(smbTag))
                    {
                        if (!fileWriterLock.Acquire())
                        {
                            throw new FabricTransientException(StringResources.Error_ImageStoreAcquireFileLockFailed, FabricErrorCode.ImageStoreAcquireFileLockFailed);
                        }

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

                        if (FabricFile.Exists(smbTag))
                        {
                            FabricFile.Delete(smbTag, deleteReadonly: true);
                        }
                        else if (FabricDirectory.Exists(smbTag))
                        {
                            FabricDirectory.Delete(smbTag, recursive: true, deleteReadOnlyFiles: true);
                        }
                    }
                }
                catch (IOException exception)
                {
                    // HResult 0x80070020: THE PROCESS CANNOT ACCESS THE FILE BECAUSE IT IS BEING USED BY ANOTHER PROCESS
                    // This work-around is done here since when we read a file from a folder we only take a reader lock on the file and not the
                    // entire folder. When we delete a folder, we only take writer lock on the folder and hence we might run into scenarios
                    // where a folder is attempted to be deleted even when a file in it is being read.
                    // Returning FabricImageStoreException, causes CM to retry the delete operation.
                    int hrError = Marshal.GetHRForException(exception);
                    TraceSource.WriteWarning(
                        TraceType,
                        "Delete of {0} failed because of {1}, hrError {2:X}.",
                        tag,
                        exception.Message,
                        hrError);

                    if (hrError == unchecked ((int)0x80070020))
                    {
                        throw new FabricTransientException(StringResources.Error_ImageStoreAcquireFileLockFailed, exception, FabricErrorCode.ImageStoreAcquireFileLockFailed);
                    }

                    throw;
                }
            }
        }