Example #1
0
        internal void Add(AsyncTaskData <T> taskData)
        {
            lock (Locker)
            {
                Tasks.Add(taskData);

                if (!Tasks.IsStarted)
                {
                    Tasks.Start(ExecMarkFileAsNew);
                }
            }
        }
Example #2
0
        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;
            }
        }
Example #4
0
 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);
     }
 }
Example #5
0
        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);
            }
        }
Example #6
0
        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);
            }
        }
Example #8
0
        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);
            }
        }
Example #9
0
 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;
     }
 }
Example #10
0
        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);
            }
        }
Example #12
0
        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.
            }
        }
Example #15
0
        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);
                }
            }
        }
Example #16
0
        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;
                        }
                    }
                }
            }
        }
Example #17
0
 internal void Add(AsyncTaskData <T> taskData)
 {
     Tasks.QueueTask((d, c) => ExecMarkFileAsNew(taskData), taskData);
 }
Example #18
0
        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());
                }
            }
        }
Example #19
0
        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);
            }
        }
Example #20
0
        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;
            }
        }
Example #21
0
        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];
            }
        }
Example #24
0
 private void UpdateProgressText(AsyncTaskData taskData, string format, string content)
 {
     taskData.UpdateTaskProgress(0, string.Format(System.Globalization.CultureInfo.CurrentCulture, format, content));
 }
Example #25
0
        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();
        }
Example #27
0
        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);
                    }
                }
            }
        }
Example #28
0
        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;
            }
        }
Example #29
0
        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);
                }
            }
        }