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); } } }