// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// Defines the QueueRecoveryHelper type.
//
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrakeWPF.Helpers
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Xml.Serialization;
using HandBrake.Interop.Utilities;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.Services.Queue.Model;
using HandBrakeWPF.Utilities;
using IQueueProcessor = HandBrakeWPF.Services.Queue.Interfaces.IQueueProcessor;
///
/// Queue Recovery Helper
///
public class QueueRecoveryHelper
{
///
/// Check if the queue recovery file contains records.
/// If it does, it means the last queue did not complete before HandBrake closed.
/// So, return a boolean if true.
///
///
/// The filter Queue Files.
///
///
/// True if there is a queue to recover.
///
public static List CheckQueueRecovery(List filterQueueFiles)
{
try
{
string tempPath = DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly());
DirectoryInfo info = new DirectoryInfo(tempPath);
IEnumerable foundFiles = info.GetFiles("*.xml").Where(f => f.Name.StartsWith("hb_queue_recovery"));
var queueFiles = GetFilesExcludingActiveProcesses(foundFiles, filterQueueFiles);
if (!queueFiles.Any())
{
return queueFiles;
}
List removeFiles = new List();
List acceptedFiles = new List();
XmlSerializer ser = new XmlSerializer(typeof(List));
foreach (string file in queueFiles)
{
try
{
using (FileStream strm = new FileStream(file, FileMode.Open, FileAccess.Read))
{
List list = ser.Deserialize(strm) as List;
if (list != null && list.Count == 0)
{
removeFiles.Add(file);
}
if (list != null && list.Count != 0)
{
List tasks = list.Where(l => l.Status != QueueItemStatus.Completed).ToList();
if (tasks.Count != 0)
{
acceptedFiles.Add(Path.GetFileName(file));
}
else
{
removeFiles.Add(file);
}
}
}
}
catch (Exception exc)
{
Debug.WriteLine(exc);
}
}
CleanupFiles(removeFiles, false);
return acceptedFiles;
}
catch (Exception exc)
{
Debug.WriteLine(exc);
return new List(); // Keep quiet about the error.
}
}
///
/// Recover a queue from file.
///
///
/// The encode Queue.
///
///
/// The error Service.
///
///
/// The silent Recovery.
///
///
/// The .
///
public static bool RecoverQueue(IQueueProcessor encodeQueue, IErrorService errorService, bool silentRecovery, List queueFilter)
{
string appDataPath = DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly());
List queueFiles = CheckQueueRecovery(queueFilter);
MessageBoxResult result = MessageBoxResult.None;
if (!silentRecovery)
{
if (queueFiles.Count == 1)
{
result =
errorService.ShowMessageBox(
"HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
"Queue Recovery Possible",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
}
else if (queueFiles.Count > 1)
{
result =
errorService.ShowMessageBox(
"HandBrake has detected multiple unfinished queue files. These will be from multiple instances of HandBrake running. Would you like to recover all unfinished jobs?",
"Queue Recovery Possible",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
}
}
else
{
result = MessageBoxResult.Yes;
}
if (result == MessageBoxResult.Yes)
{
bool isRecovered = false;
foreach (string file in queueFiles)
{
// Recover the Queue
encodeQueue.RestoreQueue(Path.Combine(appDataPath, file));
isRecovered = true;
// Cleanup
CleanupFiles(new List { file }, false);
}
return isRecovered;
}
CleanupFiles(queueFiles, true);
return false;
}
public static bool ArchivesExist()
{
string appDataPath = DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly());
DirectoryInfo info = new DirectoryInfo(appDataPath);
IEnumerable foundFiles = info.GetFiles("*.archive").Where(f => f.Name.StartsWith("hb_queue_recovery"));
return foundFiles.Any();
}
private static List GetFilesExcludingActiveProcesses(IEnumerable foundFiles, List filterQueueFiles)
{
List queueFiles = new List();
// Remove any files where we have an active instnace.
foreach (FileInfo file in foundFiles)
{
string fileProcessId = file.Name.Replace("hb_queue_recovery", string.Empty).Replace(".xml", string.Empty);
int processId;
if (!string.IsNullOrEmpty(fileProcessId) && int.TryParse(fileProcessId, out processId))
{
if (!GeneralUtilities.IsPidACurrentHandBrakeInstance(processId))
{
if (filterQueueFiles != null && filterQueueFiles.Count > 0)
{
if (filterQueueFiles.Contains(processId.ToString()))
{
queueFiles.Add(file.FullName);
}
}
else
{
queueFiles.Add(file.FullName);
}
}
}
}
return queueFiles;
}
private static void CleanupFiles(List removeFiles, bool archive)
{
string appDataPath = DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly());
// Cleanup old/unused queue files for now.
foreach (string file in removeFiles)
{
Match m = Regex.Match(file, @"([0-9]+).xml");
if (m.Success)
{
int processId = int.Parse(m.Groups[1].ToString());
if (GeneralUtilities.IsPidACurrentHandBrakeInstance(processId))
{
continue;
}
}
string fullPath = Path.Combine(appDataPath, file);
if (archive)
{
File.Move(fullPath, fullPath + ".archive");
}
else
{
File.Delete(fullPath);
}
}
TidyArchiveFiles();
}
///
/// Tidy up archive files older than 7 days.
/// Gives the user an opportunity to recover a queue file they accidentally chose not to import.
///
private static void TidyArchiveFiles()
{
string appDataPath = DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly());
DirectoryInfo info = new DirectoryInfo(appDataPath);
IEnumerable foundFiles = info.GetFiles("*.archive").Where(f => f.Name.StartsWith("hb_queue_recovery"));
DateTime LastWeek = DateTime.Now.AddDays(-7);
foreach (FileInfo file in foundFiles)
{
if (file.CreationTime < LastWeek)
{
string fullPath = Path.Combine(appDataPath, file.Name);
File.Delete(fullPath);
}
}
}
public static void ResetArchives()
{
string appDataPath = DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly());
DirectoryInfo info = new DirectoryInfo(appDataPath);
IEnumerable foundFiles = info.GetFiles("*.archive").Where(f => f.Name.StartsWith("hb_queue_recovery"));
foreach (FileInfo file in foundFiles)
{
string fullPath = Path.Combine(appDataPath, file.Name);
File.Move(fullPath, fullPath.Replace(".archive", string.Empty));
}
}
}
}