diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index feb530ce99..2d738475db 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -28,7 +28,7 @@ - + diff --git a/src/Umbraco.Core/IO/FileSystemExtensions.cs b/src/Umbraco.Core/IO/FileSystemExtensions.cs index f2152afaab..64dcfc25a0 100644 --- a/src/Umbraco.Core/IO/FileSystemExtensions.cs +++ b/src/Umbraco.Core/IO/FileSystemExtensions.cs @@ -1,10 +1,42 @@ using System; using System.IO; +using System.Threading; namespace Umbraco.Core.IO { public static class FileSystemExtensions { + + /// + /// Attempts to open the file at filePath up to maxRetries times, + /// with a thread sleep time of sleepPerRetryInMilliseconds between retries. + /// + public static FileStream OpenReadWithRetry(this FileInfo file, int maxRetries = 5, int sleepPerRetryInMilliseconds = 50) + { + var retries = maxRetries; + + while (retries > 0) + { + try + { + return File.OpenRead(file.FullName); + } + catch(IOException) + { + retries--; + + if (retries == 0) + { + throw; + } + + Thread.Sleep(sleepPerRetryInMilliseconds); + } + } + + throw new ArgumentException("Retries must be greater than zero"); + } + public static long GetSize(this IFileSystem fs, string path) { using (var file = fs.OpenFile(path)) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 7cebeb6252..b12d19d032 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -6,6 +6,7 @@ using System.Text; using System.Web.Http; using System.Web.Http.ModelBinding; using AutoMapper; +using ClientDependency.Core; using Examine.LuceneEngine; using Examine.LuceneEngine.Providers; using Newtonsoft.Json; @@ -637,15 +638,20 @@ namespace Umbraco.Web.Editors private IEnumerable GetResultForKeys(IEnumerable keys, UmbracoEntityTypes entityType) { - if (keys.Any() == false) return Enumerable.Empty(); + var keysArray = keys.ToArray(); + if (keysArray.Any() == false) return Enumerable.Empty(); var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) { - var result = Services.EntityService.GetAll(objectType.Value, keys.ToArray()) + var entities = Services.EntityService.GetAll(objectType.Value, keysArray) .WhereNotNull() .Select(Mapper.Map); + // entities are in "some" order, put them back in order + var xref = entities.ToDictionary(x => x.Id); + var result = keysArray.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null); + return result; } //now we need to convert the unknown ones @@ -664,15 +670,20 @@ namespace Umbraco.Web.Editors private IEnumerable GetResultForIds(IEnumerable ids, UmbracoEntityTypes entityType) { - if (ids.Any() == false) return Enumerable.Empty(); + var idsArray = ids.ToArray(); + if (idsArray.Any() == false) return Enumerable.Empty(); var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) { - var result = Services.EntityService.GetAll(objectType.Value, ids.ToArray()) + var entities = Services.EntityService.GetAll(objectType.Value, idsArray) .WhereNotNull() .Select(Mapper.Map); + // entities are in "some" order, put them back in order + var xref = entities.ToDictionary(x => x.Id); + var result = idsArray.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null); + return result; } //now we need to convert the unknown ones diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index d807d84a26..861750e752 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -32,6 +32,7 @@ using umbraco; using umbraco.BusinessLogic.Actions; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Configuration; +using Umbraco.Core.Persistence.FaultHandling; namespace Umbraco.Web.Editors { @@ -404,7 +405,11 @@ namespace Umbraco.Web.Editors var mediaService = ApplicationContext.Services.MediaService; var f = mediaService.CreateMedia(fileName, parentId, mediaType); - using (var fs = System.IO.File.OpenRead(file.LocalFileName)) + + var fileInfo = new FileInfo(file.LocalFileName); + var fs = fileInfo.OpenReadWithRetry(); + if (fs == null) throw new InvalidOperationException("Could not acquire file stream"); + using (fs) { f.SetValue(Constants.Conventions.Media.File, fileName, fs); }