예제 #1
0
        public static void DoWithRetry(IProgressWindow logger, Action action, int numberOfRetries, TimeSpan?retryDelay)
        {
            var retryDelayInSecondsSchedule =
                retryDelay.HasValue
                    ? new[] { retryDelay.Value }.Cycle()
                    : new[]
            {
                10,
                30,
                60,
                5 * 60,
                10 * 60,
                15 * 60,
                60 * 60,
                2 * 60 * 60,
            }.Concat(new[] { 2 * 60 * 60 }.Cycle())
            .Select(x => TimeSpan.FromSeconds(x));

            foreach (var delay in retryDelayInSecondsSchedule.Take(numberOfRetries))
            {
                try
                {
                    action();
                    return;
                }
                catch (SimpleException <DoNotRetry> ex)
                {
                    if (ex.InnerException != null)
                    {
                        throw ex.InnerException;
                    }
                    throw new ErrorMessageException(ex.Message);
                }
                catch (ErrorMessageException ex)
                {
                    logger.Log("Error: " + ex.Message);
                    logger.Log("Waiting to retry... (" + delay.ToPrettyFormat() + ")");
                    System.Threading.Thread.Sleep(delay);
                }
                catch (Exception ex)
                {
                    logger.Log(VaultServerException.WrapException(ex).ToString());
                    logger.Log("Waiting to retry... (" + delay.ToPrettyFormat() + ")");
                    System.Threading.Thread.Sleep(delay);
                }
            }
            action();
        }
        public static void LogVersion(IProgressWindow logger, System.Reflection.Assembly executingAssembly)
        {
            string  company, product;
            Version version;

            GetVersion(executingAssembly, out company, out product, out version);

            var shortVer = string.Format("{0} {1}.{2} running...", product, version.Major, version.Minor);
            var longVer  = string.Format("{0} {1} running...", product, version.ToString());

            logger.Log(shortVer, longVer);
        }
        public void Synchronize()
        {
#if DEBUG
            var watch = System.Diagnostics.Stopwatch.StartNew();
#endif
            System.Diagnostics.Debug.WriteLine("SynchronizationThread.Run()");
            StopCheck();

            if (syncTree.IsEmpty())
            {
                logWindow.Log("Not subscribed to any files, nothing to do.");
                logWindow.LogDone();
                return;
            }

            using (VaultCommunication vaultCom = new VaultCommunication()
            {
                connection = connection,
                manager = connection.WebServiceManager,
                UserId = connection.UserID,
                cache = new FunctionJsonCache(),
                Log = s => logWindow.Log(s),
                stopThread = StopThread
            })
            {
                vaultCom.ResetWorkingFoldersIfNecessary();

                StopCheck();
                logWindow.Log("Getting list of files from Vault...");
                sysTray.Start();
                sysTray.ShowIfSlow("Getting info from Vault...           ");
                StopCheck();
                List <string> missingFiles = new List <string>(), missingFolders = new List <string>();
                var           foldersToCreate       = new List <Folder>();
                var           files                 = new List <FileFolder>();
                Action        getFilesToSynchronize = () =>
                                                      files = vaultCom.GetFilesToSynchronize(syncTree, missingFolders: missingFolders, missingFiles: missingFiles, watchedFolders: foldersToCreate);
                getFilesToSynchronize();
                StopCheck();
                if (missingFolders.Any() || missingFiles.Any())
                {
                    logWindow.Log("Missing folder/files!");
                    if (vaultCom.TryRepairSynchronizationTree(syncTree))
                    {
                        getFilesToSynchronize();
                        logWindow.Log("Getting list of files from Vault again...");
                    }
                }

                //foreach (var fileFolder in files)
                //{
                //    Console.WriteLine(fileFolder.Folder.FullName + "/" + fileFolder.File.VerName);
                //}

#if DEBUG
                logWindow.Log("Time elapsed " + watch.ElapsedMilliseconds + "ms");
#endif

                logWindow.Log("");
                logWindow.Log("Checking if files are up to date (" + files.Count + " files)...");
                sysTray.ShowIfSlow("Getting info from Vault (watching " + files.Count + " files)...");

                StopCheck();
                var fileStatuses = files
                                   .Select(filefolder =>
                {
                    StopCheck();
                    var localPath = syncTree.GetLocalPathOfPath(VaultCommunication.GeneratePathFromFolderAndFile(filefolder));
                    Dbg.Trace("before vaultCom.QuickLocalFileStatus(filefolder.File, ...");
                    return(new
                    {
                        localPath,
                        filefolder,
                        status = localPath.IsSome
                                                ? vaultCom.QuickLocalFileStatus(filefolder.File, localPath.Get())
                                                : vaultCom.QuickLocalFileStatus(filefolder.File, filefolder.Folder),
                    });
                })
                                   .ToList();
                StopCheck();
                Dbg.Trace("after var fileStatuses = ...");

                //logWindow.Log(string.Join("\r\n",fileStatuses.Select(x => x.file.VerName + ": " + x.status.ToString()).ToArray()));

                var partition    = fileStatuses.PartitionBy(x => x.status.VersionState == EntityStatus.VersionStateEnum.Unknown);
                var unknownFiles = partition[true];
                fileStatuses = partition[false];

                partition = fileStatuses.PartitionBy(x => x.status.CheckoutState == EntityStatus.CheckoutStateEnum.CheckedOutByCurrentUser);
                var checkedOutByCurrentUserFiles = partition[true];
                fileStatuses = partition[false];

                logWindow.Log(checkedOutByCurrentUserFiles.Count + " files checked out by current user (skipped)");

                partition = fileStatuses.PartitionBy(x => x.status.VersionState == EntityStatus.VersionStateEnum.MatchesLatestVaultVersion && x.status.LocalEditsState == EntityStatus.LocalEditsStateEnum.DoesNotHaveLocalEdits);
                var filesUpToDate = partition[true];
                fileStatuses = partition[false];

                logWindow.Log(filesUpToDate.Count + " files up to date");

                if (!syncTree.Config.OverwriteLocallyModifiedFiles)
                {
                    partition = fileStatuses.PartitionBy(x => x.status.LocalEditsState == EntityStatus.LocalEditsStateEnum.HasLocalEdits);
                    var locallyModified = partition[true];
                    fileStatuses = partition[false];

                    logWindow.Log(locallyModified.Count + " files locally modified:");

                    foreach (var item in locallyModified)
                    {
                        logWindow.Log("  " + item.filefolder.File.VerName);
                    }
                }

                var filesToUpdate = fileStatuses.ToList();

                logWindow.Log("");
                Dbg.Trace("before if (filesToUpdate.Count != 0)");
                int numberOfErrors = missingFiles.Count + missingFolders.Count + unknownFiles.Count;
                if (filesToUpdate.Count != 0)
                {
                    logWindow.Log("Downloading " + filesToUpdate.Count + " files...");
                    sysTray.ShowNow("Getting info from Vault (watching " + files.Count + " files)...\r\n" + filesToUpdate.Count + " files out of date. Downloading (1/" + filesToUpdate.Count + ")...");
                    logWindow.LogWithProgress(null, 0);
                    int count = 0;
                    var failedDownloadsQueue = new List <string>();
                    Dbg.Trace("before vaultCom.DownloadFiles(...");
                    vaultCom.DownloadFiles(filesToUpdate.Select(x => Tuple.Create(x.filefolder, x.localPath)).ToArray(), failedDownloadsQueue, afterDownload: () =>
                    {
                        Dbg.Trace("vaultCom.DownloadFiles, afterDownload");
                        count++;
                        sysTray.ShowIfSlow("Getting info from Vault (watching " + files.Count + " files)...\r\n" + filesToUpdate.Count + " files out of date. Downloading (" + count + "/" + filesToUpdate.Count + ")...");
                        int progress = (int)Math.Round(100.0 * count / filesToUpdate.Count);
                        logWindow.LogWithProgress(null, progress);
                        StopCheck();
                    });
                    failedDownloads = failedDownloadsQueue.ToList();
                    numberOfErrors += failedDownloads.Count;
                    sysTray.ShowIfSlow("Getting info from Vault (watching " + files.Count + " files)...\r\n" + filesToUpdate.Count + " files out of date. Downloaded " + (filesToUpdate.Count - failedDownloads.Count) + " files, checking folders...");
                }

                logWindow.Log("Ensuring folder structure up to date...");
                try
                {
                    foreach (var folder in foldersToCreate)
                    {
                        StopCheck();
                        string localPath = syncTree.GetLocalPathOfPath(folder.FullName + '/').Else(() => vaultCom.GetLocalPathFromFolder(folder));
                        if (!System.IO.Directory.Exists(localPath))
                        {
                            System.IO.Directory.CreateDirectory(localPath);
                            logWindow.Log("  created " + folder.FullName + " locally");
                        }
                    }
                }
                catch (StopThreadException)
                {
                    throw;
                }
                catch { }

                if (!dontUpdateConfig)
                {
                    logWindow.Log("Updating config file...");
                    vaultCom.UpdateLastVaultId(syncTree);
                }
                StopCheck();

                if (filesToUpdate.Count == 0)
                {
                    logWindow.Log("");
                    logWindow.Log("No file to download");

                    if (numberOfErrors == 0)
                    {
                        sysTray.ShowNow("Getting info from Vault (watching " + files.Count + " files)...\r\nAll up to date!", ignoreMinimumDisplayTime: true);
                    }
                    else
                    {
                        sysTray.ShowNow("Getting info from Vault (watching " + files.Count + " files)...\r\nNothing to download.\r\nErrors occurred.", ignoreMinimumDisplayTime: true);
                    }
                }
                else
                {
                    sysTray.ShowNow("Getting info from Vault (watching " + files.Count + " files)...\r\n" + filesToUpdate.Count + " files out of date. Downloaded " + (filesToUpdate.Count - failedDownloads.Count) + " files!" + (numberOfErrors == 0 ? "" : "\r\nErrors occurred."), ignoreMinimumDisplayTime: true);
                }

                logWindow.Log("Done.");
                logWindow.LogDone();
#if DEBUG
                logWindow.Log("Time elapsed " + watch.ElapsedMilliseconds + "ms");
#endif

                if (numberOfErrors > 0)
                {
                    logWindow.Log("");
                    logWindow.Log("Errors:");
                    logWindow.Show();
                }

                // errors
                foreach (var item in missingFiles)
                {
                    errors.Add("ERROR: Couldn't find file in Vault: " + item);
                }
                foreach (var item in missingFolders)
                {
                    errors.Add("ERROR: Couldn't find folder in Vault: " + item);
                }
                foreach (var item in unknownFiles)
                {
                    errors.Add("ERROR: Couldn't get status for " + item.filefolder.File.VerName);
                }
                foreach (var item in failedDownloads)
                {
                    errors.Add("ERROR: Couldn't download " + item);
                }

                foreach (var error in errors)
                {
                    logWindow.Log(error);
                }
            }
        }