Skip import when when folder is in use

Fixed: Skip post-processing when folder is in use or series path does
not exist on disk
This commit is contained in:
Mark McDowall 2012-10-20 01:01:47 -07:00
parent 5014745f88
commit 5cc2810f77
4 changed files with 84 additions and 8 deletions

View File

@ -232,5 +232,41 @@ namespace NzbDrone.Common
{
Directory.SetLastWriteTimeUtc(path, dateTime);
}
public virtual bool IsFolderLocked(string path)
{
var files = GetFileInfos(path, "*.*", SearchOption.AllDirectories);
foreach(var fileInfo in files)
{
if (IsFileLocked(fileInfo))
return true;
}
return false;
}
public virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
}
}

View File

@ -300,6 +300,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests
Mocker.GetMock<DiskProvider>().Setup(s => s.GetDirectorySize(droppedFolder.FullName)).Returns(Constants.IgnoreFileSize - 1.Megabytes());
Mocker.GetMock<DiskProvider>().Setup(s => s.DeleteFolder(droppedFolder.FullName, true));
Mocker.GetMock<DiskProvider>().Setup(s => s.FolderExists(fakeSeries.Path)).Returns(true);
Mocker.GetMock<DiskProvider>().Setup(s => s.IsFolderLocked(droppedFolder.FullName)).Returns(false);
Mocker.GetMock<MetadataProvider>().Setup(s => s.CreateForEpisodeFiles(It.IsAny<List<EpisodeFile>>()));
//Act
@ -434,5 +435,21 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests
Mocker.GetMock<DiskProvider>().Verify(c => c.GetDirectorySize(It.IsAny<String>()), Times.Never());
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_skip_if_folder_is_in_use_by_another_process()
{
var downloadName = new DirectoryInfo(@"C:\Test\Drop\30.Rock.S01E01.Pilot");
WithValidSeries();
Mocker.GetMock<DiskProvider>()
.Setup(s => s.IsFolderLocked(downloadName.FullName))
.Returns(true);
Mocker.Resolve<PostDownloadProvider>().ProcessDownload(downloadName);
Mocker.GetMock<DiskProvider>().Verify(c => c.GetDirectorySize(It.IsAny<String>()), Times.Never());
}
}
}

View File

@ -227,14 +227,6 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests
WithValidSeries();
Mocker.GetMock<DiskProvider>()
.Setup(s => s.GetDirectorySize(downloadName))
.Returns(10);
Mocker.GetMock<DiskProvider>()
.Setup(s => s.FreeDiskSpace(It.IsAny<DirectoryInfo>()))
.Returns(10);
Mocker.GetMock<DiskProvider>()
.Setup(s => s.FolderExists(fakeSeries.Path))
.Returns(false);
@ -246,5 +238,24 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests
//Assert
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_skip_if_file_is_in_use_by_another_process()
{
var downloadName = @"C:\Test\Drop\30.Rock.S01E01.Pilot.mkv";
WithValidSeries();
Mocker.GetMock<DiskProvider>()
.Setup(s => s.IsFileLocked(It.Is<FileInfo>(f => f.FullName == downloadName)))
.Returns(true);
//Act
Mocker.Resolve<PostDownloadProvider>().ProcessVideoFile(downloadName);
//Assert
Mocker.GetMock<DiskScanProvider>().Verify(c => c.ImportFile(fakeSeries, downloadName), Times.Never());
}
}
}

View File

@ -71,6 +71,12 @@ namespace NzbDrone.Core.Providers
return;
}
if (_diskProvider.IsFolderLocked(subfolderInfo.FullName))
{
Logger.Trace("[{0}] is currently locked by another process, skipping", subfolderInfo.Name);
return;
}
string seriesName = Parser.ParseSeriesName(RemoveStatusFromFolderName(subfolderInfo.Name));
var series = _seriesProvider.FindSeries(seriesName);
@ -135,6 +141,12 @@ namespace NzbDrone.Core.Providers
return;
}
if (_diskProvider.IsFileLocked(new FileInfo(videoFile)))
{
Logger.Trace("[{0}] is currently locked by another process, skipping", videoFile);
return;
}
var seriesName = Parser.ParseSeriesName(Path.GetFileNameWithoutExtension(videoFile));
var series = _seriesProvider.FindSeries(seriesName);