internal void Add(AsyncTaskData <T> taskData) { lock (Locker) { Tasks.Add(taskData); if (!Tasks.IsStarted) { Tasks.Start(ExecMarkFileAsNew); } } }
private static void AddItemsComplete(AsyncTaskData taskData) { var args = (AddRomsToMenuData)taskData; args.MenuLayout.FinishItemsUpdate(args.Error == null); if (args.Error == null) { if (args.Destination != null) { var insertFolder = args.MenuLayout.FindViewModelForModel(args.Destination); FileNodeViewModel highlightItem = insertFolder; // NOTE: Multi-Mode Tree will need to fix this! if (insertFolder.IsOpen || (insertFolder == args.MenuLayout)) { var items = insertFolder.Items; var highlightIndex = args.InsertLocation; if (highlightIndex < 0) { highlightIndex = System.Math.Max(0, items.Count - 1); } if (highlightIndex < items.Count) { highlightItem = items[highlightIndex]; highlightItem.IsSelected = true; ////args.MenuLayout.RetainFocus = items[highlightIndex].GetHashCode(); } } else { insertFolder.IsSelected = true; ////args.MenuLayout.RetainFocus = insertFolder.GetHashCode(); } ++args.MenuLayout.RetainFocus; #if MAC if (highlightItem != null) { args.MenuLayout.CurrentSelection = highlightItem; } #endif // MAC } } if ((args.Error != null) || args.FailedToAdd.Any()) { var exception = args.Error; if (exception == null) { exception = args.FirstFilePreparationError; } IRomHelpers.ReportAddItemsError(exception, args.FailedToAdd); } }
private static void RetrieveFileSystem(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var device = data.Device; var succeeded = false; data.Result = DownloadFileSystemTables.Instance.Execute(device.Port, data, out succeeded); if (succeeded) { var fileSystemStatus = GetDirtyFlags.Instance.Execute <LfsDirtyFlags>(device.Port, data); ((FileSystem)data.Result).Status = fileSystemStatus; } }
private void ExecMarkFileAsNew(AsyncTaskData <T> obj) { try { using var scope = ServiceProvider.CreateScope(); var fileMarker = scope.ServiceProvider.GetService <FileMarker>(); fileMarker.ExecMarkFileAsNew(obj); } catch (Exception e) { Log.Error(e); } }
private static void RemoveSecondaryFirmware(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var device = data.Device; var succeeded = false; var firmwareRevisions = QueryFirmwareRevisions.Instance.Execute(device.Port, data, out succeeded) as FirmwareRevisions; System.Diagnostics.Debug.WriteLineIf(firmwareRevisions == null, "Failed to get firmware revisions."); if (device.ShouldRemoveSecondaryFirmware(data, out succeeded)) { data.Result = device.RemoveSecondaryFirmware(data, out succeeded); } }
private static void ValidateRoms(AsyncTaskData taskData) { var data = (ValidateRomsTaskData)taskData; var numUpdated = 0; foreach (var rom in RomListViewModel.Programs) { taskData.UpdateTaskProgress((++numUpdated / RomListViewModel.Programs.Count) * 100, string.Format(Resources.Strings.ValidateRomsCommand_ProgressDetailFormat, rom.Name, rom.Model.Rom.RomPath)); if (rom.RefreshFileStatus(RomListViewModel.AttachedPeripherals)) { data.UpdatedRoms.Add(rom.Model); } } }
private static void UpdateDeviceOwner(AsyncTaskData taskData) { // Skip setting dirty flags on this -- is that too risky? var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var device = data.Device; var newOwner = data.Data as string; var rootFile = device.FileSystem.Files[GlobalFileTable.RootDirectoryFileNumber]; rootFile.LongName = newOwner; var succeeded = false; data.Result = UploadDataBlockToRam.Create(0, FileSystemHelpers.ToFileByteSerializer(rootFile), 0).Execute(device.Port, data, out succeeded); if (succeeded) { data.Result = UpdateGlobalFileTable.Create(0, new[] { rootFile }).Execute(device.Port, data, out succeeded); } }
private static void OnComplete(AsyncTaskData taskData) { var data = (CheckForDevicesTaskData)taskData; Action reportDialogAction = null; var connectedPortNames = data.LtoFlashViewModel.ActiveLtoFlashDevices.Where(d => d.Device.Port != null).Select(d => d.Device.Port.Name); var devicePorts = data.LtoFlashViewModel.Devices.Except(data.LtoFlashViewModel.ActiveLtoFlashDevices).Where(d => d.Device.Port != null).Select(d => d.Device.Port.Name).ToList(); // .Where(d => d.IsValid && (d != data.LtoFlashViewModel.ActiveLtoFlashDevice)).Select(d => d.Device.Port.Name).ToList(); devicePorts.AddRange(data.ValidDevicePorts); var validPorts = devicePorts.Distinct(); // Show dialog to connect to a port if we do NOT auto-connect, and were not cancelled, and have a valid port... // ... OR we weren't cancelled AND have a valid port that's not already in the active devices list and // did not already issue a call to connect to a device during the search. var promptToConnect = !data.Cancelled; if (promptToConnect) { promptToConnect = !Properties.Settings.Default.AutomaticallyConnectToDevices && validPorts.Any(); if (!promptToConnect && !data.ReportedAnyAutoConnectDevices) { promptToConnect = validPorts.Any(); } } if (promptToConnect) { reportDialogAction = new Action(() => data.LtoFlashViewModel.PromptForDeviceSelection(validPorts.ToList())); } if (data.ReportNoneFound && !data.ReportedAnyAutoConnectDevices && !validPorts.Any()) { if (data.LtoFlashViewModel.ActiveLtoFlashDevices.Any()) { var dialog = INTV.Shared.View.SerialPortSelectorDialog.Create(Resources.Strings.CheckForDevices_PortBrowser_Title, Resources.Strings.CheckForDevices_PortBrowser_Message, connectedPortNames, connectedPortNames, Device.DefaultBaudRate, (p) => data.LtoFlashViewModel.IsLtoFlashSerialPort(p)); reportDialogAction = new Action(() => dialog.ShowDialog()); } else { reportDialogAction = new Action(() => INTV.Shared.View.OSMessageBox.Show(Resources.Strings.CheckForDevices_PortBrowserNoneFound_Message, Resources.Strings.CheckForDevices_PortBrowser_Title)); } } if (reportDialogAction != null) { // BeginInvoke so the task's progress dialog can be closed. SingleInstanceApplication.MainThreadDispatcher.BeginInvoke(reportDialogAction); } }
private static void DownloadRomComplete(AsyncTaskData taskData) { try { var data = (DownloadTaskData)taskData; if ((data.ErrorHandler != null) && (data.Error != null)) { data.ErrorHandler(Resources.Strings.DownloadRom_ErrorMessage, data.Error); } else if (taskData.Cancelled) { INTV.Shared.View.OSMessageBox.Show(Resources.Strings.DownloadRom_CancelMessage, Resources.Strings.DownloadRom_CancelTitle); } } finally { SingleInstanceApplication.Instance.IsBusy = false; } }
public static void MarkAsNew(FileEntry fileEntry, List <Guid> userIDs) { if (CoreContext.Configuration.Personal) { return; } if (fileEntry == null) { return; } userIDs = userIDs ?? new List <Guid>(); var taskData = new AsyncTaskData { FileEntry = (FileEntry)fileEntry.Clone(), UserIDs = userIDs }; if (fileEntry.RootFolderType == FolderType.BUNCH && !userIDs.Any()) { var projectTeam = Global.GetProjectTeam(fileEntry); if (!projectTeam.Any()) { return; } taskData.UserIDs = projectTeam.ToList(); } lock (SyncObj) { AsyncTasks.Add(taskData); if (!AsyncTasks.IsStarted) { AsyncTasks.Start(ExecMarkFileAsNew); } } }
private void SyncWithTimerThenExecute(AsyncTaskData data, Action <AsyncTaskData> doWork) { var timerRestore = Device.DeviceStatusUpdatePeriod; if (timerRestore == System.Threading.Timeout.Infinite) { timerRestore = Device.DefaultGarbageCollectionPeriod; } try { const long TimeoutMilliseconds = 4000; var stopwatch = System.Diagnostics.Stopwatch.StartNew(); Device.DeviceStatusUpdatePeriod = System.Threading.Timeout.Infinite; DebugOutput("SyncWithTimerThenExecute: Disabled timer: previous timeout: " + timerRestore); Device.Port.LogPortMessage("SyncWithTimerThenExecute: Disabled timer: previous timeout: " + timerRestore); while (Device.InTimer && (stopwatch.ElapsedMilliseconds < TimeoutMilliseconds)) { DebugOutput("SyncWithTimerThenExecute: Waiting for timer!"); Device.Port.LogPortMessage("SyncWithTimerThenExecute: Disabled timer: previous timeout: " + timerRestore); System.Threading.Thread.Sleep(68); } stopwatch.Stop(); if ((stopwatch.ElapsedMilliseconds > TimeoutMilliseconds) && Device.InTimer) { DebugOutput("SyncWithTimerThenExecute: THROWING TIMEOUT EXCEPTION"); Device.Port.LogPortMessage("SyncWithTimerThenExecute: THROWING TIMEOUT EXCEPTION"); throw new TimeoutException(Resources.Strings.SyncWithTimer_Execute_ErrorMessage); } using (Device.Port.SetInUse(ProtocolCommand.UpdatePortChunkSizeConfigurations)) { doWork(data); } } finally { Device.DeviceStatusUpdatePeriod = timerRestore; DebugOutput("SyncWithTimerThenExecute: Restoring timer to: " + timerRestore); Device.Port.LogPortMessage("SyncWithTimerThenExecute: Restoring timer to: " + timerRestore); } }
private static void RestoreFileSystem(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var succeeded = false; try { var restoreDirectory = data.Data as string; var menuLayoutPath = System.IO.Path.Combine(restoreDirectory, Configuration.Instance.DefaultMenuLayoutFileName); var menuLayout = MenuLayout.Load(menuLayoutPath); // First bool is whether to reset menu position data (false => RESTORE IT). // Second bool is whether to update root file name (true => RESTORE IT). data.Data = new Tuple <MenuLayout, bool, bool>(menuLayout, false, true); SyncHostToDevice(data); succeeded = data.Succeeded; } finally { data.Succeeded = succeeded; } }
private static void InstallSDLComplete(AsyncTaskData taskData) { var data = (InstallSDLTaskData)taskData; var diskImageInfo = data.DiskImageInfo; if (!string.IsNullOrEmpty(data.ErrorMessage) || (data.Error != null)) { var message = string.Format(CultureInfo.CurrentCulture, Resources.Strings.SDLInstall_GeneralFailureMessage, diskImageInfo.Version); var title = string.Format(CultureInfo.CurrentCulture, Resources.Strings.SDLInstall_Failure_Title, diskImageInfo.Version); var dialog = INTV.Shared.View.ReportDialog.Create(title, message); dialog.TextWrapping = OSTextWrapping.Wrap; dialog.ShowSendEmailButton = false; dialog.ReportText = data.ErrorMessage; dialog.Exception = data.Error; dialog.ShowDialog(Resources.Strings.ReportErrorDialogButtonText); } else { var message = string.Format(CultureInfo.CurrentCulture, Resources.Strings.SDLInstall_Success_Message, diskImageInfo.Version); var title = string.Format(CultureInfo.CurrentCulture, Resources.Strings.SDLInstall_Success_Title, diskImageInfo.Version); OSMessageBox.Show(message, title); } }
private static void CheckForUpdates(AsyncTaskData taskData) { var data = (CheckForUpdatesTaskData)taskData; if (data.CheckingAtStartup) { // Wait a little while before checking. This gives a chance for other parallel startup tasks to finish. System.Threading.Thread.Sleep(12000); } var appInfo = SingleInstanceApplication.AppInfo; var versionCheckUrl = appInfo.VersionCheckUrl; var webRequest = System.Net.WebRequest.Create(versionCheckUrl); webRequest.Proxy = null; webRequest.Timeout = 30000; try { var response = webRequest.GetResponse().GetResponseStream(); var versionStringBuffer = new char[48]; using (var reader = new System.IO.StreamReader(response)) { if (reader.BaseStream.CanTimeout) { reader.BaseStream.ReadTimeout = 20000; } reader.ReadBlock(versionStringBuffer, 0, versionStringBuffer.Length); data.UpdateVersionString = new string(versionStringBuffer); } var downloadableVersion = new System.Version(data.UpdateVersionString); data.UpdateAvailable = downloadableVersion > data.Version; } catch (System.Net.WebException) { // Most likely don't have an internet connection or some other web-related // problem occurred. Just try again on next launch. } }
private static void ReformatFileSystem(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var device = data.Device; data.Succeeded = SetDirtyFlags.Create(LfsDirtyFlags.FileSystemUpdateInProgress).Execute <bool>(device.Port, data); if (data.Succeeded) { data.Succeeded = Reformat.Instance.Execute <bool>(device.Port, data); } if (data.Succeeded) { data.Succeeded = SetDirtyFlags.Create(LfsDirtyFlags.None).Execute <bool>(device.Port, data); } if (data.Succeeded) { var fileSystem = DownloadFileSystemTables.Instance.Execute <FileSystem>(device.Port, data); if (data.Succeeded) { var fileSystemStatistics = Model.Commands.GetFileSystemStatistics.Instance.Execute <FileSystemStatistics>(device.Port, data); data.Result = new Tuple <FileSystem, FileSystemStatistics>(fileSystem, fileSystemStatistics); } } }
private static void DownloadRom(AsyncTaskData taskData) { SingleInstanceApplication.Instance.IsBusy = true; var data = (DownloadTaskData)taskData; var romPath = PrepareRom(data); data.UpdateTaskProgress(0, string.Format(CultureInfo.CurrentCulture, Resources.Strings.DownloadRom_Update_Format, romPath)); var cancelled = data.AcceptCancelIfRequested(); if (!cancelled) { using (var rom = FileUtilities.OpenFileStream(romPath)) { var configData = new Dictionary <string, object>() { { SerialPortConnection.PortNameConfigDataName, data.Intellicart.SerialPort } }; using (var port = SerialPortConnection.Create(configData)) { port.BaudRate = data.Intellicart.BaudRate; port.WriteTimeout = data.Intellicart.Timeout * 1000; // default port settings are 8,N,1 with no handshaking var bytesRemaining = (int)rom.Length; var totalBytes = rom.Length; var bytesPerSecond = data.Intellicart.BaudRate / 8; var bytesWritten = 0; var estimatedDownloadTime = ((double)rom.Length / bytesPerSecond) + 4; // give it time to finish var estimatedTimeRemaining = estimatedDownloadTime; var percentDone = 0.0; // Would like to respond to cancel requests somewhat quickly. So, let's // write out small enough chunks even at the slowest baud rate... var bytesPerWrite = (data.Intellicart.BaudRate / 2400) * 128; System.Diagnostics.Debug.Assert(bytesPerWrite > 0, "How did we get zero bytes to write?!"); port.Open(); var stopwatch = System.Diagnostics.Stopwatch.StartNew(); byte[] buffer = new byte[bytesPerWrite]; while (!cancelled && (bytesRemaining > 0)) { var updateText = string.Format(CultureInfo.CurrentCulture, Resources.Strings.DownloadRom_UpdateTitle_Format, data.Name, Math.Max(0, (int)estimatedTimeRemaining)); data.UpdateTaskTitle(updateText); bytesPerWrite = Math.Min(bytesPerWrite, bytesRemaining); var bytesRead = rom.Read(buffer, 0, bytesPerWrite); bytesWritten += bytesRead; bytesRemaining -= bytesRead; updateText = string.Format(CultureInfo.CurrentCulture, Resources.Strings.DownloadRom_Update_Format, romPath); estimatedTimeRemaining = estimatedDownloadTime - stopwatch.Elapsed.TotalSeconds; percentDone = stopwatch.Elapsed.TotalSeconds / estimatedDownloadTime; data.UpdateTaskProgress(percentDone, updateText); port.WriteStream.Write(buffer, 0, bytesRead); cancelled = data.AcceptCancelIfRequested(); } // If we close the port too soon after writing, the Intellicart will time out reading data from the stream. // This is likely due to buffering, and that the streams get disposed when the port and file streams are // disposed. On Mac in particular, the write out to the port may complete far more quickly than what the // math would indicate, based on observation. This implies one of the following: // a) Even though the synchronous write was called, the underlying implementation is asynchronous // b) It could be that the driver itself is "lying" to the underlying implementation // c) Buffering, either in the driver, kernel, or other API layers, misleads the higher-level APIs var timedOut = false; while (!cancelled && !timedOut) { var message = string.Format(Resources.Strings.DownloadRom_UpdateTitle_Format, data.Name, Math.Max(0, (int)estimatedTimeRemaining)); data.UpdateTaskTitle(message); System.Threading.Thread.Sleep(250); cancelled = data.AcceptCancelIfRequested(); var updateText = string.Format(CultureInfo.CurrentCulture, Resources.Strings.DownloadRom_Update_Format, romPath); estimatedTimeRemaining = estimatedDownloadTime - stopwatch.Elapsed.TotalSeconds; percentDone = Math.Max(100, stopwatch.Elapsed.TotalSeconds / estimatedDownloadTime); data.UpdateTaskProgress(percentDone, updateText); timedOut = estimatedTimeRemaining < 0; } } } } }
internal void Add(AsyncTaskData <T> taskData) { Tasks.QueueTask((d, c) => ExecMarkFileAsNew(taskData), taskData); }
private static void ExecMarkFileAsNew(AsyncTaskData obj) { CoreContext.TenantManager.SetCurrentTenant(Convert.ToInt32(obj.TenantID)); using (var folderDao = Global.DaoFactory.GetFolderDao()) { object parentFolderId; if (obj.FileEntry is File) parentFolderId = ((File)obj.FileEntry).FolderID; else parentFolderId = obj.FileEntry.ID; var parentFolders = folderDao.GetParentFolders(parentFolderId); parentFolders.Reverse(); var userEntriesData = new Dictionary<Guid, List<FileEntry>>(); if (obj.FileEntry.RootFolderType == FolderType.BUNCH) { if (!obj.UserIDs.Any()) return; parentFolders.Add(folderDao.GetFolder(Global.FolderProjects)); var entries = new List<FileEntry> { obj.FileEntry }; entries = entries.Concat(parentFolders.Cast<FileEntry>()).ToList(); obj.UserIDs.ForEach(userID => { if (userEntriesData.ContainsKey(userID)) userEntriesData[userID].AddRange(entries); else userEntriesData.Add(userID, entries); }); } else { var filesSecurity = Global.GetFilesSecurity(); parentFolders.ForEach(parentFolder => filesSecurity .WhoCanRead(parentFolder) .Where(x => x != obj.CurrentAccountId) .ToList() .ForEach(userID => { if (userEntriesData.ContainsKey(userID)) userEntriesData[userID].Add(parentFolder); else userEntriesData.Add(userID, new List<FileEntry> { parentFolder }); }) ); var userIDs = obj.UserIDs; if (!userIDs.Any()) userIDs = filesSecurity.WhoCanRead(obj.FileEntry).Where(x => x != obj.CurrentAccountId).ToList(); if (obj.FileEntry.RootFolderType == FolderType.USER) { var folderShare = folderDao.GetFolder(Global.FolderShare); foreach (var userID in userIDs) { var userFolderId = folderDao.GetFolderID(FileConstant.ModuleId, "my", userID.ToString(), false); Folder rootFolder = null; if (obj.FileEntry.ProviderEntry) { rootFolder = obj.FileEntry.RootFolderCreator == userID ? folderDao.GetFolder(userFolderId) : folderShare; } else if (!Equals(obj.FileEntry.RootFolderId, userFolderId)) { rootFolder = folderShare; } if (rootFolder == null) continue; if (userEntriesData.ContainsKey(userID)) userEntriesData[userID].Add(rootFolder); else userEntriesData.Add(userID, new List<FileEntry> { rootFolder }); } } if (obj.FileEntry.ProviderEntry && obj.FileEntry.RootFolderType == FolderType.COMMON) { var commonFolder = folderDao.GetFolder(Global.FolderCommon); userIDs.ForEach(userID => { if (userEntriesData.ContainsKey(userID)) userEntriesData[userID].Add(commonFolder); else userEntriesData.Add(userID, new List<FileEntry> { commonFolder }); }); } userIDs.ForEach(userID => { if (userEntriesData.ContainsKey(userID)) userEntriesData[userID].Add(obj.FileEntry); else userEntriesData.Add(userID, new List<FileEntry> { obj.FileEntry }); }); } using (var tagDao = Global.DaoFactory.GetTagDao()) { var newTags = new List<Tag>(); var updateTags = new List<Tag>(); foreach (var userID in userEntriesData.Keys) { if (tagDao.GetNewTags(userID, obj.FileEntry).Any()) continue; var entries = userEntriesData[userID].Distinct().ToList(); var exist = tagDao.GetNewTags(userID, entries.ToArray()).ToList(); var update = exist.Where(t => t.EntryType == FileEntryType.Folder).ToList(); update.ForEach(t => t.Count++); updateTags.AddRange(update); entries.ForEach(entry => { if (exist.All(tag => !tag.EntryId.Equals(entry.ID))) { newTags.Add(Tag.New(userID, entry)); } }); } if (updateTags.Any()) tagDao.UpdateNewTags(updateTags.ToArray()); if (newTags.Any()) tagDao.SaveTags(newTags.ToArray()); } } }
public static void MarkAsNew(FileEntry fileEntry, List<Guid> userIDs) { if (CoreContext.Configuration.Personal) return; if (fileEntry == null) return; userIDs = userIDs ?? new List<Guid>(); var taskData = new AsyncTaskData { FileEntry = (FileEntry)fileEntry.Clone(), UserIDs = userIDs }; if (fileEntry.RootFolderType == FolderType.BUNCH && !userIDs.Any()) { var projectTeam = Global.GetProjectTeam(fileEntry); if (!projectTeam.Any()) return; taskData.UserIDs = projectTeam.ToList(); } lock (SyncObj) { AsyncTasks.Add(taskData); if (!AsyncTasks.IsStarted) AsyncTasks.Start(ExecMarkFileAsNew); } }
private static void UpdateFirmware(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var device = data.Device; var customData = data.Data as Tuple <string, int>; var firmwareUpdateFile = customData.Item1; var succeeded = false; UploadDataBlockToRam.Create(0, new FileSystemFile(firmwareUpdateFile), 0).Execute(device.Port, data, out succeeded); if (succeeded) { ValidateFirmwareImageInRam.Instance.Execute(device.Port, data, out succeeded); if (succeeded) { // Check to see if there's an error database file. If so, and it's different than the one // we've cached in the FirmwareUpdates directory, copy it over so we'll have a matching error_db.yaml. // We're not going to complain if this part fails, so sit on any exceptions that may happen. try { var configuration = Configuration.Instance; var sourceErrorDatabaseFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(firmwareUpdateFile), ErrorLog.DefaultErrorDatabaseName); if (System.IO.File.Exists(sourceErrorDatabaseFilePath)) { if (!System.IO.Directory.Exists(configuration.FirmwareUpdatesDirectory)) { System.IO.Directory.CreateDirectory(configuration.FirmwareUpdatesDirectory); } var destinationErrorDatabaseFilePath = System.IO.Path.Combine(configuration.FirmwareUpdatesDirectory, ErrorLog.DefaultErrorDatabaseName); var crcOfSource = INTV.Core.Utility.Crc32.OfFile(sourceErrorDatabaseFilePath); var crcOfDestination = 0u; if (System.IO.File.Exists(destinationErrorDatabaseFilePath)) { crcOfDestination = INTV.Core.Utility.Crc32.OfFile(destinationErrorDatabaseFilePath); if (crcOfSource != crcOfDestination) { var backupPath = destinationErrorDatabaseFilePath.GetUniqueBackupFilePath(); System.IO.File.Move(destinationErrorDatabaseFilePath, backupPath); } } if ((crcOfDestination == 0) || (crcOfSource != crcOfDestination)) { System.IO.File.Copy(sourceErrorDatabaseFilePath, destinationErrorDatabaseFilePath); } } } catch (Exception e) { System.Diagnostics.Debug.WriteLine("Failed to copy error database file: " + e); } } else { data.FailureMessage = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.UpdateFirmwareCommand_ValidationFailedFormat, firmwareUpdateFile); } } else { data.FailureMessage = Resources.Strings.DeviceMultistageCommand_UpdateFirmware_DownloadFailed; } if (succeeded && device.ShouldRemoveSecondaryFirmware(data, out succeeded)) { device.RemoveSecondaryFirmware(data, out succeeded); } if (succeeded && !device.ShouldRemoveSecondaryFirmware(data, out succeeded)) { // Secondary is gone -- so now update firmware! ProgramSecondaryFirmware.Instance.Execute(device.Port, data, out succeeded); data.UpdateTaskProgress(0, Resources.Strings.ProtocolCommandId_WaitForBeaconPseudoCommand_Title); succeeded = device.WaitForBeacon(ProtocolCommand.WaitForBeaconTimeout * 2) && succeeded; } if (succeeded) { var newRevisions = QueryFirmwareRevisions.Instance.Execute(device.Port, data, out succeeded) as FirmwareRevisions; if (succeeded) { var deployedVersion = newRevisions.Current; succeeded = deployedVersion == customData.Item2; } } if (!succeeded && string.IsNullOrWhiteSpace(data.FailureMessage)) { data.FailureMessage = Resources.Strings.DeviceMultistageCommand_UpdateFirmware_Failed; } }
private static void CheckDevices(AsyncTaskData taskData) { var data = (CheckForDevicesTaskData)taskData; var validPorts = new HashSet <string>(); data.ValidDevicePorts = validPorts; var potentialPorts = data.LtoFlashViewModel.AvailableDevicePorts.Except(data.CurrentDevices).ToList(); if (!string.IsNullOrWhiteSpace(data.LastKnownPort) && (potentialPorts.Count > 1) && potentialPorts.Remove(data.LastKnownPort)) { potentialPorts.Insert(0, data.LastKnownPort); } foreach (var portName in potentialPorts) { var maxRetries = 1; for (var retry = 0; retry < maxRetries; ++retry) { if (data.AcceptCancelIfRequested()) { break; } var errorLogger = Properties.Settings.Default.EnablePortLogging ? new Logger(Configuration.Instance.GetPortLogPath(portName)) : null; try { var isValidDevicePort = false; var configData = new Dictionary <string, object>() { { SerialPortConnection.PortNameConfigDataName, portName } }; using (var port = SerialPortConnection.Create(configData)) { if (Properties.Settings.Default.EnablePortLogging) { port.EnableLogging(Configuration.Instance.GetPortLogPath(portName)); } port.LogPortMessage("CheckForDevices: BEGIN"); data.UpdateTaskProgress(0, string.Format(Resources.Strings.DeviceSearch_Task_Progress_Format, portName)); port.BaudRate = Device.DefaultBaudRate; port.Handshake = Device.Handshake; port.Open(); var numRetry = 4; var timeout = 1100; for (var i = 0; !data.AcceptCancelIfRequested() && (i < numRetry); ++i) { if (!data.AcceptCancelIfRequested()) { if (port.IsOpen && port.WaitForBeacon(timeout)) { isValidDevicePort = true; } } } port.LogPortMessage("CheckForDevices: END"); } if (!data.AcceptCancelIfRequested() && isValidDevicePort) { if (Properties.Settings.Default.AutomaticallyConnectToDevices && data.AutoConnect) { data.ReportedAnyAutoConnectDevices |= true; var creationInfo = new Dictionary <string, object>() { { DeviceCreationInfo.ConfigName, new DeviceCreationInfo(true, true, ActivationMode.ActivateIfFirst) } }; INTV.Shared.Interop.DeviceManagement.DeviceChange.ReportDeviceAdded(data, portName, Core.Model.Device.ConnectionType.Serial, creationInfo); data.Task.CancelTask(); } else { validPorts.Add(portName); } } } catch (UnauthorizedAccessException) { // Access is denied to the port or the current process, or another process on the system, // already has the specified COM port open either by a SerialPort instance or in unmanaged code. if (errorLogger != null) { errorLogger.Log("CheckForDevices: UnauthorizedAccessException on port " + portName); } maxRetries = RetryCount; System.Threading.Thread.Sleep(500); } catch (ArgumentOutOfRangeException) { // One or more of the properties for this instance are invalid. For example, the Parity, DataBits, // or Handshake properties are not valid values; the BaudRate is less than or equal to zero; the // ReadTimeout or WriteTimeout property is less than zero and is not InfiniteTimeout. if (errorLogger != null) { errorLogger.Log("CheckForDevices: ArgumentOutOfRangeException on port " + portName); } } catch (ArgumentException) { // The port name does not begin with "COM", or the file type of the port is not supported. if (errorLogger != null) { errorLogger.Log("CheckForDevices: ArgumentException on port " + portName); } } catch (System.IO.IOException) { // The port is in an invalid state, or an attempt to set the state of the underlying port failed. // For example, the parameters passed from this SerialPort object were invalid. if (errorLogger != null) { errorLogger.Log("CheckForDevices: IOException on port " + portName); } } catch (InvalidOperationException) { // The specified port on the current instance of the SerialPort is already open. if (errorLogger != null) { errorLogger.Log("CheckForDevices: InvalidOperationException on port " + portName); } } catch (Exception e) { // Caught some unexpected exception. if (errorLogger != null) { errorLogger.Log("CheckForDevices: Exception on port " + portName + " with message: " + e.Message); } throw; } } } if (data.CancelRequsted) { validPorts.Clear(); } }
// NOTE: The specific task data (ExecuteDeviceCommandAsyncTaskData.Data) must be a Tuple<MenuLayout, bool, bool>. // The first Boolean value indicates whether the operation should attempt to force the removal of menu position data. // The second Boolean value indicates whether the operation should update the root file's names (device name, owner). private static void SyncHostToDevice(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var device = data.Device; data.Task.UpdateTaskProgress(0, Resources.Strings.DeviceMultistageCommand_UpdatingFiles_ComputingChangesProgress); var currentDirtyFlags = GetDirtyFlags.Instance.Execute <LfsDirtyFlags>(device.Port, data); var deviceFileSystem = DownloadFileSystemTables.Instance.Execute <FileSystem>(device.Port, data); deviceFileSystem.Status = currentDirtyFlags; if (data.AcceptCancelIfRequested()) { return; } var hostData = (Tuple <MenuLayout, bool, bool>)data.Data; var hostFileSystem = hostData.Item1.FileSystem; var resetSaveMenuPosition = hostData.Item2; if (resetSaveMenuPosition) { hostFileSystem.ForceRemovalOfMenuPositionData(deviceFileSystem); } hostFileSystem.SuppressRootFileNameDifferences(device); hostFileSystem.PopulateSaveDataForksFromDevice(deviceFileSystem); // The first pass gathers all differences, including errors. var allDifferencesWithErrors = hostFileSystem.CompareTo(deviceFileSystem, device, true); #if USE_SMART_COPY // Now, use a clone of the original file system to compute the actual work to do, and use the failures for a post-op error report. var hostFileSystemWorkingCopy = hostFileSystem.Clone(); var ignoreRootFileNames = !hostData.Item3; if (ignoreRootFileNames) { hostFileSystemWorkingCopy.Files[GlobalFileTable.RootDirectoryFileNumber].ShortName = deviceFileSystem.Files[GlobalFileTable.RootDirectoryFileNumber].ShortName; hostFileSystemWorkingCopy.Files[GlobalFileTable.RootDirectoryFileNumber].LongName = deviceFileSystem.Files[GlobalFileTable.RootDirectoryFileNumber].LongName; } var partialErrors = hostFileSystemWorkingCopy.CleanUpInvalidEntries(deviceFileSystem, allDifferencesWithErrors, FileSystemHelpers.ShouldRemoveInvalidEntry, ShouldIncludeError); var allDifferences = hostFileSystemWorkingCopy.CompareTo(deviceFileSystem, device, true); #else // This will try to copy all ROMs, even incompatible ones, and should eventually be removed. var hostFileSystemWorkingCopy = hostFileSystem; var partialErrors = allDifferencesWithErrors.GetAllFailures(ShouldIncludeError); var allDifferences = allDifferencesWithErrors; #endif // USE_SMART_COPY var succeeded = true; var phaseNumber = 0; var updateString = string.Empty; // Run any delete operations... var total = allDifferences.DirectoryDifferences.ToDelete.Count + allDifferences.FileDifferences.ToDelete.Count + allDifferences.ForkDifferences.ToDelete.Count + allDifferences.ForkDifferences.ToUpdate.Count; var numComplete = 0; if (data.AcceptCancelIfRequested()) { return; } if (total > 0) { ++phaseNumber; if (!data.CancelRequsted && succeeded && allDifferences.DirectoryDifferences.ToDelete.Any()) { var deleteOpData = new DeleteOperationData(data, LfsEntityType.Directory) { Factory = (gdn) => DeleteFolder.Create((byte)(uint)gdn[0]), UpdateTitleFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_ProgressTitleFormat, UpdateTitleInfo = Resources.Strings.LfsOperation_Remove, UpdateProgressFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_DeletingItemProgressFormat, UpdateProgressInfo = Resources.Strings.DirectoriesInSentence, Phase = phaseNumber, Total = total, Current = numComplete }; currentDirtyFlags |= DeleteEntries(allDifferences.DirectoryDifferences.ToDelete, deleteOpData, currentDirtyFlags, deviceFileSystem); numComplete = deleteOpData.Current; succeeded = data.Succeeded; } if (!data.CancelRequsted && succeeded && allDifferences.FileDifferences.ToDelete.Any()) { var deleteOpData = new DeleteOperationData(data, LfsEntityType.File) { Factory = (gfn) => DeleteFile.Create((ushort)(uint)gfn[0]), UpdateTitleFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_ProgressTitleFormat, UpdateTitleInfo = Resources.Strings.LfsOperation_Remove, UpdateProgressFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_DeletingItemProgressFormat, UpdateProgressInfo = Resources.Strings.FilesInSentence, Phase = phaseNumber, Total = total, Current = numComplete }; currentDirtyFlags |= DeleteEntries(allDifferences.FileDifferences.ToDelete, deleteOpData, currentDirtyFlags, deviceFileSystem); numComplete = deleteOpData.Current; succeeded = data.Succeeded; } if (!data.CancelRequsted && succeeded && (allDifferences.ForkDifferences.ToDelete.Any() || allDifferences.ForkDifferences.ToUpdate.Any())) { var deleteOpData = new DeleteOperationData(data, LfsEntityType.Fork) { Factory = (gkn) => DeleteFork.Create((ushort)(uint)gkn[0]), UpdateTitleFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_ProgressTitleFormat, UpdateTitleInfo = Resources.Strings.LfsOperation_Remove, UpdateProgressFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_DeletingItemProgressFormat, UpdateProgressInfo = Resources.Strings.DeviceMultistageCommand_RemovingFileContents, Phase = phaseNumber, Total = total, Current = numComplete }; var forks = allDifferences.ForkDifferences.ToDelete.ToList(); var updatedForksToTreatAsDeletions = allDifferences.ForkDifferences.ToUpdate.Select(f => (uint)f.GlobalForkNumber).Where(f => !allDifferences.ForkDifferences.FailedOperations.Any(o => (o.Value.GlobalFileSystemNumber == f) && FileSystemHelpers.IsMissingForkError(o.Value))); forks.AddRange(updatedForksToTreatAsDeletions); currentDirtyFlags |= DeleteEntries(forks, deleteOpData, currentDirtyFlags, deviceFileSystem); numComplete = deleteOpData.Current; succeeded = data.Succeeded; } } if (data.AcceptCancelIfRequested()) { return; } data.CurrentlyExecutingCommand = ProtocolCommandId.UnknownCommand; data.FailureMessage = Resources.Strings.SyncHostToDeviceCommand_GatherUpdatesFailedMessage; var updateOperations = hostFileSystemWorkingCopy.GatherAllUpdates(allDifferences, device.UniqueId); if (updateOperations.Any()) { do { if (data.AcceptCancelIfRequested()) { break; } LfsUpdateOperation operation = null; data.FailureMessage = Resources.Strings.SyncHostToDevice_FetchUpdateOperationFailedMessage; updateOperations = updateOperations.FetchUpdateOperation(out operation); if (data.AcceptCancelIfRequested()) { break; } ++phaseNumber; numComplete = 0; total = operation.Forks.Count + operation.Files.Count + operation.Directories.Count; foreach (var failure in operation.Failures) { partialErrors[failure.Description] = failure.Exception; } // Load forks. var address = 0u; if (!data.CancelRequsted && succeeded && operation.Forks.Any()) { data.FailureMessage = null; var uploadOpData = new UploadDataOperationData(data, address) { TargetType = LfsEntityType.Fork, Factory = (upl) => UploadDataBlockToRam.Create((uint)upl[0], (ByteSerializer)upl[1], (uint)upl[2]), GetSerializer = FileSystemHelpers.ToForkByteSerializer, ShouldUpdateProgress = (k) => true, UpdateTitleFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_ProgressTitleFormat, UpdateTitleInfo = operation.ProgressTitle, UpdateProgressFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_TransferToRamProgressFormat, Phase = phaseNumber, Total = total, Current = numComplete }; address = UploadEntries(operation.FileSystem.Forks, operation.Forks, uploadOpData); numComplete = uploadOpData.Current; succeeded = data.Succeeded; } // Load GFT update. if (!data.CancelRequsted && succeeded && operation.Files.Any()) { data.FailureMessage = null; var fileRange = operation.GfnRange; var files = Enumerable.Range(fileRange.Minimum, (fileRange.Maximum - fileRange.Minimum) + 1); // slower than a loop, but who cares? var uploadOpData = new UploadDataOperationData(data, address) { TargetType = LfsEntityType.File, Factory = (upl) => UploadDataBlockToRam.Create((uint)upl[0], (ByteSerializer)upl[1], (uint)upl[2]), GetSerializer = FileSystemHelpers.ToFileByteSerializer, ShouldUpdateProgress = (f) => (f != null) && operation.Files.Contains(((ILfsFileInfo)f).GlobalFileNumber), UpdateTitleFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_ProgressTitleFormat, UpdateTitleInfo = operation.ProgressTitle, UpdateProgressFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_TransferToRamProgressFormat, Phase = phaseNumber, Total = total, Current = numComplete }; // THIS COULD BE DONE WITH ONE LARGE BLOCK INSTEAD OF MANY SMALLER ONES address = UploadEntries(operation.FileSystem.Files, files, uploadOpData); numComplete = uploadOpData.Current; succeeded = data.Succeeded; } // Load GDT update. if (!data.CancelRequsted && succeeded && operation.Directories.Any()) { data.FailureMessage = null; var directoryRange = operation.GdnRange; var directories = Enumerable.Range(directoryRange.Minimum, (directoryRange.Maximum - directoryRange.Minimum) + 1); // slower than a loop, but who cares? var uploadOpData = new UploadDataOperationData(data, address) { TargetType = LfsEntityType.Directory, Factory = (upl) => UploadDataBlockToRam.Create((uint)upl[0], (ByteSerializer)upl[1], (uint)upl[2]), GetSerializer = FileSystemHelpers.ToDirectoryByteSerializer, ShouldUpdateProgress = (d) => (d != null) && operation.Files.Contains(((IDirectory)d).GlobalDirectoryNumber), UpdateTitleFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_ProgressTitleFormat, UpdateTitleInfo = operation.ProgressTitle, UpdateProgressFormat = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_TransferToRamProgressFormat, Phase = phaseNumber, Total = total, Current = numComplete }; // THIS COULD BE DONE WITH ONE LARGE BLOCK INSTEAD OF MANY SMALLER ONES address = UploadEntries(operation.FileSystem.Directories, directories, uploadOpData); numComplete = uploadOpData.Current; succeeded = data.Succeeded; } if (data.AcceptCancelIfRequested()) { break; } // Everything is in RAM now, so execute commands. address = 0; // All the data was initially loaded at location zero. numComplete = 0; total = operation.Forks.Count; if (operation.Files.Count > 0) { ++total; } if (operation.Directories.Count > 0) { ++total; } // Create forks. if (!data.CancelRequsted && succeeded && operation.Forks.Any()) { data.FailureMessage = null; var numCreated = 0; var numToCreate = operation.Forks.Count; foreach (var gkn in operation.Forks) { if (data.AcceptCancelIfRequested()) { break; } address = address.Align(); var fork = operation.FileSystem.Forks[gkn]; updateString = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.DeviceMultistageCommand_UpdatingFiles_ProgressTitleFormat, operation.ProgressTitle, ++numComplete, total, phaseNumber); data.Task.UpdateTaskTitle(updateString); updateString = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.DeviceMultistageCommand_UpdatingFiles_CreatingItemProgressFormat, fork.Name, ++numCreated, numToCreate); data.Task.UpdateTaskProgress((double)numCreated / numToCreate, updateString); currentDirtyFlags |= currentDirtyFlags.UpdateFileSystemDirtyState(deviceFileSystem, data, gkn, LfsOperations.Add, LfsEntityType.Fork); CreateForkFromRam.Create(address, fork).Execute(device.Port, data, out succeeded); address += (uint)fork.SerializeByteCount; } address = address.Align(); } // Update GFT. if (!data.CancelRequsted && succeeded && operation.Files.Any()) { data.FailureMessage = null; if (data.AcceptCancelIfRequested()) { break; } var gftRange = operation.GfnRange; if (operation.Files.Count == 1) { updateString = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.DeviceMultistageCommand_UpdatingFileSystemTablesOneEntry_ProgressTitleFormat, Resources.Strings.File, gftRange.Minimum, phaseNumber); } else { updateString = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.DeviceMultistageCommand_UpdatingFileSystemTables_ProgressTitleFormat, Resources.Strings.File, gftRange.Minimum, gftRange.Maximum, phaseNumber); } data.Task.UpdateTaskTitle(updateString); data.Task.UpdateTaskProgress((double)(++numComplete) / total, Resources.Strings.DeviceMultistageCommand_UpdatingGlobalFilesTable); currentDirtyFlags |= currentDirtyFlags.UpdateFileSystemDirtyState(deviceFileSystem, data, gftRange.Minimum, LfsOperations.Update, LfsEntityType.File); UpdateGlobalFileTable.Create(address, gftRange).Execute(device.Port, data, out succeeded); address += (uint)(gftRange.Maximum - gftRange.Minimum + 1) * LfsFileInfo.FlatSizeInBytes; } // Update GDT. if (!data.CancelRequsted && succeeded && operation.Directories.Any()) { data.FailureMessage = null; if (data.AcceptCancelIfRequested()) { break; } var gdtRange = operation.GdnRange; if (operation.Directories.Count == 1) { updateString = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.DeviceMultistageCommand_UpdatingFileSystemTablesOneEntry_ProgressTitleFormat, Resources.Strings.Directory, gdtRange.Minimum, phaseNumber); } else { updateString = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.DeviceMultistageCommand_UpdatingFileSystemTables_ProgressTitleFormat, Resources.Strings.Directory, gdtRange.Minimum, gdtRange.Maximum, phaseNumber); } data.Task.UpdateTaskTitle(updateString); data.Task.UpdateTaskProgress((double)(++numComplete) / total, Resources.Strings.DeviceMultistageCommand_UpdatingGlobalDirectoriesTable); currentDirtyFlags |= currentDirtyFlags.UpdateFileSystemDirtyState(deviceFileSystem, data, gdtRange.Minimum, LfsOperations.Update, LfsEntityType.Directory); UpdateGlobalDirectoryTable.Create(address, gdtRange).Execute(device.Port, data, out succeeded); address += (uint)(gdtRange.Maximum - gdtRange.Minimum + 1) * Directory.FlatSizeInBytes; } }while (!data.CancelRequsted && succeeded && updateOperations.Any()); } if (!data.CancelRequsted && data.Succeeded) { SetDirtyFlags.Create(LfsDirtyFlags.None).Execute(device.Port, data, out succeeded); deviceFileSystem.Status = LfsDirtyFlags.None; } if (!data.CancelRequsted && data.Succeeded) { var updatedFileSystem = DownloadFileSystemTables.Instance.Execute(device.Port, data, out succeeded) as FileSystem; #if USE_SMART_COPY partialErrors = allDifferences.CombineAllFailures(partialErrors, ShouldIncludeError); #endif // USE_SMART_COPY data.Result = new Tuple <FileSystem, IDictionary <string, FailedOperationException> >(updatedFileSystem, partialErrors); } }
private static void SyncDeviceToHost(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var device = data.Device; data.Task.UpdateTaskProgress(0, Resources.Strings.DeviceMultistageCommand_UpdatingMenuLayout_ComputingChangesProgress); var customData = (Tuple <MenuLayout, bool>)data.Data; var currentDirtyFlags = GetDirtyFlags.Instance.Execute <LfsDirtyFlags>(device.Port, data); var syncErrors = new FileSystemSyncErrors(currentDirtyFlags); data.Result = syncErrors; // If customData.Item2 is true, that means we should ignore file system inconsistencies, ergo if it's false, we should NOT ignore them. if (currentDirtyFlags.HasFlag(LfsDirtyFlags.FileSystemUpdateInProgress) && !customData.Item2) { throw new InconsistentFileSystemException(Resources.Strings.DeviceMultistageCommand_UpdatingMenuLayout_InconsistentState, device.UniqueId); } var deviceFileSystem = DownloadFileSystemTables.Instance.Execute <FileSystem>(device.Port, data); deviceFileSystem.Status = currentDirtyFlags; if (data.AcceptCancelIfRequested()) { return; } var hostFileSystem = customData.Item1.FileSystem; deviceFileSystem.RemoveMenuPositionData(); // we should not preserve the menu position fork hostFileSystem.PopulateSaveDataForksFromDevice(deviceFileSystem); var allDifferences = deviceFileSystem.CompareTo(hostFileSystem); if (!allDifferences.Any()) { data.Task.CancelTask(); } // We're going to apply the changes to a clone of the original file system. if (data.AcceptCancelIfRequested()) { return; } var fileSystemToModify = hostFileSystem.Clone(); if (data.AcceptCancelIfRequested()) { return; } // Before we change anything, create backups of the ROM list and current menu layout. var configuration = SingleInstanceApplication.Instance.GetConfiguration <Configuration>(); var romsConfiguration = SingleInstanceApplication.Instance.GetConfiguration <INTV.Shared.Model.RomListConfiguration>(); if (System.IO.File.Exists(configuration.MenuLayoutPath) || System.IO.File.Exists(romsConfiguration.RomFilesPath)) { var backupTimestamp = INTV.Shared.Utility.PathUtils.GetTimeString(); var backupSubdirectory = configuration.SyncFromDeviceBackupFilenameFragment + "-" + backupTimestamp; var backupDirectory = System.IO.Path.Combine(configuration.HostBackupDataAreaPath, backupSubdirectory); if (!System.IO.Directory.Exists(backupDirectory)) { System.IO.Directory.CreateDirectory(backupDirectory); } if (System.IO.File.Exists(configuration.MenuLayoutPath)) { var backupMenuLayoutPath = System.IO.Path.Combine(backupDirectory, configuration.DefaultMenuLayoutFileName); System.IO.File.Copy(configuration.MenuLayoutPath, backupMenuLayoutPath); } if (System.IO.File.Exists(romsConfiguration.RomFilesPath)) { var backupRomListPath = System.IO.Path.Combine(backupDirectory, romsConfiguration.DefaultRomsFileName); System.IO.File.Copy(romsConfiguration.RomFilesPath, backupRomListPath); } } // First, directory deletion. if (!data.CancelRequsted) { foreach (var directory in allDifferences.DirectoryDifferences.ToDelete) { if (data.AcceptCancelIfRequested()) { break; } // We don't use RemoveAt because of the collateral damage it may cause. fileSystemToModify.Directories[(int)directory] = null; } } // Then, we process file deletion. if (!data.CancelRequsted) { foreach (var file in allDifferences.FileDifferences.ToDelete) { if (data.AcceptCancelIfRequested()) { break; } // We don't use RemoveAt because of the collateral damage it may cause. fileSystemToModify.Files[(int)file] = null; } } // Finally, fork deletion. if (!data.CancelRequsted) { foreach (var fork in allDifferences.ForkDifferences.ToDelete) { if (data.AcceptCancelIfRequested()) { break; } // We don't use RemoveAt because of the collateral damage it may cause. fileSystemToModify.Forks[(int)fork] = null; } } var roms = SingleInstanceApplication.Instance.Roms; var romsToAdd = new HashSet <string>(); var forkNumberMap = new Dictionary <ushort, ushort>(); // maps device -> local var forkSourceFileMap = new Dictionary <ushort, string>(); // maps local fork number -> source file for fork // Add new forks. if (!data.CancelRequsted) { foreach (var fork in allDifferences.ForkDifferences.ToAdd) { if (data.AcceptCancelIfRequested()) { break; } // Forks on device but not in our menu must be added. System.Diagnostics.Debug.WriteLine("Fork adds! This means CRC24 of a LUIGI -> ???"); Fork newLocalFork = null; var forkSourcePath = GetSourcePathForFork(data, fork, deviceFileSystem, roms, romsConfiguration); // retrieves the fork if necessary if (forkSourcePath != null) { newLocalFork = new Fork(forkSourcePath) { GlobalForkNumber = fork.GlobalForkNumber }; romsToAdd.Add(forkSourcePath); } else { // Is this code even reachable any more??? Looking at GetSourcePathForFork, I would think not. newLocalFork = new Fork(fork.Crc24, fork.Size, fork.GlobalForkNumber); var cacheEntry = CacheIndex.Find(fork.Crc24, fork.Size); if (cacheEntry != null) { newLocalFork.FilePath = System.IO.Path.Combine(configuration.RomsStagingAreaPath, cacheEntry.LuigiPath); } } newLocalFork.FileSystem = fileSystemToModify; fileSystemToModify.Forks.AddAndRelocate(newLocalFork); forkNumberMap[fork.GlobalForkNumber] = newLocalFork.GlobalForkNumber; if (string.IsNullOrEmpty(forkSourcePath)) { System.Diagnostics.Debug.WriteLine("Bad path in Fork add."); syncErrors.UnableToRetrieveForks.Add(newLocalFork); } forkSourceFileMap[newLocalFork.GlobalForkNumber] = forkSourcePath; } } // Update forks. if (!data.CancelRequsted) { foreach (var fork in allDifferences.ForkDifferences.ToUpdate) { if (data.AcceptCancelIfRequested()) { break; } // Forks on the device don't store file paths. var localFork = fileSystemToModify.Forks[fork.GlobalForkNumber]; forkNumberMap[fork.GlobalForkNumber] = localFork.GlobalForkNumber; var forkSourcePath = GetSourcePathForFork(data, fork, deviceFileSystem, roms, romsConfiguration); if (string.IsNullOrEmpty(forkSourcePath)) { System.Diagnostics.Debug.WriteLine("Bad path in Fork update."); syncErrors.UnableToRetrieveForks.Add(localFork); } forkSourceFileMap[localFork.GlobalForkNumber] = forkSourcePath; localFork.FilePath = forkSourcePath; if ((localFork.Crc24 != fork.Crc24) || (localFork.Size != fork.Size)) { localFork.FilePath = null; // May need to regenerate the LUIGI file... System.Diagnostics.Debug.WriteLine("Fork at path doesn't match! " + forkSourcePath); syncErrors.UnableToRetrieveForks.Add(localFork); } ProgramDescription description = null; var forkKind = deviceFileSystem.GetForkKind(fork); if (SyncForkData(localFork, forkKind, forkSourceFileMap, null, ref description)) { IEnumerable <ILfsFileInfo> filesUsingFork; if (fileSystemToModify.GetAllFilesUsingForks(new[] { localFork }).TryGetValue(localFork, out filesUsingFork)) { foreach (var program in filesUsingFork.OfType <Program>()) { // This situation can arise when we have a ROM on the local system that has the // same CRC as the one in the device's file system, but whose .cfg file has drifted // from what was in place when the LUIGI file on the device was initially created // and deployed. What we need to do in this case, then, is to force the programs // pointing to this fork to actually use the LUIGI file now. // The LUIGI file has already been put into the right place -- it's now a matter of // forcing the program to actually point to it. This runs a bit counter to how several // IRom implementations are wrappers around other types of ROMs. romsToAdd.Add(forkSourcePath); } } } else { syncErrors.UnableToRetrieveForks.Add(localFork); } } } var recoveredRomFiles = romsToAdd.IdentifyRomFiles(data.AcceptCancelIfRequested, (f) => data.UpdateTaskProgress(0, f)); var recoveredRoms = ProgramCollection.GatherRomsFromFileList(recoveredRomFiles, roms, null, data.AcceptCancelIfRequested, (f) => data.UpdateTaskProgress(0, f), null, null); if (roms.AddNewItemsFromList(recoveredRoms).Any()) { roms.Save(romsConfiguration.RomFilesPath, false); // this may throw an error, which, in this case, will terminate the operation } // Add files. if (!data.CancelRequsted) { foreach (var file in allDifferences.FileDifferences.ToAdd) { if (data.AcceptCancelIfRequested()) { break; } var fileNode = FileNode.Create((LfsFileInfo)file); fileNode.FileSystem = fileSystemToModify; fileSystemToModify.Files.AddAndRelocate(fileNode); if (file.FileType == FileType.Folder) { fileSystemToModify.Directories.AddAndRelocate((IDirectory)fileNode); } SyncFileData(fileNode, file, false, forkNumberMap, forkSourceFileMap, syncErrors); } } // Update files. var fixups = new Dictionary <FileNode, ILfsFileInfo>(); if (!data.CancelRequsted) { foreach (var file in allDifferences.FileDifferences.ToUpdate) { if (data.AcceptCancelIfRequested()) { break; } var localFile = (FileNode)fileSystemToModify.Files[file.GlobalFileNumber]; if (localFile.FileType != file.FileType) { // We've got a case of a file changing to / from a directory, which must be handled differently. // Simply null out the entry to prevent unwanted collateral damage, such as deleted forks or other files. fileSystemToModify.Files[localFile.GlobalFileNumber] = null; var localParent = (Folder)localFile.Parent; var localGdn = localFile.GlobalDirectoryNumber; var indexInParent = localParent.IndexOfChild(localFile); localFile = FileNode.Create((LfsFileInfo)file); localFile.FileSystem = fileSystemToModify; localFile.GlobalFileNumber = file.GlobalFileNumber; fileSystemToModify.Files.Add(localFile); SyncFileData(localFile, file, true, forkNumberMap, forkSourceFileMap, syncErrors); switch (file.FileType) { case FileType.File: ////System.Diagnostics.Debug.Assert(localFile.FileType == file.FileType, "File type mutation! Need to implement!"); // The directory on the local file system is being replaced with a file. It's possible that the directory // itself has been reparented to a new location, so we do not 'destructively' remove it. Instead, we will // null out its entry in the GDT / GFT and replace the GFT entry with a new file. fileSystemToModify.Directories[localGdn] = null; // so we don't accidentally nuke files and their forks - directories will be updated later break; case FileType.Folder: // The file on the local file system is a standard file, but on the device, it's now a directory. // Need to remove the file and create a directory in its place. We'll also need to populate the directory. // The directory population will need to happen after we've completely finished all the adds / updates. localFile.GlobalDirectoryNumber = file.GlobalDirectoryNumber; fileSystemToModify.Directories.Add((Folder)localFile); break; } localParent.Files[indexInParent] = localFile; fixups[localFile] = file; } else { SyncFileData(localFile, file, true, forkNumberMap, forkSourceFileMap, syncErrors); } } } // Add directories. if (!data.CancelRequsted) { foreach (var directory in allDifferences.DirectoryDifferences.ToAdd) { if (data.AcceptCancelIfRequested()) { break; } // Directory itself may already be in the file system. Now, we need to set contents correctly. var localFolder = (Folder)fileSystemToModify.Directories[directory.GlobalDirectoryNumber]; if (localFolder == null) { System.Diagnostics.Debug.WriteLine("Where's my dir?"); syncErrors.FailedToCreateEntries.Add(directory); } for (var i = 0; i < directory.PresentationOrder.ValidEntryCount; ++i) { if (data.AcceptCancelIfRequested()) { break; } var childToAdd = fileSystemToModify.Files[directory.PresentationOrder[i]]; localFolder.AddChild((IFile)childToAdd, false); } } } // Update directories. if (!data.CancelRequsted) { foreach (var directory in allDifferences.DirectoryDifferences.ToUpdate) { // Need to keep contents in sync. All other changes were handled by file update. var localFolder = (Folder)fileSystemToModify.Directories[directory.GlobalDirectoryNumber]; if (localFolder == null) { localFolder = new Folder(fileSystemToModify, directory.GlobalDirectoryNumber, string.Empty); } var localNumEntries = localFolder.PresentationOrder.ValidEntryCount; var devicePresentationOrder = directory.PresentationOrder; for (var i = devicePresentationOrder.ValidEntryCount; !data.CancelRequsted && (i < localNumEntries); ++i) { if (data.AcceptCancelIfRequested()) { break; } var prevFile = localFolder.Files[devicePresentationOrder.ValidEntryCount]; var prevParent = prevFile.Parent; localFolder.Files.RemoveAt(devicePresentationOrder.ValidEntryCount); prevFile.Parent = prevParent; } localNumEntries = localFolder.PresentationOrder.ValidEntryCount; for (var i = 0; !data.CancelRequsted && (i < (devicePresentationOrder.ValidEntryCount - localNumEntries)); ++i) { if (data.AcceptCancelIfRequested()) { break; } localFolder.Files.Add((FileNode)fileSystemToModify.Files[devicePresentationOrder[i]]); } System.Diagnostics.Debug.Assert(localFolder.Files.Count == devicePresentationOrder.ValidEntryCount, "Incorrect number of children in directory!"); for (var i = 0; !data.CancelRequsted && (i < devicePresentationOrder.ValidEntryCount); ++i) { if (data.AcceptCancelIfRequested()) { break; } var localFile = (FileNode)fileSystemToModify.Files[devicePresentationOrder[i]]; if (!ReferenceEquals(localFolder.Files[i], localFile)) { var prevFile = localFolder.Files[i]; var prevFileParent = prevFile == null ? null : prevFile.Parent; localFolder.Files[i] = localFile; localFile.Parent = localFolder; if (prevFile != null) { // The default behavior of item replacement is to null the parent of the existing item. // Therefore, because some item rearrangement results in a file shuffling 'up' or 'down' // in the same folder, we need to retain the parent. So if the item is still in here, // reset its parent. prevFile.Parent = prevFileParent; } } } } } // Now, pass back the new MenuLayout so UI thread can update and save. if (!data.CancelRequsted && data.Succeeded) { syncErrors.Data = (MenuLayout)fileSystemToModify.Directories[GlobalDirectoryTable.RootDirectoryNumber]; } }
private void UpdateProgressText(AsyncTaskData taskData, string format, string content) { taskData.UpdateTaskProgress(0, string.Format(System.Globalization.CultureInfo.CurrentCulture, format, content)); }
private static void AddItems(AsyncTaskData taskData) { var args = (AddRomsToMenuData)taskData; args.MenuLayout.StartItemsUpdate(); var insertIndex = args.InsertLocation; var destination = args.Destination; var destinationDirectories = (args.DestinationDirectories == null) ? null : args.DestinationDirectories.ToList(); var numItemsToAdd = args.ItemsToAdd.Count(); var numAdded = 0; foreach (var item in args.ItemsToAdd) { if (args.AcceptCancelIfRequested()) { break; } if (destinationDirectories != null) { destination = args.MenuLayout.MenuLayout as Folder; var folders = destinationDirectories[numAdded].Split(new[] { System.IO.Path.DirectorySeparatorChar }, System.StringSplitOptions.RemoveEmptyEntries); foreach (var folder in folders) { var existingFolder = (Folder)((Folder)destination).Files.FirstOrDefault(f => (f is Folder) && (f.Name == folder)); if (existingFolder == null) { string reasonForFailure; if (FileSystemCanAcceptMoreItems(destination, LfsEntityType.Directory, 1, true, out reasonForFailure)) { var newParentFolder = args.MenuLayout.MenuLayout.CreateFolder(folder); args.UIDispatcher.Invoke(new System.Action(() => destination.AddChild(newParentFolder, true)), OSDispatcherPriority.Background); destination = newParentFolder; } else { AddFailedEntry(args.FailedToAdd, destination, folder, reasonForFailure, item.Rom.RomPath); } } else { destination = existingFolder; } } } if (destination == null) { // default to the root destination = args.MenuLayout.MenuLayout; } ++numAdded; args.UpdateTaskProgress(((double)numAdded / numItemsToAdd) * 100, item.Name); var reasonForRejection = string.Empty; var accepted = IsAcceptableRom(item, out reasonForRejection); if (!accepted) { AddFailedEntry(args.FailedToAdd, destination, item.Name, reasonForRejection, item.Rom.RomPath); } else { string reasonForFailure; accepted = FileSystemCanAcceptMoreItems(destination, LfsEntityType.File, 1, true, out reasonForFailure); if (!accepted) { AddFailedEntry(args.FailedToAdd, destination, item.Name, reasonForFailure, item.Rom.RomPath); } } if (accepted) { try { var program = args.MenuLayout.MenuLayout.CreateProgram(item); if (insertIndex < 0) { args.UIDispatcher.Invoke(new System.Action(() => destination.AddChild(program, true)), OSDispatcherPriority.Background); } else { args.UIDispatcher.Invoke(new System.Action(() => destination.InsertChild(insertIndex, program, true)), OSDispatcherPriority.Background); ++insertIndex; } } catch (LuigiFileGenerationException exception) { AddFailedEntry(args.FailedToAdd, destination, item.Name, Resources.Strings.AddItemRejected_FailedToCreateLUIGIFile, item.Rom.RomPath); if (args.FirstFilePreparationError == null) { args.FirstFilePreparationError = exception; } } } } }
/// <summary> /// This is a general-purpose command completion routine for use with the asynchronous task system for executing commands on a Locutus device. /// </summary> /// <param name="taskData">The task data.</param> /// <remarks>This function will be called on the main thread when a Locutus command has finished executing. It will report whether the command /// successfully executed, and execute an optional callback upon success.</remarks> private static void OnComplete(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; #if REPORT_COMMAND_PERFORMANCE var portName = data.Device.Port == null ? "NO_PORT" : data.Device.Port.Name; try { #endif // REPORT_COMMAND_PERFORMANCE data.Device.IsCommandInProgress = false; data.ExitedCommand = true; data.Device.Port.LogPortMessage("<<<< ExecuteDeviceCommandAsyncTaskData COMPLETE: CommandInProgress: FALSE"); var exception = data.Error; var exceptionErrorDetail = data.DeviceExceptionDetail; var failureMessage = data.FailureMessage; var currentlyExecutingCommand = data.CurrentlyExecutingCommand; bool succeeded = data.Succeeded && (exception == null); if (succeeded && (data.OnSuccess != null)) { data.OnSuccess(data.Cancelled, data.DidShowProgress, data.Result); } var goIdle = !succeeded; if (goIdle) { data.Device.ConnectionState = ConnectionState.Idle; } if (!succeeded && (data.OnFailure != null)) { var errorMessageBuilder = new System.Text.StringBuilder(); errorMessageBuilder.Append(string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.DeviceCommand_Generic_FailedFormat, currentlyExecutingCommand)); if (!string.IsNullOrWhiteSpace(exceptionErrorDetail)) { if (errorMessageBuilder.Length > 0) { errorMessageBuilder.AppendLine(); } errorMessageBuilder.Append(exceptionErrorDetail.Trim()); } exceptionErrorDetail = errorMessageBuilder.ToString(); if (exception != null) { ErrorLog errorLog = null; var errorLogMessageString = string.Empty; if (exception is DeviceCommandExecuteFailedException) { try { data.Device.Port.LogPortMessage(">>>> ExecuteDeviceCommandAsyncTaskData COMPLETE: FETCH ERROR LOG: CommandInProgress: TRUE"); data.Device.IsCommandInProgress = true; var gotErrorSucceeded = false; errorLog = Commands.DownloadErrorLog.Instance.Execute(data.Device.Port, null, out gotErrorSucceeded) as ErrorLog; const int MaxDownloadErrorRetryCount = 3; for (int i = 0; !gotErrorSucceeded && (errorLog == null) && (i < MaxDownloadErrorRetryCount); ++i) { DebugOutput("Retry download error log attempt #" + i + 1); // Wait for a beacon and try again. if (data.Device.WaitForBeacon(ProtocolCommand.WaitForBeaconTimeout)) { errorLog = Commands.DownloadErrorLog.Instance.Execute(data.Device.Port, null, out gotErrorSucceeded) as ErrorLog; } } errorMessageBuilder.AppendLine(); if (gotErrorSucceeded) { if (errorLog.ErrorIds.All(id => id == ErrorLogId.Luigi)) { errorLogMessageString = Resources.Strings.ErrorLog_DecodeLuigiErrorMessage; } else { var errorLogContents = errorLog.GetDetailedErrorReport(data.Device.FirmwareRevisions.Current); if (string.IsNullOrWhiteSpace(errorLogContents)) { errorLogContents = Resources.Strings.ErrorBufferReport_Empty; } errorMessageBuilder.AppendLine().AppendFormat(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.ErrorBufferReport_Format, errorLogContents); errorLog = null; // we don't want to use the error log mechanism in this case } } else { errorMessageBuilder.AppendLine().AppendLine(Resources.Strings.ErrorBufferReport_FailedToRetrieve); } } catch (Exception e) { errorMessageBuilder.AppendLine().AppendLine(Resources.Strings.ErrorBufferReport_ThrewException).AppendLine().AppendLine(e.ToString()); } finally { data.Device.IsCommandInProgress = false; data.Device.Port.LogPortMessage(">>>> ExecuteDeviceCommandAsyncTaskData COMPLETE: FETCH ERROR LOG: CommandInProgress: FALSE"); } exceptionErrorDetail = errorMessageBuilder.ToString(); } if ((errorLog != null) && !string.IsNullOrEmpty(errorLogMessageString)) { exception = new DeviceCommandFailedException(errorLogMessageString, errorLog, exception as DeviceCommandExecuteFailedException); } else { exception = new DeviceCommandFailedException(currentlyExecutingCommand, exception, exceptionErrorDetail); } } else { exception = new DeviceCommandFailedException(currentlyExecutingCommand, exceptionErrorDetail); } if (string.IsNullOrWhiteSpace(failureMessage)) { var endOfFirstLine = exceptionErrorDetail.IndexOf(Environment.NewLine); if (endOfFirstLine > 0) { failureMessage = exceptionErrorDetail.Substring(0, endOfFirstLine).Trim(); } else { failureMessage = exceptionErrorDetail.Trim(); } } succeeded = data.OnFailure(failureMessage, exception); } if (goIdle) { data.Device.ConnectionState = ConnectionState.WaitForBeacon; } data.Dispose(); if (!succeeded) { if (string.IsNullOrWhiteSpace(failureMessage)) { throw new DeviceCommandFailedException(currentlyExecutingCommand, exception, exceptionErrorDetail); } else { throw new DeviceCommandFailedException(currentlyExecutingCommand, failureMessage, exception, exceptionErrorDetail); } } #if REPORT_COMMAND_PERFORMANCE } finally { data.Stopwatch.Stop(); DebugOutput(portName + ": DEVICECOMMAND FINISH: " + data.DoWorkMethodName + " DURATION: " + data.Stopwatch.Elapsed.ToString()); } #endif // REPORT_COMMAND_PERFORMANCE // I don't like doing this here -- it's too "UI-ey" for being in the Model, but // it fixes various problems and is easier than adding a universal 'on command complete' handler. INTV.Shared.ComponentModel.CommandManager.InvalidateRequerySuggested(); }
private static void ExecMarkFileAsNew(AsyncTaskData obj) { CoreContext.TenantManager.SetCurrentTenant(Convert.ToInt32(obj.TenantID)); using (var folderDao = Global.DaoFactory.GetFolderDao()) { object parentFolderId; if (obj.FileEntry.FileEntryType == FileEntryType.File) { parentFolderId = ((File)obj.FileEntry).FolderID; } else { parentFolderId = obj.FileEntry.ID; } var parentFolders = folderDao.GetParentFolders(parentFolderId); parentFolders.Reverse(); var userIDs = obj.UserIDs; var userEntriesData = new Dictionary <Guid, List <FileEntry> >(); if (obj.FileEntry.RootFolderType == FolderType.BUNCH) { if (!userIDs.Any()) { return; } parentFolders.Add(folderDao.GetFolder(Global.FolderProjects)); var entries = new List <FileEntry> { obj.FileEntry }; entries = entries.Concat(parentFolders).ToList(); userIDs.ForEach(userID => { if (userEntriesData.ContainsKey(userID)) { userEntriesData[userID].AddRange(entries); } else { userEntriesData.Add(userID, entries); } RemoveFromCahce(Global.FolderProjects, userID); }); } else { var filesSecurity = Global.GetFilesSecurity(); if (!userIDs.Any()) { userIDs = filesSecurity.WhoCanRead(obj.FileEntry).Where(x => x != obj.CurrentAccountId).ToList(); } if (obj.FileEntry.ProviderEntry) { userIDs = userIDs.Where(u => !CoreContext.UserManager.GetUsers(u).IsVisitor()).ToList(); } parentFolders.ForEach(parentFolder => filesSecurity .WhoCanRead(parentFolder) .Where(userID => userIDs.Contains(userID) && userID != obj.CurrentAccountId) .ToList() .ForEach(userID => { if (userEntriesData.ContainsKey(userID)) { userEntriesData[userID].Add(parentFolder); } else { userEntriesData.Add(userID, new List <FileEntry> { parentFolder }); } }) ); if (obj.FileEntry.RootFolderType == FolderType.USER) { var folderShare = folderDao.GetFolder(Global.FolderShare); foreach (var userID in userIDs) { var userFolderId = folderDao.GetFolderIDUser(false, userID); if (Equals(userFolderId, 0)) { continue; } Folder rootFolder = null; if (obj.FileEntry.ProviderEntry) { rootFolder = obj.FileEntry.RootFolderCreator == userID ? folderDao.GetFolder(userFolderId) : folderShare; } else if (!Equals(obj.FileEntry.RootFolderId, userFolderId)) { rootFolder = folderShare; } else { RemoveFromCahce(userFolderId, userID); } if (rootFolder == null) { continue; } if (userEntriesData.ContainsKey(userID)) { userEntriesData[userID].Add(rootFolder); } else { userEntriesData.Add(userID, new List <FileEntry> { rootFolder }); } RemoveFromCahce(rootFolder.ID, userID); } } else if (obj.FileEntry.RootFolderType == FolderType.COMMON) { userIDs.ForEach(userID => RemoveFromCahce(Global.FolderCommon, userID)); if (obj.FileEntry.ProviderEntry) { var commonFolder = folderDao.GetFolder(Global.FolderCommon); userIDs.ForEach(userID => { if (userEntriesData.ContainsKey(userID)) { userEntriesData[userID].Add(commonFolder); } else { userEntriesData.Add(userID, new List <FileEntry> { commonFolder }); } RemoveFromCahce(Global.FolderCommon, userID); }); } } else if (obj.FileEntry.RootFolderType == FolderType.Privacy) { foreach (var userID in userIDs) { var privacyFolderId = folderDao.GetFolderIDPrivacy(false, userID); if (Equals(privacyFolderId, 0)) { continue; } var rootFolder = folderDao.GetFolder(privacyFolderId); if (rootFolder == null) { continue; } if (userEntriesData.ContainsKey(userID)) { userEntriesData[userID].Add(rootFolder); } else { userEntriesData.Add(userID, new List <FileEntry> { rootFolder }); } RemoveFromCahce(rootFolder.ID, userID); } } userIDs.ForEach(userID => { if (userEntriesData.ContainsKey(userID)) { userEntriesData[userID].Add(obj.FileEntry); } else { userEntriesData.Add(userID, new List <FileEntry> { obj.FileEntry }); } }); } using (var tagDao = Global.DaoFactory.GetTagDao()) { var newTags = new List <Tag>(); var updateTags = new List <Tag>(); foreach (var userID in userEntriesData.Keys) { if (tagDao.GetNewTags(userID, obj.FileEntry).Any()) { continue; } var entries = userEntriesData[userID].Distinct().ToList(); var exist = tagDao.GetNewTags(userID, entries).ToList(); var update = exist.Where(t => t.EntryType == FileEntryType.Folder).ToList(); update.ForEach(t => t.Count++); updateTags.AddRange(update); entries.ForEach(entry => { if (entry != null && exist.All(tag => tag != null && !tag.EntryId.Equals(entry.ID))) { newTags.Add(Tag.New(userID, entry)); } }); } if (updateTags.Any()) { tagDao.UpdateNewTags(updateTags); } if (newTags.Any()) { tagDao.SaveTags(newTags); } } } }
private static void BackupFileSystem(AsyncTaskData taskData) { var data = (ExecuteDeviceCommandAsyncTaskData)taskData; var succeeded = false; try { var configuration = SingleInstanceApplication.Instance.GetConfiguration <Configuration>(); var romsConfiguration = SingleInstanceApplication.Instance.GetConfiguration <INTV.Shared.Model.RomListConfiguration>(); var roms = SingleInstanceApplication.Instance.Roms; var device = data.Device; data.UpdateTaskProgress(0, Resources.Strings.DeviceMultistageCommand_BackupFileSystem_Syncing); var deviceFileSystemFlags = GetDirtyFlags.Instance.Execute <LfsDirtyFlags>(device.Port, data); // Always re-fetch the file system. When we're done, tell the UI to refresh. var fileSystem = DownloadFileSystemTables.Instance.Execute <FileSystem>(device.Port, data); fileSystem.Status = deviceFileSystemFlags; data.Result = new FileSystemSyncErrors(deviceFileSystemFlags); // Retrieve the forks. var backupDirectory = data.Data as string; var forksToBackup = fileSystem.Forks.Where(f => f != null); if (forksToBackup.Any() && !data.AcceptCancelIfRequested()) { var forkFileNames = new List <string>(); foreach (var fork in forksToBackup) { bool dontCare; var backupDir = backupDirectory; // we don't want to modify backupDirectory var fileName = GetPathForFork(data, fork, fileSystem, roms, romsConfiguration, ref backupDir, out dontCare); fileName = System.IO.Path.GetFileName(fileName); forkFileNames.Add(fileName); } succeeded = device.RetrieveForkData(data, forksToBackup, backupDirectory, forkFileNames); } else { succeeded = data.CancelRequsted; } if (succeeded && !data.AcceptCancelIfRequested()) { data.UpdateTaskProgress(0, Resources.Strings.DeviceMultistageCommand_BackupFileSystem_CreatingMenuLayout); var menuBackupPath = System.IO.Path.Combine(backupDirectory, configuration.DefaultMenuLayoutFileName); var menuLayout = new MenuLayout(fileSystem, device.UniqueId); menuLayout.LoadComplete(false); menuLayout.Save(menuBackupPath, true); } else if (data.CancelRequsted && succeeded) { succeeded = true; } } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.Message); succeeded = false; if (!string.IsNullOrWhiteSpace(data.FailureMessage)) { var builder = new System.Text.StringBuilder(Resources.Strings.DeviceMultistageCommand_BackupFileSystem_Failed); builder.AppendLine().AppendLine(data.FailureMessage); data.FailureMessage = builder.ToString(); } else { data.FailureMessage = Resources.Strings.DeviceMultistageCommand_BackupFileSystem_Failed; } throw; } finally { data.Succeeded = succeeded; } }
private void UpdateProgressTitle(AsyncTaskData taskData, int numDiscovered) { var args = (RomDiscoveryData)taskData; taskData.UpdateTaskTitle(string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomListViewModel_Progress_Title_Format, args.Title, numDiscovered)); }
private static void InstallSDL(AsyncTaskData taskData) { var data = (InstallSDLTaskData)taskData; var diskImageInfo = data.DiskImageInfo; var progressMessage = string.Empty; if ((diskImageInfo.DownloadUrl != null) && !File.Exists(diskImageInfo.Path)) { progressMessage = string.Format( CultureInfo.CurrentCulture, Resources.Strings.SDLNotFound_Downloading_Format, diskImageInfo.Version, diskImageInfo.DownloadUrl, diskImageInfo.Path); data.UpdateTaskProgress(0, progressMessage); using (var httpClient = new System.Net.Http.HttpClient()) { var response = httpClient.GetAsync(diskImageInfo.DownloadUrl).Result; if (response.IsSuccessStatusCode) { using (var stream = response.Content.ReadAsStreamAsync().Result) using (var sdkDiskImageFile = new FileStream(diskImageInfo.Path, FileMode.Create, FileAccess.Write, FileShare.None)) { stream.CopyTo(sdkDiskImageFile); } } } } progressMessage = string.Format(CultureInfo.CurrentCulture, Resources.Strings.SDLInstall_Update_Mounting, diskImageInfo.FileName); data.UpdateTaskProgress(0, progressMessage); var sdlDmgPath = diskImageInfo.Path; string sdlDev = string.Empty; try { var result = RunExternalProgram.CallAndReturnStdOut("/usr/bin/hdiutil", "attach -noautoopen -nobrowse -readonly -plist \"" + sdlDmgPath + "\"", null); var plist = new XmlDocument(); plist.LoadXml(result); var mountInfo = GetSDLMountVolume(plist); var mountVolume = mountInfo == null ? null : mountInfo.Item2; sdlDev = mountInfo == null ? null : mountInfo.Item1; if (!string.IsNullOrEmpty(mountVolume) && Directory.Exists(mountVolume)) { progressMessage = string.Format(CultureInfo.CurrentCulture, Resources.Strings.SDLInstall_Update_Copying, diskImageInfo.FrameworkName); data.UpdateTaskProgress(0, progressMessage); var sdlSource = NSUrl.FromFilename(mountVolume).Append(diskImageInfo.FrameworkName, isDirectory: true); string errorMessage; var userLibraryDir = diskImageInfo.GetUserLibraryDirectory(out errorMessage); if ((userLibraryDir != null) && string.IsNullOrEmpty(errorMessage)) { // If the user doesn't already have a Frameworks directory, create it. NSError error; var userLibraryFrameworksDir = userLibraryDir.Append("Frameworks", true); if (Directory.Exists(userLibraryFrameworksDir.Path) || NSFileManager.DefaultManager.CreateDirectory(userLibraryFrameworksDir, true, null, out error)) { var sdlDestination = userLibraryFrameworksDir.Append(diskImageInfo.FrameworkName, isDirectory: true); if (!NSFileManager.DefaultManager.Copy(sdlSource, sdlDestination, out error)) { data.ErrorMessage = string.Format(Resources.Strings.SDLInstall_Failed_Format, diskImageInfo.Version, error.LocalizedDescription); } } else { data.ErrorMessage = string.Format(Resources.Strings.SDLInstall_Failed_Format, diskImageInfo.Version, error.LocalizedDescription); } } else { data.ErrorMessage = errorMessage; } } else { data.ErrorMessage = string.Format(Resources.Strings.SDLInstall_FailedToMount_Format, diskImageInfo.Version, sdlDmgPath, result); } } finally { if (!string.IsNullOrEmpty(sdlDev)) { progressMessage = string.Format(CultureInfo.CurrentCulture, Resources.Strings.SDLInstall_Update_Unmounting, diskImageInfo.FileName); data.UpdateTaskProgress(0, progressMessage); var result = RunExternalProgram.CallAndReturnStdOut("/usr/bin/hdiutil", "detach -force " + sdlDev, null); System.Diagnostics.Debug.WriteLine(result); } } }